/* ============================================================
   baud/ui — tokens (@layer theme)
   Themes, density, type modes, border-mode hooks.
   Values lifted verbatim from design/baud-tokens.css.
   Raw hex lives ONLY in this file.
   ============================================================ */
@layer theme, base, components, utilities;

@layer theme {
  :root {
    --font-mono: 'JetBrains Mono', ui-monospace, 'IBM Plex Mono', monospace;
    --font-sans: 'IBM Plex Sans', system-ui, sans-serif;
    --nav-w: 28ch;
  }

  /* ---------- density ---------- */
  .d-ultra { --fs: 11px; --fs-sm: 10px;   --rh: 20px; --row: 18px; --pad: 4px; --gap: 4px; }
  .d-dense { --fs: 12px; --fs-sm: 10.5px; --rh: 24px; --row: 22px; --pad: 6px; --gap: 6px; }
  .d-cozy  { --fs: 13px; --fs-sm: 11px;   --rh: 30px; --row: 27px; --pad: 8px; --gap: 8px; }

  /* ---------- type mode ---------- */
  .f-mono { --font-ui: var(--font-mono); }
  .f-mix  { --font-ui: var(--font-sans); }

  /* ---------- border modes (hooks; component layers add per-mode rules) ---------- */
  .b-line  { --border-style: solid; }
  .b-shade { --border-style: solid; }
  .b-ascii { --border-style: dashed; }

  /* ---------- themes (iTerm2 schemes) ---------- */
  .t-gruvbox {
    --bg-app: #1d2021; --bg-panel: #282828; --bg-raised: #32302f;
    --bg-hover: #3c3836; --bg-active: #504945; --bg-input: #1d2021;
    --border: #3c3836; --border-strong: #504945;
    --fg: #ebdbb2; --fg-muted: #a89984; --fg-faint: #7c6f64;
    --accent: #fabd2f; --accent-2: #83a598; --on-accent: #1d2021;
    --ok: #b8bb26; --warn: #fabd2f; --err: #fb4934; --info: #83a598;
    --sel: rgba(250, 189, 47, 0.14);
    --shadow: rgba(0, 0, 0, 0.5);
  }
  .t-mocha {
    --bg-app: #11111b; --bg-panel: #181825; --bg-raised: #1e1e2e;
    --bg-hover: #313244; --bg-active: #45475a; --bg-input: #0d0d15;
    --border: #313244; --border-strong: #45475a;
    --fg: #cdd6f4; --fg-muted: #a6adc8; --fg-faint: #6c7086;
    --accent: #89b4fa; --accent-2: #cba6f7; --on-accent: #11111b;
    --ok: #a6e3a1; --warn: #f9e2af; --err: #f38ba8; --info: #89dceb;
    --sel: rgba(137, 180, 250, 0.13);
    --shadow: rgba(0, 0, 0, 0.55);
  }
  .t-sollight {
    --bg-app: #eee8d5; --bg-panel: #fdf6e3; --bg-raised: #f4eedb;
    --bg-hover: #e9e2cd; --bg-active: #ddd6c1; --bg-input: #fdf6e3;
    --border: #d9d2bc; --border-strong: #c4bda6;
    --fg: #586e75; --fg-muted: #657b83; --fg-faint: #93a1a1;
    --accent: #268bd2; --accent-2: #2aa198; --on-accent: #fdf6e3;
    --ok: #859900; --warn: #b58900; --err: #dc322f; --info: #2aa198;
    --sel: rgba(38, 139, 210, 0.13);
    --shadow: rgba(0, 0, 0, 0.18);
  }
}
/* ============================================================
   baud/ui — base (@layer base)
   Resets, document defaults, selection, scrollbars, focus.
   ============================================================ */
@layer base {
  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body { height: 100%; }

  body {
    min-width: 1240px; /* desktop only — hard floor, horizontal scroll below */
    background: var(--bg-app);
    color: var(--fg);
    font-family: var(--font-mono);
    font-size: var(--fs);
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
    overflow: auto;
  }

  ::selection { background: var(--accent); color: var(--on-accent); }

  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: var(--bg-app); }
  ::-webkit-scrollbar-thumb { background: var(--bg-active); border: 2px solid var(--bg-app); }
  ::-webkit-scrollbar-thumb:hover { background: var(--fg-faint); }
  ::-webkit-scrollbar-corner { background: var(--bg-app); }

  button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

  :focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }
}
/* ============================================================
   baud/ui — badges & dots (@layer components)
   Lifted from design/baud-tokens.css. Tints/outlines are color-mix
   derivations of the base tone vars, so new themes only supply the
   ~20 base vars. The round .dot is the one sanctioned circle in the
   library; the in-badge dot stays a 5px square. Fixed pixel dot
   dimensions are design-spec constants, not density-driven.
   Owned by wave 1 (badge) — do not edit from other branches.
   ============================================================ */
@layer components {
  /* ---------- badge ---------- */
  .badge {
    display: inline-flex; align-items: center; gap: 5px;
    height: calc(var(--row) - 5px); padding: 0 6px;
    font-family: var(--font-ui); font-size: var(--fs-sm);
    font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
    border: 1px var(--border-style, solid) transparent; white-space: nowrap;
  }
  .badge .badge-dot { width: 5px; height: 5px; background: currentColor; flex: none; }

  /* tone text colour (scoped to badge/dot — not a global utility) */
  .badge.tone-ok,      .dot.tone-ok      { color: var(--ok); }
  .badge.tone-warn,    .dot.tone-warn    { color: var(--warn); }
  .badge.tone-err,     .dot.tone-err     { color: var(--err); }
  .badge.tone-info,    .dot.tone-info    { color: var(--info); }
  .badge.tone-accent,  .dot.tone-accent  { color: var(--accent); }
  .badge.tone-neutral, .dot.tone-neutral { color: var(--fg-muted); }

  /* tint: 15% color-mix bg + 38% border — keep this exact technique */
  .bd-tint.tone-ok     { background: color-mix(in srgb, var(--ok) 15%, transparent); border-color: color-mix(in srgb, var(--ok) 38%, transparent); }
  .bd-tint.tone-warn   { background: color-mix(in srgb, var(--warn) 15%, transparent); border-color: color-mix(in srgb, var(--warn) 38%, transparent); }
  .bd-tint.tone-err    { background: color-mix(in srgb, var(--err) 15%, transparent); border-color: color-mix(in srgb, var(--err) 38%, transparent); }
  .bd-tint.tone-info   { background: color-mix(in srgb, var(--info) 15%, transparent); border-color: color-mix(in srgb, var(--info) 38%, transparent); }
  .bd-tint.tone-accent { background: color-mix(in srgb, var(--accent) 15%, transparent); border-color: color-mix(in srgb, var(--accent) 38%, transparent); }
  .bd-tint.tone-neutral { background: var(--bg-raised); border-color: var(--border-strong); }

  .bd-outline { background: transparent; border-color: color-mix(in srgb, currentColor 55%, transparent); }

  .bd-solid.tone-ok      { background: var(--ok); color: var(--bg-panel); }
  .bd-solid.tone-warn    { background: var(--warn); color: var(--bg-panel); }
  .bd-solid.tone-err     { background: var(--err); color: var(--bg-panel); }
  .bd-solid.tone-info    { background: var(--info); color: var(--bg-panel); }
  .bd-solid.tone-accent  { background: var(--accent); color: var(--on-accent); }
  .bd-solid.tone-neutral { background: var(--fg-faint); color: var(--bg-panel); }

  /* ---------- status dot ---------- */
  /* The one sanctioned circle — boxes everywhere else stay square. */
  .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

  @media (prefers-reduced-motion: no-preference) {
    .dot.pulse { animation: baud-pulse 1.6s ease-in-out infinite; }
    @keyframes baud-pulse {
      0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 50%, transparent); }
      55% { box-shadow: 0 0 0 4px transparent; }
    }
  }
}
/* ============================================================
   baud/ui — buttons + kbd (@layer components)
   Btn (default/primary/danger/ghost × active/disabled), BtnGroup,
   Kbd chip. Lifted from design/baud-tokens.css; raw colours
   converted to tokens. Remaining px are structural constants
   (1px hairlines, -1px group fuse, small optical nudges).
   Owned by wave 1 (feat/btn) — do not edit in parallel.
   ============================================================ */
