/* ==========================================================================
   nvpn Console — design system
   Ported verbatim from the dchat Console reference (UI/style/layout only —
   ADR-0004, ADR-0008, 04c_ui-specifications.md). Vanilla CSS, no build step.
   Two dark skins via [data-theme]: "light" = Cyber Blue (nvpn default),
   "dark" = Phosphor Green. The attribute values are kept as-is from the
   source (a low-risk, literal port) — see ADR-0004's revision note.

   Sections actively used by nvpn's pages: 1-9 (tokens/layout/buttons/cards/
   badges), 17 (login, incl. the arcade variant), 18-19 (modal/toast), 20
   (utilities), 22-23 (terminal skin, mission-control gauges/radar/term-bar —
   the Overview screen). Sections 10-16 and part of 21/23 (master-detail
   messages, kanban board, annotations, commit/diff viewer, document browser,
   mascot) are dchat-specific features nvpn does not build; left in place
   as an unused, harmless carryover of the literal port rather than
   hand-trimmed, since no nvpn markup ever references those classes.
   ========================================================================== */

/* ----- 1. Design tokens --------------------------------------------------- */
:root {
  /* Typography — terminal / hacker: monospace everywhere */
  --font-sans: "JetBrains Mono", ui-monospace, "SF Mono", "Menlo", "Cascadia Code", "Consolas", monospace;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Menlo", "Cascadia Code", "Consolas", monospace;

  --fs-xs: 11px;
  --fs-sm: 12.5px;
  --fs-base: 14px;
  --fs-md: 15px;
  --fs-lg: 17px;
  --fs-xl: 21px;
  --fs-2xl: 27px;
  --fs-3xl: 34px;

  --lh-tight: 1.25;
  --lh-normal: 1.55;

  /* Spacing scale (4px base) */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;

  /* Radii — squared-off terminal chrome */
  --r-sm: 2px;
  --r-md: 2px;
  --r-lg: 3px;
  --r-xl: 3px;
  --r-full: 999px;

  /* Layout */
  --sidebar-w: 244px;
  --topbar-h: 60px;
  --content-max: 1400px;

  /* Motion */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur: 160ms;

  /* Brand hue — phosphor green */
  --brand-h: 150;
  --glow-rgb: 57, 255, 136;   /* accent glow as raw rgb, so rgba(var(--glow-rgb), a) follows the theme */
}

/* "Blue cyber" theme — the toggle's alternate skin (not a light mode). Palette pulled from the
   cyber-security reference: deep navy field, electric-blue accent, cyan-white text. */
:root[data-theme="light"] {
  --brand-h: 207;
  --glow-rgb: 43, 157, 244;
  --bg: #05101f;
  --bg-grad: radial-gradient(1200px 620px at 50% -12%, rgba(43, 157, 244, 0.16) 0%, transparent 58%);
  --surface: #091a2e;
  --surface-2: #0d2138;
  --surface-3: #132c48;
  --surface-hover: #16345a;
  --border: #1e3f63;
  --border-strong: #2a5583;
  --text: #d3e8ff;
  --text-muted: #82a9d0;
  --text-faint: #567ca0;
  --accent: #2b9df4;
  --accent-hover: #6fc2ff;
  --accent-soft: rgba(43, 157, 244, 0.16);
  --accent-contrast: #041020;
  --shadow-sm: 0 0 6px rgba(43, 157, 244, 0.12), 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 0 14px rgba(43, 157, 244, 0.16), 0 6px 18px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 0 24px rgba(43, 157, 244, 0.18), 0 18px 44px rgba(0, 0, 0, 0.7);
  --overlay: rgba(2, 8, 18, 0.72);
  --code-bg: #07162a;
  --scrim: rgba(3, 10, 20, 0.8);
}

/* Dark theme */
:root[data-theme="dark"] {
  --glow-rgb: 57, 255, 136;
  --bg: #040704;
  --bg-grad: radial-gradient(1200px 620px at 50% -12%, rgba(57, 255, 136, 0.10) 0%, transparent 58%);
  --surface: #071007;
  --surface-2: #0a140a;
  --surface-3: #0f1e10;
  --surface-hover: #0f2612;
  --border: #17401f;
  --border-strong: #1c4a2a;
  --text: #b8f5cf;
  --text-muted: #5a9d70;
  --text-faint: #3f7a52;
  --accent: #39ff88;
  --accent-hover: #8effb8;
  --accent-soft: rgba(57, 255, 136, 0.14);
  --accent-contrast: #041004;
  --shadow-sm: 0 0 6px rgba(57, 255, 136, 0.10), 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 0 14px rgba(57, 255, 136, 0.14), 0 6px 18px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 0 24px rgba(57, 255, 136, 0.16), 0 18px 44px rgba(0, 0, 0, 0.7);
  --overlay: rgba(1, 4, 1, 0.72);
  --code-bg: #050b05;
  --scrim: rgba(4, 7, 4, 0.78);
}

/* Semantic accent hues (shared, resolved per theme via mixing) */
:root {
  --c-blue: 210; --c-violet: 258; --c-green: 150; --c-amber: 38;
  --c-red: 2; --c-cyan: 190; --c-pink: 330; --c-teal: 172; --c-orange: 22; --c-slate: 220;
}

/* ----- 2. Reset & base ---------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
/* the app mount point must carry a definite height so the shell can size at 100% (a %
   height chain — not 100vh, which can overshoot the visible area and clip the sidebar foot) */
#app { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  color: var(--text);
  background: var(--bg);
  background-image: var(--bg-grad);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, p { margin: 0; }
/* Default inline-icon sizing. Component rules (.btn svg, .nav-item svg, …) have
   higher specificity and override this where a different size is wanted. */
svg { width: 15px; height: 15px; flex-shrink: 0; vertical-align: -0.15em; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font-family: inherit; cursor: pointer; }
input, select, textarea { font-family: inherit; font-size: var(--fs-base); }
::selection { background: var(--accent-soft); }

/* Scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-full); border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--text-faint); background-clip: content-box; }

/* Focus ring — keyboard accessible */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
.btn:focus-visible, .icon-btn:focus-visible { outline-offset: 3px; }

/* ----- 3. App layout ------------------------------------------------------ */
.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: 100%;
  height: 100%;
  overflow: hidden;
}

/* Sidebar */
.sidebar {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border);
  min-height: 0;
}
.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  height: var(--topbar-h);
  padding: 0 var(--sp-5);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.sidebar__logo {
  width: 30px; height: 30px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--accent), hsl(var(--brand-h), 90%, 45%));
  display: grid; place-items: center;
  color: #fff; flex-shrink: 0;
  box-shadow: var(--shadow-sm);
}
.sidebar__logo svg { width: 17px; height: 17px; }
.sidebar__title { font-weight: 650; font-size: var(--fs-md); letter-spacing: -0.01em; }
.sidebar__title small { display: block; font-weight: 500; font-size: var(--fs-xs); color: var(--text-faint); letter-spacing: 0.02em; }

.sidebar__nav { flex: 1; overflow-y: auto; padding: var(--sp-4) var(--sp-3); min-height: 0; }
.nav-group__label {
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-faint);
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
}
.nav-group:first-child .nav-group__label { padding-top: var(--sp-1); }
.nav-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px var(--sp-3);
  border-radius: var(--r-md);
  color: var(--text-muted);
  font-weight: 500; font-size: var(--fs-base);
  cursor: pointer; user-select: none;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
  position: relative;
}
.nav-item:hover { background: var(--surface-hover); color: var(--text); text-decoration: none; }
.nav-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.nav-item.active::before {
  content: ""; position: absolute; left: -3px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: var(--r-full); background: var(--accent);
}
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; stroke-width: 2; }
.nav-item__badge {
  margin-left: auto; font-size: var(--fs-xs); font-weight: 600;
  background: var(--surface-3); color: var(--text-muted);
  padding: 1px 7px; border-radius: var(--r-full); min-width: 20px; text-align: center;
}
.nav-item.active .nav-item__badge { background: var(--accent); color: var(--accent-contrast); }

.sidebar__foot { padding: var(--sp-3); border-top: 1px solid var(--border); flex-shrink: 0; }
.user-chip {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-md);
  cursor: pointer; transition: background var(--dur) var(--ease); width: 100%;
  background: none; border: none; color: var(--text); text-align: left;
}
.user-chip:hover { background: var(--surface-hover); }
.avatar {
  width: 30px; height: 30px; border-radius: var(--r-full); flex-shrink: 0;
  display: grid; place-items: center; font-weight: 650; font-size: var(--fs-sm);
  color: #fff; background: linear-gradient(135deg, hsl(258,80%,62%), hsl(210,80%,56%));
}
.user-chip__meta { min-width: 0; flex: 1; }
.user-chip__name { font-weight: 600; font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-chip__role { font-size: var(--fs-xs); color: var(--text-faint); text-transform: capitalize; }

/* Main column */
.main { grid-row: 1; display: flex; flex-direction: column; min-width: 0; height: 100%; }

/* Topbar */
.topbar {
  height: var(--topbar-h); flex-shrink: 0;
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 0 var(--sp-6);
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(160%) blur(8px);
  position: sticky; top: 0; z-index: 20;
}
.topbar__search {
  flex: 1; max-width: 560px; position: relative;
}
.topbar__search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-faint); pointer-events: none; }
.topbar__search input {
  width: 100%; height: 38px; padding: 0 var(--sp-3) 0 36px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2); color: var(--text);
  transition: border var(--dur), background var(--dur), box-shadow var(--dur);
}
.topbar__search input::placeholder { color: var(--text-faint); }
.topbar__search input:focus { outline: none; border-color: var(--accent); background: var(--surface); box-shadow: 0 0 0 3px var(--accent-soft); }
.topbar__search kbd {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-faint);
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 1px 6px; pointer-events: none;
}
.topbar__spacer { flex: 1; }
.topbar__actions { display: flex; align-items: center; gap: var(--sp-2); }

/* Content scroll region */
.content { flex: 1; overflow-y: auto; min-height: 0; display: flex; flex-direction: column; }
/* #view is the per-route mount point built in app.js. Make it fill .content (flex chain,
   NOT a percentage height — a % against this height-less div was silently 0, which left the
   overview short and dumped the slack as a bottom void). flex:1 0 auto grows it to fill on
   tall screens; basis:auto + shrink:0 keep it >= content on short screens so it overflows and
   .content (overflow-y:auto) scrolls instead of clipping. Keep #view overflow:visible. */
#view { flex: 1 0 auto; display: flex; flex-direction: column; min-width: 0; }
.page { width: 100%; max-width: var(--content-max); margin: 0 auto; padding: var(--sp-8) var(--sp-8) var(--sp-12); }
.page--wide { max-width: none; }

/* Page header */
.page-head { display: flex; align-items: flex-start; gap: var(--sp-4); margin-bottom: var(--sp-6); flex-wrap: wrap; }
.page-head__text { flex: 1; min-width: 0; }
.page-title { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }
.page-sub { color: var(--text-muted); margin-top: var(--sp-1); font-size: var(--fs-md); }
.page-head__actions { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.breadcrumb { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-3); }
.breadcrumb a { color: var(--text-muted); }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb svg { width: 13px; height: 13px; color: var(--text-faint); }