@layer components {
  /* ---------- kbd ---------- */
  .kbd {
    font-family: var(--font-mono); font-size: var(--fs-sm);
    padding: 0 4px; line-height: 1.5;
    border: 1px var(--border-style, solid) var(--border-strong);
    background: var(--bg-raised); color: var(--fg-muted);
    white-space: nowrap;
  }

  /* ---------- buttons ---------- */
  .btn {
    display: inline-flex; align-items: center; gap: var(--gap);
    height: var(--rh); padding: 0 calc(var(--pad) * 1.6);
    font-family: var(--font-ui); font-size: var(--fs-sm);
    font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--fg); background: var(--bg-raised);
    border: 1px var(--border-style, solid) var(--border-strong);
    white-space: nowrap; user-select: none;
  }
  .btn:hover { background: var(--bg-hover); }
  .btn:active { background: var(--bg-active); }
  .btn:disabled { opacity: 0.42; cursor: not-allowed; }
  .btn .kbd { margin-left: 2px; margin-right: -3px; }
  .btn-glyph { font-family: var(--font-mono); font-weight: 400; }

  .btn-primary {
    background: var(--accent); border-color: var(--accent);
    border-style: solid; /* design: stays solid even in b-ascii */
    color: var(--on-accent);
  }
  .btn-primary:hover { background: color-mix(in srgb, var(--accent) 86%, var(--fg)); }
  .btn-primary:active { background: color-mix(in srgb, var(--accent) 75%, var(--bg-app)); }
  /* design rgba(0,0,0,.18) → on-accent tint so it tracks the theme */
  .btn-primary .kbd {
    background: color-mix(in srgb, var(--on-accent) 18%, transparent);
    border-color: transparent; color: var(--on-accent);
  }

  .btn-danger {
    background: transparent;
    border-color: color-mix(in srgb, var(--err) 55%, transparent);
    color: var(--err);
  }
  .btn-danger:hover { background: var(--err); color: var(--bg-panel); border-color: var(--err); }

  .btn-ghost { background: transparent; border-color: transparent; color: var(--fg-muted); }
  .btn-ghost:hover { background: var(--bg-hover); color: var(--fg); }

  .btn.is-active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

  /* ---------- button group (fused borders) ---------- */
  .btn-group { display: inline-flex; }
  .btn-group .btn { margin-left: -1px; }
  .btn-group .btn:first-child { margin-left: 0; }
  .btn-group .btn.is-active { position: relative; z-index: 1; }
}
/* ============================================================
   baud/ui — choice controls (@layer components)
   Checkbox / Radio (.cbx) and segmented Toggle (.tg), lifted
   from design/baud-tokens.css. Real <input> elements underneath
   (visually hidden, still focusable); glyphs and the accent
   segment are painted by CSS from :checked — zero client logic.
   Owned by feat/choice-controls — do not edit in parallel.
   ============================================================ */
@layer components {
  /* ---------- checkbox / radio ---------- */
  .cbx {
    position: relative;
    display: inline-flex; align-items: center; gap: var(--gap);
    cursor: pointer; user-select: none;
    color: var(--fg);
  }

  /* the real input: visually hidden but focusable (never display:none) */
  .cbx-input {
    position: absolute;
    width: 1px; height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
  }

  .cbx-box { color: var(--fg-muted); white-space: pre; }
  .cbx:hover .cbx-box { color: var(--accent); }

  /* glyphs are ::before content keyed on input type + :checked */
  .cbx-box::before { content: "[ ]"; }
  .cbx-input:checked + .cbx-box::before { content: "[x]"; }
  .cbx-input[type="radio"] + .cbx-box::before { content: "( )"; }
  .cbx-input[type="radio"]:checked + .cbx-box::before { content: "(\2022)"; }

  .cbx-input:checked + .cbx-box { color: var(--accent); font-weight: 700; }

  /* focus ring lands on the glyph while the hidden input holds focus */
  .cbx-input:focus-visible + .cbx-box {
    outline: 1px solid var(--accent);
    outline-offset: 1px;
  }

  .cbx:has(.cbx-input:disabled) { opacity: 0.42; cursor: not-allowed; }

  /* ---------- toggle (segmented radio strip) ---------- */
  .tg {
    display: inline-flex;
    border: 1px var(--border-style, solid) var(--border-strong);
    background: var(--bg-input);
    user-select: none;
  }
  .tg-opt {
    position: relative;
    display: flex; align-items: center;
    height: calc(var(--rh) - var(--pad));
    padding: 0 calc(var(--pad) * 1.5);
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--fg-faint);
    cursor: pointer;
  }
  .tg-opt:hover { color: var(--fg); }

  .tg-input {
    position: absolute;
    width: 1px; height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
  }

  .tg-opt:has(.tg-input:checked) { background: var(--accent); color: var(--on-accent); }
  .tg-opt:has(.tg-input:focus-visible) {
    outline: 1px solid var(--accent);
    outline-offset: 1px;
    z-index: 1;
  }
  .tg-opt:has(.tg-input:disabled) { opacity: 0.42; cursor: not-allowed; }

  .b-shade .tg { border-color: transparent; background: var(--bg-raised); }
}
/* ============================================================
   baud/ui — pagination & diff viewer (@layer components)
   Lifted nearly verbatim from design/baud-extras.css (pagination,
   diff sections). Fixed pixel gaps/widths are design-spec
   constants, not density-driven. Adaptations: .pager-btn is
   inline-flex (it can render as an <a> in link mode — same box
   either way, no underline); the diff header tone spans are
   scoped classes instead of the prototype's tone-* utilities.
   Owned by wave 3 (pagination/diff) — do not edit from other
   branches.
   ============================================================ */
@layer components {
  /* ---------- pagination ---------- */
  .pager {
    display: flex; align-items: center; gap: 8px;
    height: var(--rh); padding: 0 var(--pad);
    border-top: 1px solid var(--border); background: var(--bg-raised);
    font-size: var(--fs-sm); color: var(--fg-muted); white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  .pager-info { color: var(--fg-faint); }
  .pager-btn {
    display: inline-flex; align-items: center;
    padding: 0 5px; color: var(--fg-muted); border: 1px solid transparent;
    height: calc(var(--row) - 4px); text-decoration: none;
  }
  .pager-btn:hover { color: var(--fg); background: var(--bg-hover); }
  .pager-btn:disabled { opacity: 0.35; cursor: not-allowed; }
  .pager-btn:disabled:hover { color: var(--fg-muted); background: transparent; }
  .pager-btn.more { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); padding: 0 8px; }
  .pager-spring { flex: 1; }

  /* ---------- diff viewer ---------- */
  .diff { font-variant-numeric: tabular-nums; }
  .diff-hd {
    display: flex; align-items: center; gap: 8px;
    height: var(--row); padding: 0 var(--pad);
    background: var(--bg-raised); border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm); color: var(--fg-muted);
  }
  .diff-hd .diff-file { color: var(--accent); }
  .diff-hd .diff-adds { color: var(--ok); }
  .diff-hd .diff-dels { color: var(--err); }
  .diff-line { display: flex; height: var(--row); align-items: center; white-space: pre; overflow: hidden; }
  .diff-no { flex: none; width: 36px; text-align: right; padding-right: 8px; color: var(--fg-faint); font-size: var(--fs-sm); user-select: none; }
  .diff-sign { flex: none; width: 16px; text-align: center; user-select: none; }
  .diff-text { overflow: hidden; text-overflow: ellipsis; }
  .diff-line.add { background: color-mix(in srgb, var(--ok) 10%, transparent); }
  .diff-line.add .diff-sign, .diff-line.add .diff-text { color: var(--ok); }
  .diff-line.del { background: color-mix(in srgb, var(--err) 10%, transparent); }
  .diff-line.del .diff-sign, .diff-line.del .diff-text { color: var(--err); }
  .diff-line.hunk { background: color-mix(in srgb, var(--info) 8%, transparent); color: var(--info); font-size: var(--fs-sm); padding-left: 52px; }
}
/* ============================================================
   baud/ui — date picker (@layer components)
   Lifted from design/baud-tokens.css (".dp-*" block; the trigger
   lifts the .select-trigger recipe, the menu the .menu recipe,
   the nav buttons the .x-btn recipe with accent hover). Month
   navigation is an htmx round-trip re-rendering the menu
   fragment; open/close and picking are local hyperscript.
   Token-only colours; remaining px are structural constants
   (1px hairlines, small optical nudges from the design).
   Owned by feat/datepicker — do not edit in parallel.
   ============================================================ */
@layer components {
  .dp { position: relative; display: inline-flex; }

  /* ---------- trigger (the .select-trigger recipe) ---------- */
  .dp-trigger {
    display: flex; align-items: center; justify-content: space-between;
    gap: calc(var(--gap) * 1.3);
    height: var(--rh); padding: 0 var(--pad);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
    color: var(--fg);
  }
  .dp-trigger:hover { border-color: var(--fg-faint); }
  .dp-glyph { color: var(--fg-faint); font-size: var(--fs-sm); }
  .dp-value { flex: 1; text-align: left; font-variant-numeric: tabular-nums; }
  .dp-chev { color: var(--fg-faint); font-size: var(--fs-sm); }
  .dp-chev::before { content: "▼"; }
  .dp.open .dp-chev::before { content: "▲"; }

  /* ---------- menu (the .menu recipe; design min-width 232px ≈ 32ch) ---------- */
  .dp-menu {
    display: none;
    position: absolute; top: calc(100% + 2px); left: 0;
    min-width: 32ch;
    padding: var(--pad);
    background: var(--bg-panel);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 10px 30px var(--shadow);
    z-index: 60;
  }
  .dp.open .dp-menu { display: block; }

  /* ---------- header nav ---------- */
  .dp-hd { display: flex; align-items: center; gap: 2px; padding: 2px 2px 6px; }
  .dp-nav { color: var(--fg-faint); padding: 0 2px; font-size: var(--fs); }
  .dp-nav:hover { color: var(--accent); }
  .dp-title {
    flex: 1; text-align: center;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--fg-muted);
  }

  /* ---------- grid ---------- */
  .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
  .dp-dow { text-align: center; font-size: var(--fs-sm); color: var(--fg-faint); padding: 2px 0; }
  .dp-day {
    height: calc(var(--row) + 1px);
    text-align: center;
    color: var(--fg-muted);
    font-variant-numeric: tabular-nums;
  }
  .dp-day:hover { background: var(--bg-hover); color: var(--fg); }
  .dp-day.out { color: var(--fg-faint); opacity: 0.45; }
  .dp-day.today { box-shadow: inset 0 0 0 1px var(--border-strong); }
  .dp-day.sel { background: var(--accent); color: var(--on-accent); font-weight: 700; }

  /* ---------- preset row ---------- */
  .dp-presets {
    display: flex; gap: 4px;
    padding-top: 6px; margin-top: 6px;
    border-top: 1px var(--border-style, solid) var(--border);
  }
  .dp-preset {
    flex: 1; height: calc(var(--row) - 2px);
    font-size: var(--fs-sm); color: var(--fg-muted);
    border: 1px var(--border-style, solid) var(--border);
    background: var(--bg-raised);
  }
  .dp-preset:hover { color: var(--accent); border-color: var(--accent); }
}
/* ============================================================
   baud/ui — feedback: progress · spinner · panel states ·
   confirm input (@layer components)
   Lifted nearly verbatim from design/baud-extras.css (progress/
   spinner, states sections). Remaining px are design-spec
   structural constants (skeleton bar height, optical
   letter-spacing, small gaps). Adaptations: the prog bar tones
   are scoped classes instead of the prototype's tone-*
   utilities; the spinner's braille frames are a discrete
   ::before content animation (the JS the prototype used is
   banned here) — reduced motion pins the static first frame;
   the confirm rows are component glue for the prototype's
   inline styles. Owned by wave 4 (feedback) — do not edit from
   other branches.
   ============================================================ */
@layer components {
  /* ---------- progress ---------- */
  .prog { display: flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .prog-label { color: var(--fg-muted); font-size: var(--fs-sm); min-width: 90px; overflow: hidden; text-overflow: ellipsis; }
  .prog-bar { letter-spacing: -0.5px; }
  .prog-bar.tone-accent { color: var(--accent); }
  .prog-bar.tone-warn   { color: var(--warn); }
  .prog-bar.tone-ok     { color: var(--ok); }
  .prog-bar.tone-err    { color: var(--err); }
  .prog-bar.tone-info   { color: var(--info); }
  .prog-bar .prog-rest  { color: var(--fg-faint); }
  .prog-pct { color: var(--fg-muted); font-size: var(--fs-sm); min-width: 42px; text-align: right; }

  /* ---------- spinner ----------
     Braille frames ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ at 80ms = one 0.8s loop. content is a
     discrete-animatable property in modern Chromium, so the frames cycle
     with zero client logic; step-end holds each frame for its full
     segment. Outside the no-preference media query (or with animations
     unsupported) the static first frame renders. */
  .spinner { display: inline-block; width: 1.2ch; text-align: center; color: var(--accent); }
  .spinner::before { content: "⠋"; }
  @media (prefers-reduced-motion: no-preference) {
    .spinner::before { animation: baud-spin 0.8s step-end infinite; }
    @keyframes baud-spin {
      0%   { content: "⠋"; }
      10%  { content: "⠙"; }
      20%  { content: "⠹"; }
      30%  { content: "⠸"; }
      40%  { content: "⠼"; }
      50%  { content: "⠴"; }
      60%  { content: "⠦"; }
      70%  { content: "⠧"; }
      80%  { content: "⠇"; }
      90%, 100% { content: "⠏"; }
    }
  }

  /* ---------- panel states ---------- */
  .pstate {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; padding: 22px 12px; text-align: center; color: var(--fg-faint);
  }
  .pstate-glyph { font-size: calc(var(--fs) * 1.6); line-height: 1; }
  .pstate-title { color: var(--fg-muted); font-weight: 600; }
  .pstate-sub { font-size: var(--fs-sm); max-width: 320px; }
  .pstate-act { margin-top: 4px; }
  .pstate.err .pstate-glyph, .pstate.err .pstate-title { color: var(--err); }
  .skel-row { display: flex; gap: 8px; align-items: center; height: var(--row); padding: 0 var(--pad); }
  .skel-cell { height: 9px; background: var(--bg-active); flex: none; }
  @media (prefers-reduced-motion: no-preference) {
    .skel-cell { animation: baud-skel-fade 1.1s ease-in-out infinite alternate; }
    .skel-row:nth-child(2) .skel-cell { animation-delay: 0.12s; }
    .skel-row:nth-child(3) .skel-cell { animation-delay: 0.24s; }
    .skel-row:nth-child(4) .skel-cell { animation-delay: 0.36s; }
    .skel-row:nth-child(5) .skel-cell { animation-delay: 0.48s; }
    @keyframes baud-skel-fade { from { opacity: 1; } to { opacity: 0.35; } }
  }

  /* ---------- confirm input ---------- */
  .confirm { display: flex; flex-direction: column; gap: var(--gap); }
  .confirm-row { display: flex; align-items: center; gap: var(--gap); }
  .confirm-expect { color: var(--err); user-select: all; }
}
/* ============================================================
   baud/ui — fleetctl demo console (@layer components)
   Composition glue only: the console is built from shipped
   components; these rules tile the main column, pad the metric
   panel bodies and tone-code the log tail. Tokens only.
   Owned by wave 5 (fleetctl) — do not edit from other branches.
   ============================================================ */
@layer components {
  /* the shared view tabpanel fills the shell's main scroll region */
  [data-shell] > main > .tab-panel { height: 100%; }

  .fleet-main {
    display: flex; flex-direction: column;
    gap: var(--gap); padding: var(--pad);
    height: 100%; min-height: 0;
  }

  /* ---------- metrics strip ---------- */
  .fleet-metrics {
    flex: none;
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: var(--gap);
  }
  .fleet-pad {
    display: flex; flex-direction: column;
    gap: var(--gap); padding: var(--pad);
  }
  /* metric value hierarchy — the prototype's MetricCell big numbers
     (design/baud-app.jsx): 1.5× base size, bold, tone via the fl-*
     classes below. */
  .fl-metric {
    font-size: calc(var(--fs) * 1.5);
    font-weight: 700;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
  }

  /* ---------- hosts table + log tail split ---------- */
  .fleet-hosts-panel { flex: 1.6 1 0; min-height: calc(var(--row) * 8); }
  .fleet-hosts-panel > .panel-bd { display: flex; flex-direction: column; }
  .fleet-log-panel { flex: 1 1 0; min-height: calc(var(--row) * 5); }

  /* ---------- nav ---------- */
  .fleet-nav-h {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-faint);
  }

  /* ---------- log tail ---------- */
  .fleet-log { padding: calc(var(--pad) * 0.5) 0; font-variant-numeric: tabular-nums; }
  .fleet-log-line {
    display: flex; align-items: center;
    gap: calc(var(--gap) * 1.5);
    height: var(--row); padding: 0 var(--pad);
    white-space: nowrap; overflow: hidden;
  }
  .fl-time { flex: none; color: var(--fg-faint); }
  .fl-lvl {
    flex: none; width: 5ch;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
    text-transform: uppercase;
  }
  .fl-pod { flex: none; width: 18ch; color: var(--accent); overflow: hidden; text-overflow: ellipsis; }
  .fl-msg { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

  /* console text tones — scoped per component, cf. the tables.css and
     feedback.css tone classes (the prototype's tone-* utilities). */
  .fl-ok { color: var(--ok); }
  .fl-warn { color: var(--warn); }
  .fl-err { color: var(--err); }
  .fl-info { color: var(--info); }
  .fl-faint { color: var(--fg-faint); }
  .fl-accent { color: var(--accent); }
}
/* ============================================================
   baud/ui — field + input primitives (@layer components)
   Lifted from design/baud-tokens.css ("inputs" block).
   Owned by wave 1 (feat/field-input) — do not edit in parallel.
   ============================================================ */
@layer components {
  /* ---------- input ---------- */
  .input-wrap {
    display: flex; align-items: center;
    gap: calc(var(--gap) * 0.8);
    height: var(--rh);
    padding: 0 var(--pad);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
  }
  .input-wrap:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
  }
  .input-wrap.err { border-color: var(--err); }
  .input-wrap.err:focus-within {
    border-color: var(--err);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--err) 35%, transparent);
  }
  .input-wrap .affix {
    color: var(--fg-faint);
    font-size: var(--fs-sm);
    white-space: nowrap;
  }
  .input {
    flex: 1; min-width: 0; height: 100%;
    background: none; border: none; outline: none;
    color: var(--fg); font: inherit;
  }
  .input::placeholder { color: var(--fg-faint); }
  .input:disabled { cursor: not-allowed; }
  .input-wrap:has(> .input:disabled) { opacity: 0.42; }

  /* ---------- field ---------- */
  .field {
    display: flex; flex-direction: column;
    gap: calc(var(--gap) * 0.5);
    min-width: 0;
  }
  .field-label {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--fg-muted);
  }
  .field-hint { font-size: var(--fs-sm); color: var(--fg-faint); }
  .field-hint.err { color: var(--err); }
}
/* ============================================================
   baud/ui — deflist & breadcrumb (@layer components)
   Lifted from design/baud-extras.css onto semantic dl/dt/dd and
   nav > ol markup (base.css zeroes margins/padding). Fixed pixel
   gaps are design-spec constants, not density-driven.
   Owned by wave 2 (deflist/breadcrumb) — do not edit from other
   branches.
   ============================================================ */