/* ----- 4. Buttons --------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: 38px; padding: 0 var(--sp-4);
  border-radius: var(--r-md); border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text);
  font-weight: 550; font-size: var(--fs-base); white-space: nowrap;
  transition: all var(--dur) var(--ease);
}
.btn:hover { background: var(--surface-hover); border-color: var(--text-faint); text-decoration: none; }
.btn:active { transform: translateY(0.5px); }
.btn svg { width: 16px; height: 16px; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn--ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn--ghost:hover { background: var(--surface-hover); color: var(--text); }
.btn--danger { color: hsl(2, 72%, 56%); border-color: color-mix(in srgb, hsl(2,72%,56%) 40%, var(--border)); }
.btn--danger:hover { background: hsla(2, 72%, 56%, 0.1); border-color: hsl(2,72%,56%); }
.btn--sm { height: 30px; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
.btn--icon { width: 38px; padding: 0; }
.btn:disabled { opacity: 0.5; pointer-events: none; }
.btn.is-loading { pointer-events: none; position: relative; color: transparent; }
.btn.is-loading::after {
  content: ""; position: absolute; width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: spin 0.6s linear infinite; color: var(--accent-contrast);
}

.icon-btn {
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: var(--r-md); border: 1px solid transparent;
  background: transparent; color: var(--text-muted);
  transition: all var(--dur) var(--ease);
}
.icon-btn:hover { background: var(--surface-hover); color: var(--text); }
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn--bordered { border-color: var(--border); background: var(--surface-2); }

/* ----- 5. Cards ----------------------------------------------------------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
}
.card--pad { padding: var(--sp-5); }
.card__head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border);
}
.card__title { font-weight: 650; font-size: var(--fs-md); flex: 1; }
.card__title-icon { color: var(--text-muted); display: grid; place-items: center; }
.card__title-icon svg { width: 18px; height: 18px; }
.card__body { padding: var(--sp-5); }
.card__body--flush { padding: 0; }

/* Stat tiles */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--sp-4); }
.stat-tile {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: var(--sp-5); box-shadow: var(--shadow-sm); position: relative; overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur);
}
.stat-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.stat-tile__icon {
  width: 38px; height: 38px; border-radius: var(--r-md); display: grid; place-items: center;
  margin-bottom: var(--sp-4); color: var(--accent); background: var(--accent-soft);
}
.stat-tile__icon svg { width: 20px; height: 20px; }
.stat-tile__value { font-size: var(--fs-3xl); font-weight: 720; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-tile__label { color: var(--text-muted); font-size: var(--fs-sm); font-weight: 500; margin-top: var(--sp-2); }
.stat-tile__sub { margin-top: var(--sp-3); font-size: var(--fs-xs); color: var(--text-faint); display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.stat-tile__accent { position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--accent); opacity: 0.9; }

/* Distribution bars */
.dist { display: flex; flex-direction: column; gap: var(--sp-3); }
.dist__row { display: grid; grid-template-columns: 130px 1fr 44px; align-items: center; gap: var(--sp-3); }
.dist__label { font-size: var(--fs-sm); color: var(--text-muted); display: flex; align-items: center; gap: var(--sp-2); }
.dist__track { height: 8px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
/* display:block is LOAD-BEARING. The fill is a <span> inside a plain block track, so it stays
   inline — and an inline box ignores width/height outright. The JS sets style="width:N%" and the
   rule sets height:100%, and BOTH were silently dropped: every bar in the app rendered its track
   and a 0x0 fill. Measured before the fix: renderedW 0, renderedH 0 with width:100% set. */
.dist__fill { display: block; height: 100%; border-radius: var(--r-full); background: var(--accent); transition: width 0.5s var(--ease); min-width: 3px; }
.dist__fill { box-shadow: 0 0 8px -1px hsla(var(--bh, var(--brand-h)), 90%, 55%, 0.55); }
.dist__count { text-align: right; font-weight: 650; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

/* "You are here" summary band — three zone cards (current work · last review · liveness) */
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-5); align-items: start; margin-bottom: var(--sp-5); }
.summary__zone {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: var(--sp-4) var(--sp-5); min-width: 0;
}
.summary__zone .detail__section-label { display: flex; align-items: center; gap: 6px; }
.summary__zone .detail__section-label svg { width: 14px; height: 14px; }
.summary__task {
  display: block; color: var(--text); font-weight: 600; font-size: var(--fs-base); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.summary__task:hover { color: var(--accent); text-decoration: none; }
.summary__task .kcard__seq { margin-right: 4px; }

/* ----- 6. Badges & pills -------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: var(--r-full);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.02em;
  white-space: nowrap; line-height: 1.5;
  border: 1px solid transparent;
}
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge--soft { background: var(--surface-3); color: var(--text-muted); }
.badge--outline { background: transparent; border-color: var(--border-strong); color: var(--text-muted); }

/* Themed badge — set --bh (hue) inline or via type class */
.badge[data-hue] {
  color: hsl(var(--bh), 68%, var(--bl, 46%));
  background: hsla(var(--bh), 70%, 55%, 0.13);
  border-color: hsla(var(--bh), 60%, 55%, 0.22);
}
:root[data-theme="dark"] .badge[data-hue] { color: hsl(var(--bh), 78%, 74%); background: hsla(var(--bh), 65%, 60%, 0.16); }

/* Message-type / status color map via CSS custom prop --bh set inline in JS.
   Kept as utility classes for legend swatches. */
.swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* ----- 7. Tables ---------------------------------------------------------- */
.table-wrap { overflow-x: auto; border-radius: var(--r-lg); }
table.data { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
table.data thead th {
  text-align: left; font-weight: 600; font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-faint);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--surface); z-index: 2; white-space: nowrap;
}
table.data tbody td { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); vertical-align: middle; }
table.data tbody tr { transition: background var(--dur) var(--ease); }
table.data tbody tr:hover { background: var(--surface-hover); }
table.data tbody tr.is-clickable { cursor: pointer; }
table.data tbody tr:last-child td { border-bottom: none; }
table.data .cell-mono { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-muted); }
table.data .cell-num { font-variant-numeric: tabular-nums; text-align: right; }
.cell-truncate { max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cell-strong { font-weight: 550; color: var(--text); }

/* Row selected (master-detail) */
table.data tbody tr.is-selected { background: var(--accent-soft); }
table.data tbody tr.is-selected:hover { background: var(--accent-soft); }

/* ----- 8. Filters / toolbar ----------------------------------------------- */
.toolbar {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  margin-bottom: var(--sp-5);
}
.toolbar__grow { flex: 1; min-width: 180px; }
.field {
  height: 36px; padding: 0 var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); color: var(--text);
  transition: border var(--dur), box-shadow var(--dur);
}
.field:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
select.field { padding-right: var(--sp-6); cursor: pointer; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
.search-field { position: relative; display: flex; align-items: center; }
.search-field svg { position: absolute; left: 11px; width: 15px; height: 15px; color: var(--text-faint); pointer-events: none; }
.search-field .field { padding-left: 34px; width: 100%; }
.filter-chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 30px; padding: 0 var(--sp-2) 0 var(--sp-3); border-radius: var(--r-full);
  background: var(--accent-soft); color: var(--accent); font-size: var(--fs-sm); font-weight: 550;
  border: 1px solid transparent;
}
.filter-chip button { background: none; border: none; color: inherit; display: grid; place-items: center; padding: 2px; border-radius: 50%; }
.filter-chip button:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.filter-chip svg { width: 13px; height: 13px; }

/* Toggle switch */
.toggle { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; user-select: none; font-size: var(--fs-sm); color: var(--text-muted); }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle__track { width: 34px; height: 20px; border-radius: var(--r-full); background: var(--surface-3); border: 1px solid var(--border-strong); position: relative; transition: background var(--dur); flex-shrink: 0; }
.toggle__track::after { content: ""; position: absolute; top: 1px; left: 1px; width: 16px; height: 16px; border-radius: 50%; background: var(--surface); box-shadow: var(--shadow-sm); transition: transform var(--dur) var(--ease); }
.toggle input:checked + .toggle__track { background: var(--accent); border-color: var(--accent); }
.toggle input:checked + .toggle__track::after { transform: translateX(14px); background: #fff; }
.toggle input:focus-visible + .toggle__track { box-shadow: 0 0 0 3px var(--accent-soft); }

/* ----- 9. States: empty / loading / error --------------------------------- */
.state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: var(--sp-12) var(--sp-6); gap: var(--sp-3);
  color: var(--text-muted);
}
.state__icon {
  width: 52px; height: 52px; border-radius: var(--r-lg); display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-faint); margin-bottom: var(--sp-2);
}
.state__icon svg { width: 26px; height: 26px; }
.state__title { font-weight: 650; font-size: var(--fs-lg); color: var(--text); }
.state__msg { max-width: 400px; font-size: var(--fs-base); }
.state--error .state__icon { color: hsl(2, 72%, 58%); background: hsla(2, 72%, 58%, 0.12); }

/* Skeleton */
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--r-sm);
}
.skel-row { height: 44px; margin-bottom: 1px; }
.skel-line { height: 12px; margin: 8px 0; }
.skel-tile { height: 132px; border-radius: var(--r-lg); }
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@keyframes spin { to { transform: rotate(360deg); } }

.spinner { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--border-strong); border-top-color: var(--accent); animation: spin 0.65s linear infinite; }
.spinner--center { margin: var(--sp-12) auto; }

/* ----- 10. Master-detail (messages) --------------------------------------- */
.split {
  display: grid; grid-template-columns: minmax(340px, 460px) 1fr; gap: var(--sp-5);
  align-items: start;
}
.split__list { min-width: 0; }
.split__detail { min-width: 0; position: sticky; top: var(--sp-5); }
@media (max-width: 1080px) { .split { grid-template-columns: 1fr; } .split__detail { position: static; } }

/* Message list rows */
.msg-list { display: flex; flex-direction: column; }
.msg-row {
  display: flex; gap: var(--sp-3); padding: var(--sp-4);
  border-bottom: 1px solid var(--border); cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.msg-row:hover { background: var(--surface-hover); }
.msg-row.is-selected { background: var(--accent-soft); }
.msg-row.is-selected .msg-row__subject { color: var(--accent); }
.msg-row__body { flex: 1; min-width: 0; }
.msg-row__top { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 3px; }
.msg-row__subject { font-weight: 600; font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-row__meta { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--text-faint); flex-wrap: wrap; }
.msg-row__excerpt { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.msg-row__seq { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-faint); flex-shrink: 0; }

/* Party route chip */
.route { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); }
.route svg { width: 11px; height: 11px; color: var(--text-faint); }
.party-tag { font-family: var(--font-mono); font-weight: 700; font-size: var(--fs-xs); letter-spacing: 0.03em; }
.party-tag--ARCH { color: hsl(258, 70%, 62%); }
.party-tag--DEV { color: hsl(190, 72%, 46%); }
.party-tag--BOTH { color: var(--text-muted); }
:root[data-theme="dark"] .party-tag--ARCH { color: hsl(258, 80%, 74%); }
:root[data-theme="dark"] .party-tag--DEV { color: hsl(190, 80%, 60%); }

/* ----- 11. Message detail ------------------------------------------------- */
.detail { }
.detail__head { padding: var(--sp-5) var(--sp-5) var(--sp-4); border-bottom: 1px solid var(--border); }
.detail__subject { font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.01em; line-height: 1.3; }
.detail__meta { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--text-muted); }
.detail__meta-item { display: inline-flex; align-items: center; gap: 5px; }
.detail__meta-item svg { width: 14px; height: 14px; color: var(--text-faint); }
.detail__section { padding: var(--sp-5); border-bottom: 1px solid var(--border); }
.detail__section:last-child { border-bottom: none; }
.detail__section-label { font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-faint); margin-bottom: var(--sp-3); }
.chip-list { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.tag-chip { font-size: var(--fs-xs); font-weight: 550; color: var(--text-muted); background: var(--surface-2); border: 1px solid var(--border); padding: 2px 9px; border-radius: var(--r-full); }
.ref-chip { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--accent); background: var(--accent-soft); padding: 2px 8px; border-radius: var(--r-sm); }

/* ----- 12. Markdown body -------------------------------------------------- */
.md { font-size: var(--fs-md); line-height: var(--lh-normal); color: var(--text); word-wrap: break-word; overflow-wrap: anywhere; }
.md > *:first-child { margin-top: 0; }
.md > *:last-child { margin-bottom: 0; }
.md h1, .md h2, .md h3, .md h4 { font-weight: 680; line-height: 1.3; margin: var(--sp-5) 0 var(--sp-3); letter-spacing: -0.01em; }
.md h1 { font-size: var(--fs-xl); }
.md h2 { font-size: var(--fs-lg); padding-bottom: var(--sp-2); border-bottom: 1px solid var(--border); }
.md h3 { font-size: var(--fs-md); }
.md h4 { font-size: var(--fs-base); color: var(--text-muted); }
.md p { margin: var(--sp-3) 0; }
.md ul, .md ol { margin: var(--sp-3) 0; padding-left: var(--sp-6); }
.md li { margin: var(--sp-1) 0; }
.md li::marker { color: var(--text-faint); }
.md a { text-decoration: underline; text-underline-offset: 2px; }
.md strong { font-weight: 680; color: var(--text); }
.md em { font-style: italic; }
.md code {
  font-family: var(--font-mono); font-size: 0.86em;
  background: var(--code-bg); padding: 1.5px 5px; border-radius: var(--r-sm);
  border: 1px solid var(--border); color: var(--text);
}
.md pre {
  background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--sp-4); overflow-x: auto; margin: var(--sp-4) 0;
}
.md pre code { background: none; border: none; padding: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text); }
.md blockquote { margin: var(--sp-4) 0; padding: var(--sp-2) var(--sp-4); border-left: 3px solid var(--accent); background: var(--accent-soft); border-radius: 0 var(--r-sm) var(--r-sm) 0; color: var(--text-muted); }
.md blockquote p { margin: var(--sp-2) 0; }
.md hr { border: none; border-top: 1px solid var(--border); margin: var(--sp-5) 0; }
.md table { border-collapse: collapse; margin: var(--sp-4) 0; font-size: var(--fs-sm); display: block; overflow-x: auto; }
.md table th, .md table td { border: 1px solid var(--border); padding: var(--sp-2) var(--sp-3); text-align: left; }
.md table th { background: var(--surface-2); font-weight: 650; }
.md table tr:nth-child(even) td { background: color-mix(in srgb, var(--surface-2) 50%, transparent); }

/* ----- 13. Attachments ---------------------------------------------------- */
.attach-grid { display: flex; flex-direction: column; gap: var(--sp-3); }
.attach {
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; background: var(--surface-2);
}
.attach__head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); }
.attach__icon { width: 32px; height: 32px; border-radius: var(--r-sm); display: grid; place-items: center; background: var(--surface-3); color: var(--text-muted); flex-shrink: 0; }
.attach__icon svg { width: 17px; height: 17px; }
.attach__meta { flex: 1; min-width: 0; }
.attach__name { font-weight: 550; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach__sub { font-size: var(--fs-xs); color: var(--text-faint); }
.attach__preview { border-top: 1px solid var(--border); padding: var(--sp-3); background: var(--surface); }
.attach__preview img { max-width: 100%; border-radius: var(--r-sm); display: block; }
.attach__preview pre { margin: 0; max-height: 320px; overflow: auto; font-family: var(--font-mono); font-size: var(--fs-sm); white-space: pre-wrap; color: var(--text-muted); }

/* ----- 14. Annotations ---------------------------------------------------- */
.anno-strip { display: flex; flex-direction: column; gap: var(--sp-3); }
.anno {
  display: flex; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2);
}
.anno__bar { width: 3px; border-radius: var(--r-full); flex-shrink: 0; background: var(--accent); }
.anno__body { flex: 1; min-width: 0; }
.anno__top { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: 3px; }
.anno__note { font-size: var(--fs-sm); color: var(--text); white-space: pre-wrap; }
.anno__foot { font-size: var(--fs-xs); color: var(--text-faint); margin-top: var(--sp-2); display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }
.anno__actions { display: flex; gap: var(--sp-1); }
.anno-form { border: 1px dashed var(--border-strong); border-radius: var(--r-md); padding: var(--sp-4); background: var(--surface-2); }
.label-picker { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-3); }
.label-opt {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border-radius: var(--r-full);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-muted);
  font-size: var(--fs-sm); font-weight: 550; cursor: pointer; transition: all var(--dur);
}
.label-opt:hover { border-color: var(--text-faint); color: var(--text); }
.label-opt.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.label-opt .badge__dot { width: 7px; height: 7px; }
textarea.field { min-height: 76px; padding: var(--sp-3); resize: vertical; width: 100%; line-height: 1.5; }

/* ----- 15. Timeline (thread / task) --------------------------------------- */
.timeline { position: relative; padding-left: var(--sp-6); }
.timeline::before { content: ""; position: absolute; left: 15px; top: 8px; bottom: 8px; width: 2px; background: var(--border); }
.tl-node { position: relative; margin-bottom: var(--sp-5); }
.tl-node:last-child { margin-bottom: 0; }
.tl-node__dot {
  position: absolute; left: calc(-1 * var(--sp-6) + 8px); top: 4px;
  width: 16px; height: 16px; border-radius: 50%; border: 3px solid var(--bg);
  background: var(--accent); z-index: 1;
}
.tl-node__card { border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); box-shadow: var(--shadow-sm); }
.tl-node__head { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.tl-node__subject { font-weight: 600; font-size: var(--fs-base); flex: 1; min-width: 120px; }
.tl-node__body { padding: var(--sp-4); }
.tl-node__time { font-size: var(--fs-xs); color: var(--text-faint); }

/* ----- 16. Kanban board --------------------------------------------------- */
.board { display: flex; gap: var(--sp-4); overflow-x: auto; padding-bottom: var(--sp-4); align-items: flex-start; }
.board__col { flex: 1 1 264px; min-width: 236px; max-width: 360px; display: flex; flex-direction: column; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-lg); max-height: calc(100vh - 240px); }
.board__col-head { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--surface-2); border-radius: var(--r-lg) var(--r-lg) 0 0; z-index: 1; }
.board__col-title { font-weight: 650; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em; }
.board__col-count { margin-left: auto; font-size: var(--fs-xs); font-weight: 650; color: var(--text-muted); background: var(--surface); border: 1px solid var(--border); padding: 1px 8px; border-radius: var(--r-full); }
.board__col-dot { width: 8px; height: 8px; border-radius: 50%; }
.board__cards { padding: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-3); overflow-y: auto; min-height: 60px; }
.kcard {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4); cursor: pointer; box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur), border-color var(--dur);
}
.kcard:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.kcard__top { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.kcard__seq { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-faint); }
.kcard__subject { font-weight: 550; font-size: var(--fs-sm); line-height: 1.4; margin-bottom: var(--sp-3); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.kcard__foot { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.board__col--blockers { background: hsla(2, 72%, 55%, 0.06); border-color: hsla(2, 72%, 55%, 0.28); }
.board__col--blockers .board__col-head { background: transparent; }
.board__empty { padding: 16px 12px; text-align: center; font-size: var(--fs-xs); color: var(--text-faint); font-style: italic; }
.board__hidden { margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-1, 4px); font-size: var(--fs-xs); color: var(--text-muted); }
.board__showall { color: var(--accent, hsl(220, 70%, 58%)); text-decoration: none; font-weight: 600; }
.board__showall:hover { text-decoration: underline; }

/* Priority / risk mini indicators */
.dot-risk { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot-risk--GREEN { background: hsl(150, 62%, 45%); }
.dot-risk--AMBER { background: hsl(38, 92%, 52%); }
.dot-risk--RED { background: hsl(2, 74%, 56%); }
.prio { font-size: var(--fs-xs); font-weight: 700; padding: 1px 6px; border-radius: var(--r-sm); }
.prio--P1 { color: hsl(2, 74%, 56%); background: hsla(2, 74%, 56%, 0.12); }
.prio--P2 { color: hsl(38, 84%, 46%); background: hsla(38, 84%, 50%, 0.14); }
.prio--P3 { color: hsl(210, 12%, 50%); background: var(--surface-3); }

/* ----- 17. Login ---------------------------------------------------------- */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: var(--sp-6); position: relative; }
.login-card {
  width: 100%; max-width: 400px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow-lg); padding: var(--sp-8); position: relative; z-index: 1;
}
.login-brand { display: flex; flex-direction: column; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-6); text-align: center; }
.login-brand .sidebar__logo { width: 48px; height: 48px; border-radius: 12px; }
.login-brand .sidebar__logo svg { width: 26px; height: 26px; }
.login-title { font-size: var(--fs-2xl); font-weight: 720; letter-spacing: -0.02em; }
.login-sub { color: var(--text-muted); font-size: var(--fs-base); }
.form-group { margin-bottom: var(--sp-4); }
.form-label { display: block; font-size: var(--fs-sm); font-weight: 600; margin-bottom: var(--sp-2); color: var(--text); }
.form-input {
  width: 100%; height: 42px; padding: 0 var(--sp-4);
  border: 1px solid var(--border-strong); border-radius: var(--r-md);
  background: var(--surface-2); color: var(--text);
  transition: border var(--dur), box-shadow var(--dur), background var(--dur);
}
.form-input:focus { outline: none; border-color: var(--accent); background: var(--surface); box-shadow: 0 0 0 3px var(--accent-soft); }
.form-input--err { border-color: hsl(2, 72%, 56%); }
.form-error { color: hsl(2, 72%, 56%); font-size: var(--fs-sm); margin-top: var(--sp-3); display: flex; align-items: center; gap: var(--sp-2); }
.form-error svg { width: 15px; height: 15px; flex-shrink: 0; }
.login-foot { margin-top: var(--sp-5); text-align: center; font-size: var(--fs-xs); color: var(--text-faint); }
.login-bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.login-bg::before { content: ""; position: absolute; width: 600px; height: 600px; border-radius: 50%; background: radial-gradient(circle, var(--accent-soft), transparent 65%); top: -20%; left: -10%; opacity: 0.6; }
.login-bg::after { content: ""; position: absolute; width: 500px; height: 500px; border-radius: 50%; background: radial-gradient(circle, hsla(190, 80%, 60%, 0.12), transparent 65%); bottom: -15%; right: -5%; }