@layer components {
  /* ---------- definition list ---------- */
  .dl { display: grid; grid-template-columns: max-content 1fr; column-gap: 14px; }
  .dl > .dl-k {
    height: var(--row); display: flex; align-items: center;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.06em; text-transform: uppercase; color: var(--fg-faint);
    white-space: nowrap;
  }
  .dl > .dl-v {
    height: var(--row); display: flex; align-items: center; gap: 6px;
    min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
  }
  .dl-lines > .dl-k, .dl-lines > .dl-v { border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); }

  /* ---------- breadcrumb ---------- */
  .crumbs { display: flex; align-items: center; gap: 4px; white-space: nowrap; min-width: 0; list-style: none; }
  .crumbs > li { display: flex; align-items: center; gap: 4px; min-width: 0; }
  .crumb { color: var(--fg-faint); padding: 0 2px; text-decoration: none; }
  a.crumb:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
  .crumb.cur { color: var(--fg); font-weight: 600; }
  .crumb-sep { color: var(--fg-faint); user-select: none; }
}
/* ============================================================
   baud/ui — modal & drawer overlays (@layer components)
   Lifted from design/baud-components.css (modal / drawer / palette
   overlays section). Additions over the design source: the
   .overlay-static class-toggle variant (the always-in-DOM sheet
   instances stay display:none until .open), the .drawer-bd body
   slot (the prototype inlined these styles on .panel-bd), the
   header-scoped .x-btn recipe (design/baud-tokens.css), and the
   ~160ms entrance animations behind prefers-reduced-motion per the
   design animation policy. Fixed pixel sizes/paddings are design-
   spec constants, not density-driven; border style flows through
   --border-style so b-ascii dashes automatically.
   Owned by wave 4 (modal-drawer) — do not edit from other branches.
   ============================================================ */