/* ----- 17b. Arcade login — glowing grid + sign-in card -------------------- */
.login-arcade { min-height: 100vh; }
.login-grid {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0;
  background-color: #050806;
  background-image:
    linear-gradient(hsla(var(--brand-h),55%,45%,0.14) 1px, transparent 1px),
    linear-gradient(90deg, hsla(var(--brand-h),55%,45%,0.14) 1px, transparent 1px);
  background-size: 44px 44px;
}
:root[data-theme="light"] .login-grid { background-color: #03080f; }
.login-cell {
  position: absolute; width: 44px; height: 44px;
  background: hsl(var(--brand-h), 85%, 52%); opacity: 0;
  box-shadow: 0 0 16px -2px hsla(var(--brand-h),90%,55%,0.5);
  animation: login-glow linear infinite;
}
@keyframes login-glow { 0%, 100% { opacity: 0; } 45%, 55% { opacity: var(--b, 0.5); } }

.login-card--arcade {
  max-width: 420px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-8) var(--sp-8) var(--sp-6);
  box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 40px -20px rgba(var(--glow-rgb),0.4);
}
.login-logo { width: 54px; height: 54px; margin: 0 auto var(--sp-4); border: 1px solid var(--accent);
  border-radius: var(--r-md); overflow: hidden; background: #000; box-shadow: 0 0 14px rgba(var(--glow-rgb),0.35), inset 0 0 10px rgba(var(--glow-rgb),0.2); }
.login-logo img { width: 100%; height: 100%; object-fit: contain; }
.login-signin { text-align: center; color: var(--accent); font-size: var(--fs-3xl); font-weight: 800;
  letter-spacing: 0.14em; margin-bottom: var(--sp-6); text-shadow: 0 0 18px rgba(var(--glow-rgb),0.45); }
.login-field {
  width: 100%; height: 52px; padding: 0 var(--sp-4); margin-bottom: var(--sp-4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-3); color: var(--text); font: inherit;
  transition: border var(--dur), box-shadow var(--dur);
}
.login-field::placeholder { color: var(--text-muted); }
.login-field:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 16px -4px rgba(var(--glow-rgb),0.4); }
.login-field--err { border-color: hsl(2, 80%, 60%); }
.login-links { display: flex; justify-content: space-between; align-items: center; margin: var(--sp-1) 0 var(--sp-5); }
.login-link { background: none; border: 0; cursor: pointer; font: inherit; font-size: var(--fs-sm); padding: 0; }
.login-link--muted { color: var(--text-muted); }
.login-link--muted:hover { color: var(--text); }
.login-link--accent { color: var(--accent); font-weight: 600; }
.login-link--accent:hover { color: var(--accent-hover); }
.login-submit {
  width: 100%; height: 50px; border: 0; border-radius: var(--r-md); cursor: pointer;
  background: var(--accent); color: var(--accent-contrast); font: inherit; font-size: var(--fs-md); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  box-shadow: 0 0 20px -2px rgba(var(--glow-rgb),0.55); transition: background var(--dur), box-shadow var(--dur);
}
.login-submit:hover { background: var(--accent-hover); }
.login-submit:disabled { opacity: 0.7; cursor: default; }
.login-card--arcade .login-foot { margin-top: var(--sp-5); }

/* ----- 18. Modal / drawer ------------------------------------------------- */
.overlay {
  position: fixed; inset: 0; background: var(--overlay); z-index: 100;
  display: grid; place-items: center; padding: var(--sp-6);
  animation: fade-in var(--dur) var(--ease);
}
.modal {
  width: 100%; max-width: 480px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow-lg); overflow: hidden;
  animation: pop-in var(--dur) var(--ease); max-height: 88vh; display: flex; flex-direction: column;
}
.modal__head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-5) var(--sp-5) var(--sp-4); }
.modal__title { font-weight: 680; font-size: var(--fs-lg); flex: 1; }
.modal__body { padding: 0 var(--sp-5) var(--sp-5); overflow-y: auto; }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--sp-2); padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--border); background: var(--surface-2); }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pop-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }

/* Dropdown menu */
.menu {
  position: absolute; min-width: 190px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg); padding: var(--sp-1); z-index: 10000;
  animation: pop-in var(--dur) var(--ease);
}
.menu__item { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm); cursor: pointer; font-size: var(--fs-base); color: var(--text); width: 100%; background: none; border: none; text-align: left; }
.menu__item:hover { background: var(--surface-hover); }
.menu__item svg { width: 16px; height: 16px; color: var(--text-muted); }
.menu__item--danger { color: hsl(2, 72%, 56%); }
.menu__item--danger svg { color: inherit; }
.menu__sep { height: 1px; background: var(--border); margin: var(--sp-1) 0; }
.menu__label { padding: var(--sp-2) var(--sp-3) var(--sp-1); font-size: var(--fs-xs); color: var(--text-faint); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }

/* ----- 19. Toast ---------------------------------------------------------- */
.toast-host { position: fixed; bottom: var(--sp-6); right: var(--sp-6); z-index: 200; display: flex; flex-direction: column; gap: var(--sp-3); }
.toast {
  display: flex; align-items: center; gap: var(--sp-3); min-width: 260px; max-width: 400px;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md); background: var(--surface);
  border: 1px solid var(--border); box-shadow: var(--shadow-lg);
  animation: toast-in 0.24s var(--ease); font-size: var(--fs-base);
}
.toast__icon { width: 20px; height: 20px; flex-shrink: 0; }
.toast--success .toast__icon { color: hsl(150, 62%, 44%); }
.toast--error .toast__icon { color: hsl(2, 72%, 56%); }
.toast--info .toast__icon { color: var(--accent); }
.toast__msg { flex: 1; }
.toast.is-leaving { animation: toast-out 0.2s var(--ease) forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateX(20px); } }

/* ----- 20. Misc utilities ------------------------------------------------- */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); }
@media (max-width: 900px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }
.row { display: flex; align-items: center; gap: var(--sp-3); }
.row--wrap { flex-wrap: wrap; }
.gap-2 { gap: var(--sp-2); }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mb-4 { margin-bottom: var(--sp-4); }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.mono { font-family: var(--font-mono); }
.nowrap { white-space: nowrap; }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.hidden { display: none !important; }
.flex-1 { flex: 1; }
.divider { height: 1px; background: var(--border); margin: var(--sp-4) 0; }
.section-title { font-size: var(--fs-lg); font-weight: 680; letter-spacing: -0.01em; margin-bottom: var(--sp-4); display: flex; align-items: center; gap: var(--sp-3); }
.count-pill { font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); background: var(--surface-3); padding: 1px 9px; border-radius: var(--r-full); }
.pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-top: var(--sp-5); flex-wrap: wrap; }
.pagination__info { font-size: var(--fs-sm); color: var(--text-muted); }

/* Health indicators */
.health-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) 0; border-bottom: 1px solid var(--border); }
.health-row:last-child { border-bottom: none; }
.health-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.health-dot--ok { background: hsl(150, 62%, 45%); box-shadow: 0 0 0 3px hsla(150, 62%, 45%, 0.18); }
.health-dot--warn { background: hsl(38, 90%, 52%); box-shadow: 0 0 0 3px hsla(38, 90%, 52%, 0.18); }
.health-dot--bad { background: hsl(2, 74%, 56%); box-shadow: 0 0 0 3px hsla(2, 74%, 56%, 0.18); }

/* Highlighted search snippet */
mark, .hl { background: hsla(45, 100%, 55%, 0.32); color: inherit; padding: 0 2px; border-radius: 3px; font-weight: 600; }
:root[data-theme="dark"] mark, :root[data-theme="dark"] .hl { background: hsla(45, 100%, 55%, 0.26); color: #ffe8a3; }

/* Responsive: collapse sidebar on narrow screens */
.menu-toggle { display: none; }
@media (max-width: 860px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w); z-index: 90; transform: translateX(-100%); transition: transform var(--dur) var(--ease); box-shadow: var(--shadow-lg); }
  .sidebar.is-open { transform: none; }
  .menu-toggle { display: grid; }
  .sidebar-scrim { position: fixed; inset: 0; background: var(--overlay); z-index: 80; }
  .page { padding: var(--sp-5); }
  .topbar { padding: 0 var(--sp-4); }
  .topbar__search kbd { display: none; }
}

/* ==========================================================================
   21. V2 cockpit — typed-ref chips, commit modal, evidence, cockpit pages
   ========================================================================== */

/* Typed-ref chips (extend the base .ref-chip) */
.ref-chip { display: inline-flex; align-items: center; gap: 4px; }
.ref-chip svg { width: 12px; height: 12px; }
button.ref-chip { border: none; font-family: var(--font-mono); font-size: var(--fs-xs); line-height: 1.5; }
.ref-chip--sha, .ref-chip--reg, .ref-chip--link { cursor: pointer; transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.ref-chip--sha:hover, .ref-chip--reg:hover, .ref-chip--link:hover { background: var(--accent); color: var(--accent-contrast); text-decoration: none; }
.ref-chip--file { color: var(--text-muted); background: var(--surface-2); border: 1px solid var(--border); cursor: default; }
.ref-chip--milestone { box-shadow: inset 0 0 0 1px hsla(150, 60%, 50%, 0.55); }
.ref-chip__ms { display: inline-flex; color: hsl(150, 62%, 44%); }
.ref-chip__ms svg { width: 11px; height: 11px; }
:root[data-theme="dark"] .ref-chip__ms { color: hsl(150, 62%, 62%); }

/* Evidence blocks (message-detail attachments + commit diffs) */
pre.evidence {
  margin: 0; background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--sp-3); overflow: auto; max-height: 480px;
  font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.5; white-space: pre; color: var(--text);
}
.ev-line { display: block; min-height: 1.5em; }
.ev-pass { background: hsla(150, 60%, 45%, 0.14); color: hsl(150, 52%, 38%); }
.ev-fail { background: hsla(2, 72%, 55%, 0.14); color: hsl(2, 64%, 50%); }
:root[data-theme="dark"] .ev-pass { color: hsl(150, 60%, 66%); }
:root[data-theme="dark"] .ev-fail { color: hsl(2, 82%, 72%); }
.ev-more { margin-top: var(--sp-2); }

/* Diff line coloring (shared: commit modal + diff-kind evidence) */
.diff-add { background: hsla(150, 60%, 45%, 0.16); color: hsl(150, 50%, 36%); }
.diff-del { background: hsla(2, 72%, 55%, 0.16); color: hsl(2, 62%, 48%); }
.diff-hunk { color: var(--text-muted); background: color-mix(in srgb, var(--surface-3) 60%, transparent); }
.diff-meta { color: var(--text-faint); font-weight: 600; }
:root[data-theme="dark"] .diff-add { color: hsl(150, 60%, 66%); }
:root[data-theme="dark"] .diff-del { color: hsl(2, 82%, 72%); }
.diff-add-t { color: hsl(150, 52%, 40%); font-weight: 650; }
.diff-del-t { color: hsl(2, 64%, 50%); font-weight: 650; }
:root[data-theme="dark"] .diff-add-t { color: hsl(150, 60%, 64%); }
:root[data-theme="dark"] .diff-del-t { color: hsl(2, 80%, 70%); }

/* Commit modal */
.commit-meta__subject { font-weight: 680; font-size: var(--fs-lg); line-height: 1.3; margin-bottom: var(--sp-2); }
.commit-meta__row { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center; font-size: var(--fs-sm); color: var(--text-muted); }
.commit-meta__row > span { display: inline-flex; align-items: center; gap: 4px; }
.commit-meta__row svg { width: 14px; height: 14px; color: var(--text-faint); }
.commit-body { margin: var(--sp-4) 0; padding: var(--sp-3) var(--sp-4); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); font-size: var(--fs-sm); }
.commit-files { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-2); }
.commit-file { border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; background: var(--surface-2); }
.commit-file__head { display: flex; align-items: center; gap: var(--sp-2); width: 100%; padding: var(--sp-2) var(--sp-3); background: none; border: none; color: var(--text); text-align: left; }
.commit-file__head:hover { background: var(--surface-hover); }
.commit-file__head svg { width: 15px; height: 15px; color: var(--text-muted); }
.commit-file__chevron { display: inline-flex; transition: transform var(--dur) var(--ease); }
.commit-file.is-open .commit-file__chevron { transform: rotate(90deg); }
.commit-file__path { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); }
.commit-file__stat { flex-shrink: 0; font-family: var(--font-mono); font-size: var(--fs-xs); }
.commit-file__body { display: none; border-top: 1px solid var(--border); }
.commit-file.is-open .commit-file__body { display: block; }
.commit-file__body .evidence { border: none; border-radius: 0; max-height: 440px; }
.commit-cited { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--border); }

/* Citations modal (register / reverse-lookup) */
.refs-list { display: flex; flex-direction: column; margin-top: var(--sp-2); }
.refs-list__row { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-1); border-bottom: 1px solid var(--border); }
.refs-list__row:last-child { border-bottom: none; }
a.refs-list__row { text-decoration: none; }
a.refs-list__row:hover { background: var(--surface-hover); text-decoration: none; }

/* Tabs (task detail) */
.tabs { display: flex; gap: var(--sp-1); border-bottom: 1px solid var(--border); margin-bottom: var(--sp-5); }
.tab { display: inline-flex; align-items: center; gap: 6px; padding: var(--sp-2) var(--sp-4); background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-weight: 550; font-size: var(--fs-base); margin-bottom: -1px; }
.tab svg { width: 15px; height: 15px; }
.tab:hover { color: var(--text); }
.tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }

/* Deliverables tab */
.deliv-commits { display: flex; flex-direction: column; gap: var(--sp-3); }
.deliv-commit { display: flex; align-items: flex-start; gap: var(--sp-3); }
.deliv-commit > .ref-chip { flex-shrink: 0; margin-top: 1px; }
.deliv-commit__meta { font-size: var(--fs-sm); }

/* Since-you-were-away digest banner + bell badge */
.digest-banner {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-5);
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  border-radius: var(--r-lg);
}
.digest-banner__icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-md); background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); flex-shrink: 0; }
.digest-banner__icon svg { width: 18px; height: 18px; }
.digest-banner__title { font-weight: 650; font-size: var(--fs-base); }
.digest-banner__sub { font-size: var(--fs-sm); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.digest-banner__x { flex-shrink: 0; }
/* Documents: "this copy is behind git" banner. Shaped like .digest-banner but in
   the alert hue and NOT dismissible — a mirror that quietly hides its own drift
   gets quoted as current. It sits full-width above the document body so the
   warning is read before the content is. */
.stale-banner {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); margin: 0;
  background: hsla(2, 74%, 56%, 0.10);
  border-bottom: 1px solid hsla(2, 74%, 56%, 0.32);
}
.stale-banner__icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-md); background: hsla(2, 74%, 56%, 0.18); color: hsl(2, 74%, 52%); flex-shrink: 0; }
.stale-banner__icon svg { width: 18px; height: 18px; }
.stale-banner__title { font-weight: 680; font-size: var(--fs-base); color: hsl(2, 68%, 46%); }
.stale-banner__msg { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
:root[data-theme="dark"] .stale-banner__icon { color: hsl(2, 85%, 68%); }
:root[data-theme="dark"] .stale-banner__title { color: hsl(2, 85%, 70%); }

/* Documents: "what you are reading is EXTRACTED TEXT, not the file" banner.
   Same shape and same placement rule as .stale-banner — above the content, full
   width, not dismissible — because it makes the same kind of claim: the thing on
   screen is not what it appears to be. Amber rather than red: an extraction is a
   caveat, not a fault, and burning the alert hue on it would blunt the red that
   means "this copy is wrong". It carries its own Download so the honest path
   (read the real file) is also the shortest one. */
.extract-banner {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: hsla(38, 84%, 52%, 0.10);
  border-bottom: 1px solid hsla(38, 84%, 52%, 0.30);
}
.extract-banner__icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-md); background: hsla(38, 84%, 52%, 0.18); color: hsl(38, 78%, 42%); flex-shrink: 0; }
.extract-banner__icon svg { width: 18px; height: 18px; }
.extract-banner__title { font-weight: 680; font-size: var(--fs-base); color: hsl(38, 72%, 38%); }
.extract-banner__msg { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
:root[data-theme="dark"] .extract-banner__icon { color: hsl(38, 90%, 66%); }
:root[data-theme="dark"] .extract-banner__title { color: hsl(38, 90%, 68%); }

/* Kind badge — provenance. The icon is not decoration: hue alone is invisible to a
   colour-blind reader and dies in a greyscale screenshot, and "is this git canon?"
   is exactly the question that must not be answered wrongly. */
.badge--kind svg { width: 12px; height: 12px; }

/* ----- Documents: drag-and-drop upload ------------------------------------ */
/* The zone wraps the LIST, so the drop target is the thing you are looking at
   rather than a separate strip you have to aim for. It only becomes visible when a
   file is actually over it (.is-dragging, set from JS on a counted dragenter) — a
   permanent dashed box would be chrome on every page load for an action taken rarely.
   position:relative is load-bearing: the veil is absolutely positioned against it. */
.dropzone { position: relative; border-radius: var(--r-lg); }
.dropzone__veil {
  position: absolute; inset: 0; z-index: 5;
  display: none; place-items: center;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  border: 2px dashed var(--accent); border-radius: var(--r-lg);
  /* The veil must never eat the drop event or the dragleave bookkeeping: pointer
     events pass through to the zone underneath, which is what listens. */
  pointer-events: none;
}
.dropzone.is-dragging .dropzone__veil { display: grid; }
.dropzone__veil-inner {
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--accent); font-weight: 650; font-size: var(--fs-md);
  padding: var(--sp-3) var(--sp-5); border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--accent);
}
.dropzone__veil-inner svg { width: 18px; height: 18px; }

/* Per-file upload report. It stays on screen after the batch settles — a failure
   that auto-dismisses is a failure nobody read, and the name of the file that
   failed is the only thing that makes it retryable. */
.upload-panel { padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); }
.upload-panel__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.upload-panel__title { font-weight: 650; font-size: var(--fs-sm); }
.upload-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.upload-item__top { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
.upload-item__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); }
.upload-item__size { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.upload-item__ok { color: hsl(150, 60%, 40%); display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* The error text is allowed to take room and wrap: truncating it to a tidy width
   would cut off the half of "413 file too large" that says what to do about it. */
.upload-item__err { color: hsl(2, 72%, 50%); display: inline-flex; align-items: center; gap: 4px; max-width: 60%; }
.upload-item__ok svg, .upload-item__err svg { width: 13px; height: 13px; flex-shrink: 0; }
.upload-item__bar { height: 3px; margin-top: 5px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.upload-item__fill { height: 100%; background: var(--accent); width: 0; transition: width 120ms linear; }
.upload-item--failed .upload-item__fill { background: hsl(2, 72%, 52%); }
/* Chunked/compressed bodies report no total, so there is no honest percentage to
   draw — a sweeping bar says "working" without claiming progress it cannot measure. */
.upload-item__fill.is-indeterminate { animation: upload-sweep 1.1s var(--ease) infinite; transition: none; }
@keyframes upload-sweep { 0% { opacity: 0.25; } 50% { opacity: 0.9; } 100% { opacity: 0.25; } }
:root[data-theme="dark"] .upload-item__ok { color: hsl(150, 70%, 62%); }
:root[data-theme="dark"] .upload-item__err { color: hsl(2, 85%, 70%); }

.bell-btn { position: relative; }
.bell-btn__badge {
  position: absolute; top: 2px; right: 2px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: var(--r-full); background: hsl(2, 74%, 56%); color: #fff;
  font-size: 9px; font-weight: 700; display: grid; place-items: center; line-height: 1;
  box-shadow: 0 0 0 2px var(--surface);
}

/* Flow-metrics tiles */
.stat-grid--flow { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.stat-tile--flow { padding: var(--sp-4); }
.stat-tile--flow .stat-tile__icon { margin-bottom: var(--sp-3); }
.stat-tile--flow .stat-tile__value { font-size: var(--fs-2xl); }

/* Human-action queue cards */
.action-list { display: flex; flex-direction: column; gap: var(--sp-4); }
.action-card {
  position: relative; display: flex; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); overflow: hidden;
}
.action-card__rail { position: absolute; inset: 0 auto 0 0; width: 3px; }
.action-card__icon { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; flex-shrink: 0; }
.action-card__icon svg { width: 17px; height: 17px; }
.action-card__body { flex: 1; min-width: 0; }
.action-card__title { font-weight: 600; color: var(--text); line-height: 1.4; }
.action-card__text { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--text-muted); }
.age-pill { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); font-weight: 600; color: hsl(38, 84%, 42%); }
.age-pill svg { width: 12px; height: 12px; }
:root[data-theme="dark"] .age-pill { color: hsl(38, 88%, 62%); }

/* ==========================================================================
   22. Hacker terminal skin — CRT scanlines, phosphor glow, mono chrome
   ========================================================================== */

/* CRT scanline + flicker overlays (both dark skins; flicker tints with the theme accent) */
body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 9998;
  background: repeating-linear-gradient(to bottom,
    rgba(0,0,0,0) 0px, rgba(0,0,0,0) 2px, rgba(0,0,0,0.30) 3px, rgba(0,0,0,0) 4px);
  mix-blend-mode: overlay;
}
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 9997;
  background: var(--accent); animation: hk-flicker 4s steps(2) infinite;
}
@keyframes hk-flicker { 0%, 100% { opacity: 0.03; } 50% { opacity: 0.012; } }
@keyframes hk-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* Uppercase mono chrome */
.sidebar__title, .page-title { text-transform: uppercase; letter-spacing: 0.04em; }
.page-title, .sidebar__title { text-shadow: 0 0 10px rgba(var(--glow-rgb),0.32); }
.nav-item { text-transform: uppercase; letter-spacing: 0.03em; font-size: var(--fs-sm); }
.nav-group__label { letter-spacing: 0.12em; }
.nav-group__label::before { content: "// "; opacity: 0.7; }