@layer components {
  /* ---------- backdrop ---------- */
  .overlay {
    position: fixed; inset: 0; z-index: 100;
    background: color-mix(in srgb, var(--shadow) 60%, transparent);
    display: flex; align-items: flex-start; justify-content: center;
  }
  /* static sheet variant: in the DOM from first render, shown by the
     Overlay behavior toggling .open */
  .overlay.overlay-static:not(.open) { display: none; }

  /* ---------- modal ---------- */
  .modal {
    margin-top: 9vh; width: 540px; max-width: 92vw;
    background: var(--bg-panel);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 24px 60px var(--shadow);
    display: flex; flex-direction: column;
  }
  .modal-hd {
    display: flex; align-items: center; justify-content: space-between;
    height: calc(var(--rh) + 4px); padding: 0 10px;
    border-bottom: 1px var(--border-style, solid) var(--border);
  }
  .modal-title {
    font-family: var(--font-ui); font-size: var(--fs); font-weight: 700;
    letter-spacing: 0.06em; text-transform: uppercase;
  }
  .modal-hd .x-btn { color: var(--fg-faint); padding: 0 2px; font-size: var(--fs); }
  .modal-hd .x-btn:hover { color: var(--err); }
  .modal-bd { padding: 12px 10px; display: flex; flex-direction: column; gap: 10px; }
  .modal-ft {
    display: flex; justify-content: flex-end; gap: var(--gap);
    padding: 8px 10px;
    border-top: 1px var(--border-style, solid) var(--border);
    background: var(--bg-raised);
  }

  /* ---------- drawer ---------- */
  .overlay.drawer-wrap { background: color-mix(in srgb, var(--shadow) 45%, transparent); }
  .drawer {
    position: absolute; top: 0; right: 0; bottom: 0; width: 420px; max-width: 90vw;
    background: var(--bg-panel);
    border-left: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: -18px 0 50px var(--shadow);
    display: flex; flex-direction: column;
  }
  .drawer-bd {
    flex: 1; min-height: 0; overflow: auto;
    padding: 12px 10px; display: flex; flex-direction: column; gap: 10px;
  }

  /* ---------- entrances (animation policy: ~160ms, motion-gated) ------ */
  @media (prefers-reduced-motion: no-preference) {
    .modal { animation: modal-in 0.16s ease-out; }
    @keyframes modal-in { from { transform: translateY(-8px); opacity: 0; } to { transform: none; opacity: 1; } }
    .drawer { animation: drawer-in 0.16s ease-out; }
    @keyframes drawer-in { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
  }
}
/* ============================================================
   baud/ui — command palette (@layer components)
   Lifted from design/baud-components.css ("command palette" +
   overlay blocks); raw colours converted to tokens. Remaining px
   are structural constants from the design handoff (560px panel,
   64px category column, 1px hairlines, 2px accent inset, shadow
   geometry). Backdrop classes are palette-scoped so the file
   never collides with the modal/drawer overlay waves.
   Owned by wave 4 (feat/palette) — do not edit in parallel.
   ============================================================ */
@layer components {
  /* ---------- backdrop ---------- */
  .palette-overlay {
    position: fixed; inset: 0; z-index: 100;
    background: color-mix(in srgb, var(--shadow) 60%, transparent);
    display: none;
    align-items: flex-start; justify-content: center;
  }
  .palette-overlay.open { display: flex; }
  /* component-sheet variant: inline, no backdrop, no stacking */
  .palette-overlay.palette-static {
    position: static; inset: auto; z-index: auto;
    background: none; justify-content: flex-start;
  }
  .palette-static .palette { margin-top: 0; }

  /* ---------- panel ---------- */
  .palette {
    margin-top: 12vh; width: 560px; max-width: 92vw;
    background: var(--bg-panel); border: 1px var(--border-style, solid) var(--accent);
    box-shadow: 0 24px 60px var(--shadow);
  }
  .palette-input {
    display: flex; align-items: center;
    gap: calc(var(--gap) * 1.2);
    padding: 0 calc(var(--pad) * 1.7);
    height: calc(var(--rh) + 8px);
    border-bottom: 1px var(--border-style, solid) var(--border);
  }
  .palette-input .prompt { color: var(--accent); font-weight: 700; }

  /* ---------- rows ---------- */
  .palette-list {
    max-height: calc(var(--row) * 14);
    overflow: auto; padding: 3px 0;
  }
  .palette-item {
    display: flex; align-items: center;
    gap: calc(var(--gap) * 1.3);
    width: 100%; height: calc(var(--row) + 2px);
    padding: 0 calc(var(--pad) * 1.7);
    color: var(--fg-muted);
    text-align: left; white-space: nowrap; text-decoration: none;
  }
  .palette-item .pi-cat {
    color: var(--fg-faint); font-size: var(--fs-sm);
    width: 64px; flex: none;
    text-transform: uppercase; letter-spacing: 0.06em;
  }
  .palette-item .pi-keys { margin-left: auto; display: flex; gap: 3px; }
  .palette-item:hover { background: var(--bg-hover); color: var(--fg); }
  .palette-item.hl {
    background: var(--sel); color: var(--fg);
    box-shadow: inset 2px 0 0 var(--accent);
  }
  .palette-empty { padding: calc(var(--pad) * 2.3) calc(var(--pad) * 1.7); color: var(--fg-faint); }
}
/* ============================================================
   baud/ui — panel, statusbar, toolbar (@layer components)
   Lifted from design/baud-components.css (panel / status bar /
   toolbar sections); the prototype's .panel root class becomes
   the data-panel activation attribute. Border style flows through
   --border-style so b-ascii dashes automatically; the ┌─ … ─┐
   title wrap stays behind the b-ascii mode class (experimental
   per the design spec). Fixed pixel gaps/paddings are design-spec
   constants, not density-driven.
   Owned by wave 2 (panel) — do not edit from other branches.
   ============================================================ */
@layer components {
  /* ---------- panel ---------- */
  [data-panel] {
    position: relative; display: flex; flex-direction: column; min-width: 0;
    background: var(--bg-panel); border: 1px var(--border-style, solid) var(--border);
  }
  .panel-hd {
    flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px;
    height: var(--rh); padding: 0 var(--pad);
    border-bottom: 1px var(--border-style, solid) var(--border);
  }
  .panel-title {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .panel-acts { display: flex; align-items: center; gap: 4px; }
  .panel-bd { flex: 1; min-height: 0; overflow: auto; }

  /* border-mode variants: b-shade swaps hairlines for a raised header
     fill; b-ascii (dashes via --border-style) adds the title glyph wrap. */
  .b-shade [data-panel] { border-color: transparent; }
  .b-shade .panel-hd { border-bottom-color: transparent; background: var(--bg-raised); }

  .b-ascii .panel-title::before {
    content: "┌─ ";
    color: var(--fg-faint); font-family: var(--font-mono); font-weight: 400;
    text-transform: none; letter-spacing: 0;
  }
  .b-ascii .panel-title::after {
    content: " ─┐";
    color: var(--fg-faint); font-family: var(--font-mono); font-weight: 400;
  }

  /* ---------- status bar ---------- */
  .statusbar {
    flex: none; display: flex; align-items: stretch;
    height: var(--rh); background: var(--bg-raised);
    border-top: 1px var(--border-style, solid) var(--border-strong);
    font-size: var(--fs-sm); color: var(--fg-muted);
    overflow: hidden; white-space: nowrap;
  }
  .sb-cell { display: flex; align-items: center; gap: 5px; padding: 0 9px; border-right: 1px solid var(--border); }
  .sb-cell:last-child { border-right: none; }
  .sb-spring { flex: 1; border-right: none; }
  .sb-mode { background: var(--accent); color: var(--on-accent); font-weight: 700; letter-spacing: 0.08em; }

  /* inside the shell footer slot the strip chrome (height, fill, top
     hairline) comes from [data-statusbar] — the inner strip just fills */
  [data-statusbar] > .statusbar { flex: 1; min-width: 0; height: auto; border-top: none; }

  /* ---------- toolbar ---------- */
  .toolbar { display: flex; align-items: center; gap: var(--gap); flex-wrap: nowrap; }
}
/* ============================================================
   baud/ui — popover + tooltip (@layer components)
   .pop-wrap/.popover anchored quick-actions panel lifted from
   design/baud-components.css ("popover" block); [data-tip]
   pure-CSS tooltip lifted from design/baud-extras.css
   ("tooltip" block), .tip class renamed to the [data-tip]
   attribute per the data-* component philosophy. Raw colours
   converted to tokens. Remaining px are structural constants
   from the design CSS (280px panel, 10px/8px panel pad/gap,
   4px/5px anchor offsets, 3px/7px tip pad, 4px arrow, shadow
   geometry, underline offset).
   Owned by wave 4 (feat/popover-tooltip) — do not edit in
   parallel.
   ============================================================ */
@layer components {
  /* ---------- popover ---------- */
  .pop-wrap { position: relative; display: inline-flex; }
  .pop-wrap > .popover { display: none; }
  .pop-wrap.open > .popover { display: flex; }
  .popover {
    position: absolute; top: calc(100% + 4px); left: 0; z-index: 70;
    width: 280px;
    background: var(--bg-panel);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 12px 36px var(--shadow);
    padding: 10px;
    flex-direction: column; gap: 8px;
  }

  /* ---------- tooltip (pure CSS, data-tip attribute) ---------- */
  [data-tip] { position: relative; }
  [data-tip]::after {
    content: attr(data-tip);
    position: absolute; left: 50%; bottom: calc(100% + 5px); transform: translateX(-50%);
    background: var(--bg-raised); color: var(--fg);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 6px 18px var(--shadow);
    padding: 3px 7px; font-size: var(--fs-sm); font-family: var(--font-mono);
    white-space: pre; pointer-events: none; opacity: 0; z-index: 90;
  }
  [data-tip]::before {
    /* arrow: solid border triangle is structural, not a hairline */
    content: ""; position: absolute; left: 50%; bottom: calc(100% + 1px); transform: translateX(-50%);
    border: 4px solid transparent; border-top-color: var(--border-strong);
    pointer-events: none; opacity: 0; z-index: 90;
  }
  [data-tip]:hover::after, [data-tip]:hover::before,
  [data-tip]:focus-visible::after, [data-tip]:focus-visible::before { opacity: 1; }
  /* the 150ms show delay rides the opacity transition, so it is
     reduced-motion-gated: with reduced motion the tip flips instantly */
  @media (prefers-reduced-motion: no-preference) {
    [data-tip]::after, [data-tip]::before { transition: opacity 0.08s ease-in 0.15s; }
  }
  .tip-under {
    text-decoration: underline dotted var(--fg-faint);
    text-underline-offset: 3px;
    cursor: help;
  }
}
/* ============================================================
   baud/ui — select / menu / combobox (@layer components)
   Native .select-native baseline, .select-trigger + .menu
   enhancement, combobox filter highlight. Lifted from
   design/baud-tokens.css ("select / menu" block); raw colours
   converted to tokens. Remaining px are structural constants
   (1px hairlines, 2px menu offset, glow ring).
   Owned by wave 2 (feat/select-combobox) — do not edit in parallel.
   ============================================================ */
@layer components {
  /* ---------- root ---------- */
  .select { position: relative; display: inline-flex; }

  /* ---------- native baseline ---------- */
  .select-native {
    appearance: none;
    width: 100%; height: var(--rh);
    padding: 0 calc(var(--pad) * 4) 0 var(--pad);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
    color: var(--fg); font: inherit;
    cursor: pointer;
  }
  .select-native:hover { border-color: var(--fg-faint); }
  .select-native:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
  }
  .select-native:disabled { opacity: 0.42; cursor: not-allowed; }
  .select-native + .select-chev {
    position: absolute; right: var(--pad); top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
  }

  /* ---------- enhanced trigger ---------- */
  .select-trigger {
    display: flex; align-items: center; justify-content: space-between;
    gap: calc(var(--gap) * 1.3);
    width: 100%; height: var(--rh);
    padding: 0 var(--pad);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
    color: var(--fg);
    white-space: nowrap;
  }
  .select-trigger:hover { border-color: var(--fg-faint); }
  .select-trigger:disabled { opacity: 0.42; cursor: not-allowed; }

  .select-chev { color: var(--fg-faint); font-size: var(--fs-sm); }
  .select-chev::before { content: "▼"; }
  .select.open .select-chev::before { content: "▲"; }

  /* ---------- menu ---------- */
  .select > .menu { display: none; }
  .select.open > .menu { display: block; }
  .menu {
    position: absolute; top: calc(100% + 2px); left: 0; min-width: 100%;
    background: var(--bg-panel);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 10px 30px var(--shadow);
    z-index: 60;
    max-height: calc(var(--row) * 13);
    overflow: auto;
    padding: 2px 0;
  }
  .menu-right { left: auto; right: 0; }

  .menu-item {
    display: flex; align-items: center; justify-content: space-between;
    gap: calc(var(--gap) * 2.5);
    width: 100%; height: var(--row);
    padding: 0 calc(var(--pad) * 1.5);
    color: var(--fg-muted);
    text-align: left; white-space: nowrap;
  }
  .menu-item[hidden] { display: none; }
  .menu-item:hover { background: var(--bg-hover); color: var(--fg); }
  /* keyboard-highlighted row (aria-activedescendant target) */
  .menu-item.hl-row { background: var(--bg-hover); color: var(--fg); }
  .menu-item.is-active { color: var(--accent); }

  .menu-side { display: inline-flex; align-items: center; gap: var(--gap); }
  .menu-check { color: var(--accent); font-size: var(--fs-sm); display: none; }
  .menu-item.is-active .menu-check { display: inline; }
  .menu-sep { height: 1px; background: var(--border); margin: 2px 0; }

  .menu-empty {
    display: none; align-items: center;
    height: var(--row); padding: 0 calc(var(--pad) * 1.5);
    color: var(--fg-faint); font-size: var(--fs-sm);
  }
  .menu:not(:has(.menu-item:not([hidden]))) .menu-empty { display: flex; }

  /* ---------- combobox ---------- */
  .combobox > .input-wrap { flex: 1; min-width: 0; cursor: text; }
  .cb-match { color: var(--accent); font-weight: 700; }
  .cb-meta { color: var(--fg-faint); font-size: var(--fs-sm); }
}
/* ============================================================
   baud/ui — component sheet + demo chrome (@layer components)
   Sheet sections, token swatches, tweaks panel, demo placeholders.
   Owned by wave 0 (foundation).
   ============================================================ */
@layer components {
  /* ---------- sheet scaffolding ---------- */
  .sheet-wrap { padding: calc(var(--pad) * 2); }
  .sheet-section { display: flex; flex-direction: column; gap: var(--gap); }
  .sheet-h {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint);
    display: flex; align-items: center; gap: var(--gap);
  }
  .sheet-h::after { content: ""; flex: 1; height: 1px; background: var(--border); }
  .sheet-row { display: flex; align-items: center; gap: var(--gap); flex-wrap: wrap; }

  /* ---------- token swatches ---------- */
  .swatch { display: flex; flex-direction: column; gap: calc(var(--gap) * 0.5); width: 11ch; }
  .swatch-chip { height: calc(var(--row) + var(--pad)); border: 1px var(--border-style, solid) var(--border); }
  .swatch-name { font-size: var(--fs-sm); color: var(--fg-muted); }

  .swatch-chip[data-token="bg-app"] { background: var(--bg-app); }
  .swatch-chip[data-token="bg-panel"] { background: var(--bg-panel); }
  .swatch-chip[data-token="bg-raised"] { background: var(--bg-raised); }
  .swatch-chip[data-token="bg-hover"] { background: var(--bg-hover); }
  .swatch-chip[data-token="bg-active"] { background: var(--bg-active); }
  .swatch-chip[data-token="bg-input"] { background: var(--bg-input); }
  .swatch-chip[data-token="border"] { background: var(--border); }
  .swatch-chip[data-token="border-strong"] { background: var(--border-strong); }
  .swatch-chip[data-token="fg"] { background: var(--fg); }
  .swatch-chip[data-token="fg-muted"] { background: var(--fg-muted); }
  .swatch-chip[data-token="fg-faint"] { background: var(--fg-faint); }
  .swatch-chip[data-token="accent"] { background: var(--accent); }
  .swatch-chip[data-token="accent-2"] { background: var(--accent-2); }
  .swatch-chip[data-token="on-accent"] { background: var(--on-accent); }
  .swatch-chip[data-token="ok"] { background: var(--ok); }
  .swatch-chip[data-token="warn"] { background: var(--warn); }
  .swatch-chip[data-token="err"] { background: var(--err); }
  .swatch-chip[data-token="info"] { background: var(--info); }
  .swatch-chip[data-token="sel"] { background: var(--sel); }
  .swatch-chip[data-token="shadow"] { background: var(--shadow); }

  /* ---------- tweaks panel (sheet only) ---------- */
  .tweaks {
    position: fixed; right: calc(var(--gap) * 2); bottom: calc(var(--rh) + var(--gap) * 2);
    z-index: 80;
    display: flex; flex-direction: column; gap: var(--gap);
    padding: var(--pad);
    background: var(--bg-panel);
    border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 10px 30px var(--shadow);
  }
  .tweaks-h {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 700;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint);
  }
  .tweak-row { display: flex; align-items: center; gap: calc(var(--gap) * 0.5); }
  .tweak-label {
    width: 9ch;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase; color: var(--fg-muted);
  }
  .tweak-btn {
    height: calc(var(--rh) - var(--pad));
    padding: 0 var(--pad);
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--fg-faint);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
  }
  .tweak-btn:hover { color: var(--fg); background: var(--bg-hover); }
  .tweak-btn.is-active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

  /* ---------- sheet pane demos ---------- */
  .pane-demo { height: calc(var(--row) * 8); border: 1px var(--border-style, solid) var(--border); background: var(--bg-panel); }
  .pane-box { padding: var(--pad); background: var(--bg-panel); }
  .pane-box-title {
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-muted);
  }
  .pane-box-note { font-size: var(--fs-sm); color: var(--fg-faint); }
  /* The wave-0 fleetctl placeholder nav chrome (.demo-nav / .demo-main-panes)
     left with the placeholder — the real console's glue lives in
     components/fleetctl.css (wave 5). */
}
/* ============================================================
   baud/ui — shell + panes (@layer components)
   App frame grid, pane tiling, split gutters, brand.
   Owned by wave 0 (foundation) — later waves add their own
   components/<area>.css files; never edit this one in parallel.
   ============================================================ */
@layer components {
  /* ---------- app shell ---------- */
  [data-shell] {
    display: grid;
    grid-template-columns: var(--nav-w, 28ch) 1fr;
    grid-template-rows: auto 1fr auto;
    height: 100dvh;
    min-width: 0;
    min-height: 0;
    background: var(--bg-app);
  }
  /* data-nav is optional; without it the shell collapses to one column */
  [data-shell]:not(:has(> [data-nav])) { grid-template-columns: 1fr; }

  [data-shell] > [data-topbar],
  [data-shell] > [data-statusbar] { grid-column: 1 / -1; }

  [data-shell] > [data-topbar] {
    display: flex; align-items: center;
    gap: calc(var(--gap) * 1.6);
    height: calc(var(--rh) + var(--pad));
    padding: 0 calc(var(--pad) * 1.6);
    background: var(--bg-panel);
    border-bottom: 1px var(--border-style, solid) var(--border-strong);
    white-space: nowrap;
  }

  [data-shell] > [data-nav] {
    min-height: 0; overflow: auto;
    padding: var(--pad);
    background: var(--bg-panel);
    border-right: 1px var(--border-style, solid) var(--border);
  }

  /* main is the only scroll container of the frame */
  [data-shell] > main {
    min-width: 0; min-height: 0; overflow: auto;
  }

  [data-shell] > [data-statusbar] {
    display: flex; align-items: stretch;
    height: var(--rh);
    background: var(--bg-raised);
    border-top: 1px var(--border-style, solid) var(--border-strong);
    font-size: var(--fs-sm);
    color: var(--fg-muted);
    overflow: hidden; white-space: nowrap;
  }

  .b-shade [data-shell] > [data-topbar] { border-bottom-color: transparent; background: var(--bg-raised); }
  .b-shade [data-shell] > [data-nav] { border-right-color: transparent; background: var(--bg-raised); }

  /* ---------- brand (topbar) ---------- */
  .brand { display: flex; align-items: baseline; gap: var(--gap); white-space: nowrap; }
  .brand-name { font-weight: 700; color: var(--accent); letter-spacing: 0.04em; }
  .brand-sub { font-size: var(--fs-sm); color: var(--fg-faint); }

  /* ---------- panes ---------- */
  /* Grid template is applied by the Panes hyperscript behavior from the
     data-panes / data-panes-rows value. Without it (no client runtime) the
     grid degrades to a static single-column stack — by design. */
  [data-panes], [data-panes-rows] {
    display: grid;
    min-width: 0; min-height: 0;
  }
  [data-panes] > *, [data-panes-rows] > * {
    min-width: 0; min-height: 0; overflow: auto;
  }

  /* ---------- split gutter (resizable panes) ---------- */
  .split-gutter {
    position: relative;
    display: flex; align-items: center; justify-content: center;
    background: transparent;
    user-select: none;
    touch-action: none;
    overflow: hidden;
    cursor: col-resize;
  }
  .split-gutter::after { content: "\22EE"; color: var(--fg-faint); font-size: var(--fs-sm); }
  .split-gutter:hover, .split-gutter.drag { background: color-mix(in srgb, var(--accent) 18%, transparent); }
  .split-gutter:hover::after, .split-gutter.drag::after { color: var(--accent); }
  [data-panes-rows] > .split-gutter { cursor: row-resize; }
  [data-panes-rows] > .split-gutter::after { content: "\22EF"; }
}
/* ============================================================
   baud/ui — data table (@layer components)
   Lifted nearly verbatim from design/baud-components.css
   ("data table"): sticky --bg-raised UPPERCASE header, --row
   rows, hover --bg-hover, selected row --sel + 2px accent inset
   bar + ▌ row mark, right-aligned numeric columns, opt-in
   zebra/lines variants, tone-coded threshold cells. Sort is
   htmx (th hx-get) — no client styling state here. Fixed px
   (arrow size/offset, inset bar, cell max-width) are design-spec
   constants, not density-driven. Owned by feat/datatable — do
   not edit in parallel.
   ============================================================ */