/* Terminal-prompt logo */
.sidebar__logo, .login-brand .sidebar__logo {
  background: transparent; border: 1px solid var(--accent);
  box-shadow: 0 0 10px rgba(var(--glow-rgb),0.35), inset 0 0 8px rgba(var(--glow-rgb),0.20);
}
.sidebar__logo svg, .login-brand .sidebar__logo svg { color: var(--accent); }
/* robot logo image — transparent PNG on a black box, so the glowing lines pop */
.sidebar__logo { overflow: hidden; background: #000; }
.sidebar__logo img { width: 100%; height: 100%; object-fit: contain; }

/* Accent glow on key values + primary action */
.stat-tile__value { text-shadow: 0 0 12px rgba(var(--glow-rgb),0.38); }
.nav-item.active { text-shadow: 0 0 8px rgba(var(--glow-rgb),0.5); }
.btn--primary { box-shadow: 0 0 12px rgba(var(--glow-rgb),0.35); }
.btn--primary { text-transform: uppercase; letter-spacing: 0.03em; }
:root[data-theme="dark"] .health-dot--ok { box-shadow: 0 0 8px hsla(150,90%,55%,0.6), 0 0 0 3px hsla(150,62%,45%,0.18); }

/* Blinking caret trailing the active nav row */
.nav-item.active::after {
  content: "_"; color: var(--accent); font-weight: 700; margin-left: 4px;
  animation: hk-blink 1s step-end infinite;
}
.nav-item.active .nav-item__badge { margin-left: auto; }
.nav-item.active::after { order: 3; }

/* Green search caret + focus glow */
.topbar__search input { caret-color: var(--accent); }
.topbar__search input:focus { box-shadow: 0 0 0 1px var(--accent), 0 0 14px rgba(var(--glow-rgb),0.22); }

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* ==========================================================================
   23. Mission-control overview — terminal top bar, gauge rings, labeled cards,
       bracket status badges, radar core. Every number is wired to real data;
       the chrome (radar sweep, prompt string) is decoration that claims nothing.
   ========================================================================== */

/* ---- gauge tag colours (hue per metric) ---------------------------------- */
.gauge-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--sp-3); }
.gauge { display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  gap: var(--sp-2); min-width: 0; height: 100%;
  padding: var(--sp-4) var(--sp-2); border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); }
.gauge__tag { align-self: flex-start; font-size: var(--fs-xs); color: var(--text-faint); letter-spacing: 0.14em; }
.gauge__ring { width: 62px; height: 62px; border-radius: 50%; display: grid; place-items: center;
  border: 2px solid hsl(var(--gh), 85%, 55%);
  background: radial-gradient(circle, hsla(var(--gh), 85%, 50%, 0.10), transparent 68%); }
:root[data-theme="dark"] .gauge__ring {
  box-shadow: 0 0 16px -3px hsla(var(--gh), 90%, 55%, 0.75), inset 0 0 14px -5px hsla(var(--gh), 90%, 55%, 0.6); }
.gauge__num { font-size: var(--fs-xl); font-weight: 700; line-height: 1; color: hsl(var(--gh), 88%, 62%); }
:root[data-theme="dark"] .gauge__num { text-shadow: 0 0 12px hsla(var(--gh), 90%, 55%, 0.6); }
.gauge__label { font-size: var(--fs-xs); color: var(--text-muted); letter-spacing: 0.06em; text-align: center; }

/* outlined bracket tag for recent-activity rows (matches the benchmark's boxed tags) */
.act-tag { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 2px;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.06em; white-space: nowrap;
  color: hsl(var(--bh), 85%, 66%); border: 1px solid hsla(var(--bh), 70%, 52%, 0.55);
  background: hsla(var(--bh), 70%, 50%, 0.07); }
:root[data-theme="dark"] .act-tag { text-shadow: 0 0 8px hsla(var(--bh), 90%, 55%, 0.35); }
.gauge[data-k="msg"] { --gh: 150; } .gauge[data-k="blk"] { --gh: 2; }
.gauge[data-k="mst"] { --gh: 188; } .gauge[data-k="pin"] { --gh: 38; }
.gauge[data-k="tsk"] { --gh: 150; } .gauge[data-k="tsk"] .gauge__ring { border-color: var(--text-muted); box-shadow: 0 0 14px -4px hsla(150,10%,60%,0.5); }
.gauge[data-k="tsk"] .gauge__num { color: var(--text); text-shadow: none; }

/* ---- labeled terminal card header ---------------------------------------- */
.mc-card { border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  padding: var(--sp-4) var(--sp-5); }
.mc-head { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-4);
  font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text); }
.mc-head__i { color: var(--accent); }
.mc-head__meta { margin-left: auto; font-weight: 500; text-transform: none; letter-spacing: 0;
  color: var(--text-faint); font-size: var(--fs-xs); }
.mc-head__meta--accent { color: var(--accent); font-weight: 700; }

/* ---- key/value stat rows (SYSTEM OVERVIEW) ------------------------------- */
.sys-stat { display: flex; justify-content: space-between; padding: 5px 0; font-size: var(--fs-sm);
  border-bottom: 1px dashed var(--border); }
.sys-stat:last-child { border-bottom: 0; }
.sys-stat__k { color: var(--text-muted); }
.sys-stat__v { color: var(--text); font-weight: 600; }
.sys-stat__v--alert { color: hsl(2, 80%, 62%); }
.meter { display: flex; align-items: center; gap: var(--sp-3); padding: 4px 0; font-size: var(--fs-xs); }
.meter__k { color: var(--text-muted); min-width: 34px; }
.meter__track { flex: 1; height: 8px; background: var(--surface-3); border: 1px solid var(--border); border-radius: 2px; overflow: hidden; }
.meter__fill { display: block; height: 100%; background: repeating-linear-gradient(90deg, var(--accent) 0 3px, transparent 3px 5px); }
.meter__v { color: var(--text); min-width: 36px; text-align: right; }

/* ---- bracket status badge  [OK] [STAFFED] [HOLD] ------------------------- */
/* inline-flex + reset button natives so a <button> and a <span> render identically and centered */
.term-badge { display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.06em; line-height: 1.4;
  padding: 2px 6px; border: 1px solid var(--border-strong); border-radius: 2px; color: var(--text-muted);
  background: transparent; -webkit-appearance: none; appearance: none; white-space: nowrap; }
.term-badge::before { content: "["; } .term-badge::after { content: "]"; }
.term-badge--ok { color: hsl(150, 85%, 60%); border-color: hsla(150, 70%, 45%, 0.5); }
.term-badge--hold { color: hsl(38, 90%, 60%); border-color: hsla(38, 80%, 50%, 0.5); }
.term-badge--bad { color: hsl(2, 85%, 64%); border-color: hsla(2, 75%, 50%, 0.5); }

/* ---- status row (heartbeats / integrity) -------------------------------- */
.mc-row { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border); }
.mc-row:last-child { border-bottom: 0; }
.mc-row__dot { width: 9px; height: 9px; border-radius: 50%; margin-top: 4px; flex: none;
  background: var(--c, var(--accent)); box-shadow: 0 0 8px var(--c, var(--accent)); }
.mc-row__body { flex: 1; min-width: 0; }
.mc-row__top { display: flex; align-items: center; gap: var(--sp-2); }
.mc-row__title { font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.mc-row__badge { margin-left: auto; }
.mc-row__sub { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; word-break: break-word; }

/* ---- radar core (decoration — asserts no number) ------------------------ */
.radar { position: relative; height: 180px; border-radius: var(--r-md);
  background: radial-gradient(circle at 50% 50%, hsla(var(--brand-h),80%,45%,0.08), transparent 62%), var(--surface-2);
  overflow: hidden; display: grid; place-items: center; }
/* darker radar bed in the blue skin so the blue sweep/rings read clearly */
:root[data-theme="light"] .radar {
  background: radial-gradient(circle at 50% 50%, hsla(var(--brand-h),85%,50%,0.10), transparent 62%), #030b16; }
.radar__grid { position: absolute; inset: 0;
  background-image: linear-gradient(hsla(var(--brand-h),60%,40%,0.08) 1px, transparent 1px),
                    linear-gradient(90deg, hsla(var(--brand-h),60%,40%,0.08) 1px, transparent 1px);
  background-size: 40px 40px; }
/* concentric circle field, centered, contained to the panel height */
.radar__scope { position: relative; height: 88%; aspect-ratio: 1; border-radius: 50%;
  border: 1px solid hsla(var(--brand-h),70%,45%,0.22); }
.radar__scope::before, .radar__scope::after { content: ""; position: absolute; border-radius: 50%;
  border: 1px solid hsla(var(--brand-h),70%,45%,0.16); }
.radar__scope::before { inset: 17%; } .radar__scope::after { inset: 40%; }
.radar__sweep { position: absolute; inset: -1px; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, hsla(var(--brand-h),90%,55%,0.06) 24deg, hsla(var(--brand-h),90%,55%,0.30) 42deg, transparent 44deg);
  animation: radar-sweep 4s linear infinite; }
@keyframes radar-sweep { to { transform: rotate(360deg); } }
.radar__core { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center;
  color: var(--accent); font-size: var(--fs-xs); text-shadow: 0 0 10px var(--accent); z-index: 3; line-height: 1.3; }
.radar__blip { position: absolute; width: 7px; height: 7px; border-radius: 50%; transform: translate(-50%, -50%);
  background: var(--c, var(--accent)); box-shadow: 0 0 8px var(--c, var(--accent)); z-index: 2; }
.radar__foot { position: absolute; left: var(--sp-4); bottom: var(--sp-3); font-size: var(--fs-xs);
  color: var(--text-faint); z-index: 3; }

/* ---- sidebar: ~/nav header + BUS HEALTH & AGENTS panel ------------------- */
.nav-home { font-size: var(--fs-xs); color: var(--text-faint); letter-spacing: 0.12em;
  padding: var(--sp-2) var(--sp-4) var(--sp-1); }
.sidebar__panel { margin: var(--sp-3) var(--sp-3) 0; padding: var(--sp-3); border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface); }
.sidebar__panel-head { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text); margin-bottom: var(--sp-2); }
.sidebar__panel-head::first-letter { color: var(--accent); }
.bh-row { display: flex; align-items: center; gap: var(--sp-2); padding: 4px 0; font-size: var(--fs-xs);
  border-bottom: 1px dashed var(--border); min-width: 0; }
.bh-row:last-child { border-bottom: 0; }
.bh-row__dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
/* A flex item's default min-width:auto is its min-content width, so the meta (the heartbeat lane
   string — free text, any length) refused to shrink, collapsed the NAME instead, and still spilled
   past the panel border. The meta must absorb ALL the shrink: min-width:0 + ellipsis.
   The NAME must absorb NONE of it — flex-shrink:0. Measured: with both shrinkable, basis-weighted
   shrink still cut "ARCH" to 12px ("A…"), because losing 4 chars of a short identity costs the same
   flex arithmetic as losing 4 of a long lane. The identity is what the row is FOR, so it is pinned;
   max-width caps a pathologically long name so it can never eat the whole row instead. */
.bh-row__name { color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  flex: 0 0 auto; min-width: 0; max-width: 60%; }
.bh-row__meta { margin-left: auto; color: var(--text-faint); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; flex: 0 1 auto; min-width: 0; }

/* ---- terminal top bar ---------------------------------------------------- */
.term-bar { display: flex; align-items: center; gap: var(--sp-4); height: var(--topbar-h); padding: 0 var(--sp-5);
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); box-sizing: border-box; }
.term-bar__logo { width: 42px; height: 42px; flex: none; display: grid; place-items: center; font-weight: 700;
  border: 1px solid var(--accent); border-radius: var(--r-md); color: var(--accent);
  box-shadow: 0 0 10px rgba(var(--glow-rgb),0.35), inset 0 0 8px rgba(var(--glow-rgb),0.2); }