@layer components {
  .dt { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
  .dt th {
    position: sticky; top: 0; z-index: 2;
    height: var(--row); padding: 0 var(--pad);
    background: var(--bg-raised);
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase; color: var(--fg-muted);
    text-align: left; white-space: nowrap;
    border-bottom: 1px var(--border-style, solid) var(--border-strong);
  }
  .dt th.sortable { cursor: pointer; user-select: none; }
  .dt th.sortable:hover { color: var(--fg); }
  .dt th.sorted { color: var(--accent); }
  .dt th .sort-arrow { font-size: 9px; margin-left: 3px; }
  .dt td {
    height: var(--row); padding: 0 var(--pad);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 320px;
    border-bottom: 1px var(--border-style, solid) color-mix(in srgb, var(--border) 55%, transparent);
  }
  .dt .num { text-align: right; }
  .dt th.num { text-align: right; }
  .dt tbody tr { cursor: default; }
  .dt tbody tr:hover td { background: var(--bg-hover); }
  .dt tbody tr.sel td { background: var(--sel); }
  .dt tbody tr.sel td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
  .dt-zebra tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--bg-raised) 50%, transparent); }
  .dt-zebra tbody tr:hover td { background: var(--bg-hover); }
  .dt-zebra tbody tr.sel td { background: var(--sel); }
  .dt-lines td, .dt-lines th { border-right: 1px var(--border-style, solid) color-mix(in srgb, var(--border) 55%, transparent); }
  .dt-lines td:last-child, .dt-lines th:last-child { border-right: none; }
  .dt .row-mark { color: var(--fg-faint); width: 1%; }
  .dt tr.sel .row-mark { color: var(--accent); }

  /* tone-coded threshold cells (DataTableProps.CellTone hook) */
  .dt td.tone-ok { color: var(--ok); }
  .dt td.tone-warn { color: var(--warn); }
  .dt td.tone-err { color: var(--err); }
  .dt td.tone-info { color: var(--info); }
  .dt td.tone-accent { color: var(--accent); }
  .dt td.tone-faint { color: var(--fg-faint); }
}
/* ============================================================
   baud/ui — tabs (@layer components)
   Lifted from design/baud-components.css. Two variants: underline
   (2px accent underline on the active tab) and boxed (bordered
   strip, active = accent fill). Tabs are real <button role=tab>
   elements (button resets live in base.css) — or <a role=tab>
   links in the progressive-enhancement NavHref mode, hence the
   anchor reset below; count badges reuse
   the Badge primitive, compacted to tab scale below. Fixed pixel
   paddings/gaps are design-spec constants, not density-driven.
   Owned by feat/tabs — do not edit in parallel.
   ============================================================ */
@layer components {
  .tabs { display: flex; align-items: stretch; }

  /* NavHref mode tabs are anchors — strip the UA link styling so they
     read identically to the button tabs (colors come from the variant
     rules below). */
  a.tab { text-decoration: none; cursor: pointer; }

  /* ---------- underline ---------- */
  .tabs-underline { border-bottom: 1px var(--border-style, solid) var(--border); gap: 2px; }
  .tabs-underline .tab {
    display: flex; align-items: center; gap: 6px;
    height: calc(var(--rh) + 2px); padding: 0 10px;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--fg-faint);
    border-bottom: 2px solid transparent; margin-bottom: -1px;
  }
  .tabs-underline .tab:hover { color: var(--fg-muted); background: var(--bg-hover); }
  .tabs-underline .tab.is-active { color: var(--fg); border-bottom-color: var(--accent); }

  /* ---------- boxed ---------- */
  .tabs-boxed { border: 1px var(--border-style, solid) var(--border-strong); }
  .tabs-boxed .tab {
    display: flex; align-items: center; gap: 6px;
    height: calc(var(--rh) - 2px); padding: 0 10px;
    font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
    letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--fg-faint);
    border-right: 1px var(--border-style, solid) var(--border-strong);
  }
  .tabs-boxed .tab:last-child { border-right: none; }
  .tabs-boxed .tab:hover { color: var(--fg); background: var(--bg-hover); }
  .tabs-boxed .tab.is-active { background: var(--accent); color: var(--on-accent); }

  /* ---------- count badge: the Badge primitive at tab scale ---------- */
  .tab .badge {
    height: auto; padding: 0 4px; line-height: 1.5;
    font-family: var(--font-mono); letter-spacing: 0;
    background: var(--bg-active); color: var(--fg-muted); border-color: transparent;
  }
  /* design dims the badge into the accent fill with a translucent overlay —
     derived from --on-accent so themes only supply base vars */
  .tab.is-active .badge {
    background: color-mix(in srgb, var(--on-accent) 20%, transparent);
    color: inherit;
  }
  .tabs-underline .tab.is-active .badge { background: var(--bg-active); color: var(--fg); }

  /* ---------- panes ---------- */
  .tab-panel { min-width: 0; }
  .tab-panel[hidden] { display: none; }

  /* border-mode variants (b-ascii dashes via --border-style) */
  .b-shade .tabs-boxed { border-color: transparent; background: var(--bg-raised); }
  .b-shade .tabs-boxed .tab { border-right-color: var(--bg-panel); }
}
/* ============================================================
   baud/ui — tag input (@layer components)
   Lifted from design/baud-extras.css ("tag input" block). The
   suggestion menu reuses the canonical .menu/.menu-item rules
   (selects.css owns those); only the .open/.empty display gating
   and the meta span are tags-scoped here. .x-btn (design
   baud-tokens.css) is scoped under .tag-chip to avoid collisions.
   Chip tint = the shared accent color-mix technique.
   Owned by feat/taginput — do not edit in parallel.
   ============================================================ */