.term-bar__id { flex: none; }
.term-bar__prompt { font-size: var(--fs-sm); }
.term-bar__prompt .tb-user { color: var(--accent); }
.term-bar__prompt .tb-cmd { color: var(--text); }
.term-bar__sub { font-size: var(--fs-xs); color: var(--text-faint); letter-spacing: 0.08em; text-transform: uppercase; }
.term-bar__cmd { flex: 1; display: flex; align-items: center; gap: var(--sp-2); min-width: 120px;
  padding: var(--sp-2) var(--sp-3); border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--code-bg); }
.term-bar__cmd .tb-dollar { color: var(--accent); }
.term-bar__cmd input { flex: 1; background: transparent; border: 0; color: var(--text); font: inherit; outline: none; caret-color: var(--accent); }
.term-bar__meta { display: flex; gap: var(--sp-2); flex: none; }
.term-bar__clock { flex: none; text-align: right; }
.tb-time { font-size: var(--fs-lg); font-weight: 700; color: var(--text); letter-spacing: 0.02em; }
.tb-time { text-shadow: 0 0 10px rgba(var(--glow-rgb),0.3); }
.tb-time small { font-size: var(--fs-xs); color: var(--text-muted); margin-left: 3px; }
.tb-date { font-size: var(--fs-xs); color: var(--text-faint); }

/* brighter, thicker distribution bars inside mission-control cards (matches the benchmark) */
.mc-card .dist { gap: 5px; }
.mc-card .dist__track { height: 10px; background: var(--surface-3); border-radius: 2px; }
.mc-card .dist__fill { border-radius: 2px; background: hsl(var(--bh, 150), 85%, 52%) !important; }
:root[data-theme="dark"] .mc-card .dist__fill { box-shadow: 0 0 10px -1px hsla(var(--bh, 150), 90%, 55%, 0.75); }
.mc-card .dist__label { color: var(--text-muted); }

/* radar + a data card side by side, equal height */
.mc-core-row { display: grid; grid-template-columns: 1fr 340px; gap: var(--sp-4); align-items: stretch; }
@media (max-width: 1100px) { .mc-core-row { grid-template-columns: 1fr; } }
/* compact single-line side rows so the card never grows taller than the radar */
.side-row { padding: var(--sp-2) 0 !important; gap: var(--sp-2); }
.side-row .cell-truncate { font-size: var(--fs-sm); }

/* ---- mission-control page layout ---------------------------------------- */
.mc-layout { display: grid; grid-template-columns: 1fr 340px; gap: var(--sp-4); align-items: stretch; margin-top: 0; }
/* the overview: comfortable sizes that fill a normal screen without a big void or internal scroll,
   vertically centred so any spare height on a tall screen splits top/bottom (safe = never clips) */
.page--mc { padding: var(--sp-5) var(--sp-8); flex: 1; box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: safe center; }
.page--mc .mc-layout { gap: var(--sp-4); }
.page--mc .mc-main { gap: var(--sp-4); }
.page--mc .mc-rail { gap: var(--sp-4); }
.page--mc .mc-top-right { gap: var(--sp-2); }
.page--mc .gauge { padding: var(--sp-2) var(--sp-1); }
.page--mc .gauge__ring { width: 50px; height: 50px; }
.page--mc .gauge__num { font-size: var(--fs-lg); }
.page--mc .mc-hw { padding: var(--sp-2) var(--sp-4); }
.page--mc .mc-hw .mc-head { margin-bottom: var(--sp-1); }
.page--mc .hw-cell { padding: var(--sp-1) var(--sp-3); }
.page--mc .radar { height: 220px; }
.page--mc .mc-card .dist { gap: 5px; }
/* Uniform card gaps: absorb any height difference between the two columns into the
   DECORATIVE mascot (grow-only, never below its natural size) instead of a gap between two
   data cards — Tasks / Milestones / Messages keep an even --sp-4 rhythm, and the rail's
   bottom card still lines up with the main column's bottom when main is the taller column. */
.page--mc .mc-mascot { flex: 1 0 auto; display: flex; align-items: center; justify-content: center; min-height: 0; }

/* Task board — one cell per board column, each showing the real per-status total. */
.tb-strip { display: flex; gap: var(--sp-2); }
.tb-cell { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: var(--sp-3) var(--sp-2); border-radius: var(--r-md);
  border: 1px solid hsla(var(--bh), 55%, 55%, 0.28); background: hsla(var(--bh), 65%, 50%, 0.06);
  text-decoration: none; transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease); }
.tb-cell:hover { border-color: hsla(var(--bh), 70%, 58%, 0.55); background: hsla(var(--bh), 65%, 50%, 0.12); }
.tb-cell__n { font-family: var(--font-mono); font-size: var(--fs-2xl); font-weight: 700; line-height: 1; color: hsl(var(--bh), 72%, 50%); }
:root[data-theme="dark"] .tb-cell__n { color: hsl(var(--bh), 82%, 70%); text-shadow: 0 0 12px hsla(var(--bh), 90%, 55%, 0.4); }
.tb-cell__l { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; text-align: center; }
.tb-cell--zero { opacity: 0.42; }
.tb-cell--zero .tb-cell__n { color: var(--text-faint); text-shadow: none; }
.mc-main { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.mc-rail { display: flex; flex-direction: column; gap: var(--sp-4); }

/* decorative mascot in the right-most column */
.mc-mascot { pointer-events: none; }
.mc-mascot img { max-width: 100%; max-height: 220px; width: auto; height: auto; display: block; margin: 0 auto;
  mix-blend-mode: screen; opacity: 0.92; }
:root[data-theme="light"] .mc-mascot img { mix-blend-mode: normal; opacity: 0.8; }

/* ---- mascot ACTIVITY TELL: eyes blink + heart beats only while work is actually running ----
   The mascot is a flat PNG, so the eyes/heart cannot be animated in place — these are glow
   overlays laid ON TOP at the features' real positions. The coordinates are DERIVED from the
   PNG's own pixels (clustering its red eye pixels and cyan core, n=411/467/3099), not eyeballed,
   so they stay locked to the artwork at any rendered size. mix-blend-mode:screen makes them ADD
   light to the existing glow rather than paint a disc over it.
   The `is-working` class is set from REAL liveness (agents running / wip held) — an idle mascot
   must look idle, or the tell is decoration that asserts something false. */
.mascot-frame { position: relative; display: inline-block; line-height: 0; }
.mascot-eye, .mascot-heart { position: absolute; transform: translate(-50%, -50%); border-radius: 50%;
  pointer-events: none; opacity: 0; mix-blend-mode: screen; }
.mascot-eye { width: 11%; height: 6.5%;
  background: radial-gradient(ellipse at center, rgba(255,95,75,0.95) 0%, rgba(255,60,45,0.45) 45%, rgba(255,50,40,0) 75%); }
.mascot-eye--l { left: 43.4%; top: 23.7%; }
.mascot-eye--r { left: 57.1%; top: 24.4%; }
.mascot-heart { left: 50.1%; top: 81.8%; width: 30%; height: 26%;
  background: radial-gradient(circle at center, rgba(125,235,255,0.9) 0%, rgba(70,190,255,0.4) 40%, rgba(50,170,255,0) 70%); }

.mc-mascot.is-working .mascot-eye { animation: mascot-blink 3.2s var(--ease) infinite; }
.mc-mascot.is-working .mascot-eye--r { animation-delay: 0.07s; }   /* eyes not perfectly in sync = alive */
.mc-mascot.is-working .mascot-heart { animation: mascot-beat 1.8s ease-in-out infinite; }

@keyframes mascot-blink {
  0%, 68% { opacity: 0; }
  71% { opacity: 0.95; }
  75% { opacity: 0.08; }
  79% { opacity: 0.9; }
  88% { opacity: 0.3; }
  100% { opacity: 0; }
}
@keyframes mascot-beat {   /* double-thump, like a real beat, not a sine pulse */
  0%, 100% { opacity: 0.12; transform: translate(-50%, -50%) scale(0.92); }
  12% { opacity: 0.85; transform: translate(-50%, -50%) scale(1.08); }
  26% { opacity: 0.3;  transform: translate(-50%, -50%) scale(0.97); }
  40% { opacity: 0.62; transform: translate(-50%, -50%) scale(1.03); }
  58% { opacity: 0.18; transform: translate(-50%, -50%) scale(0.94); }
}

/* ---- VOICE states. Declared AFTER .is-working deliberately: same specificity, so source order
   makes listening/speaking win when both classes are present. The three states must be visually
   DISTINCT or the mascot stops telling you anything: working = red blink, listening = cyan eyes
   breathing, speaking = fast heart thump. */
.mc-mascot.is-listening .mascot-eye {
  background: radial-gradient(ellipse at center, rgba(125,235,255,0.95) 0%, rgba(70,190,255,0.4) 45%, rgba(50,170,255,0) 75%);
  animation: mascot-listen 1.4s ease-in-out infinite;
}
.mc-mascot.is-listening .mascot-heart { animation: mascot-listen 1.4s ease-in-out infinite; animation-delay: 0.2s; }
.mc-mascot.is-speaking .mascot-eye { animation: none; opacity: 0.5; }
.mc-mascot.is-speaking .mascot-heart { animation: mascot-speak 0.42s ease-in-out infinite; }
@keyframes mascot-listen { 0%, 100% { opacity: 0.14; } 50% { opacity: 0.9; } }
@keyframes mascot-speak {
  0%, 100% { opacity: 0.3;  transform: translate(-50%, -50%) scale(0.96); }
  50%      { opacity: 0.95; transform: translate(-50%, -50%) scale(1.10); }
}
.voice-btn.is-live { color: hsl(2, 85%, 62%); animation: voice-pulse 1s ease-in-out infinite; }
.voice-btn.is-busy { color: var(--accent); }
@keyframes voice-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }
.mc-top { display: grid; grid-template-columns: 300px 1fr; gap: var(--sp-4); align-items: stretch; }
.mc-top .mc-head { flex-wrap: wrap; }
/* right block: gauges (shrink to fill) stacked over the horizontal high-water strip;
   together they equal the SYSTEM OVERVIEW card height */
.mc-top-right { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.mc-top-right .gauge-row { flex: 1; }

/* HIGH-WATER SEQ as a compact horizontal strip */
.mc-hw { padding: var(--sp-3) var(--sp-4); }
.mc-hw .mc-head { margin-bottom: var(--sp-2); }
.hw-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-2); }
.hw-cell { border: 1px solid var(--border); border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3);
  background: var(--surface-2); min-width: 0; }
.hw-cell__top { display: flex; align-items: center; gap: var(--sp-2); }
.hw-cell__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.hw-cell__title { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hw-cell .term-badge { margin-left: auto; }
.hw-cell__sub { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 1100px) { .hw-strip { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 1000px) {
  .mc-layout, .mc-top { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .gauge-row { grid-template-columns: repeat(2, 1fr); }
  .term-bar { flex-wrap: wrap; }
  .term-bar__cmd { order: 5; flex-basis: 100%; }
}

/* interface-sound toggle — muted state must be visible at a glance, not hidden in a menu */
.sfx-btn.is-muted { opacity: 0.35; }
.sfx-btn.is-muted::after { content: ''; position: absolute; inset: 30% 12%; border-top: 1.5px solid currentColor;
  transform: rotate(-45deg); pointer-events: none; }
.sfx-btn { position: relative; }

/* ambience toggle — lit while the bed is playing, so its state is never a guess */
.ambient-btn.is-live { color: var(--accent); }
:root[data-theme="dark"] .ambient-btn.is-live { text-shadow: 0 0 10px hsla(var(--brand-h), 90%, 55%, 0.7); }

/* ==========================================================================
   23. Documents: the folder browser (Drive-like browse mode)
   --------------------------------------------------------------------------
   The one idea every rule here serves: a MIRRORED folder is git's, and the
   server refuses every write into it. So read-only must be VISIBLE before a
   click, not explained after a refusal — hence a lock chip on the row, a
   muted row treatment, a banner on the folder you are standing in, and a
   dropzone that turns red and says why instead of accepting the file.
   ========================================================================== */

/* Breadcrumb + folder actions. Its own class rather than the global .breadcrumb:
   this one carries buttons (the router drives navigation, so a crumb cannot be an
   <a href>) and has to wrap on a deep path without pushing the actions off screen. */
.fs-bar { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.fs-crumbs { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; flex: 1; min-width: 0; font-size: var(--fs-sm); }
.fs-crumbs svg { width: 13px; height: 13px; color: var(--text-faint); flex: none; }
.fs-crumb {
  font: inherit; color: var(--text-muted); background: none; border: 0; cursor: pointer;
  padding: 2px 6px; border-radius: var(--r-sm);
}
.fs-crumb:hover { color: var(--accent); background: var(--surface-hover); }
/* The last crumb is where you ARE — a link to the page you are on is a dead control. */
.fs-crumb--current { color: var(--text); font-weight: 650; cursor: default; padding: 2px 6px; }

/* One notice strip, three jobs: read-only, truncated, and "you are searching". They
   share a shape because they answer the same class of question — what is this view
   not telling me — and a user who has read one can read the others at a glance. */
.fs-note {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2); color: var(--text-muted); font-size: var(--fs-sm);
}
.fs-note svg { width: 15px; height: 15px; flex: none; }
.fs-note--lock { border-color: color-mix(in srgb, hsl(210, 70%, 50%) 35%, var(--border)); background: hsla(210, 70%, 50%, 0.07); }
.fs-note--lock svg { color: hsl(210, 70%, 50%); }
/* Truncation is a warning, not a note: files are missing from what is on screen. */
.fs-note--warn { border-color: color-mix(in srgb, hsl(38, 84%, 50%) 45%, var(--border)); background: hsla(38, 84%, 50%, 0.09); color: var(--text); }
.fs-note--warn svg { color: hsl(38, 84%, 45%); }
:root[data-theme="dark"] .fs-note--warn svg { color: hsl(38, 88%, 62%); }

/* Folder rows. Same .msg-row chrome as the document rows deliberately — they are one
   list and a second visual language would make the folders look like a separate
   widget rather than the first N entries of the same directory. */
.fs-row { align-items: center; }
.fs-row:focus-visible { outline-offset: -2px; }
.fs-row__icon { display: grid; place-items: center; flex: none; color: var(--accent); }
.fs-row__icon svg { width: 20px; height: 20px; }
/* Read-only is dimmed, not hidden: you can still browse in, you just cannot write. */
.fs-row--locked .fs-row__icon { color: var(--text-faint); }
.fs-lock {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-faint);
  padding: 1px 6px; border: 1px solid var(--border); border-radius: var(--r-full);
}
.fs-lock svg { width: 11px; height: 11px; }
/* The per-row action (delete an empty folder, move a document) is quiet until the row
   is touched — it is the rare verb, and a trash can on every row reads as a threat.
   It stays reachable on keyboard focus, or it would not exist without a mouse.
   pointer-events goes with the opacity ON PURPOSE: a transparent button still takes
   clicks, and an invisible delete control sitting in a row you are aiming at is the
   one way this affordance could do damage. */
.fs-row__act, .msg-row .fs-row__act {
  flex: none; opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.msg-row:hover .fs-row__act, .fs-row__act:focus-visible { opacity: 1; pointer-events: auto; }

/* "in <folder>" on a search hit — search is global and flat, so the folder is the
   only thing that says where the document actually lives. */
.fs-inpath { margin-top: 5px; }
.fs-inpath__btn {
  display: inline-flex; align-items: center; gap: 5px;
  font: inherit; font-size: var(--fs-xs); color: var(--text-muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-full); padding: 2px 9px 2px 7px; cursor: pointer;
}
.fs-inpath__btn:hover { color: var(--accent); border-color: var(--accent); }
.fs-inpath__btn svg { width: 12px; height: 12px; }

/* A drop that will be refused must LOOK refused while the file is still in the air.
   The veil is armed either way (it is what swallows the drop — see the dragover
   handler), but in this state it is red and says why instead of promising an upload. */
.dropzone.is-refusing .dropzone__veil { border-color: hsl(2, 72%, 56%); }
.dropzone.is-refusing .dropzone__veil-inner { color: hsl(2, 72%, 50%); border-color: hsl(2, 72%, 56%); }
:root[data-theme="dark"] .dropzone.is-refusing .dropzone__veil-inner { color: hsl(2, 85%, 70%); }

/* ----- 14. Document row — copy control (T-01) ------------------------------
   .msg-row is `display:flex; gap: var(--sp-3)` and its existing per-row action
   (.fs-row__act) is only opacity:0 at rest — a second action element would still
   consume flex gap + width while invisible, narrowing every row's text column.
   .dx-act stays zero-footprint at rest (width 0, no border/padding, overflow
   hidden) and cancels the gap it would otherwise introduce with a matching
   negative margin, then expands on hover AND on keyboard focus (never
   hover-only — that would be unreachable by keyboard). */
.dx-act {
  flex: none; width: 0; min-width: 0;
  padding: 0; border: 0; margin-left: calc(var(--sp-3) * -1);
  overflow: hidden; opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.msg-row:hover .dx-act,
.msg-row:focus-within .dx-act,
.dx-act:focus-visible {
  width: 38px; min-width: 38px; margin-left: 0; opacity: 1; pointer-events: auto;
}
/* While its menu is open the trigger keeps its expanded box. openMenu moves focus into
   the menu, and the menu is a child of <body>, so :focus-within on the row and
   :focus-visible on the button both go false and the box would collapse to width 0 —
   reflowing the row 38px underneath an open menu that is pointing at it. Same
   specificity (0,3,0) as the rules above; wins on source order. Matches nothing at rest. */
.msg-row .dx-act[aria-expanded="true"] {
  width: 38px; min-width: 38px; margin-left: 0; opacity: 1; pointer-events: auto;
}

/* ----- 15. Browse folder header — direct-child summary (T-02) --------------
   A quiet, always-on line under the breadcrumb/lock note, not a `.fs-note` strip:
   `.fs-note` is this page's "what is this view not telling me" shape (read-only,
   truncated, searching) and a routine count does not warrant that weight. Token-
   styled only — no new declaration on any existing class, nothing reflows. */
/* Hidden at rest, still IN FLOW. The freeze constrains the at-rest box, and a box with
   height:0 + overflow:hidden + no margin contributes exactly zero to block flow — so
   .fs-bar's own margin-bottom (12px) stays the only gap above the list and the card
   sits at its baseline y. No positioning context, no markup move, no JS. Revealed by
   hovering/focusing the header block, the same gesture that reveals .dx-sort. The line
   WRAPS rather than clipping, which keeps folderSummary's "in the N loaded here"
   truncation clause intact at every width. */
.dx-sum {
  font-size: var(--fs-xs); color: var(--text-faint);
  height: 0; margin-bottom: 0; overflow: hidden;
}
#doc-browse-bar:hover .dx-sum,
#doc-browse-bar:focus-within .dx-sum { height: auto; margin-bottom: var(--sp-3); }

/* ----- 16. Browse folder header — sort control honesty note (T-03) ---------
   The "Sort documents" control itself needs no new rule: it is a plain
   .btn.btn--ghost.btn--sm dropped into the existing .row.gap-2 action group, which is
   already a flex row built to hold buttons — nothing else in that row moves or
   resizes because of it. This is only the note that appears BELOW the bar, in the
   same quiet always-on-line idiom as .dx-sum above (not a `.fs-note` strip, for the
   same reason .dx-sum isn't one — see its comment), and only while a non-default sort
   is active on a truncated folder (documents.js: sortNoteText). Nothing renders, and
   nothing reflows, in the default state. */
.dx-sortnote { font-size: var(--fs-xs); color: var(--text-faint); margin-bottom: var(--sp-3); }

/* ----- 17. Keyboard shortcuts help overlay content (T-04) -------------------
   The overlay CHROME (.modal/.overlay) is entirely existing and untouched — this is
   only the static list painted inside it. `kbd` is an ELEMENT selector and restyling
   it would reach into every <kbd> the app ever grows, so every key renders as
   `<kbd class="dx-key">` and is styled by class, never by tag. .topbar__search kbd
   (line ~270) is a different, unrelated rule scoped away from the modal — nothing here
   inherits from or conflicts with it. */
.dx-help__title {
  font-size: var(--fs-xs); font-weight: 650; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-faint); margin: var(--sp-4) 0 var(--sp-2);
}
.dx-help__title:first-child { margin-top: 0; }
.dx-help__row {
  display: flex; align-items: baseline; gap: var(--sp-3); padding: var(--sp-1) 0;
  font-size: var(--fs-sm); color: var(--text-muted);
}
.dx-help__keys { display: flex; align-items: baseline; gap: 4px; flex-shrink: 0; min-width: 100px; }
.dx-key {
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-faint);
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 1px 6px;
}

/* ----- 16a. Browse bar — zero-footprint sort control (design-freeze restore) -
   Same idiom as .dx-act (section 14) and for the same reason: .fs-crumbs is
   `flex: 1 1 0%`, so ANY width in the sibling .row.gap-2 comes straight out of the
   breadcrumb box. width:0 + a margin-left that cancels the .gap-2 keeps .row.gap-2
   at exactly the New-folder button's own width, so the bar is byte-identical to
   baseline. `border-width` (not `border`) is zeroed, so the revealed button keeps
   .btn--ghost's transparent border and .btn:hover can still paint one.
   documents.js drops the .dx-sort class once a non-default sort is active — a sort
   the user picked is a state they invoked, and the control that says WHICH sort is
   active has to be visible once there is something to say. */
.dx-sort {
  flex: none; width: 0; min-width: 0;
  padding: 0; border-width: 0; margin-left: calc(var(--sp-2) * -1);
  overflow: hidden; opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.fs-bar:hover .dx-sort,
.fs-bar:focus-within .dx-sort,
.dx-sort:focus-visible,
.dx-sort[aria-expanded="true"] {
  width: auto; padding: 0 var(--sp-3); border-width: 1px; margin-left: 0;
  opacity: 1; pointer-events: auto;
}

/* ----- 16b. Move trigger keeps its box while its menu is open ---------------
   openMenu now moves focus into the menu (a <body> child), so .fs-row__act's only
   reveal paths — .msg-row:hover and :focus-visible — both go false on the keyboard
   path and the trigger would vanish, and with pointer-events:none the next click
   would fall through to the row and navigate. Baseline left focus on the anchor, so
   this rule restores baseline behaviour rather than adding any. Same [aria-expanded]
   hatch already used by .dx-act and .dx-sort. Ties .msg-row:hover .fs-row__act at
   (0,3,0) and wins on source order. Matches nothing at rest — the markup ships
   aria-expanded="false" and openMenu resets it to "false" on every close path. */
.msg-row .fs-row__act[aria-expanded="true"] { opacity: 1; pointer-events: auto; }