@layer components {
  .tags { position: relative; display: block; min-width: 0; }

  .tags-wrap {
    display: flex; align-items: center; flex-wrap: wrap; gap: 3px;
    min-height: var(--rh); padding: 2px var(--pad);
    background: var(--bg-input);
    border: 1px var(--border-style, solid) var(--border-strong);
    cursor: text; position: relative;
  }
  .tags-wrap:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
  }

  .tag-chip {
    display: inline-flex; align-items: center; gap: 4px;
    height: calc(var(--row) - 4px); padding: 0 2px 0 6px;
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border: 1px var(--border-style, solid) color-mix(in srgb, var(--accent) 40%, transparent);
    color: var(--fg); font-size: var(--fs-sm); white-space: nowrap;
  }
  .tag-chip .tag-k { color: var(--fg-faint); }
  .tag-chip .x-btn { color: var(--fg-faint); padding: 0 2px; font-size: var(--fs-sm); }
  .tag-chip .x-btn:hover { color: var(--err); }

  .tags-input {
    flex: 1; min-width: 80px;
    background: none; border: none; outline: none;
    color: var(--fg); font: inherit;
    height: calc(var(--row) - 2px);
  }
  .tags-input::placeholder { color: var(--fg-faint); }
  /* chips present ⇒ the placeholder hint retires (design parity) */
  .tags-wrap:has(.tag-chip) .tags-input::placeholder { color: transparent; }

  /* ---------- suggestion menu ----------
     The dropdown is the canonical .menu/.menu-item (selects.css owns
     those rules). .tags-menu remains only to gate painting on the
     TagInput behavior's .open/.empty state and to style the meta span. */
  .tags-menu { display: none; }
  /* .open is toggled by the TagInput behavior; .empty means every
     suggestion is filtered out or already added */
  .tags.open > .tags-menu:not(.empty) { display: block; }
  .tags-menu .tags-menu-meta { color: var(--fg-faint); font-size: var(--fs-sm); }
}
/* ============================================================
   baud/ui — toasts (@layer components)
   Lifted from design/baud-components.css (toasts section) nearly
   verbatim. Fixed pixel offsets/gaps are design-spec constants,
   not density-driven (panels.css precedent); colours are tokens
   only. The stack is fixed bottom-right, above the statusbar
   (bottom: --rh + 12px tracks the statusbar height per density).
   .toast-title/.toast-body split the prototype's single msg span
   into the spec's "title + optional body" lines. The outer border
   flows through --border-style (b-ascii dashes); the 3px tone bar
   stays solid — it is a fill, not a hairline. Entrance slide-in
   only under prefers-reduced-motion: no-preference.
   Owned by wave 4 (toasts) — do not edit from other branches.
   ============================================================ */
@layer components {
  .toasts {
    position: fixed; right: 12px; bottom: calc(var(--rh) + 12px); z-index: 200;
    display: flex; flex-direction: column; gap: 6px;
  }
  .toast {
    display: flex; align-items: center; gap: 8px;
    min-width: 280px; max-width: 380px; padding: 7px 9px;
    background: var(--bg-panel); border: 1px var(--border-style, solid) var(--border-strong);
    box-shadow: 0 10px 30px var(--shadow);
    border-left: 3px solid var(--fg-faint);
  }
  .toast.tone-ok { border-left-color: var(--ok); color: var(--fg); }
  .toast.tone-err { border-left-color: var(--err); color: var(--fg); }
  .toast.tone-warn { border-left-color: var(--warn); color: var(--fg); }
  .toast.tone-info { border-left-color: var(--info); color: var(--fg); }
  .toast .toast-glyph { font-weight: 700; }
  .toast.tone-ok .toast-glyph { color: var(--ok); }
  .toast.tone-err .toast-glyph { color: var(--err); }
  .toast.tone-warn .toast-glyph { color: var(--warn); }
  .toast.tone-info .toast-glyph { color: var(--info); }
  .toast .toast-msg { flex: 1; display: flex; flex-direction: column; min-width: 0; }
  .toast .toast-title { color: var(--fg); }
  .toast .toast-body { font-size: var(--fs-sm); color: var(--fg-muted); }
  .toast .x-btn { color: var(--fg-faint); padding: 0 2px; font-size: var(--fs); }
  .toast .x-btn:hover { color: var(--err); }
  @media (prefers-reduced-motion: no-preference) {
    .toast { animation: toast-in 0.16s ease-out; }
    @keyframes toast-in { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
  }
}
/* ============================================================
   baud/ui — tree (@layer components)
   Lifted from design/baud-components.css. Box-drawing branch
   glyphs live in the markup (mono, white-space: pre); the ▸/▾
   disclosure flips via CSS content on the native <details>
   open state — no client logic. Fixed pixel gaps and the 2px
   accent inset are design-spec constants, not density-driven.
   Owned by wave 3 (tree) — do not edit from other branches.
   ============================================================ */
@layer components {
  .tree { list-style: none; user-select: none; }
  .tree ul { list-style: none; }
  .tree-row {
    display: flex; align-items: center; gap: 5px;
    height: var(--row); padding: 0 var(--pad);
    white-space: nowrap; cursor: pointer; color: var(--fg-muted);
  }
  .tree-row:hover { background: var(--bg-hover); color: var(--fg); }
  .tree-row.sel { background: var(--sel); color: var(--fg); box-shadow: inset 2px 0 0 var(--accent); }
  .tree-glyph { color: var(--fg-faint); font-family: var(--font-mono); white-space: pre; }
  .tree-row.sel .tree-glyph { color: var(--accent); }
  .tree-meta { margin-left: auto; font-size: var(--fs-sm); color: var(--fg-faint); }

  /* native disclosure: hide the UA marker, draw ▸/▾ in the glyph slot */
  summary.tree-row { list-style: none; }
  summary.tree-row::-webkit-details-marker { display: none; }
  .tree-disclosure::before { content: "▸ "; }
  .tree-branch[open] > summary .tree-disclosure::before { content: "▾ "; }
}
/* ============================================================
   baud/ui — utilities (@layer utilities)
   The COMPLETE utility inventory. Deliberately starved —
   composition glue only. Do not add more.
   ============================================================ */
@layer utilities {
  .hstack { display: flex; align-items: center; gap: var(--gap); }
  .vstack { display: flex; flex-direction: column; gap: var(--gap); }
  .fill   { flex: 1; min-width: 0; }
  .scroll { overflow: auto; min-height: 0; }

  .gap-0 { gap: 0; }
  .gap-1 { gap: calc(var(--gap) * 0.5); }
  .gap-2 { gap: var(--gap); }
  .gap-3 { gap: calc(var(--gap) * 2); }

  /* forms use this, not a general grid */
  [data-form-grid] {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: calc(var(--gap) * 2);
    row-gap: var(--gap);
    align-items: center;
  }
  [data-form-grid="2"] { grid-template-columns: 1fr 1fr; }
}
