/* The Lab's stylesheet, and the only file in lab/ with a raw colour value.
   Every value is the product's own (docs/design-system.md): the instrument
   that tunes the product reads like the product it tunes. Three tokens are
   the Lab's alone, recorded in design-system.md §7.3: the score bands, and
   the pulse that travels an edge when a pass runs. */

/* The app's redesign faces (2026-09-28), self-hosted because the Lab's policy
   loads fonts from itself only: Figtree for words, Barlow Condensed for the
   big figures. Both SIL Open Font License; the Latin files next/font serves. */
@font-face { font-family: "Figtree"; src: url("./fonts/Figtree-300_900.woff2") format("woff2"); font-weight: 300 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Barlow Condensed"; src: url("./fonts/BarlowCondensed-600.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Barlow Condensed"; src: url("./fonts/BarlowCondensed-700.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Inconsolata"; src: url("./fonts/Inconsolata-300_700.woff2") format("woff2"); font-weight: 300 700; font-style: normal; font-display: swap; }

:root {
  /* The app's redesign surfaces (2026-09-28, app/src/styles/theme.css): a
     near-black with a breath of blue, each step up a panel (Niko, 2026-09-29:
     "the new design that we have for the app is also shown in the Lab"). */
  --surface-0: #0b0c0f;
  --surface-1: #15171c;
  --surface-2: #1c1f26;
  --surface-3: #272b34;
  --surface-invert: #ffffff;
  --border-subtle: #22262e;
  --border-strong: #2e333d;
  --ink-muted: #a3aab6;
  --ink-secondary: #c9ced7;
  --ink-primary: #f5f6f8;
  /* Each speaker's own colour, the app's sixteen (app/src/lib/speaker-colors.ts, 2026-09-29). */
  --speaker-red: #e5242b;
  --speaker-orange: #ff8a3d;
  --speaker-amber: #f5b331;
  --speaker-yellow: #e5d54b;
  --speaker-lime: #a8d94a;
  --speaker-green: #4cc97a;
  --speaker-mint: #2fd3a4;
  --speaker-teal: #33c9c1;
  --speaker-cyan: #3dbde8;
  --speaker-sky: #62a8ff;
  --speaker-blue: #2563eb;
  --speaker-indigo: #8484ff;
  --speaker-violet: #a67cff;
  --speaker-purple: #c874f2;
  --speaker-magenta: #f06bd3;
  --speaker-pink: #ff72a8;
  --ink-on-invert: #151515;

  /* Brand, not data (design-system.md §4.1b-2): the mark, and nothing else. */

  --accent-kept: #00a189;      /* the answered teal: a kept generation */
  --accent-reverted: #c28000;  /* the dropped amber: a reverted one */
  /* The same two as TEXT, one step lighter so words on a nested box still
     clear 4.5:1 (5.4:1 on surface-2, 4.6:1 on surface-3; 2026-09-15). The
     accents above stay for fills and edges. */
  --ink-kept: #00b39a;
  --ink-reverted: #d49200;
  /* The focus ring is grey, like the app's (Niko, 2026-09-23: "remove all
     the blue outlines"): it says where the keyboard is, and that needs no hue. */
  --focus: var(--ink-muted);
  --danger: #db4241;
  /* White words on a red button, and the red a shade deeper under them so
     they read at 4.5:1 or better (Niko, 2026-09-23: "make the text white"). */
  --ink-on-danger: #ffffff;
  --danger-fill: #b8302f;
  --ink-danger: #ec6d6c;
  --rec: #db4241;

  /* The Lab's own four (design-system.md §7.3). A score under 5, 5 to 7,
     7 and above: the same values as reverted, kept and danger, so no new hue
     enters, named for what they mean here. And the pulse: SOMETHING IS
     RUNNING RIGHT NOW, the dot on a wire, the ring on a step, a generation
     being measured, a shot filling, a download in progress. One meaning. */
  --score-low: #db4241;
  --score-mid: #c28000;
  --score-high: #00a189;
  --pulse: #5b86ff;
  /* The Command tab's colour (Niko, 2026-09-23: "more colorful reasonably").
     Health first: green all is well, amber switched off by choice, red down
     or failing. Then three chart hues and money's gold, which mean nothing
     beyond telling one chart from the next. */
  --ok: #3ccf7f;
  --warn: #e0a526;
  --bad: #ec6d6c;
  --chart-a: #5fb3ff;
  --chart-b: #a78bfa;
  --chart-c: #4fd1a5;
  --money: #f2c14e;
  /* The Users tab's two kinds of account, on its avatars and chips only. */
  --tier-streamer: #c084fc; --tier-viewer: #5fb3ff;
  /* App Config's marks: changed from what ships, and settings the autopilot may tune. */
  --cfg-ai: #5fb3ff;
  /* The Activity log's sources (Niko, 2026-09-23: "make the logs colored"):
     one hue per part of the app, meaning only where a line came from, on the
     log alone. Kept clear of the health hues above, which the log's levels
     use, and of each other. Errors take --bad and board writes stay grey. */
  --log-lab: #5fb3ff; --log-command: #c084fc; --log-accounts: #22d3ee; --log-debates: #818cf8;
  --log-viewers: #f472b6; --log-moderation: #f0abfc; --log-money: #fde047; --log-verification: #bef264;

  --font-sans: "Figtree", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: "Barlow Condensed", "Arial Narrow", ui-sans-serif, sans-serif;
  --font-mono: "Inconsolata", ui-monospace, SFMono-Regular, Menlo, monospace;

  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px; --s10: 40px;
  --r-sm: 4px; --r-md: 8px; --r-lg: 12px; --r-full: 9999px;
  --t-fast: 120ms cubic-bezier(0.2, 0, 0, 1);
  --t-base: 180ms cubic-bezier(0.2, 0, 0, 1);
  --shadow-overlay: 0 8px 24px -8px rgb(0 0 0 / 0.55);
  --shadow-lift: 0 6px 16px -6px rgb(0 0 0 / 0.5);
  /* The flair palette (0090): the only colours a reward's design may name,
     the same values as the app's --color-flair-* (app/src/styles/theme.css). */
  --flair-ember: #ff6a3d; --flair-gold: #f2c14e; --flair-mint: #4fd1a5; --flair-sky: #5fb3ff;
  --flair-violet: #a78bfa; --flair-rose: #f472b6; --flair-ice: #cfefff; --flair-ash: #9aa3ad;
  /* Rarity, on reward surfaces only; the label always says it too. */
  --rarity-common: #a8acb3; --rarity-rare: #5fb3ff; --rarity-epic: #a78bfa; --rarity-legendary: #f2c14e;
}

/* ------------------------------------------------------------------ reset */
/* The scrollbar and the selection are the app's (app/src/styles/theme.css): left to the browser they are the one light thing on the page. */
* { box-sizing: border-box; margin: 0; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
::selection { background: var(--surface-3); color: var(--ink-primary); }
[hidden] { display: none !important; }
html { color-scheme: dark; background: var(--surface-0); }
body {
  background: var(--surface-0); color: var(--ink-primary);
  font: 14px/20px var(--font-sans);
  -webkit-font-smoothing: antialiased;
}
h1 { font: 800 30px/36px var(--font-sans); letter-spacing: -0.02em; text-wrap: balance; }
h2 { font: 800 18px/28px var(--font-sans); color: var(--ink-primary); }
h3 { font: 700 14px/20px var(--font-sans); color: var(--ink-primary); }
p { font-size: 14px; line-height: 20px; color: var(--ink-secondary); max-width: 62ch; }
a { color: var(--ink-primary); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--ink-primary); }
code { font-family: var(--font-mono); font-size: 12px; background: var(--surface-2); padding: 1px var(--s1); border-radius: var(--r-sm); }
.mono, .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* Secondary text is the app's (primitives/type.ts `hint`, `errorText`, `label`): 14px in a light ink, never a small grey. */
.hint { color: var(--ink-secondary); font-size: 14px; }
.err { color: var(--ink-danger); font-size: 14px; }
.err:empty, .hint:empty { display: none; }
.empty { color: var(--ink-secondary); font-size: 14px; padding: var(--s3) 0; }
.eyebrow { font: 600 14px/20px var(--font-sans); color: var(--ink-secondary); }

/* ----------------------------------------------------------------- shell */
.console { display: flex; min-height: 100dvh; }
.stale { position: fixed; bottom: var(--s4); left: 50%; z-index: 30; transform: translateX(-50%); display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border-radius: var(--r-lg); background: var(--surface-2); color: var(--ink-primary); box-shadow: var(--shadow-overlay); font-size: 14px; }
/* The app's rail (app-header.tsx), measure for measure (Niko, 2026-10-04: "it
   should mimic the app"): 240px with its edge inside, 20px above and below,
   8px at the sides. Its head is the app's too: the lockup alone, starting on
   the icons' own column (8px of rail, 16px of row), centred on a 40px row
   with 16px under it. "Contraverse Lab" is too long for the rail at the
   app's 22px, so here it is as wide as the row and as tall as that makes it. */
.rail {
  position: sticky; top: 0; align-self: flex-start;
  display: flex; flex-direction: column;
  width: 240px; flex-shrink: 0; height: 100dvh;
  padding: var(--s5) var(--s2);
  border-right: 1px solid var(--border-subtle);
  background: var(--surface-0);
}
.rail-bar { display: flex; align-items: center; flex: none; height: 56px; padding: 0 var(--s4) var(--s4); }
/* From 861px up the bar is only the lockup and the menu is the rail itself:
   every popover default put back, as the app's rail does from md. */
.rail-burger, .env-switch.small { display: none; }
.rail-menu { position: static; inset: auto; display: flex; flex: 1; flex-direction: column; gap: var(--s1); width: auto; height: auto; margin: 0; padding: 0; border: 0; background: none; color: inherit; overflow: visible; }
.rail .brand { flex: 1; min-width: 0; }
.rail .brand img { display: block; width: 100%; height: auto; }
.rail nav { display: flex; flex-direction: column; gap: var(--s1); }
/* The Lab's search (2026-09-23): the app's own shape (omni-search.tsx). A
   button in the rail that looks like the field it opens, and a panel holding
   the real one: 48px, a fill and no border. Its hover edge is an inset ring,
   because even a clear border takes 1px and puts this row's icon 1px right of
   every other row's. */
.lab-search { display: flex; align-items: center; justify-content: flex-start; gap: var(--s3); flex: none; width: 100%; height: 48px; margin-bottom: var(--s1); padding: 0 var(--s4); border: 0; border-radius: var(--r-lg); background: var(--surface-2); box-shadow: inset 0 0 0 1px transparent; color: var(--ink-muted); font: 400 16px/24px var(--font-sans); text-align: left; white-space: nowrap; overflow: hidden; cursor: pointer; transition: box-shadow var(--t-fast), color var(--t-fast); }
.lab-search:hover { box-shadow: inset 0 0 0 1px var(--ink-muted); color: var(--ink-secondary); }
.lab-search kbd { margin: 0 var(--s1); padding: 2px 6px; border: 1px solid var(--ink-muted); border-radius: var(--r-sm); background: var(--surface-3); font: 400 12px/24px var(--font-mono); color: var(--ink-primary); }
dialog.lab-search-dialog { width: min(640px, 94vw); padding: var(--s6); margin-top: 12vh; }
.lab-search-field { display: flex; align-items: center; gap: var(--s3); padding: 0 var(--s3); border-radius: var(--r-lg); background: var(--surface-2); color: var(--ink-muted); }
.lab-search-field input[type="search"] { flex: 1; min-width: 0; height: 44px; padding: 0; border: 0; background: transparent; color: var(--ink-primary); font: 400 16px/24px var(--font-sans); }
.lab-search-field input[type="search"]:focus-visible { outline: none; }
.lab-search-field input[type="search"]::placeholder { color: var(--ink-muted); }
.lab-search-list { display: flex; flex-direction: column; gap: var(--s1); max-height: 50vh; overflow-y: auto; overscroll-behavior: contain; margin: var(--s3) 0 0; padding: 0; list-style: none; }
.lab-search-row { display: flex; align-items: center; gap: var(--s3); width: 100%; height: auto; padding: var(--s2) var(--s3); border: 0; border-radius: var(--r-lg); background: transparent; color: var(--ink-secondary); text-align: left; cursor: pointer; }
.lab-search-row.on { background: var(--surface-3); color: var(--ink-primary); }
.lab-search-row:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.lab-search-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 400 16px/24px var(--font-sans); }
.lab-search-where { flex: none; font: 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.lab-search-busy { display: flex; align-items: center; height: 40px; padding: 0 var(--s3); color: var(--ink-muted); }
.lab-search-busy .spin { width: 16px; height: 16px; border: 2px solid currentColor; border-right-color: transparent; border-radius: var(--r-full); animation: turn 0.8s linear infinite; }
@media (prefers-reduced-motion: reduce) { .lab-search-busy .spin { animation: none; } }
.lab-search-none { padding: var(--s2) var(--s3); color: var(--ink-secondary); font-size: 16px; line-height: 24px; }
.lab-search-foot { max-width: none; margin: var(--s3) 0 0; padding-top: var(--s3); border-top: 1px solid var(--border-subtle); color: var(--ink-secondary); font-size: 14px; line-height: 20px; }
/* A row of the app's rail, Sign out included, as its account row is one: 44px,
   16px bold, in secondary ink until it is under the pointer or chosen. The
   app's own Tabler drawings at 24px with their 2px line, in the row's ink, so
   icon and word light up together (the app's [data-line-ink], 2026-10-01).
   The chosen row is plain primary ink: the app's metal is a library the Lab
   does not load, and this is what the app draws without it. */
.nav-item, .signout {
  display: flex; align-items: center; justify-content: flex-start; gap: var(--s3); flex: none;
  width: 100%; height: 44px; padding: 0 var(--s4);
  border: 0; border-radius: var(--r-lg);
  background: none; color: var(--ink-secondary);
  font: 700 16px/24px var(--font-sans); text-align: left; white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.nav-item svg, .signout svg, .lab-search svg { flex: none; width: 24px; height: 24px; }
.nav-item[aria-current="page"] { background: var(--surface-2); color: var(--ink-primary); }
:is(.nav-item, .signout):hover:not(:disabled) { background: var(--surface-1); color: var(--ink-primary); }
.nav-item .badge { margin-left: auto; }
.rail-foot { margin-top: auto; display: flex; flex-direction: column; gap: var(--s1); padding-top: var(--s5); }
/* Staging or Production for every tab at once (2026-09-25): two halves on a
   surface-2 track, the chosen one solid white with dark words. It says which
   database every tab writes to, so it is the one switch that does not wear
   the quiet segment (design review, 2026-10-04: a step-lighter half read
   1.16:1 against its track). */
.env-switch { display: grid; grid-template-columns: 1fr 1fr; border-radius: var(--r-lg); background: var(--surface-2); }
.env-switch button {
  height: 32px; padding: 0 10px; border: 0; border-radius: var(--r-lg);
  background: none; color: var(--ink-secondary); font: 700 14px/20px var(--font-sans);
}
.env-switch button:hover:not(:disabled, [aria-checked="true"]) { background: var(--surface-3); color: var(--ink-primary); }
.env-switch button[aria-checked="true"] { background: var(--surface-invert); color: var(--ink-on-invert); }

.content { min-width: 0; flex: 1; display: flex; flex-direction: column; }
/* The app's page shell (primitives/page.ts): one width, 32px round the page. */
main.panel { width: 100%; max-width: 1760px; margin: 0 auto; padding: var(--s8); }
main.panel.canvas-page { max-width: none; padding: 0; flex: 1; display: flex; flex-direction: column; min-height: 100dvh; }

@media (max-width: 860px) {
  .console { display: block; }
  /* The app's phone shape (Niko, 2026-09-25: "the exact same way that it
     works on the app"): a 52px bar with the menu, the lockup and a small
     database switch, and the tabs in a panel that drops under it. */
  .rail { position: sticky; top: 0; z-index: 20; display: block; width: auto; height: auto; padding: 0; border-bottom: 1px solid var(--border-subtle); background: var(--surface-0); }
  .rail-bar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: var(--s2); height: 52px; padding: 0 var(--s3); }
  .rail .brand { min-width: 0; }
  .rail .brand img { width: 255px; max-width: 100%; height: auto; }
  .rail-burger { display: flex; align-items: center; justify-content: center; justify-self: start; width: 40px; height: 40px; padding: 0; border: 0; border-radius: var(--r-lg); background: none; color: var(--ink-secondary); cursor: pointer; transition: background-color var(--t-fast), color var(--t-fast); }
  .rail-burger:hover { background: var(--surface-1); color: var(--ink-primary); }
  .rail-burger:active { background: var(--surface-2); }
  .rail-burger:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
  .env-switch.small { display: grid; justify-self: end; }
  .env-switch.small button { height: 36px; padding: 0 var(--s2); }
  .rail-menu:not(:popover-open) { display: none; }
  .rail-menu:popover-open { position: fixed; inset: 52px 0 auto 0; gap: var(--s2); max-height: calc(100dvh - 52px); overflow-y: auto; overscroll-behavior: contain; padding: var(--s2) var(--s4) var(--s4); border-bottom: 1px solid var(--border-subtle); background: var(--surface-0); }
  /* The bar carries the switch; the menu ends on Sign out under a rule, as the app's account group does. */
  .rail-foot { margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--border-subtle); }
  .rail-foot .env-switch { display: none; }
  main.panel { padding: var(--s8) var(--s4); }
  main.panel.canvas-page { min-height: calc(100dvh - 53px); }
}

/* The app's title row (primitives/page.ts): the title top left, what sits beside it level with its top, and 24px to what is under it. */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; column-gap: var(--s6); row-gap: var(--s4); flex-wrap: wrap; }
.page-head > div { min-width: 0; }
.page-head p { padding-top: var(--s2); }
.page-head .actions { display: flex; align-items: center; gap: var(--s3); flex-shrink: 0; flex-wrap: wrap; }
.page-head .state { display: flex; align-items: center; gap: var(--s2); font-size: 14px; }
/* With nothing to say it takes no place in the row, or its gap pushes the first button off the page's edge on a phone. */
.page-head .state:has(> :only-child:empty) { display: none; }

/* ----------------------------------------------------------------- cards */
.cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); margin-top: var(--s6); align-items: start; }
.cards .wide { grid-column: 1 / -1; }
.cards > section { min-width: 0; }
@media (max-width: 1100px) { .cards { grid-template-columns: 1fr; } }
/* The app's `card` (primitives/card.ts): one step up from the page, a hairline edge, 12px corners. */
section.card, .cards > section {
  border: 1px solid var(--border-subtle); border-radius: var(--r-lg);
  background: var(--surface-1);
  padding: var(--s5);
  display: flex; flex-direction: column; gap: var(--s4);
}
.card-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); min-height: 20px; }
.card-head h2 { flex: none; }
.card-head .aside { color: var(--ink-secondary); font-size: 14px; font-weight: 400; }
.card-head .spacer { flex: 1; }
.unit-id {
  border: 1px solid var(--border-subtle); border-radius: var(--r-sm);
  padding: 0 var(--s1); margin-right: var(--s2);
  color: var(--ink-muted); font: 400 10px/16px var(--font-mono);
}
.unit-id:empty { display: none; }
.facts { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: var(--s2) var(--s4); }
.facts dt { color: var(--ink-secondary); font-size: 14px; }
.facts dd { color: var(--ink-primary); font-size: 14px; margin: 0; }

/* ------------------------------------------------------------ help + tips */
.help, .tip {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  border: 1px solid var(--border-strong); border-radius: var(--r-full);
  color: var(--ink-muted); font: 500 11px/1 var(--font-sans);
  cursor: default;
}
.help { width: 18px; height: 18px; }
.tip { width: 16px; height: 16px; font-size: 10px; }
.help:hover, .help:focus-visible, .tip:hover, .tip:focus-visible { border-color: var(--ink-muted); color: var(--ink-primary); }
.help:focus-visible, .tip:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.tip-source { display: none; }
.tipbox {
  position: fixed; z-index: 50;
  max-width: 280px;
  border-radius: var(--r-lg);
  background: var(--surface-2); color: var(--ink-secondary);
  padding: var(--s3);
  font: 400 14px/20px var(--font-sans);
  box-shadow: var(--shadow-overlay);
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
  pointer-events: none;
}
.tipbox.wide { pointer-events: auto; max-width: 420px; padding: var(--s4); }
.tipbox h3 { margin-bottom: var(--s2); }
.tipbox p + p { margin-top: var(--s3); }

/* ---------------------------------------------------------------- inputs */
.row { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.row.end { justify-content: flex-end; }
.with-button { display: flex; align-items: stretch; gap: var(--s2); }
.with-button input { flex: 1 1 auto; min-width: 0; }
.with-button button { flex: none; }
label { color: var(--ink-secondary); font-size: 14px; }
input[type="text"], input[type="number"], input[type="password"], input[type="search"], select, textarea {
  background: var(--surface-2); color: var(--ink-primary);
  border: 1px solid transparent; border-radius: var(--r-lg);
  padding: 0 var(--s3); height: 36px;
  font: 14px/1 var(--font-sans);
  transition: border-color var(--t-fast);
}
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--ink-muted); }
input.num, select.fixture { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
input.num { width: 80px; text-align: center; }
textarea { height: auto; padding: var(--s3); font: 12px/1.6 var(--font-mono); width: 100%; min-height: 200px; resize: vertical; }
select { padding-right: var(--s6); appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%23a3aab6' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-position: right 12px center; background-repeat: no-repeat;
}
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 1px;
}
input[type="checkbox"], input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  width: 16px; height: 16px; margin: 0; flex: none;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: transparent;
  transition: background-color var(--t-fast), border-color var(--t-fast);
}
input[type="radio"] { border-radius: var(--r-full); }
input[type="checkbox"]:hover:not(:disabled), input[type="radio"]:hover:not(:disabled) { border-color: var(--ink-muted); }
input[type="checkbox"]:checked {
  border-color: var(--surface-invert);
  background: var(--surface-invert)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='8' fill='none' stroke='%23151515' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 4l2.5 2.5L9 1'/%3E%3C/svg%3E")
    center / 9px 7px no-repeat;
}
input[type="radio"]:checked { border-color: var(--surface-invert); background: var(--surface-invert); box-shadow: inset 0 0 0 3px var(--surface-1); }
input:disabled, select:disabled, textarea:disabled, button:disabled { opacity: 0.45; cursor: default; }
.check { display: inline-flex; align-items: center; gap: var(--s2); cursor: pointer; }
.check input { cursor: pointer; }

/* Buttons, from app/src/components/primitives/button.tsx, property for
   property, at its 36px size (and 32px for .small). A bare <button> is the
   app's ghost: a 12% white lift rather than a surface, so it is a step
   lighter than whatever it sits on with no per-area fill, and a border only
   on hover (founder 2026-09-15); .primary is its white one; .quiet is a text
   button. */
button {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: 36px; padding: 0 var(--s4);
  border: 1px solid transparent; border-radius: var(--r-lg);
  background: color-mix(in oklab, var(--surface-invert) 12%, transparent); color: var(--ink-primary);
  font: 600 14px/1 var(--font-sans); cursor: pointer;
  white-space: nowrap;
  transition: color var(--t-fast), background-color var(--t-fast), border-color var(--t-fast), opacity var(--t-fast), box-shadow var(--t-fast);
}
/* In :where, so a button with a look of its own (a rail row, a table's name, a link) keeps its ground under the pointer. */
button:where(:hover:not(:disabled)) { background-color: color-mix(in oklab, var(--surface-invert) 18%, transparent); }
button:hover:not(:disabled) { border-color: var(--ink-muted); }
button:active:not(:disabled) { opacity: 0.75; }
button:disabled { cursor: default; opacity: 0.45; }
button.primary { background: var(--surface-invert); border-color: var(--surface-invert); color: var(--ink-on-invert); }
button.primary:hover:not(:disabled) { opacity: 0.9; border-color: var(--surface-invert); }
/* Red is flat (Niko, 2026-09-23: "the flat red with no borders"): a solid
   fill, white words, no edge and no ring, a little deeper under the pointer.
   Doubled class so the per-area button fills (tables, cards) never repaint it. */
button.danger.danger { background: var(--danger-fill); border-color: transparent; color: var(--ink-on-danger); box-shadow: none; }
button.danger.danger:hover:not(:disabled) { background: color-mix(in oklab, var(--danger-fill) 85%, var(--surface-0)); border-color: transparent; box-shadow: none; }
button.small { height: 32px; padding: 0 var(--s3); font-size: 12px; }
button.quiet {
  height: auto; padding: 0; border: 0; background: none;
  color: var(--ink-secondary); font: inherit; text-decoration: underline; text-underline-offset: 2px;
}
button.quiet:hover:not(:disabled) { color: var(--ink-primary); }
button.quiet:disabled { text-decoration: none; }
button.icon { width: 28px; height: 28px; padding: 0; background: none; color: var(--ink-muted); }
button.icon:hover:not(:disabled) { color: var(--ink-primary); border-color: var(--border-strong); background: var(--surface-2); }
button.icon svg { width: 16px; height: 16px; }
button .spin { width: 12px; height: 12px; border: 2px solid currentColor; border-right-color: transparent; border-radius: var(--r-full); animation: turn 0.8s linear infinite; }
@keyframes turn { to { transform: rotate(360deg); } }

/* The app's `segment` (primitives/button.tsx): a filter, a range, a two-way
   switch. 32px, 14px bold, the chosen one filled a step lighter. One rule,
   where each tab once drew its own and four of them were white capsules. */
:is(.users-filter button, .rw-kinds button, .rw-seg button, .rw-filter button, .cfg-area, .log-chip, .cmd-range, .sc-seg button) {
  height: 32px; padding: 0 10px; border: 0; border-radius: var(--r-lg);
  background: none; color: var(--ink-secondary); font: 700 14px/20px var(--font-sans);
}
:is(.users-filter button, .rw-kinds button, .rw-seg button, .rw-filter button, .cfg-area, .log-chip, .cmd-range, .sc-seg button):hover:not(:disabled, [aria-pressed="true"], [aria-checked="true"], [aria-selected="true"]) { background: var(--surface-2); color: var(--ink-primary); }
:is(.users-filter button, .rw-kinds button, .rw-seg button, .rw-filter button, .cfg-area, .log-chip, .cmd-range, .sc-seg button):is([aria-pressed="true"], [aria-checked="true"], [aria-selected="true"]) { background: var(--surface-3); color: var(--ink-primary); }

/* A tag or a count, as the app draws a chip (design-system §4.3b): a 24px
   block with 8px corners and 14px semibold words, never a capsule. */
.badge {
  display: inline-flex; align-items: center; gap: var(--s1);
  height: 24px; padding: 0 var(--s2);
  border-radius: var(--r-md); background: var(--surface-3);
  color: var(--ink-secondary); font: 600 14px/20px var(--font-sans); white-space: nowrap;
}
.badge.count { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* Score chips: the one place the Lab colours a number. Under 5, 5 to 7, 7 up. */
.score {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; height: 22px; padding: 0 6px;
  border-radius: var(--r-sm);
  font: 700 12px/1 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--ink-primary); background: color-mix(in oklab, var(--ink-muted) 14%, transparent);
}
.score.low { color: var(--ink-danger); background: color-mix(in oklab, var(--score-low) 14%, transparent); }
.score.mid { color: var(--score-mid); background: color-mix(in oklab, var(--score-mid) 14%, transparent); }
.score.high { color: var(--score-high); background: color-mix(in oklab, var(--score-high) 14%, transparent); }
.score.none { color: var(--ink-muted); font-weight: 400; }
td.score-cell { padding: var(--s1) var(--s2); }

/* ------------------------------------------------------------ the banner */
.banner {
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  padding: var(--s4) var(--s5);
  border: 1px solid var(--border-subtle); border-radius: var(--r-lg);
  background: var(--surface-1);
  margin-bottom: var(--s6);
  animation: rise 420ms ease-out both;
}
.banner .what { flex: 1; min-width: 240px; display: flex; flex-direction: column; gap: 2px; }
.banner .what b { font-weight: 600; color: var(--ink-primary); }
.banner .what span { color: var(--ink-secondary); font-size: 14px; }
.banner .acts { display: flex; gap: var(--s2); }

/* ----------------------------------------------------------------- login */
.door { min-height: 100dvh; display: grid; place-items: center; padding: var(--s6); }
/* Never both at once (Niko, 2026-09-23: scrolling up past the Lab found the
   code prompt still drawn above it). Whatever path shows a door by mistake,
   a signed-in console hides it. */
body:has(#console:not([hidden])) .door { display: none !important; }
/* The card's own rhythm: one gap between the PARTS (the lockup, the fields,
   the button), a tighter one inside a field, so a label belongs to the box
   under it rather than floating between two. One value for all of it read as
   a list of unrelated rows. */
.door form,
.door > div {
  display: flex; flex-direction: column; gap: var(--s6);
  width: min(448px, 100%); padding: var(--s8);
  border: 1px solid var(--border-subtle); border-radius: var(--r-lg); background: var(--surface-1);
}
.gate-fields { display: flex; flex-direction: column; gap: var(--s5); }
.gate-field { display: flex; flex-direction: column; gap: var(--s2); }
/* The refusal belongs to the button, not between the form and it: the line is
   reserved so nothing jumps when an answer is refused, and it sits close
   enough to read as the answer to the press. */
.gate-act { display: flex; flex-direction: column; gap: var(--s2); }
.door .err { min-height: 20px; margin: 0; }
.door .err:empty { display: block; }
.door .hint { margin: 0; }
/* The check is the first thing anybody sees, so it is the bigger card: the
   orb, the line, then the widget. */
.door .check-card { width: min(520px, 100%); gap: var(--s5); align-items: center; text-align: center; }
/* The check is the one screen with room for the lockup at full size. */
.door .check-card img { width: 470px; max-width: 100%; height: auto; margin-bottom: var(--s2); }
.check-card .orb { display: grid; place-items: center; min-height: 128px; }
#check-say { color: var(--ink-secondary); font-size: 16px; }
#check-captcha { width: 100%; }
/* The app's sign-in card (auth-flow.tsx): the lockup centred at 24px, its 40px fields and its 44px button. */
.door img { display: block; width: 279px; max-width: 100%; height: auto; margin: 0 auto; }
.door label { color: var(--ink-primary); font-size: 16px; line-height: 24px; }
.door input { width: 100%; height: 40px; font-size: 16px; }
.door button { width: 100%; height: 44px; font-size: 16px; }
/* Turnstile's box, reserved before Cloudflare paints into it: 68px is the
   4px step above the widget's own 65px, so the card never jumps. */
.door .captcha { min-height: 68px; }

/* ------------------------------------------------------------------ rows */
.source {
  display: grid; grid-template-columns: 16px minmax(0, 1fr) auto;
  align-items: center; gap: var(--s3);
  padding: var(--s3) 0; border-top: 1px solid var(--border-subtle);
}
.source:first-of-type { border-top: 0; padding-top: 0; }
.source .what { display: flex; flex-direction: column; gap: 2px; min-width: 0; cursor: pointer; }
.source .name { font-size: 14px; font-weight: 600; color: var(--ink-primary); }
.source .meta { color: var(--ink-secondary); font-size: 14px; }
.source .when { display: flex; align-items: center; gap: var(--s2); }
.source .when span { color: var(--ink-muted); font: 12px var(--font-mono); }

.pick { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; align-items: center;
        gap: var(--s3); padding: var(--s3) 0; border-top: 1px solid var(--border-subtle); cursor: pointer; }
.pick:first-of-type { border-top: 0; padding-top: 0; }
.pick:last-of-type { padding-bottom: 0; }
.pick .name { font-size: 14px; font-weight: 600; color: var(--ink-primary); }
.pick .meta { color: var(--ink-secondary); font-size: 14px; }
.pick .what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pick .len { font: 400 12px var(--font-mono); color: var(--ink-muted); white-space: nowrap; }

.fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); }
.fields label { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); font-size: 14px; color: var(--ink-secondary); }
.fields label > .tip { position: absolute; right: 0; top: 0; }
.fields input, .fields select { width: 100%; }
@media (max-width: 700px) { .fields { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.fields.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fields.setup > label.full { grid-column: 1 / -1; }
.fields.setup textarea { min-height: 72px; font: 14px/20px var(--font-sans); }
@media (max-width: 700px) { .fields.two { grid-template-columns: minmax(0, 1fr); } }
.model-row { display: grid; grid-template-columns: 148px minmax(0, 1fr); gap: var(--s3); align-items: start; }
.model-row > label { padding-top: var(--s2); }
.model-pick { width: 100%; }
@media (max-width: 700px) { .model-row { grid-template-columns: minmax(0, 1fr); } .model-row > label { padding-top: 0; } }
.estimate { border-left: 2px solid var(--border-strong); padding-left: var(--s3); color: var(--ink-secondary); }
.estimate.over { border-left-color: var(--score-low); color: var(--ink-primary); font-weight: 500; }

.weights { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.weights label { display: flex; flex-direction: column; gap: var(--s1); font-size: 12px; color: var(--ink-secondary); }
.weights label .why { color: var(--ink-muted); font-size: 11px; line-height: 14px; min-height: 28px; }
.weights input { width: 100%; }
@media (max-width: 700px) { .weights { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ------------------------------------------------------------ model picker */
.picked { display: flex; align-items: center; gap: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); padding: var(--s2) var(--s3); }
.picked .id { min-width: 0; flex: 1; font-family: var(--font-mono); font-size: 14px; color: var(--ink-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picked .cost { flex: none; font-family: var(--font-mono); font-size: 11px; color: var(--ink-muted); }
/* Which upstream serves the chosen model: OpenRouter routes to whoever it
   likes unless it is told, and the same id from two providers is not the same
   model. */
.endpoints { display: flex; align-items: center; gap: var(--s2); font-size: 12px; color: var(--ink-muted); }
.endpoints-label { font: 600 14px/20px var(--font-sans); color: var(--ink-secondary); }
.endpoints select { flex: 1; min-width: 0; }
.search { position: relative; }
.search svg { position: absolute; left: var(--s3); top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--ink-muted); pointer-events: none; }
.search input { width: 100%; height: 36px; padding-left: 34px; }
.options { overflow: hidden; border-radius: var(--r-lg); background: var(--surface-2); }
.options ul { list-style: none; margin: 0; padding: 0; max-height: 256px; overflow-y: auto; }
.option { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); cursor: pointer; transition: background-color var(--t-fast); }
.option.active { background: var(--surface-3); }
.option.chosen .label { font-weight: 600; }
.option .what { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.option .label { font-size: 14px; color: var(--ink-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.option .id { font-family: var(--font-mono); font-size: 10px; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.option .cost { flex: none; font-family: var(--font-mono); font-size: 10px; color: var(--ink-muted); text-align: right; }
.options-note { padding: var(--s4) var(--s3); text-align: center; font-size: 14px; color: var(--ink-muted); }

/* ---------------------------------------------------------------- tables */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th { text-align: left; color: var(--ink-secondary); font-weight: 700; font-size: 14px; line-height: 20px; padding: var(--s2); white-space: nowrap; }
td { padding: var(--s2); vertical-align: top; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.record-scroll { overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.record-scroll::-webkit-scrollbar { height: 10px; }
.record-scroll::-webkit-scrollbar-track { background: transparent; }
.record-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-full); border: 3px solid var(--surface-1); }
.record-scroll table { min-width: max-content; }
.record-scroll th:first-child, .record-scroll td:first-child { position: sticky; left: 0; z-index: 1; background: var(--surface-1); }
.record-scroll tr > th:first-child { text-align: left; white-space: nowrap; padding-right: var(--s4); }
.record-scroll td { min-width: 104px; padding-right: var(--s4); }
.record-scroll td.wrap { max-width: 260px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--font-sans); }
.record-scroll tr.rule td, .record-scroll tr.rule th { border-top: 1px solid var(--border-subtle); }
.run + .run { margin-top: var(--s6); padding-top: var(--s4); border-top: 1px solid var(--border-subtle); }
.run-head { display: flex; align-items: center; gap: var(--s2); font: 500 12px var(--font-mono); color: var(--ink-secondary); margin-bottom: var(--s2); }
.run-head span { color: var(--ink-muted); font-weight: 400; }
.del { width: 20px; height: 20px; padding: 0; flex: none; border: 1px solid transparent; border-radius: var(--r-sm); background: none; color: var(--ink-muted); font: 400 14px/1 var(--font-sans); }
.del:hover:not(:disabled) { border-color: var(--danger); color: var(--ink-danger); background: none; }
th .del { margin-left: var(--s2); vertical-align: middle; }
.verdict { font-weight: 600; font-size: 12px; }
.verdict.kept { color: var(--ink-kept); }
.verdict.reverted { color: var(--ink-reverted); }
.verdict.running { color: var(--pulse); }
.verdict.stopped, .verdict.interrupted, .verdict.inconclusive { color: var(--ink-muted); }

/* ------------------------------------------------------------- live log */
details.fold > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--s2); }
details.fold .fold-body { margin-top: var(--s2); }
input.wide { width: 100%; }
.canvas-err { padding: var(--s2) var(--s5); }
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary .chev { transition: transform var(--t-fast); }
details.fold[open] > summary .chev { transform: rotate(90deg); }
#log { max-height: 360px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; font: 12px/18px var(--font-mono); margin-top: var(--s3); }
.log-line { display: flex; gap: var(--s2); align-items: baseline; }
.log-line .t { color: var(--ink-muted); flex-shrink: 0; }
.log-line .tag { flex-shrink: 0; padding: 0 var(--s1); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); color: var(--ink-secondary); font-size: 11px; }
.log-line .msg { color: var(--ink-secondary); white-space: pre-wrap; word-break: break-word; }
.log-line.warn .msg { color: var(--ink-primary); font-weight: 600; }

/* --------------------------------------------------------------- bones */
/* Skeletons (design-system.md §7b, drawn from ui/bones.js): each tab's own
   markup with a bone where the data lands. A bone is one step above the box
   it sits in: 2 in a card, 1 on the page, 3 in a box inside a card. */
.bone { position: relative; overflow: hidden; background-color: var(--surface-2); border-radius: var(--r-md); }
#cfg-body .bone { background-color: var(--surface-1); }
:where(.vscores > div, .cmd-tile, .cmd-chart-card, .cmd-plan, .cmd-play, .cmd-spend-hero, .svc, .ustat, .markets-row, .ureport, .vdoc, .vdecide, .gen, .rw-card, .rw-tile, .rw-case, .rw-market, .envpick label, .log-lines, .options, .picked, dialog.users .vsec) .bone { background-color: var(--surface-3); }
:where(.users-grant) .bone { background-color: var(--surface-1); }
/* The app's shimmer (its theme.css): a soft band every 800px sliding right at 400px a second, one pace on every bone, after a beat. */
/* The app's own (app/src/styles/theme.css): one soft wash crossing each bone left to right, every bone in the same 1.4s, then a rest. */
.bone::after { content: ""; position: absolute; inset: 0; background-image: linear-gradient(90deg, transparent, color-mix(in oklab, var(--ink-primary) 6%, transparent), transparent); transform: translateX(-100%); animation: bone-sweep 2s ease-in-out 400ms infinite; }
@keyframes bone-sweep { from { transform: translateX(-100%); } 70%, to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .bone::after { animation: none; content: none; } }
/* In a line of text: the line keeps its own height, so the row does too. */
.bone.word { display: inline-block; height: 0.8em; max-width: 100%; vertical-align: middle; }
.bone.block { display: block; max-width: 100%; }
.bone.chip { display: inline-block; height: 24px; border-radius: var(--r-md); vertical-align: middle; }
.bone-btn { display: inline-block; flex: none; width: 84px; height: 36px; max-width: 100%; border-radius: var(--r-lg); }
.uavatar.bone { background-color: var(--surface-2); }

/* ---------------------------------------------------------------- dialogs */
dialog { color: inherit; }
dialog.confirm, dialog.sheet {
  margin: auto; padding: var(--s6);
  border: 0; border-radius: var(--r-lg);
  background: var(--surface-1); color: var(--ink-secondary);
  box-shadow: var(--shadow-overlay);
  opacity: 0; transform: scale(0.95);
  transition: opacity 300ms ease, transform 300ms ease, overlay 300ms ease allow-discrete, display 300ms ease allow-discrete;
}
dialog.confirm { max-width: 460px; }
dialog.sheet { width: min(640px, 94vw); max-height: 88dvh; overflow-y: auto; }
dialog.confirm[open], dialog.sheet[open] { opacity: 1; transform: none; }
@starting-style { dialog.confirm[open], dialog.sheet[open] { opacity: 0; transform: scale(0.95); } }
dialog::backdrop { background: rgb(0 0 0 / 0); backdrop-filter: blur(2px); transition: background-color 300ms ease, overlay 300ms ease allow-discrete, display 300ms ease allow-discrete; }
dialog[open]::backdrop { background: rgb(0 0 0 / 0.55); }
@starting-style { dialog[open]::backdrop { background: rgb(0 0 0 / 0); } }
@media (prefers-reduced-motion: reduce) { dialog, dialog::backdrop { transition-duration: 1ms; } dialog.confirm, dialog.sheet { transform: none; } }
dialog.confirm h2, dialog.sheet h2 { margin-bottom: var(--s3); font: 600 20px/28px var(--font-sans); }
dialog.confirm .body p { max-width: none; }
dialog.confirm .body p + p { margin-top: var(--s3); }
.confirm-acts, .sheet-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); margin-top: var(--s6); }
dialog.confirm.danger .confirm-acts { justify-content: space-between; }
dialog.sheet .field { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s4); }
dialog.sheet .field input, dialog.sheet .field textarea { width: 100%; }
dialog.sheet .field textarea { min-height: 96px; font: 14px/20px var(--font-sans); }

/* ------------------------------------------------------------------ watch */
dialog.watch {
  margin: auto; width: min(1100px, 94vw); max-height: 90dvh;
  flex-direction: column; gap: var(--s3);
  padding: var(--s4); border: 0;
  border-radius: var(--r-lg); background: var(--surface-1); color: var(--ink-primary);
  box-shadow: var(--shadow-overlay);
}
/* Flex only while open: an author `display` outranks the browser's own
   dialog:not([open]) { display: none }, so set unconditionally it leaves a
   closed dialog drawn on the page. */
dialog.watch[open] { display: flex; }
.watch-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.watch-title { font: 600 20px/28px var(--font-sans); margin: 0; }
.watch-sub { margin: var(--s1) 0 0; font-size: 12px; color: var(--ink-muted); }
.watch-tabs { display: flex; flex-wrap: wrap; gap: var(--s1); }
.watch-tab { font: 11px var(--font-mono); height: auto; padding: var(--s1) var(--s2); border: 1px solid transparent; border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink-secondary); display: flex; gap: var(--s2); align-items: baseline; }
.watch-tab.on { background: var(--surface-3); color: var(--ink-primary); font-weight: 500; }
.watch-tab-phase { color: var(--ink-muted); }
.watch-body { overflow: auto; min-height: 0; overflow-wrap: anywhere; }
.wflags { list-style: none; margin: 0 0 var(--s3); padding: var(--s2) var(--s3); border-left: 2px solid var(--border-strong); background: var(--surface-2); border-radius: var(--r-sm); display: flex; flex-direction: column; gap: var(--s1); }
.wflags li { font: 11px var(--font-mono); color: var(--ink-secondary); }
.weye { border-left-style: dotted; }
.weye-h { color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; font-size: 10px; }
.watch-stats { display: flex; flex-wrap: wrap; gap: var(--s4); padding-bottom: var(--s3); }
.watch-stats div { display: flex; flex-direction: column; }
.watch-stats b { font: 16px var(--font-mono); font-variant-numeric: tabular-nums; }
.watch-stats span { font-size: 11px; color: var(--ink-muted); }
.watch-cols { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--s4); }
.watch-board, .watch-tx { min-width: 0; }
@media (max-width: 800px) { .watch-cols { grid-template-columns: minmax(0, 1fr); } }
.wq { font: 800 18px/28px var(--font-sans); margin: 0 0 var(--s3); }
.wlink { margin: 0 0 var(--s3); font-size: 14px; color: var(--ink-secondary); }
/* The board as the app draws it (2026-09-29): flat boxes, a step of fill per nesting. */
.wnow { margin-bottom: var(--s4); display: flex; flex-direction: column; gap: var(--s2); }
.wnow h3 { font-size: 16px; }
.wnow p { color: var(--ink-primary); max-width: none; font-size: 18px; line-height: 28px; }
.wargued { background: var(--surface-2); border-radius: var(--r-lg); padding: var(--s4); margin-bottom: var(--s4); box-shadow: 0 0 0 2px var(--rec); display: flex; flex-direction: column; gap: var(--s2); }
.wmark { align-self: flex-start; background: var(--surface-invert); color: var(--ink-on-invert); font-weight: 700; padding: 0 var(--s2); border-radius: var(--r-sm); line-height: 24px; }
.wtopic-line { font-weight: 700; color: var(--ink-primary); font-size: 16px; line-height: 24px; max-width: none; }
.wsub-line { color: var(--ink-secondary); max-width: none; }
.wbig { font: 800 22px/30px var(--font-sans); text-wrap: balance; }
.wevery { font: 800 16px/24px var(--font-sans); margin: var(--s4) 0 var(--s3); }
.wtopic { background: transparent; border-radius: var(--r-lg); padding: var(--s4); margin-bottom: var(--s3); display: flex; flex-direction: column; gap: var(--s3); }
.wtopic.unfiled { background: color-mix(in oklab, var(--warn) 6%, var(--surface-0)); }
.wtopic-head { display: flex; align-items: baseline; gap: var(--s2); }
.wtopic-head h3 { font: 800 18px/26px var(--font-sans); }
.wsum { max-width: none; }
.wsub { background: var(--surface-2); border-radius: var(--r-lg); padding: var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.wsub.inner { background: var(--surface-3); }
.wsub h4 { font: 700 16px/24px var(--font-sans); color: var(--ink-primary); }
.wquestion { font: 800 16px/24px var(--font-sans); color: var(--ink-primary); max-width: none; }
.wmoved { font-size: 14px; font-weight: 600; color: var(--ink-secondary); }
.wcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s3); }
.wcol { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; }
.wpos { background: var(--surface-3); border-radius: var(--r-lg); padding: var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
/* Each answer in its speaker's own colour, as the board draws it (2026-09-29); `--look` is set per column. */
.wcol[style] .wpos { background: color-mix(in oklab, var(--look) 16%, var(--surface-2)); }
.wcol[style] .wpos-who { color: var(--look); }
.wpos-who { font-weight: 700; color: var(--ink-primary); display: flex; gap: var(--s2); align-items: baseline; flex-wrap: wrap; }
.wpos-standing { font-size: 14px; font-weight: 700; color: var(--ink-secondary); text-transform: capitalize; }
.wpos-text { color: var(--ink-primary); max-width: none; font-weight: 600; }
.wwarn { font-size: 14px; font-weight: 600; color: var(--warn); }
.wnone { font-style: italic; color: var(--ink-secondary); }
.wclaims { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.wclaim { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s2); font-size: 14px; align-items: baseline; }
.wclaim-t { font: 14px var(--font-mono); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.wclaim-text { color: var(--ink-primary); }
.wclaim-meta { grid-column: 2; font-size: 14px; color: var(--ink-secondary); }
.wev { grid-column: 2; font-size: 14px; color: var(--ink-secondary); padding-left: var(--s2); }
.watch-tx h3 { font-size: 12px; margin: 0 0 var(--s2); color: var(--ink-secondary); }
.wlines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.wlines li { display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: var(--s2); font-size: 12px; align-items: baseline; }
.wline-t { font: 10px var(--font-mono); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.wline-who { font: 10px var(--font-mono); color: var(--ink-secondary); }

/* --------------------------------------------------------------- lineage */
.lineage { display: flex; gap: var(--s4); overflow-x: auto; padding-bottom: var(--s2); align-items: stretch; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.gen {
  flex: 0 0 auto; min-width: 248px; max-width: 320px; display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s3); border: 1px solid transparent; border-radius: var(--r-lg);
  background: var(--surface-2); position: relative;
  animation: rise 420ms ease-out both;
}
/* The line of descent. A generation that grew from the one before it sits on
   the spine and its connector is solid; one that grew from further back, because
   everything since was thrown away, hangs below the spine on a dashed stub. */
.gen + .gen::before { content: ""; position: absolute; left: calc(var(--s4) * -1); top: var(--s10); width: var(--s4); height: 0; border-top: 1px solid var(--border-strong); }
.gen.from-spine::before { border-top-color: var(--accent-kept); border-top-width: 2px; }
.gen.from-branch::before { border-top-style: dashed; }
.gen.from-branch { margin-top: var(--s4); }
.gen.measuring { border-color: var(--pulse); }
.gen.kept { border-color: color-mix(in oklab, var(--accent-kept) 55%, var(--border-subtle)); }
.gen.reverted { border-color: color-mix(in oklab, var(--accent-reverted) 55%, var(--border-subtle)); }
.gen.stopped .gen-stage, .gen.interrupted .gen-stage { color: var(--ink-muted); }
.gen-head { display: flex; justify-content: space-between; align-items: baseline; }
.gen-n { font: 700 14px var(--font-mono); color: var(--ink-primary); }
.gen-of { color: var(--ink-muted); font-weight: 400; }
.gen-stage { font: 11px var(--font-mono); color: var(--ink-muted); text-transform: uppercase; letter-spacing: .06em; }
.gen.measuring .gen-stage, .gen.proposing .gen-stage { color: var(--pulse); }
.gen.kept .gen-stage { color: var(--ink-kept); }
.gen.reverted .gen-stage { color: var(--ink-reverted); }
.gen-parent { font: 11px var(--font-mono); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cands { display: flex; flex-direction: column; gap: var(--s2); }
.gen-foot { margin-top: auto; display: flex; align-items: baseline; gap: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--border-subtle); }
.gen-agg { font: 700 18px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.gen-agg.pending { color: var(--ink-muted); font-size: 14px; font-weight: 400; }
.gen-delta { font: 12px var(--font-mono); }
.gen-delta.up { color: var(--ink-kept); }
.gen-delta.down { color: var(--ink-reverted); }
.cand { border: 1px solid transparent; border-radius: var(--r-md); padding: var(--s2); background: var(--surface-3); transition: opacity 300ms ease, border-color 300ms ease, background 300ms ease; animation: rise 360ms ease-out both; }
.cand header { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s2); }
.cand-title { font-size: 12px; font-weight: 600; color: var(--ink-primary); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cand-file { font: 10px var(--font-mono); color: var(--ink-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip { font: 9px var(--font-mono); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-muted); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0 4px; flex: none; }
.cand.measuring { border-color: color-mix(in oklab, var(--pulse) 45%, var(--border-subtle)); }
.cand.won { border-color: var(--accent-kept); background: color-mix(in oklab, var(--accent-kept) 8%, var(--surface-3)); }
.cand.lost { opacity: .42; }
.cand footer { display: flex; justify-content: space-between; align-items: baseline; margin-top: var(--s2); }
.cand-stage { font: 10px var(--font-mono); color: var(--ink-muted); text-transform: uppercase; letter-spacing: .05em; }
.cand.won .cand-stage { color: var(--ink-kept); }
.cand-agg { font: 700 14px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.shots { display: flex; flex-direction: column; gap: 2px; margin-top: var(--s2); }
.shot { position: relative; height: 16px; border-radius: var(--r-sm); background: var(--surface-2); overflow: hidden; border: 0; padding: 0; font: inherit; cursor: pointer; width: 100%; display: block; }
.shot:hover { outline: 1px solid var(--border-strong); }
.shot-fill { position: absolute; inset: 0 auto 0 0; background: var(--pulse); transition: width 1.1s linear; }
.shot.judging .shot-fill { background: color-mix(in oklab, var(--pulse) 70%, var(--ink-primary)); animation: shot-breathe 2.4s ease-in-out infinite; }
/* Slow and shallow: a bar half its brightness once a second read as a glitch. */
@keyframes shot-breathe { 50% { opacity: 0.8; } }
.shot.done .shot-fill { background: color-mix(in oklab, var(--accent-kept) 70%, var(--surface-3)); }
.shot.failed .shot-fill, .shot.cut .shot-fill { background: color-mix(in oklab, var(--danger) 60%, var(--surface-3)); }
.shot-n { position: absolute; left: 5px; top: 0; line-height: 16px; font: 10px var(--font-mono); color: var(--ink-secondary); }
.shot-score { position: absolute; right: 5px; top: 0; line-height: 16px; font: 10px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
/* The pass strip under a candidate: the tick's seven passes as ticks that light. */
.passes { display: flex; gap: 2px; margin-top: var(--s2); }
.passes span { flex: 1; height: 4px; border-radius: var(--r-sm); background: var(--surface-2); transition: background-color var(--t-fast); }
.passes span.lit { background: var(--pulse); }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .gen, .cand, .banner { animation: none; } .shot-fill { transition: none; } .shot.judging .shot-fill { animation: none; } }

/* ----------------------------------------------------------------- ingest */
#ingest-view .card { background: transparent; border: 0; border-radius: 0; padding: 0; }
#ingest-view .card + .card { margin-top: var(--s5); padding-top: var(--s5); border-top: 1px solid var(--border-subtle); }
.card h2 { margin-bottom: var(--s3); }
.meta-title { margin: 0 0 var(--s1); font-size: 16px; font-weight: 500; }
.phase { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s3); }
.phase strong { font-weight: 500; }
.phase .pct { font: 500 12px var(--font-mono); color: var(--ink-muted); margin-left: auto; }
.bar { height: 4px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.bar span { display: block; height: 100%; background: var(--pulse); transition: width 0.3s ease; }
.bar.is-indeterminate span { width: 30%; animation: slide 1.4s ease-in-out infinite; }
/* Driven a frame at a time from JS, which does its own easing. */
.bar.is-live span { transition: none; }
.meter { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s3); }
.meter span { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--ink-muted); }
.meter button { margin-left: auto; }
@keyframes slide { 0% { margin-left: -30%; } 100% { margin-left: 100%; } }
.speaker { display: grid; gap: var(--s3); border-top: 1px solid var(--border-subtle); padding: var(--s5) 0; }
.speaker:first-of-type { border-top: 0; padding-top: var(--s2); }
.speaker.is-dropped { opacity: 0.5; }
.speaker .who { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s1); }
.speaker .stats { font: 400 12px var(--font-mono); color: var(--ink-muted); }
.speaker .opens { margin: 0; color: var(--ink-secondary); font-size: 14px; line-height: 20px; font-style: italic; max-width: 70ch; }
.sample { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.sample audio { flex: 1 1 240px; min-width: 0; height: 32px; }
.sample .at { flex: none; height: 32px; padding: 0 var(--s3); font: 500 12px var(--font-mono); white-space: nowrap; }
.sample .at svg { width: 16px; height: 11px; flex: none; }
.card.video .video-body { display: flex; gap: var(--s4); align-items: flex-start; }
.card.video .poster { width: 200px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-md); flex: none; }
.card.video .video-meta { min-width: 0; display: flex; flex-direction: column; gap: var(--s1); }
@media (max-width: 760px) { .card.video .video-body { flex-direction: column; } .card.video .poster { width: 100%; max-width: 320px; } }
.field { display: flex; flex-direction: column; gap: var(--s2); max-width: 520px; }
.field input { width: 100%; }
.form-acts { display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--border-subtle); }
.form-acts .hint { margin-right: auto; }
.speaker-fields { display: flex; flex-direction: column; gap: var(--s2); align-items: stretch; }
.speaker-fields input:not([type="checkbox"]), .speaker-fields select { width: 100%; }
.speaker-fields label { display: flex; align-items: center; gap: var(--s2); font-size: 14px; color: var(--ink-secondary); }
@media (min-width: 700px) {
  .speaker { grid-template-columns: minmax(0, 1fr) 240px; align-items: start; column-gap: var(--s6); }
  .speaker .who, .speaker .opens, .speaker .sample { grid-column: 1; }
  .speaker .speaker-fields { grid-column: 2; grid-row: 1 / span 3; }
}
.chip.is-weak { color: var(--ink-reverted); border-color: var(--accent-reverted); }
.chip.is-merge { color: var(--ink-kept); border-color: var(--accent-kept); }
.actions { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.error { color: var(--ink-danger); }
.done .path, .path { font: 400 12px var(--font-mono); color: var(--ink-kept); }
.stored { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s4); padding: var(--s3) 0; border-top: 1px solid var(--border-subtle); }
.stored:first-of-type { border-top: 0; padding-top: 0; }
.stored .acts { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; justify-content: flex-end; }
.stored .what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.stored .name { font-size: 14px; font-weight: 600; color: var(--ink-primary); }
.stored .meta { color: var(--ink-secondary); font-size: 14px; }
@media (prefers-reduced-motion: reduce) { .bar span { transition: none; } .bar.is-indeterminate span { animation: none; width: 100%; opacity: 0.4; margin-left: 0; } }

/* ------------------------------------------------------------- replay env */
.envpick { display: flex; flex-direction: column; gap: var(--s2); }
.envpick label { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s3); border: 1px solid transparent; border-radius: var(--r-lg); background: var(--surface-2); cursor: pointer; }
.envpick label:hover { border-color: var(--ink-muted); }
.envpick label:has(:checked) { background: var(--surface-3); }
.envpick label:has(:disabled) { cursor: default; opacity: .5; }
.envpick .what { display: flex; flex-direction: column; gap: 2px; }
.envpick .name { font-weight: 600; color: var(--ink-primary); }
.envpick .meta { font: 14px/20px var(--font-mono); color: var(--ink-secondary); }
.toggle svg { width: 16px; height: 16px; flex: none; }
.toggle .off { display: none; }
.toggle[aria-pressed="true"] { background: var(--surface-invert); border-color: var(--surface-invert); color: var(--ink-on-invert); }
.toggle[aria-pressed="true"] .on { display: none; }
.toggle[aria-pressed="true"] .off { display: block; }
.laptop-only { display: flex; flex-direction: column; gap: var(--s3); align-items: flex-start; padding: var(--s6) 0; }
.folder-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }
.folder-row .hint { min-width: 0; }
.replay-now { margin-top: var(--s4); }
/* Go live arrives in the head beside Stop once every speaker holds, and
   leaves when the debate is live (Niko, 2026-10-05: "give it a graceful
   animation"). It rises in on `rise`, with no fill after it, so the dimmed
   and pressed looks still show. Leaving, the transition keeps it drawn
   until it has faded. */
#replay-live { animation: rise 420ms ease-out backwards; }
#replay-live[hidden] { opacity: 0; transform: translateY(6px); transition: opacity var(--t-base), transform var(--t-base), display 180ms allow-discrete; }
@media (prefers-reduced-motion: reduce) { #replay-live { animation: none; } #replay-live[hidden] { transition: none; } }
.replay-now a { color: var(--ink-primary); text-decoration: underline; text-underline-offset: 2px; }

/* ================================================================ canvas */
.topbar {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s8);
  border-bottom: 1px solid var(--border-subtle); background: var(--surface-0);
  position: sticky; top: 0; z-index: 5;
}
.topbar .spacer { flex: 1; }
.topbar .prod { display: flex; align-items: center; gap: var(--s2); min-width: 0; max-width: 40vw; color: var(--ink-muted); font: 12px var(--font-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .prod b { color: var(--ink-secondary); font-weight: 500; }
.topbar .sep { width: 1px; height: 20px; background: var(--border-subtle); }
/* The history the Algorithm row opens into (2026-09-27). */
.version-list { display: flex; flex-direction: column; gap: var(--s1); max-width: 720px; }
.version-row {
  display: grid; grid-template-columns: 44px 48px minmax(0, 1fr) auto; align-items: center; gap: var(--s3);
  width: 100%; height: auto; padding: var(--s2) var(--s3);
  border: 1px solid transparent; border-radius: var(--r-md); background: none;
  text-align: left; font: inherit; font-weight: 400; color: var(--ink-primary);
}
.version-row:hover:not(:disabled) { background: var(--surface-2); border-color: var(--border-subtle); }
.version-row .v { font: 600 12px var(--font-mono); color: var(--ink-primary); }
.version-row .t { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.version-row .t b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.version-row .t span { font: 11px var(--font-mono); color: var(--ink-muted); }
.version-row .marks { display: flex; gap: var(--s1); }
.version-row.current { background: var(--surface-2); }

/* The pipeline canvas, drawn as n8n draws a workflow (canvas.js): a dotted
   ground that moves and grows with what stands on it, square tiles with a
   glyph and a name under each, a port on either side, and wires between
   ports. Measures are canvas.js's: a 64px tile on a 152 by 220 grid, and a
   step as wide as its name may run. */
.canvas-wrap { position: relative; flex: 1; min-height: 560px; overflow: hidden; background: var(--surface-0);
  background-image: radial-gradient(circle, var(--border-strong) 1px, transparent 1.5px); background-size: 24px 24px;
  cursor: grab; user-select: none; }
.canvas-wrap.dragging { cursor: grabbing; }
.canvas { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
.wires { position: absolute; left: 0; top: 0; z-index: 1; pointer-events: none; overflow: visible; }
.wires path.wire { fill: none; stroke: var(--ink-muted); stroke-opacity: 0.6; stroke-width: 2; stroke-linecap: round; transition: stroke var(--t-fast), stroke-opacity var(--t-fast); }
/* A feed, not a step: dotted, as n8n draws what a node is handed. */
.wires path.wire.dashed { stroke-dasharray: 1 7; }
.wires path.wire.hot, .wires path.wire.walked, .wires path.wire.walk { stroke: var(--ink-primary); stroke-opacity: 1; }
.wires path.wire.lit, .wires path.wire.flow { stroke: var(--pulse); stroke-opacity: 1; }
.wires path.wire.flow, .wires path.wire.walk { stroke-dasharray: 8 8; animation: wire-flow 480ms linear infinite; }
@keyframes wire-flow { to { stroke-dashoffset: -16; } }
.wires .dot { fill: var(--pulse); }
.wires .dot.walk { fill: var(--ink-primary); }
/* A group of steps: a labelled frame behind them, as a sticky note is in n8n. */
.fframe {
  position: absolute; padding: 12px; pointer-events: none; white-space: nowrap;
  border: 1px solid var(--border-subtle); border-radius: var(--r-lg);
  background: var(--surface-1);
  font: 600 16px/20px var(--font-sans); color: var(--ink-secondary);
}
.fnode { position: absolute; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 4px; color: var(--ink-primary); cursor: grab; }
.fnode.lifted { z-index: 3; cursor: grabbing; }
/* The tile and its name are one button that opens the step; the padlock under
   them is a second. Set outright: the global button rule would box it. */
.fnode .fopen {
  display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; height: auto; padding: 0;
  background: none; border: 0; border-radius: 0; font: inherit; color: inherit; white-space: normal; cursor: pointer;
}
.fnode .fopen:focus-visible { outline: none; }
.fnode .ftile, .lg-tile {
  position: relative; display: grid; place-items: center; flex: none; width: 64px; height: 64px;
  background: var(--surface-2); border: 2px solid color-mix(in oklab, var(--ink-muted) 50%, var(--surface-2)); color: var(--ink-primary);
  transition: border-color var(--t-fast), background-color var(--t-fast), box-shadow var(--t-fast);
}
.fnode:hover .ftile { border-color: var(--ink-muted); }
.fnode .fopen:focus-visible .ftile { outline: 2px solid var(--focus); outline-offset: 4px; }
/* The step whose panel is open: the light edge and one fill up, as a pressed tile is anywhere. */
.fnode.pressed .ftile { border-color: var(--ink-primary); background: var(--surface-3); }
.fnode.lifted .ftile { box-shadow: var(--shadow-lift); }
/* Where Play a tick is, and where it has been. */
.fnode.walked .ftile, .fnode.demo .ftile { border-color: var(--ink-primary); }
/* Code decides here, not a model: a dashed edge. The board is where it all lands. */
.fnode.k-code .ftile, .fnode.k-gate .ftile, .fnode.k-locked .ftile, .lg-tile.k-code, .lg-tile.k-locked { border-style: dashed; }
.fnode.k-sink .ftile, .lg-tile.k-sink { background: var(--surface-3); border-color: var(--ink-muted); }
/* Nothing to open: the median has no prompt and no settings. */
.fnode.k-locked .fopen { cursor: default; }
.fnode.k-locked .ftile, .lg-tile.k-locked { opacity: 0.7; }
.fnode.k-locked:hover .ftile { border-color: color-mix(in oklab, var(--ink-muted) 50%, var(--surface-2)); }
.fnode.off .ftile { opacity: 0.5; }
.fnode.off .ftitle { color: var(--ink-secondary); }
.fnode .ftitle { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; max-width: 100%; font: 600 14px/18px var(--font-sans); text-align: center; }
/* A wire leaves by the round port and enters by the flat one. Each is centred on the tile's edge, which is drawing, not spacing. */
.fnode .fport { position: absolute; top: 50%; background: var(--surface-0); border: 1.5px solid var(--ink-muted); }
.fnode .fport.in { left: -6px; width: 8px; height: 16px; margin-top: -8px; border-radius: 2px; }
.fnode .fport.out { right: -8px; width: 12px; height: 12px; margin-top: -6px; border-radius: var(--r-full); }
/* A pass is running on this step: an arc circles its tile, in `--pulse`, and the count of shots in it sits on its corner.
   Play a tick circles a step the same way in white, because nothing is running. */
.fnode .fring { position: absolute; inset: -2px; width: 64px; height: 64px; pointer-events: none; opacity: 0; }
:is(.fnode, .lg-draw) .fring :is(path, rect) { fill: none; stroke: var(--ink-primary); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 30 70; }
.fnode.active .fring, .fnode.demo .fring { opacity: 1; }
.fnode.active .fring path, .lg-draw .fring.run rect { stroke: var(--pulse); }
.fnode.active .fring path, .fnode.demo .fring path { animation: ring-run 1.1s linear infinite; }
.fnode.active .ftile { border-color: color-mix(in oklab, var(--pulse) 50%, var(--surface-2)); }
@keyframes ring-run { to { stroke-dashoffset: -100; } }
/* How many of the step's settings are off what ships, on the corner opposite the count of shots. */
:is(.fnode, .lg-draw) .fchanged { position: absolute; top: -8px; left: -8px; min-width: 20px; height: 20px; padding: 0 4px; border-radius: var(--r-sm); background: var(--surface-3); box-shadow: 0 0 0 1px var(--border-strong); color: var(--ink-primary); font: 700 12px/20px var(--font-mono); text-align: center; }
:is(.fnode, .lg-draw) .live { position: absolute; top: -8px; right: -8px; display: none; min-width: 20px; height: 20px; padding: 0 4px; border-radius: var(--r-sm); background: var(--pulse); color: var(--ink-on-invert); font: 700 12px/20px var(--font-mono); text-align: center; }
.fnode.active .live:not(:empty) { display: block; }
@media (prefers-reduced-motion: reduce) {
  .fnode.active .fring path, .fnode.demo .fring path { animation: none; stroke-dasharray: none; }
  .wires path.wire.flow, .wires path.wire.walk { animation: none; stroke-dasharray: none; }
}
/* Under the name. Three lock states, three shapes, and the word beside each: a lock is not a 2px difference. */
.fnode .fmeta { display: flex; align-items: center; justify-content: center; height: 20px; font: 14px/20px var(--font-sans); color: var(--ink-secondary); white-space: nowrap; }
.fnode .flock {
  display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 4px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--ink-secondary); font: 14px/20px var(--font-sans);
  transition: color var(--t-fast), background-color var(--t-fast);
}
.fnode button.flock { cursor: pointer; }
.fnode button.flock:hover { color: var(--ink-primary); background: var(--surface-2); }
.fnode button.flock:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.fnode button.flock:active:not(:disabled) { opacity: 0.75; }
.fnode button.flock:disabled { opacity: 0.45; cursor: default; }
.fnode .flock.closed { color: var(--ink-primary); }
.fnode .flock.bone { width: 64px; padding: 0; }
.fnode .lock { width: 14px; height: 14px; flex: none; }
/* The legend (Niko, 2026-10-22: "a legend ... like a number in the top
   corner"). A white number marks each kind of thing on the canvas: a step's
   kind just right of its count of running calls, a frame's above its top
   right corner, and one wire of each kind at its middle. canvas.js keeps them
   one size on screen through --lgn. The card pinned top right says what each
   number is, beside a drawing in the canvas's own classes on the canvas's own
   ground, and then the marks that carry no number. */
.lgn { display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: var(--r-full); background: var(--surface-invert); color: var(--ink-on-invert); font: 700 12px/1 var(--font-mono); }
.canvas .lgn { position: absolute; z-index: 3; pointer-events: none; transform: scale(var(--lgn, 1)); }
.fnode .lgn { left: 100px; top: -8px; transform-origin: 0 0; }
.fframe .lgn { right: -1px; bottom: calc(100% + 4px); transform-origin: 100% 100%; }
.canvas > .lgn { transform: translate(-50%, -50%) scale(var(--lgn, 1)); }
.canvas-wrap:not(.legend) :is(.canvas .lgn, .legend-card) { display: none; }
#config-legend[aria-pressed="true"] { background: var(--surface-3); border-color: var(--border-strong); }
.legend-card {
  position: absolute; top: var(--s4); right: var(--s4); z-index: 5; width: 336px; max-height: calc(100% - 88px); overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--s3); padding: var(--s3) var(--s4) var(--s4);
  border: 1px solid var(--border-subtle); border-radius: var(--r-lg); background: var(--surface-1); box-shadow: var(--shadow-overlay);
  cursor: default; user-select: text;
}
.legend-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.legend-list { display: flex; flex-direction: column; gap: var(--s1); padding: 0; list-style: none; }
.legend-list + .legend-list { padding-top: var(--s3); border-top: 1px solid var(--border-subtle); }
.legend-list li { display: grid; grid-template-columns: 20px 64px minmax(0, 1fr); align-items: center; gap: var(--s3); font: 14px/20px var(--font-sans); color: var(--ink-secondary); }
.legend-list .lg-draw { grid-column: 2; display: flex; align-items: center; justify-content: center; gap: var(--s1); height: 32px; border-radius: var(--r-sm); background: var(--surface-0); }
.lg-tile { width: 28px; height: 28px; border-radius: 6px; }
.lg-draw .fring { position: absolute; inset: -2px; width: calc(100% + 4px); height: calc(100% + 4px); }
.lg-draw .live { display: block; }
.lg-draw .wires { position: static; }
.lg-frame { width: 48px; height: 28px; border: 1px solid var(--border-subtle); border-radius: 6px; background: var(--surface-1); }
.lg-locks { color: var(--ink-secondary); }
.lg-locks .lock { width: 14px; height: 14px; }
.lg-off { font: 600 14px/20px var(--font-sans); color: var(--ink-secondary); }
/* The canvas's own controls, where n8n keeps them: zoom at the bottom left, the run in the middle. */
.canvas-tools { position: absolute; left: var(--s4); bottom: var(--s4); display: flex; gap: var(--s1); z-index: 4; padding: var(--s1); border-radius: var(--r-lg); background: var(--surface-2); box-shadow: var(--shadow-overlay); }
.canvas-tools button.icon { width: 36px; height: 36px; padding: 0; background: none; color: var(--ink-primary); }
.canvas-tools button.icon:hover:not(:disabled) { background: var(--surface-3); }
.canvas-play { position: absolute; left: 50%; bottom: var(--s4); z-index: 4; transform: translateX(-50%); display: inline-flex; align-items: center; gap: var(--s2); }
.canvas-play svg { width: 16px; height: 16px; flex: none; }
.canvas-play.going .go, .canvas-play:not(.going) .halt { display: none; }
.canvas-hint { position: absolute; right: var(--s4); bottom: var(--s4); z-index: 4; padding: var(--s2) var(--s3); border-radius: var(--r-md); background: var(--surface-0); font: 14px/20px var(--font-sans); color: var(--ink-secondary); pointer-events: none; }
/* Under this the sentence would run into Play a tick; the controls say enough. */
@media (max-width: 1480px) { .canvas-hint { display: none; } }
/* The last request and reply a step made, under its settings, from the trace. */
/* The autopilot's agents strip: a chip per agent, lit while it runs. */
.agents-now { display: flex; flex-wrap: wrap; gap: 8px; }
.agents-now .agent { display: flex; flex-direction: column; gap: 2px; min-width: 112px; padding: 8px 12px; border-radius: var(--r-lg); background: var(--surface-2); border: 1px solid transparent; transition: border-color 120ms ease-out; }
.agents-now .agent b { font-size: 12px; font-weight: 600; color: var(--ink-secondary); }
.agents-now .agent .last { font-family: var(--font-mono); font-size: 11px; color: var(--ink-muted); }
.agents-now .agent.lit { border-color: var(--pulse); }
.agents-now .agent.lit b { color: var(--ink-primary); }
/* App Config: a group is a step with its glyph and its sentence; a row says what it does. */
.settings tr.grp td { padding-top: 20px; }
.settings .gmark { display: inline-flex; width: 16px; height: 16px; margin-right: 8px; vertical-align: -3px; color: var(--ink-secondary); }
.settings .gmark svg { width: 16px; height: 16px; }
.settings .gwhat { display: block; margin: var(--s1) 0 0 24px; color: var(--ink-secondary); }
.settings .glock { margin-left: 8px; color: var(--ink-muted); font-family: var(--font-mono); font-size: 11px; }
.settings td.name .sentence { margin: var(--s1) 0 0; max-width: 60ch; font: 14px/20px var(--font-sans); color: var(--ink-secondary); }
.fcall { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
.fcall .eyebrow { display: flex; align-items: center; gap: 8px; }
.fcall .eyebrow b { color: var(--ink-primary); font-weight: 600; }
.fcall .eyebrow .cost { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--ink-muted); }
.fcall details { border-radius: var(--r-lg); background: var(--surface-2); }
.fcall summary { cursor: pointer; padding: 8px 12px; font-size: 12px; color: var(--ink-secondary); list-style: none; }
.fcall summary::-webkit-details-marker { display: none; }
.fcall pre { margin: 0; padding: 0 12px 12px; max-height: 360px; overflow: auto; white-space: pre-wrap; word-break: break-word; font-family: var(--font-mono); font-size: 11px; line-height: 16px; color: var(--ink-secondary); }
.fcall .none { font-size: 12px; color: var(--ink-muted); }


/* App Config: every setting on one page, its own tab. */
/* Its areas, as sub-tabs (2026-09-23). */
.cfg-areas { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s6); }
.cfg-area-count { font: 400 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-muted); }
/* Where the Lab's search lands: lit, then fading back. */
@keyframes lab-lit { from { background-color: color-mix(in oklab, var(--focus) 24%, transparent); outline-color: var(--focus); } to { background-color: transparent; outline-color: transparent; } }
/* A table row cannot hold an outline or a shadow, so its cells take the light. */
.lab-lit:not(tr), tr.lab-lit > td { animation: lab-lit 3s ease-out 1; }
.lab-lit:not(tr) { outline: 2px solid transparent; outline-offset: 2px; border-radius: var(--r-md); }
@media (prefers-reduced-motion: reduce) { .lab-lit:not(tr), tr.lab-lit > td { animation: none; background-color: color-mix(in oklab, var(--focus) 16%, transparent); } }
.cfgbar { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: var(--s3); margin-top: var(--s2);
  height: 60px; padding: var(--s3) 0; box-sizing: border-box;
  background: var(--surface-0); border-bottom: 1px solid var(--border-subtle); }
.cfgbar input { width: min(320px, 100%); }
.cfgbar .spacer { flex: 1; }
table.settings { width: 100%; border-collapse: collapse; }
/* Below the sticky bar and the column heads when a jump brings a row to the top. */
table.settings tr { scroll-margin-top: 112px; }
table.settings th { position: sticky; top: 60px; z-index: 1; background: var(--surface-0); text-align: left; padding: var(--s3) var(--s3); border-bottom: 1px solid var(--border-subtle); }
table.settings td { padding: var(--s3); border-bottom: 1px solid var(--border-subtle); vertical-align: middle; }
/* Each step is a section with a real heading (2026-09-23: "clear sections and
   headings and not a bunch of small text"). */
table.settings tr.grp td { padding: var(--s8) var(--s3) var(--s3); border-bottom: 1px solid var(--border-strong); }
table.settings tr.grp .gname { font: 600 17px/24px var(--font-sans); color: var(--ink-primary); }
table.settings tr.grp .gmark { width: 16px; height: 16px; margin-right: var(--s2); vertical-align: -2px; color: var(--ink-primary); }
table.settings tr.grp .gwhat { font: 14px/20px var(--font-sans); }
table.settings tr.grp .glock { margin-left: var(--s2); font: 500 11px/16px var(--font-mono); color: var(--ink-secondary); text-transform: uppercase; letter-spacing: 0.06em; }
table.settings tr.setting:hover td { background: var(--surface-1); }
table.settings tr.setting.open td { background: var(--surface-1); border-bottom-color: transparent; }
table.settings td.name { width: 30%; }
table.settings td.name .rowopen { display: block; width: 100%; height: auto; padding: 0; border: 0; background: none; text-align: left; color: inherit; font: inherit; cursor: pointer; }
table.settings td.name .rowopen b { display: block; font-weight: 600; font-size: 16px; line-height: 20px; color: var(--ink-primary); }
table.settings td.name .rowopen .key { display: block; margin-top: 2px; font: 11px/16px var(--font-mono); color: var(--ink-muted); word-break: break-all; }
table.settings td.name .rowopen:hover b { text-decoration: underline; text-underline-offset: 2px; }
table.settings td.name .rowopen:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }
table.settings td.stage { width: 22%; }
table.settings td.stage input:not([type="checkbox"]), table.settings td.stage select { height: 36px; width: 100%; max-width: 240px; font-size: 14px; }
table.settings td.stage button.quiet { font: 14px/20px var(--font-mono); text-decoration: none; }
table.settings td.stage button.quiet:hover:not(:disabled) { text-decoration: underline; text-underline-offset: 2px; }
table.settings td.prod { width: 20%; max-width: 28ch; font: 14px/20px var(--font-mono); color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.settings td.when { width: 12%; font: 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The tags sit side by side, never stacked (Niko, 2026-09-23). */
table.settings td.marks { text-align: right; white-space: nowrap; }
table.settings .ai { display: inline-block; margin-left: var(--s2); font: 500 9px/14px var(--font-mono); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0 4px; }
table.settings tr.dirty td.stage { box-shadow: inset 2px 0 var(--ink-primary); }
/* A row opens into itself, with what the row does not say: what moving the
   setting does, the editor of one too long for a cell, and its buttons. */
table.settings tr.editor > td { padding: 0 var(--s3) var(--s5); background: var(--surface-1); }
table.settings tr.editor .cfgfield { max-width: 760px; padding-top: var(--s3); }
table.settings tr.editor .rowfoot { display: flex; gap: var(--s4); padding-top: var(--s4); }
table.settings tr.editor textarea { width: 100%; }

/* App Config, clearer (Niko, 2026-09-23: "easier to use with buttons and not
   all links ... make the text a little bigger ... use some color"). */
table.settings tr.grp .gname { font-size: 18px; line-height: 28px; }
table.settings td.name .rowopen b { font: 600 16px/24px var(--font-sans); }
table.settings td.name .rowopen .key { font-size: 12px; }
table.settings td.name .sentence { max-width: 64ch; font: 14px/22px var(--font-sans); color: var(--ink-secondary); }
table.settings td.stage input:not([type="checkbox"]), table.settings td.stage select { height: 40px; max-width: 260px; font-size: 16px; }
table.settings td.stage .cfg-val { display: block; max-width: 240px; margin-bottom: var(--s2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 14px/20px var(--font-mono); color: var(--ink-secondary); }
table.settings td.prod { font-size: 14px; color: var(--ink-secondary); }
table.settings td.prod.behind { color: var(--warn); }
table.settings td.prod { white-space: normal; }
table.settings td.prod .prod-val { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.settings td.prod button { margin-top: var(--s2); }
table.settings tr.editor .rowfoot { gap: var(--s2); }
table.settings .mark { display: inline-flex; align-items: center; height: 24px; margin: var(--s1) 0 var(--s1) var(--s2); padding: 0 var(--s2); border: 0; border-radius: var(--r-md); background: var(--surface-3); color: var(--ink-secondary); font: 600 14px/20px var(--font-sans); text-transform: none; letter-spacing: 0; white-space: nowrap; }
table.settings td.marks button { margin: var(--s1) 0 var(--s1) var(--s2); vertical-align: middle; }
table.settings .mark.behind { background: color-mix(in oklab, var(--warn) 14%, transparent); color: var(--warn); }
table.settings .mark.ai { background: color-mix(in oklab, var(--cfg-ai) 14%, transparent); color: var(--cfg-ai); }

/* The node panel: slides in from the right, over the canvas. */
.fpanel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(460px, 100%); z-index: 6;
  display: flex; flex-direction: column;
  background: var(--surface-1); box-shadow: var(--shadow-overlay);
  transform: translateX(100%); transition: transform var(--t-base);
}
.fpanel.open { transform: none; }
.fpanel-head { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s4) var(--s5); border-bottom: 1px solid var(--border-subtle); }
.fpanel-head .titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fpanel-head .fwhat { color: var(--ink-secondary); }
.fpanel-body { flex: 1; overflow-y: auto; padding: var(--s4) var(--s5) var(--s8); display: flex; flex-direction: column; gap: var(--s5); scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.fpanel .fdetail { color: var(--ink-secondary); }
.fpanel .freads { font: 11px var(--font-mono); color: var(--ink-muted); }
.fpanel .lockbox { display: flex; align-items: center; gap: var(--s3); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.fpanel .lockbox .lock { width: 16px; height: 16px; flex: none; color: var(--ink-primary); }
.fpanel .lockbox .what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fpanel .lockbox .what b { font-weight: 500; }
.fpanel .lockbox .what span { color: var(--ink-muted); font-size: 12px; }
.fpanel .cfgfield .stamp { display: flex; align-items: baseline; gap: var(--s3); margin: -4px 0 0; font: 11px/16px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.fpanel .cfgfield .stamp button.quiet { font: 11px/16px var(--font-mono); }
.history { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s4); }
.hrow { display: grid; grid-template-columns: 88px 168px minmax(0, 1fr); align-items: baseline; gap: var(--s3); padding: var(--s2) 0; border-top: 1px solid var(--border-subtle); }
.hrow:first-child { border-top: 0; }
.hwhen { font-size: 11px; color: var(--ink-secondary); }
.hsource { font: 11px/16px var(--font-mono); color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; }
.hval { min-width: 0; font: 12px/16px var(--font-mono); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.hval .del { color: var(--ink-muted); text-decoration: line-through; }
.hval .add { color: var(--ink-primary); }
.fpanel .keys { font: 10px var(--font-mono); color: var(--ink-muted); word-break: break-all; padding-top: var(--s4); border-top: 1px solid var(--border-subtle); }
.cfgfield { display: flex; flex-direction: column; gap: var(--s2); }
.cfghead { display: flex; align-items: baseline; gap: var(--s2); }
.cfghead label { font-weight: 500; color: var(--ink-primary); flex: 1; }
.cfghead .ai { font: 500 9px/14px var(--font-mono); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0 4px; }
.cfgfield .help { display: block; width: auto; height: auto; border: 0; border-radius: 0; font: 14px/22px var(--font-sans); color: var(--ink-secondary); justify-content: flex-start; cursor: default; }
.cfgfield .moves { font: 14px/20px var(--font-sans); color: var(--ink-secondary); }
.cfgfield textarea { min-height: 200px; }
.cfgfield input[type="text"], .cfgfield input[type="number"], .cfgfield select { width: 100%; }
.cfgfield input[type="number"] { max-width: 160px; }
.cfgfield .toggle-row { display: flex; align-items: center; gap: var(--s2); }
.cfgfoot { display: flex; align-items: center; gap: var(--s3); }
.cfgdiff { margin: 0; font: 11px/16px var(--font-mono); white-space: pre-wrap; max-height: 200px; overflow-y: auto; border-left: 2px solid var(--border-subtle); padding-left: var(--s2); }
.cfgdiff .add { display: block; color: var(--ink-primary); }
.cfgdiff .del { display: block; color: var(--ink-muted); text-decoration: line-through; }
.cfgdiff:empty { display: none; }
details.shipped > summary { cursor: pointer; color: var(--ink-muted); font-size: 12px; }
details.shipped pre { margin-top: var(--s2); max-height: 220px; overflow: auto; font: 11px/16px var(--font-mono); white-space: pre-wrap; color: var(--ink-secondary); border-left: 2px solid var(--border-subtle); padding-left: var(--s2); }
.cfgplan { display: flex; flex-direction: column; gap: var(--s2); }
.cfgplanrow { display: grid; grid-template-columns: minmax(0, 1fr) 120px; align-items: center; gap: var(--s3); font-size: 12px; color: var(--ink-secondary); }
.cfgplanrow input[type="checkbox"] { justify-self: start; }

/* The Autopilot's Algorithms card: a row a run, what it produced and its download. */
.alg { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
.alg + .alg { border-top: 1px solid var(--border-subtle); }
.alg-what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s1); }
.alg-what b, .alg-what .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alg-what b { font-weight: 500; }
.alg-what b .mono { margin-right: var(--s2); }

/* Version detail sheet. */
.vhead { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.vhead .v { font: 600 16px var(--font-mono); }
.vdesc { white-space: pre-wrap; color: var(--ink-secondary); margin-top: var(--s3); max-width: none; }
.vlog { margin-top: var(--s4); }
.vlog .vdesc { margin-top: var(--s2); }
.vscores { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--s2); margin-top: var(--s4); }
.vscores div { display: flex; flex-direction: column; gap: 2px; padding: var(--s2) var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.vscores b { font: 600 14px var(--font-mono); font-variant-numeric: tabular-nums; }
.vscores span { font-size: 11px; color: var(--ink-muted); }
.vchanges { margin-top: var(--s4); display: flex; flex-direction: column; gap: var(--s2); }
.vchange { display: flex; flex-direction: column; gap: 2px; padding: var(--s2) 0; border-top: 1px solid var(--border-subtle); }
.vchange b { font-weight: 500; }
.vchange .diff { font: 11px/16px var(--font-mono); color: var(--ink-muted); overflow-wrap: anywhere; }
.vchange .diff .del { text-decoration: line-through; margin-right: var(--s2); }
.vchange .diff .add { color: var(--ink-primary); }

/* Ingest, deployed: a file off this computer instead of a link. */
.filepick { display: flex; flex-direction: column; gap: var(--s2); }
.filepick input[type="file"] { font: 14px var(--font-sans); color: var(--ink-secondary); }
.filepick input[type="file"]::file-selector-button {
  height: 32px; margin-right: var(--s3); padding: 0 var(--s4);
  border: 1px solid transparent; border-radius: var(--r-lg);
  background: var(--surface-2); color: var(--ink-primary); font: 500 14px var(--font-sans); cursor: pointer;
  transition: border-color var(--t-fast), background-color var(--t-fast);
}
.filepick input[type="file"]::file-selector-button:hover { border-color: var(--ink-muted); }
.filepick input[type="file"]::file-selector-button:active { opacity: 0.75; }
.filepick input[type="file"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }

/* ----------------------------------------------------------- verify users */
/* The reviewer's queue and inspector (verify.js). Achromatic like all chrome;
   the one colour is ink-danger on a flagged link, which is wrong in the same
   sense an error is, and is the one thing on the page a reviewer must not miss. */
.verify-line { margin-top: var(--s4); }
.vscroll { overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
/* Fixed columns, so Pending and Decided line up as one list read in two parts. */
.verify-q { table-layout: fixed; min-width: 880px; }
.verify-q th:nth-child(1) { width: 19%; }
.verify-q th:nth-child(2) { width: 17%; }
.verify-q th:nth-child(3), .verify-q th:nth-child(5) { width: 13%; }
.verify-q th:nth-child(4), .verify-q th:nth-child(8) { width: 10%; }
.verify-q th:nth-child(6), .verify-q th:nth-child(7) { width: 9%; }
.verify-q td { overflow-wrap: anywhere; }
.verify-q td > span { white-space: nowrap; }
.verify-q tbody tr { cursor: pointer; }
.verify-q tbody td { border-top: 1px solid var(--border-subtle); transition: background-color var(--t-fast); }
.verify-q tbody tr:hover td { background: var(--surface-2); }
.verify-q tbody tr:active td { background: var(--surface-3); }
.verify-q .rowopen { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; height: auto; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; white-space: normal; }
.verify-q .rowopen b { font-weight: 500; color: var(--ink-primary); }
.verify-q tr:hover .rowopen b { text-decoration: underline; text-underline-offset: 2px; }
.verify-q .rowopen:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }
.vsub { display: block; font: 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-secondary); }
.vquiet { color: var(--ink-muted); }
.vflag { color: var(--ink-danger); }
.pre { white-space: pre-line; }

dialog.verify { padding: var(--s6); gap: var(--s4); }
dialog.verify .watch-sub { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
dialog.verify a:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-radius: var(--r-sm); }
.vwho { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s2); }
.vwho p { max-width: none; }
.vtags { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); }
.vmain { display: flex; flex-direction: column; gap: var(--s8); min-width: 0; }
.vside { align-self: start; position: sticky; top: 0; min-width: 0; }
.vsec { display: flex; flex-direction: column; gap: var(--s3); }
.vsec-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3); padding-bottom: var(--s2); border-bottom: 1px solid var(--border-subtle); }
.vsec-head h3, .vdecide h3 { font-size: 16px; line-height: 20px; }
.vsec-head button { margin-left: auto; }
/* The legal line on anything a model wrote: the app's AiLabel, property for property. Never smaller, never below the fold of its heading. */
/* The app's AiLabel (ai-label.tsx), drawn from the same numbers: the legal label reads the same on both surfaces. */
.ailabel { display: inline-block; padding: var(--s1) var(--s2); border: 1px solid var(--border-strong); border-radius: var(--r-sm); font: 400 11px/16px var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-secondary); }
.vlinks, .vdocs { list-style: none; padding: 0; }
.vlinks { display: flex; flex-direction: column; gap: var(--s2); }
.vlinks li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3); font: 12px/16px var(--font-mono); color: var(--ink-secondary); }
.vlinks li > :first-child { min-width: 0; overflow-wrap: anywhere; }
.vword { font: 11px/16px var(--font-mono); color: var(--ink-muted); }
.vword.vflag { color: var(--ink-danger); }
.vdocs { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--s3); }
.vdoc { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.vdoc-name { color: var(--ink-primary); }
.vdoc-act { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); }
/* A document holds its box from the start, so the image landing moves nothing. */
.vwait { height: 320px; background-color: var(--surface-3); }
.vthumb { display: block; width: 100%; height: auto; padding: 0; background: var(--surface-3); overflow: hidden; cursor: zoom-in; }
.vthumb img { display: block; width: 100%; height: 320px; object-fit: contain; }
.vzoom { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: var(--s3); }
.vzoom-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.vzoom img { display: block; max-width: 100%; margin: 0 auto; }
.vreport { display: flex; flex-direction: column; gap: var(--s4); }
.vscore { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s4); }
.vscore b { font: 600 28px/32px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.vscore b span { font-size: 14px; font-weight: 400; color: var(--ink-muted); }
.vscore p { flex: 1; min-width: 24ch; }
.vcats { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--s2); }
.vcats > div { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.vcats dt { font: 11px/16px var(--font-mono); color: var(--ink-muted); }
.vcats dd { font-size: 12px; line-height: 16px; color: var(--ink-secondary); }
.vcats dd.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 16px; line-height: 20px; color: var(--ink-primary); }
.vgroup { display: flex; flex-direction: column; gap: var(--s1); }
.vlist { display: flex; flex-direction: column; gap: var(--s1); padding-left: var(--s5); color: var(--ink-secondary); }
.vdecide { display: flex; flex-direction: column; gap: var(--s4); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); }
.vfield { display: flex; flex-direction: column; gap: var(--s2); }
.vfield input, .vfield textarea { width: 100%; }
.vdecide input, .vdecide textarea { background-color: var(--surface-3); }
.vfield input { font-family: var(--font-mono); }
.vfield textarea { min-height: 96px; font: 14px/20px var(--font-sans); }
.vfield input[aria-invalid="true"] { border-color: var(--danger); }
.vacts { display: flex; flex-wrap: wrap; gap: var(--s2); padding-top: var(--s4); border-top: 1px solid var(--border-subtle); }
.vsaid { color: var(--ink-primary); }

/* ---------------------------------------------------------------- markets */
/* The prediction markets tab (markets.js). Flat and achromatic: the card is
   surface-1, a market inside it surface-2, and the only outline is hover or
   focus on something clickable. A price is a number, not a verdict, so it
   carries no hue; movement is the app's `--color-trend-*` and stays there. */
.markets-line { margin-top: var(--s4); }
.markets-find { display: flex; gap: var(--s2); }
.markets-find input { flex: 1; min-width: 0; }
.markets-rows { list-style: none; display: flex; flex-direction: column; gap: var(--s2); padding: 0; max-height: 420px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.markets-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4);
  padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2);
}
.markets-what { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.markets-what b { font-weight: 500; color: var(--ink-primary); overflow-wrap: anywhere; }
.markets-meta { font: 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-secondary); overflow-wrap: anywhere; }
.markets-act { display: flex; align-items: center; gap: var(--s3); flex-shrink: 0; }
.markets-price { font: 500 16px/24px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
/* Topics (0134, Niko 2026-09-23): a question with its outcomes under it, and
   The suggested topics on shelves, surest first. */
.mtopics { display: flex; flex-direction: column; gap: var(--s4); max-height: 560px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.mtopics .markets-rows { max-height: none; overflow: visible; }
.mtopic { display: flex; flex-direction: column; gap: var(--s2); }
.mtopic-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.mtopic-head b { flex: 1 1 240px; min-width: 0; font: 600 16px/24px var(--font-sans); color: var(--ink-primary); overflow-wrap: anywhere; }
.mchip { display: inline-flex; align-items: center; height: 24px; padding: 0 var(--s2); border-radius: var(--r-md); background: var(--surface-3); color: var(--ink-secondary); font: 600 14px/20px var(--font-sans); white-space: nowrap; }
.mchip.count { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.mchip.ok { color: var(--ok); background: color-mix(in oklab, var(--ok) 14%, transparent); }
.mchip.warn { color: var(--warn); background: color-mix(in oklab, var(--warn) 14%, transparent); }
.mline { display: flex; flex-wrap: wrap; gap: var(--s1); }
.mscan { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: var(--s4); }
.mscan-head { display: flex; align-items: baseline; gap: var(--s3); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.mscan-head b { margin-left: auto; font: 600 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); white-space: nowrap; }
.mscan-track { height: 8px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.mscan-fill { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--ink-muted); transition: width var(--t-base); }
.mscan.running .mscan-fill { background: var(--pulse); }
.mscan.failed .mscan-head span { color: var(--bad); }
.markets-row button.primary:disabled { background: var(--surface-3); border-color: var(--surface-3); color: var(--ink-secondary); }
.mshelves { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: var(--s4); }
.mshelf { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; }
.mshelf h3 { display: flex; align-items: center; gap: var(--s2); margin: 0; font: 600 16px/24px var(--font-sans); color: var(--ink-primary); }
/* Thirteen numbers, each with what it is and what moving it does. */
@media (max-width: 700px) { .markets-row { flex-direction: column; } .markets-act { align-self: flex-end; } }
/* The markets' pictures (0195): a market's square beside its words, Commons'
   files to pick from, the two crops being approved, and the library. */
.mpic-thumb { flex-shrink: 0; border-radius: var(--r-md); object-fit: cover; background: var(--surface-2); }
.mpic-thumb.none { border: 1px dashed var(--border-strong); background: none; }
.markets-row:has(> .mpic-thumb) { align-items: center; }
.mpic-pick { height: 32px; max-width: 280px; font-size: 14px; }
.mpic-grid { list-style: none; padding: 0; margin: var(--s4) 0 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); gap: var(--s3); }
.mpic-card { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s2); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.mpic-card img { width: 100%; height: 120px; object-fit: cover; border-radius: var(--r-md); background: var(--surface-3); }
.mpic-card img.none { visibility: hidden; }
.mpic-card b { font-weight: 500; color: var(--ink-primary); overflow-wrap: anywhere; }
.mpic-card button { margin-top: auto; }
.mpic-approve { display: flex; flex-direction: column; gap: var(--s3); margin-top: var(--s4); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); }
.mpic-crops { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: flex-end; }
.mpic-crop { border-radius: var(--r-md); background: var(--surface-3); }
.mpic-fields { display: flex; flex-wrap: wrap; gap: var(--s2); }
.mpic-fields input { flex: 1 1 200px; min-width: 0; }
.mpic-library-head { margin: var(--s6) 0 var(--s3); font: 600 16px/24px var(--font-sans); color: var(--ink-primary); }


/* ------------------------------------------------------------------ log
   One line per thing the runner said: the time, where it came from, and its
   own words. Mono, because the lines are full of ids and numbers. */
/* The Activity log (2026-09-23): every part of the app, coloured by where a
   line came from and how serious it is. */
.log-filters { margin-bottom: var(--s3); }
/* One row of filters (Niko, 2026-09-23: "too many pills"): dropdowns, a
   select for the window, two searches and saving. */
.log-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.log-bar select, .log-bar input[type="search"], .log-drop > summary { height: 36px; font-size: 14px; }
.log-bar input[type="search"] { flex: 1 1 120px; width: auto; min-width: 0; max-width: 240px; }
.log-bar select.log-view { width: 152px; }
.log-bar select.log-since { width: 128px; }
.log-bar-acts { display: inline-flex; gap: var(--s2); margin-left: auto; }
.log-drop { position: relative; }
.log-drop > summary { display: inline-flex; align-items: center; gap: var(--s1); padding: 0 var(--s3); border: 1px solid transparent; border-radius: var(--r-lg); background: var(--surface-2); color: var(--ink-secondary); list-style: none; cursor: pointer; white-space: nowrap; }
.log-drop > summary::-webkit-details-marker { display: none; }
.log-drop > summary::after { content: "▾"; margin-left: var(--s1); color: var(--ink-muted); }
.log-drop > summary b { font-weight: 600; color: var(--ink-primary); }
.log-drop > summary:hover { border-color: var(--ink-muted); }
.log-drop > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.log-drop[open] > summary { border-color: var(--ink-muted); background: var(--surface-3); }
.log-drop-panel { position: absolute; top: calc(100% + var(--s1)); left: 0; z-index: 20; display: flex; flex-direction: column; gap: var(--s1); min-width: 220px; padding: var(--s2); border-radius: var(--r-lg); background: var(--surface-2); box-shadow: var(--shadow-overlay); }
.log-tick { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) var(--s2); border-radius: var(--r-md); font-size: 14px; line-height: 20px; color: var(--ink-primary); cursor: pointer; }
.log-tick:hover { background: var(--surface-3); }
.log-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--src, var(--ink-muted)); }
.log-drop-acts { display: flex; gap: var(--s2); padding-top: var(--s2); margin-top: var(--s1); border-top: 1px solid var(--border-subtle); }
@media (max-width: 860px) { .log-bar input[type="search"] { width: 100%; } .log-bar-acts { margin-left: 0; } }
/* One hue per part of the app, meaning only where a line came from. */
.src.lab, .log-src.lab { --src: var(--log-lab); }
.src.command, .log-src.command { --src: var(--log-command); }
.src.accounts, .log-src.accounts { --src: var(--log-accounts); }
.src.debates, .log-src.debates { --src: var(--log-debates); }
.src.viewers, .log-src.viewers { --src: var(--log-viewers); }
.src.moderation, .log-src.moderation { --src: var(--log-moderation); }
.src.money, .log-src.money { --src: var(--log-money); }
.src.verification, .log-src.verification { --src: var(--log-verification); }
.src.errors, .log-src.errors { --src: var(--bad); }
.src.ledger, .log-src.ledger { --src: var(--ink-muted); }
.lvl.info { --src: var(--ink-muted); }
.lvl.warn { --src: var(--warn); }
.lvl.error { --src: var(--bad); }
.log-lines {
  display: flex; flex-direction: column;
  max-height: 640px; overflow-y: auto; margin: 0; padding: var(--s2) 0;
  border-radius: var(--r-lg); background: var(--surface-2); list-style: none;
  font-size: 14px;
}
.log-line { display: grid; grid-template-columns: 124px 152px 8px minmax(0, 1fr) auto; gap: var(--s3); align-items: baseline; padding: var(--s1) var(--s3); border-left: 2px solid transparent; }
.log-line:hover { background: var(--surface-3); }
.log-line.warn { border-left-color: var(--warn); background: color-mix(in oklab, var(--warn) 5%, transparent); }
.log-line.error { border-left-color: var(--bad); background: color-mix(in oklab, var(--bad) 8%, transparent); }
.log-at { font: 12px/20px var(--font-mono); color: var(--ink-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.log-day { color: var(--ink-muted); opacity: 0.7; }
.log-src { font: 600 11px/20px var(--font-mono); color: var(--src, var(--ink-secondary)); text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.log-lvl { width: 8px; height: 8px; border-radius: 50%; align-self: center; background: var(--ink-muted); opacity: 0.5; }
.log-lvl.warn { background: var(--warn); opacity: 1; }
.log-lvl.error { background: var(--bad); opacity: 1; }
.log-text { font: 14px/20px var(--font-mono); color: var(--ink-primary); overflow-wrap: anywhere; }
.log-line.error .log-text { color: var(--ink-danger); }
.log-links { display: flex; gap: var(--s2); white-space: nowrap; }
.log-who, .log-debate { height: 20px; padding: 0 var(--s1); border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink-secondary); font: 12px/20px var(--font-mono); cursor: pointer; }
.log-who:hover, .log-debate:hover { background: var(--surface-1); color: var(--ink-primary); }
.log-none, .log-more { padding: var(--s3); color: var(--ink-muted); }
/* A phone keeps the colour: the time, source and level on one row, the line under them. */
@media (max-width: 860px) {
  .log-line { grid-template-columns: auto minmax(0, 1fr) 8px; row-gap: var(--s1); }
  .log-text, .log-links { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------- rewards */
@font-face { font-family: "Special Elite"; src: url("./fonts/SpecialElite-400.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
/* The inks the cosmetics block names, in this surface's tokens. A preview's
   name wears Contributor's gold, the rank of the badge it stands beside. */
:root {
  --rw-shine: var(--ink-primary);
  --rw-quiet: var(--ink-secondary);
  --rw-ghost: var(--ink-muted);
  --rw-deep: var(--surface-0);
  --rw-paper: var(--surface-3);
  --rw-type: "Special Elite", var(--font-mono);
  --rw-rank: #dcae40;
}
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.rw-name { color: var(--rw-rank); font-weight: 600; white-space: nowrap; }
.rw-rank { display: block; width: 100%; height: 100%; object-fit: contain; }
.rw-badge-plain { display: inline-block; flex-shrink: 0; }

/* The studio: a kind, its templates as live cards, then the editor beside
   the reward drawn where it will be worn. */
.rw-kinds { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s4) 0; }
.rw-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: var(--s3); }
.rw-card { display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; gap: var(--s2); min-width: 0; height: auto; padding: var(--s3); white-space: normal; border: 1px solid transparent; border-radius: var(--r-lg); background: var(--surface-2); color: var(--ink-primary); text-align: left; font: inherit; cursor: pointer; }
.rw-card:hover { border-color: var(--border-strong); background: var(--surface-3); }
.rw-card[aria-pressed="true"] { border-color: var(--ink-muted); }
.rw-card b { font: 600 14px/20px var(--font-sans); }
.rw-gallery, .rw-card .rw-stage { min-width: 0; }
.rw-card span.hint-line { font-size: 12px; line-height: 16px; color: var(--ink-secondary); }
#rewards-studio { margin-top: var(--s6); }
.rw-stage { display: grid; place-items: center; height: 80px; padding: 0 var(--s2); border-radius: var(--r-lg); background: var(--surface-1); overflow: hidden; font-size: 20px; }
.rw-stage:has(> .rw-banner) { padding: 0; }
.rw-stage .rw-banner { width: 100%; height: 100%; }

.rw-editor { display: grid; grid-template-columns: minmax(260px, 2fr) minmax(0, 3fr); gap: var(--s6); margin-top: var(--s6); padding-top: var(--s6); border-top: 1px solid var(--border-subtle); }
@media (max-width: 900px) { .rw-editor { grid-template-columns: minmax(0, 1fr); } }
.rw-fields { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }
.rw-fields h3 { margin: 0; font: 600 16px/24px var(--font-sans); }
.rw-param { display: flex; flex-direction: column; gap: var(--s2); }
.rw-param-label { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.rw-seg { display: flex; flex-wrap: wrap; gap: var(--s1); }
.rw-seg button { min-width: 36px; }
.rw-swatches { display: flex; flex-wrap: wrap; gap: var(--s2); }
.rw-swatch { width: 28px; height: 28px; padding: 0; border-radius: var(--r-full); background: var(--swatch); border: 2px solid transparent; }
.rw-swatch:hover { border-color: var(--ink-muted); }
.rw-swatch[aria-checked="true"] { border-color: var(--ink-primary); box-shadow: 0 0 0 2px var(--surface-1) inset; }
.rw-actions { display: flex; align-items: center; gap: var(--s2); }
.rw-actions .spacer { flex: 1; }

.rw-looks { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.rw-looks-head { display: flex; align-items: center; gap: var(--s3); }
.rw-looks-head h3 { margin: 0; font: 600 16px/24px var(--font-sans); }
.rw-places { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--s3); }
.rw-place { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; }
.rw-place > span { font: 600 14px/20px var(--font-sans); color: var(--ink-secondary); }
.rw-chat { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-1); font-size: 14px; line-height: 20px; }
.rw-chat-who { display: flex; align-items: center; gap: var(--s1); min-width: 0; }
.rw-chat-who .rw-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rw-chat p { margin: 0; color: var(--ink-secondary); }
.rw-lb { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border-radius: var(--r-lg); background: var(--surface-1); font-size: 14px; }
.rw-lb .rw-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rw-lb-place { width: 16px; text-align: right; font: 12px/16px var(--font-mono); color: var(--ink-muted); }
.rw-lb-rating { margin-left: auto; font: 14px/20px var(--font-mono); color: var(--ink-primary); }
.rw-panel { border-radius: var(--r-lg); background: var(--surface-1); overflow: hidden; }
.rw-panel .rw-banner { height: 88px; }
.rw-panel-row { display: flex; align-items: flex-start; gap: var(--s3); padding: 0 var(--s4) var(--s4); margin-top: -28px; position: relative; }
.rw-panel-name { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); min-width: 0; padding-top: 32px; font-size: 20px; line-height: 28px; }
.rw-panel-name .rw-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.rw-reel { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s4); width: 168px; height: 176px; border-radius: var(--r-lg); background: var(--surface-2); overflow: hidden; }
.rw-reel-art { display: grid; place-items: center; width: 100%; height: 64px; }
.rw-reel-art > * { transform: scale(1.25); }
.rw-reel-art .rw-banner { width: 120px; height: 40px; }
.rw-reel b { max-width: 100%; padding: 0 var(--s3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 500 14px/20px var(--font-sans); }
.rw-reel::after { content: ""; position: absolute; inset: auto 0 0; height: 4px; background: var(--rarity); }

/* The library and the board. */
.rw-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s4); margin-top: var(--s4); align-items: start; }
.rw-left, .rw-right { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }
@media (max-width: 1100px) { .rw-grid { grid-template-columns: minmax(0, 1fr); } }
.rw-filter { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0; }
.rw-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: var(--s3); }
.rw-chips, .rw-markets { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.rw-tile { display: flex; flex-direction: column; gap: var(--s3); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); border: 1px solid transparent; cursor: grab; min-width: 0; }
.rw-tile:hover { border-color: var(--border-strong); }
.rw-tile.dragging { opacity: 0.5; }
.rarity-common { --rarity: var(--rarity-common); } .rarity-rare { --rarity: var(--rarity-rare); }
.rarity-epic { --rarity: var(--rarity-epic); } .rarity-legendary { --rarity: var(--rarity-legendary); }
.rw-tile-what { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.rw-tile-what b { font: 600 14px/20px var(--font-sans); color: var(--ink-primary); overflow-wrap: anywhere; }
.rw-tile-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font: 12px/16px var(--font-mono); color: var(--ink-muted); }
.rw-rarity { display: inline-flex; align-items: center; gap: var(--s1); color: var(--rarity); }
.rw-rarity::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--rarity); }
.rw-tile-act { display: flex; gap: var(--s2); }
.rw-tile-act select { flex: 1; min-width: 0; }

.rw-cases { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--s3); margin-top: var(--s3); }
.rw-case, .rw-market { padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); border: 1px dashed transparent; display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.rw-case.over, .rw-market.over { border-color: var(--ink-muted); background: var(--surface-3); }
.rw-case-head { display: flex; align-items: center; gap: var(--s3); }
.rw-case-head img { width: 32px; height: 32px; }
.rw-case-head div { display: flex; flex-direction: column; gap: var(--s1); }
.rw-chip { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) var(--s2); border-radius: var(--r-md); background: var(--surface-1); min-width: 0; }
.rw-chip-art { display: grid; place-items: center; flex-shrink: 0; min-width: 40px; max-width: 120px; height: 32px; overflow: hidden; font-size: 14px; }
.rw-chip-art .rw-banner { width: 56px; height: 24px; border-radius: var(--r-sm); }
.rw-chip-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.rw-chip input { width: 72px; }
.rw-chip button.icon { padding: 0 var(--s2); }
.rw-drop-hint { margin: 0; padding: var(--s3); border-radius: var(--r-md); border: 1px dashed var(--border-strong); color: var(--ink-muted); font-size: 12px; text-align: center; }
.rw-odds { margin: 0; font: 11px/16px var(--font-mono); color: var(--ink-muted); }
.rw-markets { margin-top: var(--s3); }
.rw-market-what { display: flex; flex-direction: column; gap: var(--s1); }
.rw-market-what b { font-weight: 500; overflow-wrap: anywhere; }

/* cosmetics:start. A reward's art (Niko, 2026-09-23). The same block, to the
   character, in the app's theme and the Lab's, so the Lab's preview is what
   the app draws; the Lab's rewards test fails when they differ. Colours are the reward's own --flair-* (set on the element from
   its design) and the --rw-* inks each surface names outside this block. Flat
   art like the pack icons (design-system §3): no blur, no glow, and still
   under reduced motion. */
.rw-name { font-synthesis: none; }
.flair-highlighter, .flair-annotated, .flair-chrome, .flair-redacted { position: relative; isolation: isolate; }
.flair-highlighter::before {
  content: ""; position: absolute; z-index: -1; left: -0.2em; right: -0.2em; top: 0.52em; bottom: -0.06em;
  background: color-mix(in srgb, var(--flair-tint) 40%, transparent);
  border-radius: 0.35em 0.1em 0.4em 0.12em;
  transform: skewX(-12deg); transform-origin: left center;
  animation: rw-swipe 0.6s cubic-bezier(0.2, 0, 0, 1) both;
}
@keyframes rw-swipe { from { transform: skewX(-12deg) scaleX(0); } }
.flair-annotated::after {
  content: ""; position: absolute; left: -0.1em; right: -0.1em; bottom: -0.32em; height: 0.44em;
  background: var(--flair-tint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 4C30 1 62 2 118 3M8 8C42 5 82 6 110 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 10' preserveAspectRatio='none'%3E%3Cpath d='M2 4C30 1 62 2 118 3M8 8C42 5 82 6 110 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  animation: rw-draw 0.9s cubic-bezier(0.2, 0, 0, 1) both;
}
@keyframes rw-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.flair-holo, .flair-chrome, .flair-magma, .flair-scoreboard { -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.flair-holo {
  background-image:
    repeating-linear-gradient(115deg, transparent 0 2px, color-mix(in srgb, var(--rw-shine) 55%, transparent) 2px 3px, transparent 3px 6px),
    linear-gradient(115deg, var(--flair-from) 0%, var(--flair-to) 16%, var(--rw-shine) 24%, var(--flair-from) 36%, color-mix(in srgb, var(--flair-to) 50%, var(--flair-from)) 50%, var(--flair-to) 64%, var(--rw-shine) 72%, var(--flair-from) 84%, var(--flair-to) 100%);
  background-size: 100% 100%, 300% 100%;
  animation: rw-foil 5s ease-in-out infinite alternate;
}
@keyframes rw-foil { from { background-position: 0 0, 0 0; } to { background-position: 0 0, 100% 0; } }
.flair-chrome {
  background-image: linear-gradient(180deg,
    var(--rw-shine) 0%,
    color-mix(in srgb, var(--flair-tint) 55%, var(--rw-shine)) 46%,
    color-mix(in srgb, var(--flair-tint) 45%, var(--rw-deep)) 50%,
    color-mix(in srgb, var(--flair-tint) 70%, var(--rw-deep)) 56%,
    var(--flair-tint) 72%,
    color-mix(in srgb, var(--flair-tint) 40%, var(--rw-shine)) 100%);
}
.flair-chrome::after {
  content: ""; position: absolute; right: -0.32em; top: -0.28em; width: 0.7em; height: 0.7em;
  background: var(--rw-shine);
  clip-path: polygon(50% 0, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0 50%, 42% 42%);
  transform: scale(0);
  animation: rw-glint 4.5s ease-in-out infinite;
}
@keyframes rw-glint { 0%, 70%, 100% { transform: scale(0) rotate(0); } 80% { transform: scale(1) rotate(45deg); } 90% { transform: scale(0.3) rotate(90deg); } }
.flair-magma {
  background-image:
    radial-gradient(circle at 20% 55%, var(--flair-to) 0 9%, color-mix(in srgb, var(--flair-to) 60%, transparent) 16%, transparent 30%),
    radial-gradient(circle at 75% 35%, var(--flair-to) 0 8%, color-mix(in srgb, var(--flair-to) 60%, transparent) 14%, transparent 28%),
    radial-gradient(circle at 50% 85%, var(--rw-shine) 0 3%, transparent 14%),
    linear-gradient(color-mix(in srgb, var(--flair-from) 80%, var(--rw-deep)), color-mix(in srgb, var(--flair-from) 55%, var(--rw-deep)));
  background-size: 180% 180%, 220% 220%, 260% 260%, 100% 100%;
  animation: rw-flow 7s ease-in-out infinite alternate;
}
@keyframes rw-flow { from { background-position: 0 0, 100% 100%, 50% 0, 0 0; } to { background-position: 100% 60%, 0 20%, 20% 100%, 0 0; } }
.flair-signal { text-shadow: -1px 0 var(--flair-from), 1px 0 var(--flair-to); animation: rw-glitch 5s steps(1) infinite; }
@keyframes rw-glitch {
  0%, 88%, 100% { text-shadow: -1px 0 var(--flair-from), 1px 0 var(--flair-to); }
  90% { text-shadow: -3px 0 var(--flair-from), 2px 0 var(--flair-to); }
  93% { text-shadow: 2px -1px var(--flair-from), -3px 1px var(--flair-to); }
  96% { text-shadow: -2px 1px var(--flair-from), 2px 0 var(--flair-to); }
}
.flair-scoreboard {
  font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em;
  background-image: linear-gradient(90deg, var(--flair-tint) 0 42%, color-mix(in srgb, var(--flair-tint) 40%, var(--rw-shine)) 50%, var(--flair-tint) 58%);
  background-size: 300% 100%;
  -webkit-mask: radial-gradient(circle, black 0.075em, transparent 0.09em) 0 0 / 0.16em 0.16em;
  mask: radial-gradient(circle, black 0.075em, transparent 0.09em) 0 0 / 0.16em 0.16em;
  animation: rw-led 3.6s linear infinite;
}
@keyframes rw-led { from { background-position: 100% 0; } to { background-position: 0 0; } }
.flair-redacted { font-family: var(--rw-type); font-weight: 400; }
.flair-redacted::after {
  content: ""; position: absolute; left: -0.15em; right: -0.15em; top: 0.1em; bottom: 0.05em;
  background: var(--flair-tint); transform: scaleX(0); transform-origin: left center;
  animation: rw-redact 7s cubic-bezier(0.2, 0, 0, 1) infinite;
}
@keyframes rw-redact {
  0%, 60% { transform: scaleX(0); transform-origin: left center; }
  68%, 84% { transform: scaleX(1); transform-origin: left center; }
  85% { transform: scaleX(1); transform-origin: right center; }
  93%, 100% { transform: scaleX(0); transform-origin: right center; }
}

/* Frames: the art fills the box and the badge sits in its hole, so nothing
   hangs outside what the layout gave it. */
.rw-frame { position: relative; display: inline-block; flex-shrink: 0; vertical-align: middle; --fw: calc(var(--frame-px, 40px) * var(--frame-weight, 4) / 60); }
.rw-frame > svg, .rw-frame > .rw-frame-art { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.rw-frame > .rw-frame-art { object-fit: contain; }
.rw-hole { position: absolute; inset: 14%; display: grid; place-items: center; }
.rw-hole > * { width: 100%; height: 100%; }
.frame-ring::before, .frame-crest::before { content: ""; position: absolute; border-radius: 50%; border: var(--fw) solid var(--flair-tint); }
.frame-ring::before { inset: 0; }
.frame-ring .rw-hole { inset: calc(var(--fw) + 6%); }
.frame-crest { --frame-weight: 4; }
.frame-crest::before { inset: 22% 11% 0; }
.frame-crest .rw-hole { inset: calc(22% + var(--fw) + 5%) calc(11% + var(--fw) + 5%) calc(var(--fw) + 5%); }
.rw-crest { position: absolute; top: 0; left: 32%; width: 36%; height: 36%; object-fit: contain; }
.frame-upload .rw-hole { inset: 12%; }
.frame-laurel .rw-hole { inset: 21%; }
.frame-rosette .rw-hole { inset: 15% 25% 35%; }
.frame-guilloche .rw-hole { inset: 12%; }
.frame-radar .rw-hole { inset: 12%; }
.frame-reticle .rw-hole { inset: 15%; }
.frame-radar::before {
  content: ""; position: absolute; inset: 4%; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 62%, color-mix(in srgb, var(--flair-tint) 60%, transparent) 100%);
  animation: rw-spin 3.2s linear infinite;
}
.frame-guilloche > svg { animation: rw-spin 40s linear infinite; }
.frame-reticle > svg { animation: rw-close 2.4s ease-in-out infinite alternate; }
@keyframes rw-spin { to { transform: rotate(1turn); } }
@keyframes rw-close { to { transform: scale(0.9); } }

/* The drawn shapes (lib/cosmetic-art.ts). */
.rw-art .a { fill: var(--flair-tint, var(--flair-from)); }
.rw-art .b { fill: var(--flair-to); }
.rw-art .s { fill: none; stroke: var(--flair-tint, var(--flair-from)); stroke-width: 1.4; }
.rw-art .s2 { fill: none; stroke: var(--flair-to); stroke-width: 1.4; }
.rw-art .bold { stroke-width: 5; stroke-linecap: square; }
.rw-art .k { fill: none; stroke: var(--rw-deep); stroke-width: 2; }
.rw-art .g { fill: var(--rw-ghost); opacity: 0.3; }
.rw-art .t { fill: var(--rw-ghost); font: 600 7px var(--font-mono); }
.frame-laurel .s { stroke-width: 1.8; }
.frame-guilloche .s { stroke-width: 0.8; }
.banner-guilloche .s, .banner-guilloche .s2 { stroke-width: 0.7; }
.banner-topographic .s { stroke-width: 0.8; opacity: 0.8; }
.banner-transcript .a { opacity: 0.55; }

/* Banners. */
.rw-banner { position: relative; display: block; overflow: hidden; background-color: var(--rw-paper); background-size: cover; background-position: center; }
.rw-banner > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.banner-gradient { background-image: linear-gradient(var(--banner-angle, 90deg), var(--flair-from), var(--flair-to)); }
.banner-hemicycle, .banner-transcript { background-color: var(--rw-deep); }
.banner-waveform .bar { transform-box: fill-box; transform-origin: center; animation: rw-breathe 1.8s ease-in-out infinite alternate; animation-delay: calc(var(--i, 0) * -70ms + var(--rw-at, 0s)); }
/* Each wearer's loops start at their own point, so a list of them never
   pulses as one: `--rw-at` is a negative delay set per person (`rewardPhase`). */
.flair-holo, .flair-chrome::after, .flair-magma, .flair-signal, .flair-scoreboard, .flair-redacted::after,
.frame-radar::before, .frame-guilloche > svg, .frame-reticle > svg { animation-delay: var(--rw-at, 0s); }
@keyframes rw-breathe { from { transform: scaleY(0.45); } }

/* Titles: never taller than the 20px tag chip beside them, and the words
   end in an ellipsis rather than leaving the chip. */
.rw-title { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; height: 20px; vertical-align: middle; white-space: nowrap; font: 500 11px/16px var(--font-sans); }
.rw-title > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.title-chip { padding: 0 6px; border-radius: 10px; background: var(--rw-paper); color: var(--rw-quiet); }
.title-chip img, .title-chip svg { width: 12px; height: 12px; flex-shrink: 0; }
.title-label {
  height: 18px; padding: 0 8px; background: color-mix(in srgb, var(--flair-tint) 62%, var(--rw-deep)); color: var(--rw-shine);
  font: 700 11px/18px var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase;
  text-shadow: 0 1px 0 color-mix(in srgb, var(--flair-tint) 25%, var(--rw-deep)), 0 -1px 0 color-mix(in srgb, var(--rw-shine) 30%, transparent);
  clip-path: polygon(0 2px, 3px 0, 100% 0, calc(100% - 2px) 50%, 100% 100%, 2px 100%, 0 calc(100% - 2px));
}
.title-stamp {
  height: 16px; padding: 0 4px; border: 1.5px solid var(--flair-tint); border-radius: 2px; color: var(--flair-tint);
  font: 400 11px/13px var(--rw-type); letter-spacing: 0.08em; text-transform: uppercase; transform: rotate(-2deg);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='20'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.4 1.9'/%3E%3C/filter%3E%3Crect width='60' height='20' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / 60px 20px;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='20'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.4 1.9'/%3E%3C/filter%3E%3Crect width='60' height='20' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / 60px 20px;
}
.title-receipt {
  position: relative; height: 18px; padding: 0 12px 0 16px; background: var(--rw-shine); color: var(--rw-deep);
  font: 700 11px/18px var(--font-mono); letter-spacing: 0.04em; text-transform: uppercase;
  clip-path: polygon(0 0, 100% 0, calc(100% - 3px) 17%, 100% 33%, calc(100% - 3px) 50%, 100% 67%, calc(100% - 3px) 83%, 100% 100%, 0 100%);
}
.title-receipt::before {
  content: ""; position: absolute; left: 4px; top: 4px; bottom: 4px; width: 8px;
  background: repeating-linear-gradient(90deg, var(--rw-deep) 0 1px, transparent 1px 2px, var(--rw-deep) 2px 4px, transparent 4px 5px);
}
.title-ribbon {
  height: 18px; padding: 0 12px; background: var(--flair-tint); color: var(--rw-deep); font: 700 11px/18px var(--font-sans);
  clip-path: polygon(0 0, 100% 0, calc(100% - 6px) 50%, 100% 100%, 0 100%, 6px 50%);
}
.title-exhibit { gap: 6px; color: var(--rw-quiet); }
.title-exhibit b {
  display: inline-grid; place-items: center; flex-shrink: 0; width: 18px; height: 16px; padding-top: 2px;
  background: var(--flair-tint); color: var(--rw-deep); font: 800 11px/1 var(--font-sans);
  clip-path: polygon(22% 0, 78% 0, 100% 100%, 0 100%);
}

@media (prefers-reduced-motion: reduce) {
  .flair-highlighter::before, .flair-annotated::after, .flair-chrome::after, .flair-redacted::after,
  .flair-holo, .flair-magma, .flair-signal, .flair-scoreboard,
  .frame-radar::before, .frame-guilloche > svg, .frame-reticle > svg, .banner-waveform .bar { animation: none; }
}
/* cosmetics:end */


/* ---- the Users tab ---- */
.users-list tbody tr { cursor: pointer; }
.users-list tbody td { border-top: 1px solid var(--border-subtle); transition: background-color var(--t-fast); }
.users-list tbody tr:hover td { background: var(--surface-2); }
.users-list tbody tr:active td { background: var(--surface-3); }
.users-list .rowopen { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; height: auto; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; white-space: normal; }
.users-list .rowopen b { font-weight: 500; color: var(--ink-primary); }
.users-list .rowopen:focus-visible, .linkish:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }
.linkish { height: auto; padding: 0; border: 0; background: none; color: var(--ink-primary); font: 12px/16px var(--font-mono); text-decoration: underline; text-underline-offset: 2px; }
.linkish:hover { color: var(--ink-secondary); }
.linkish:active { opacity: 0.75; }
.vsec h4 { margin: var(--s2) 0 0; font: 500 10px/14px var(--font-mono); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.users-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); font-size: 14px; color: var(--ink-secondary); }
.users-lines li { display: flex; flex-direction: column; gap: 2px; padding-bottom: var(--s2); border-bottom: 1px solid var(--border-subtle); }
.users-lines li:last-child { border-bottom: 0; }
.users-ban { display: flex; flex-direction: column; gap: var(--s2); }
.users-ban .row { flex-wrap: wrap; }
.users-ban input { flex: 1; min-width: 140px; }
/* The amount is a few digits; the note takes the rest of the row. */
/* Give or take points: a real form in its own box, the fields a step darker
   than the dialog with a visible edge, so they read as places to type. */
.users-grant { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-3); }
.users-grant-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3); }
.users-grant label { display: flex; flex-direction: column; gap: var(--s1); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.users-grant label.grow { flex: 1 1 240px; }
.users-grant input { height: 40px; background: var(--surface-1); border-color: var(--border-strong); font-size: 14px; }
.users-grant input.num-in { width: 128px; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.users-grant button { height: 40px; }

/* ---- one account (Niko, 2026-09-22: "not enough clear headings and its just
   a bunch of text"): a summary strip under the name, four tabs, rows that
   read as one line, sub-headings that read as headings, long lists folded. */
.users-summary { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); }
.users-say { margin: 0; }
.users-say:empty { display: none; }
/* The app's `tab` (primitives/button.tsx): 44px, 16px bold words on a 2px underline, 28px apart. */
.users-tabs { display: flex; gap: 28px; margin-bottom: var(--s5); border-bottom: 1px solid var(--border-subtle); }
.users-tabs button { height: 44px; padding: 0; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--ink-secondary); font: 700 16px/24px var(--font-sans); transition: color var(--t-fast), border-color var(--t-fast); }
.users-tabs button:hover { color: var(--ink-primary); }
.users-tabs button[aria-selected="true"] { color: var(--ink-primary); border-bottom-color: var(--ink-primary); }
.users-tabs button:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.users-pane { display: flex; flex-direction: column; gap: var(--s8); min-width: 0; }
dialog.users .vsec h4 { margin: var(--s3) 0 0; font: 600 14px/20px var(--font-sans); color: var(--ink-primary); text-transform: none; letter-spacing: 0; }
dialog.users .users-lines li { display: block; line-height: 20px; }
dialog.users .users-lines li .pre { display: block; margin-bottom: 2px; color: var(--ink-primary); }
dialog.users .users-lines li .vsub { margin-top: 2px; }
.users-more { align-self: flex-start; }
.pill-icon { display: inline-flex; flex: none; }

/* ---- Users, remade (Niko, 2026-09-23: "not sectioned well with headings
   ... a lot of the same text and there are no colors"): the totals first,
   filters as buttons, reports as cards, accounts with a face and coloured
   standing, and one account as cards with a number row and chips. */
.users-glance { display: grid; grid-template-columns: repeat(auto-fit, minmax(144px, 1fr)); gap: var(--s2); margin: var(--s4) 0; }
.uglance { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); height: auto; padding: var(--s3) var(--s4); border: 1px solid var(--border-subtle); border-radius: var(--r-lg); background: var(--surface-1); color: var(--ink-primary); font: inherit; text-align: left; }
.uglance b { font: 600 28px/36px var(--font-mono); font-variant-numeric: tabular-nums; }
.uglance span { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.uglance .bone.fig { width: 48px; height: 28px; margin: 4px 0; }
.uglance .bone.cap { width: 72px; height: 12px; margin: 4px 0; }
button.uglance { cursor: pointer; }
button.uglance:active:not(:disabled) { background: var(--surface-2); }
button.uglance[aria-pressed="true"] { border-color: var(--ink-primary); }
.uglance.streamer b { color: var(--tier-streamer); }
.uglance.viewer b { color: var(--tier-viewer); }
.uglance.ok b { color: var(--ok); }
.uglance.warn b { color: var(--warn); }
.uglance.bad b { color: var(--bad); }
.users-search { margin-left: auto; width: 280px; max-width: 100%; }
.users-filter { display: flex; flex-wrap: wrap; gap: var(--s1); margin: var(--s3) 0 var(--s4); }
.uchip { display: inline-flex; align-items: center; gap: var(--s1); height: 24px; padding: 0 var(--s2); border-radius: var(--r-md); background: var(--surface-3); color: var(--ink-secondary); font: 600 14px/20px var(--font-sans); white-space: nowrap; }
.uchip.ok { color: var(--ok); background: color-mix(in oklab, var(--ok) 14%, transparent); }
.uchip.warn { color: var(--warn); background: color-mix(in oklab, var(--warn) 14%, transparent); }
.uchip.bad { color: var(--bad); background: color-mix(in oklab, var(--bad) 14%, transparent); }
.uchip.streamer { color: var(--tier-streamer); background: color-mix(in oklab, var(--tier-streamer) 14%, transparent); }
.uchip.viewer { color: var(--tier-viewer); background: color-mix(in oklab, var(--tier-viewer) 14%, transparent); }
.uavatar { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; border-radius: 50%; background: var(--tier-viewer); color: var(--surface-0); font: 600 14px/1 var(--font-sans); }
.uavatar.streamer { background: var(--tier-streamer); }
.uavatar.big { width: 48px; height: 48px; font-size: 20px; }
.users-list .rowopen { flex-direction: row; align-items: center; gap: var(--s3); }
.users-list td { font-size: 14px; vertical-align: middle; }
.uname { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.uname b { font-size: 14px; line-height: 20px; }
.umeta { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s3); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.umeta a { color: var(--ink-secondary); }
.ureports { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--s3); }
.ureport { display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.ureport-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.ureport-when { margin-left: auto; font: 12px/16px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.ureport-body { margin: 0; padding: var(--s2) var(--s3); border-radius: var(--r-sm); background: var(--surface-3); color: var(--ink-primary); font-size: 14px; line-height: 20px; white-space: pre-wrap; overflow-wrap: anywhere; }
.ureport-note { margin: 0; font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.ureports-none { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.udot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); }
.udot.ok { background: var(--ok); }
.uhead { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
dialog.users .watch-sub { font-size: 14px; line-height: 20px; }
.ustats { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: var(--s2); margin-top: var(--s4); }
.ustat { display: flex; flex-direction: column; gap: 2px; padding: var(--s2) var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.ustat b { font: 600 20px/28px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.ustat span { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
dialog.users .users-pane { gap: var(--s3); }
dialog.users .vsec { padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); }
dialog.users .vsec-head { padding-bottom: 0; border-bottom: 0; }
dialog.users .vsec-head h3 { font-size: 16px; line-height: 24px; }
dialog.users .facts { grid-template-columns: 160px minmax(0, 1fr); }
dialog.users .facts dt, dialog.users .facts dd { font-size: 14px; line-height: 20px; }
dialog.users .facts dd { color: var(--ink-primary); }
dialog.users .vsec h4 { margin: var(--s4) 0 0; font-size: 14px; line-height: 20px; }
dialog.users .users-lines li { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3) 0; }
.uline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); min-width: 0; }
.utext { margin: 0; font-size: 14px; line-height: 20px; color: var(--ink-secondary); overflow-wrap: anywhere; }
.utext.strong { color: var(--ink-primary); }
.utext.quiet { font: 12px/16px var(--font-mono); color: var(--ink-muted); }
@media (max-width: 860px) {
  .users-search { width: 100%; margin-left: 0; }
  dialog.users .facts { grid-template-columns: minmax(0, 1fr); }
}

/* ---- the Command tab (Niko, 2026-09-22, and 2026-09-23 for the colour):
   the app on one page and a switch for every part of it. Green all is well,
   amber switched off by choice, red down or failing. */
.cmd-pill { display: inline-flex; align-items: center; gap: var(--s2); height: 24px; padding: 0 var(--s2); border-radius: var(--r-md); font: 600 14px/20px var(--font-sans); white-space: nowrap; color: var(--ink-secondary); background: var(--surface-3); }
.cmd-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.cmd-pill.ok { color: var(--ok); background: color-mix(in oklab, var(--ok) 14%, transparent); }
.cmd-pill.warn { color: var(--warn); background: color-mix(in oklab, var(--warn) 14%, transparent); }
.cmd-pill.bad { color: var(--bad); background: color-mix(in oklab, var(--bad) 16%, transparent); }
/* Live is not a fault: the word stays plain, and only the dot takes the
   recording red, beating, the way a camera's light does. */
.cmd-pill.live { color: var(--ink-primary); }
.cmd-pill.live::before { background: var(--rec); animation: cmd-beat 1.6s ease-in-out infinite; }
@keyframes cmd-beat { 50% { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) { .cmd-pill.live::before { animation: none; } }

.cmd-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: var(--s2); }
.cmd-tile { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3) var(--s4); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.cmd-tile-label { font-size: 14px; line-height: 18px; color: var(--ink-secondary); }
.cmd-tile-value { font: 600 32px/40px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.cmd-tile-detail { font: 14px/20px var(--font-mono); color: var(--ink-secondary); overflow-wrap: anywhere; }
.cmd-tile.bad { background: color-mix(in oklab, var(--bad) 10%, var(--surface-2)); }
.cmd-tile.bad .cmd-tile-value { color: var(--bad); }
.cmd-tile.warn { background: color-mix(in oklab, var(--warn) 9%, var(--surface-2)); }
.cmd-tile.warn .cmd-tile-value { color: var(--warn); }
.cmd-tile.money .cmd-tile-value { color: var(--money); }

.cmd-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--s2); margin-top: var(--s2); }
.cmd-chart-card { padding: var(--s3) var(--s4); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.cmd-chart { display: flex; flex-direction: column; gap: var(--s2); margin: 0; }
.cmd-chart figcaption, .cmd-chart-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.cmd-chart figcaption b, .cmd-chart-head b { font-weight: 600; color: var(--ink-primary); }
.cmd-chart-total { font: 600 20px/28px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.cmd-ranges { display: flex; gap: var(--s1); margin-left: auto; }
.cmd-plot { position: relative; height: 112px; padding-top: var(--s4); }
.cmd-peak { position: absolute; top: 0; right: 0; font: 11px/16px var(--font-mono); color: var(--ink-muted); }
.cmd-bars { display: flex; align-items: flex-end; gap: 2px; height: 100%; border-bottom: 1px solid var(--border-strong); }
.cmd-bar { flex: 1; min-width: 0; border-radius: var(--r-sm) var(--r-sm) 0 0; transition: opacity var(--t-fast); }
/* Ninety days on a phone: a hair between bars rather than bars that overflow. */
.cmd-bars.dense { gap: 1px; }
.cmd-bar.a { background: var(--chart-a); }
.cmd-bar.b { background: var(--chart-b); }
.cmd-bar.c { background: var(--chart-c); }
.cmd-bar.zero { background: var(--surface-3); }
.cmd-bar:hover { opacity: 0.7; }
.cmd-axis { display: flex; justify-content: space-between; font: 11px/16px var(--font-mono); color: var(--ink-muted); }

/* Spend (Niko, 2026-09-23: "redesign this to be elite"): one window at a
   time, chosen in the card's head. Its total, where the month is heading
   and the shape of the spend first; then where it went, a bar a line. */
.card-head .cmd-periods { margin: 0; flex-wrap: wrap; }
.cmd-spend-top { display: grid; grid-template-columns: minmax(240px, 320px) minmax(0, 1fr); gap: var(--s3); }
.cmd-spend-hero { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.cmd-spend-label { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-spend-total { font: 600 40px/48px var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; color: var(--money); overflow-wrap: anywhere; }
.cmd-spend-sub { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-delta { font: 500 12px/16px var(--font-mono); }
.cmd-delta.up { color: var(--bad); }
.cmd-delta.down { color: var(--ok); }
.cmd-delta.flat { color: var(--ink-muted); }
.cmd-spend-pace { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s2); margin-top: var(--s1); padding: var(--s2) var(--s3); border-radius: var(--r-md); background: var(--surface-3); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-spend-pace b { font: 600 16px/24px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.cmd-spend-quick { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); margin: auto 0 0; padding-top: var(--s3); border-top: 1px solid var(--border-subtle); font-size: 14px; line-height: 20px; }
.cmd-spend-quick.flush { margin: 0; padding-top: var(--s2); }
.cmd-spend-quick dt { color: var(--ink-secondary); }
.cmd-spend-quick dd { margin: 0; text-align: right; font: 600 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); }
.cmd-spend-chart .cmd-plot { height: 176px; }
.cmd-bar.money { background: var(--money); }
.cmd-spend-split { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.8fr); gap: var(--s6); margin-top: var(--s2); }
.cmd-split { margin: 0; padding: 0; list-style: none; }
.cmd-split li { display: grid; grid-template-columns: minmax(96px, 1fr) minmax(48px, 1fr) auto 40px; align-items: center; gap: var(--s3); padding: var(--s2) 0; border-top: 1px solid var(--border-subtle); }
.cmd-split-name { display: flex; flex-direction: column; min-width: 0; font-size: 14px; line-height: 20px; color: var(--ink-primary); }
.cmd-split-name small { font-size: 12px; line-height: 16px; color: var(--ink-muted); }
.cmd-split-track { height: 8px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.cmd-split-fill { display: block; height: 100%; border-radius: inherit; background: var(--money); }
.cmd-split b { font: 600 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); text-align: right; white-space: nowrap; }
.cmd-split-pct { font: 12px/16px var(--font-mono); color: var(--ink-muted); text-align: right; }
.cmd-split li.zero .cmd-split-name, .cmd-split li.zero b { color: var(--ink-muted); }
.cmd-spend-top-debate { display: flex; flex-direction: column; margin: var(--s2) 0 0; font-size: 14px; line-height: 20px; }
.cmd-spend-top-debate a { color: var(--ink-primary); overflow-wrap: anywhere; }
.cmd-spend-top-debate a:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-radius: var(--r-sm); }
.cmd-spend-top-debate span { font: 12px/16px var(--font-mono); color: var(--ink-muted); }
@media (max-width: 1100px) { .cmd-spend-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 860px) { .cmd-spend-top, .cmd-spend-split { grid-template-columns: minmax(0, 1fr); } }

.cmd-table { width: 100%; }
.cmd-table th { padding: 0 var(--s3) var(--s2) 0; }
.cmd-table td { padding: var(--s3) var(--s3) var(--s3) 0; border-top: 1px solid var(--border-subtle); vertical-align: top; }
.cmd-table td.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.cmd-table a { color: var(--ink-primary); }
.cmd-table a:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-radius: var(--r-sm); }

/* All Debates (2026-09-23). Each state keeps the colour it has elsewhere in
   the Lab: live the recording red dot, paused amber, ended green, setup the
   pulse blue, deleted red and dimmed while it waits out its 30 days. */
/* Live is not a fault here either: the figure stays plain and a beating dot says it. */
.uglance.live b::before { content: ""; display: inline-block; width: 8px; height: 8px; margin: 0 var(--s2) 4px 0; border-radius: 50%; background: var(--rec); vertical-align: middle; animation: cmd-beat 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .uglance.live b::before { animation: none; } }
.uglance.setup b { color: var(--pulse); }
.cmd-pill.setup { color: var(--pulse); background: color-mix(in oklab, var(--pulse) 14%, transparent); }
.debates-list .debate { display: flex; flex-direction: column; gap: 2px; min-width: 200px; max-width: 480px; }
.debates-list td { font-family: var(--font-sans); }
.debates-list td.mono { white-space: nowrap; }
.debates-list .debate b { font-weight: 500; color: var(--ink-primary); }
.debates-list .debate > span:not(.umeta) { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
/* Where the audio came from, as a mark beside the name; the name opens the drawer (Niko, 2026-10-20). */
.debates-list .debate-name { display: flex; align-items: flex-start; gap: var(--s2); }
.debates-list .debate-name .capture-icon { margin-top: 1px; }
.debates-list .debate-name button { display: inline; min-width: 0; height: auto; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; color: var(--ink-primary); font: inherit; font-weight: 500; line-height: 20px; white-space: normal; text-align: left; cursor: pointer; }
.debates-list .debate-name button:hover { text-decoration: underline; text-underline-offset: 3px; }
.capture-icon { display: inline-flex; flex: none; width: 18px; height: 18px; color: var(--ink-secondary); }
.capture-icon svg { width: 100%; height: 100%; }
.debates-list td.end { text-align: right; white-space: nowrap; }
.debates-list .cost-toggle { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 0; padding: var(--s1) var(--s2); margin: calc(-1 * var(--s1)) calc(-1 * var(--s2)); border: 1px solid transparent; border-radius: var(--r-md); background: none; color: var(--ink-primary); font: 500 14px/20px var(--font-mono); cursor: pointer; transition: background var(--t-fast), border-color var(--t-fast); }
.debates-list .cost-toggle span { font: 12px/16px var(--font-sans); color: var(--ink-muted); }
.debates-list .cost-toggle:hover { background: var(--surface-2); }
.debates-list .cost-toggle:active { background: var(--surface-3); }
.debates-list .cost-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.debates-list .cost-toggle[aria-expanded="true"] { background: var(--surface-2); }
.debates-list tr.cost-row td { padding-top: 0; }
.debates-list .cost-items { display: grid; grid-template-columns: minmax(120px, max-content) minmax(0, max-content) max-content; column-gap: var(--s6); row-gap: var(--s1); margin: 0; padding: var(--s3) var(--s4); list-style: none; border-radius: var(--r-lg); background: var(--surface-2); }
.debates-list .cost-items li { display: contents; }
.debates-list .cost-items span { font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.debates-list .cost-items b { font: 500 14px/20px var(--font-mono); color: var(--ink-primary); text-align: right; }
.debates-list .cost-items li.step > span:first-child { padding-left: var(--s4); color: var(--ink-muted); }
.debates-list .cost-items li.step > * { font-size: 12px; line-height: 16px; }
.debates-list .cost-items li.step b { font-weight: 400; color: var(--ink-secondary); }
.debates-list tr.gone .debate-name button, .debates-list tr.gone .debate > span { color: var(--ink-muted); }
.debates-list .acts { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--s2); }
.debates-list .acts .err { flex-basis: 100%; max-width: 240px; margin: 0 0 0 auto; white-space: normal; text-align: right; }
/* Open sits with the row's other actions on one line; an action's error, when there is one, goes below them. */
.debates-list td.end .acts { min-width: max-content; }
.debates-list .acts .err:empty { display: none; }
/* Opens a page, so it stays a link; it looks like a small ghost button. */
.debates-list a.button { display: inline-flex; align-items: center; height: 32px; padding: 0 var(--s3); border: 1px solid transparent; border-radius: var(--r-lg); background: color-mix(in oklab, var(--surface-invert) 12%, transparent); color: var(--ink-primary); font: 600 12px/1 var(--font-sans); text-decoration: none; transition: border-color var(--t-fast), opacity var(--t-fast); }
.debates-list a.button:hover { border-color: var(--ink-muted); }
.debates-list a.button:active { opacity: 0.75; }
.debates-list .gone-cell { display: inline-flex; flex-direction: column; align-items: flex-end; gap: var(--s2); }
.debates-list .gone-cell .err { max-width: 240px; margin: 0; white-space: normal; text-align: right; }
.debates-list .erase { font: 12px/16px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-danger); }
/* System status (2026-09-23): providers as groups, services as rows, a
   coloured mark and coloured words for how each is, no pills. */
.sys-summary { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s4); font-size: 16px; }
.sys-summary b { font-weight: 600; }
.sys-summary.ok b { color: var(--ok); }
.sys-summary.warn b { color: var(--warn); }
.sys-summary.down b { color: var(--bad); }
.sys-mark { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; }
.sys-mark svg { width: 16px; height: 16px; }
.sys-mark.ok { color: var(--ok); background: color-mix(in oklab, var(--ok) 16%, transparent); }
.sys-mark.warn { color: var(--warn); background: color-mix(in oklab, var(--warn) 16%, transparent); }
.sys-mark.down { color: var(--bad); background: color-mix(in oklab, var(--bad) 18%, transparent); }
.sys-summary .sys-mark { width: 32px; height: 32px; }
.sys-what { display: flex; flex-direction: column; min-width: 0; }
.sys-what b { font: 600 14px/20px var(--font-sans); color: var(--ink-primary); overflow-wrap: anywhere; }
.sys-what span { font: 12px/16px var(--font-mono); color: var(--ink-muted); overflow-wrap: anywhere; }
.sys-now { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3); min-width: 0; }
.sys-state { font: 600 14px/20px var(--font-sans); }
.sys-state.ok { color: var(--ok); }
.sys-state.warn { color: var(--warn); }
.sys-state.down { color: var(--bad); }
.sys-ms { font: 12px/16px var(--font-mono); color: var(--ink-secondary); font-variant-numeric: tabular-nums; }
.sys-note { flex-basis: 100%; font-size: 12px; line-height: 16px; color: var(--ink-muted); }
.sys-when { font: 12px/16px var(--font-mono); color: var(--ink-muted); }
@media (max-width: 860px) {
  .sys-now { grid-column: 2 / 4; }
  .sys-when { grid-column: 2 / 4; }
}
/* Quick actions (2026-09-23): several switches at once, the button first
   and what it does under it, small enough to sit above the live debates. */
.cmd-plays { display: grid; grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); gap: var(--s2); }
.cmd-play { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.cmd-play p { margin: 0; font-size: 12px; line-height: 16px; color: var(--ink-muted); }
/* A real button on the box, not red words on it (Niko, 2026-09-23: "add real buttons"). */
.cmd-play button { align-self: stretch; }
.cmd-play button.go, table.settings button.go { background: var(--ok); border-color: var(--ok); color: var(--surface-0); }
.cmd-play button.go:hover:not(:disabled), table.settings button.go:hover:not(:disabled) { border-color: var(--ok); opacity: 0.9; }
.cmd-sub { margin: var(--s5) 0 var(--s2); font: 600 14px/20px var(--font-sans); color: var(--ink-secondary); }
.cmd-foot { margin: var(--s3) 0 0; }
.cmd-link { display: inline; height: auto; padding: 0; border: 0; border-radius: var(--r-sm); background: none; font: inherit; color: var(--ink-secondary); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.cmd-link:hover:not(:disabled) { color: var(--ink-primary); }
.cmd-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.svc-toggle { align-self: flex-start; margin-top: var(--s1); font: 12px/16px var(--font-sans); }

/* The status line (2026-09-23): one verdict, and a chip for each thing that
   needs a person, which takes you to its card. */
.cmd-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); }
.cmd-status > b { font: 600 18px/24px var(--font-sans); color: var(--ink-primary); }
.cmd-status.ok > b { color: var(--ok); }
.cmd-status.warn > b { color: var(--warn); }
.cmd-status.bad > b { color: var(--bad); }
.cmd-chips { display: flex; flex-wrap: wrap; gap: var(--s2); flex-basis: 100%; }
.cmd-chip { height: auto; min-height: 32px; padding: var(--s2) var(--s3); border-radius: var(--r-lg); border: 1px solid transparent; background: var(--surface-2); color: var(--ink-primary); font: 500 14px/20px var(--font-sans); text-align: left; white-space: normal; }
.cmd-chip::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); }
.cmd-chip.warn::before { background: var(--warn); }
.cmd-chip.bad::before { background: var(--bad); }
.cmd-chip:hover:not(:disabled) { border-color: var(--border-strong); background: var(--surface-3); }

/* Plans (2026-09-23): a bar per limit, green, amber at 75%, red at 90%. */
.cmd-plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--s2); }
.cmd-plan { display: flex; flex-direction: column; gap: var(--s4); padding: var(--s4); border-radius: var(--r-lg); background: var(--surface-2); min-width: 0; }
.cmd-plan-head { display: flex; align-items: baseline; gap: var(--s2); }
.cmd-plan-head b { font: 600 16px/24px var(--font-sans); color: var(--ink-primary); }
.cmd-plan-head span { font: 12px/16px var(--font-mono); color: var(--ink-muted); }
.cmd-plan-head a { margin-left: auto; font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-plan-head a:hover { color: var(--ink-primary); }
.cmd-meter { display: flex; flex-direction: column; gap: var(--s1); }
.cmd-meter-head { display: flex; align-items: baseline; gap: var(--s2); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-meter-head b { margin-left: auto; font: 600 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); white-space: nowrap; }
.cmd-meter-pct { width: 40px; text-align: right; font: 600 14px/20px var(--font-mono); color: var(--ok); }
.cmd-meter.warn .cmd-meter-pct { color: var(--warn); }
.cmd-meter.bad .cmd-meter-pct { color: var(--bad); }
.cmd-meter-track { height: 8px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.cmd-meter-fill { display: block; height: 100%; border-radius: inherit; background: var(--ok); }
.cmd-meter.warn .cmd-meter-fill { background: var(--warn); }
.cmd-meter.bad .cmd-meter-fill { background: var(--bad); }
.cmd-meter-note { font-size: 12px; line-height: 16px; color: var(--ink-muted); }
.cmd-plan-note { margin: 0; font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-plan-limits { margin: 0; padding: 0; list-style: none; }
.cmd-plan-limits li { display: flex; justify-content: space-between; gap: var(--s3); padding: var(--s1) 0; border-top: 1px solid var(--border-subtle); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.cmd-plan-limits b { font: 600 14px/20px var(--font-mono); color: var(--ink-primary); }

/* Services (2026-09-23): one row per service with its own switches, and
   its parts nested under it with a mark and a state each, no buttons. */
.svc-list { display: flex; flex-direction: column; gap: var(--s2); }
.svc { border-radius: var(--r-lg); background: var(--surface-2); }
.svc-head { display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); }
.svc-what { display: flex; flex-direction: column; min-width: 0; }
.svc-what b { font: 600 16px/24px var(--font-sans); color: var(--ink-primary); }
.svc-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); }
.svc-does { max-width: 68ch; font: 14px/20px var(--font-sans); color: var(--ink-secondary); }
.svc-part .svc-does { grid-column: 2 / -1; font-size: 12px; line-height: 16px; }
.svc-parts { display: flex; flex-direction: column; margin: 0 var(--s4) 0 calc(var(--s4) + 44px); padding-bottom: var(--s2); border-left: 2px solid var(--border-strong); }
.svc-part { display: grid; grid-template-columns: 24px minmax(140px, 1fr) minmax(160px, 1.4fr) minmax(0, 0.9fr); align-items: center; gap: var(--s3); padding: var(--s2) 0 var(--s2) var(--s3); }
.svc-part + .svc-part { border-top: 1px solid var(--border-subtle); }
.svc-fold > summary { list-style: none; cursor: pointer; }
.svc-fold > summary::-webkit-details-marker { display: none; }
.svc-fold > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-md); }
.svc-fold[open] .svc-acts .hint { visibility: hidden; }
.sys-mark.small { width: 20px; height: 20px; }
.sys-mark.small svg { width: 12px; height: 12px; }
@media (max-width: 860px) {
  .svc-head { grid-template-columns: 32px 1fr; }
  .svc-acts { grid-column: 1 / -1; justify-content: flex-start; }
  .svc-parts { margin-left: var(--s4); }
  .svc-part { grid-template-columns: 24px 1fr; }
  .svc-part .sys-now, .svc-part .sys-when { grid-column: 2; }
}
.confirm-password { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s4); color: var(--ink-primary); }
.confirm-password input { width: 100%; }
@media (max-width: 640px) {
  .cmd-charts { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------- the debate drawer */
/* One debate beside the list (Niko, 2026-10-20, item 13): a column of the
   console's own, so the list stays where it was. Under 1280px it covers the
   page, and in a window of its own (#debate=…&solo=1) it is the page. */
.drawer { position: sticky; top: 0; align-self: flex-start; flex: 0 0 min(960px, 58vw); min-width: 0; height: 100dvh; overflow-y: auto; display: flex; flex-direction: column; gap: var(--s4); padding: var(--s6); border-left: 1px solid var(--border-subtle); background: var(--surface-0); }
.drawer[hidden] { display: none; }
@media (max-width: 1280px) { .drawer { position: fixed; top: 0; right: 0; bottom: 0; left: auto; z-index: 25; width: min(960px, 100%); box-shadow: var(--shadow-overlay); } }
@media (max-width: 860px) { .drawer { padding: var(--s4); } }
.console.solo .rail, .console.solo .content { display: none; }
.console.solo .drawer { position: static; flex: 1; width: auto; height: auto; min-height: 100dvh; max-width: 1760px; margin: 0 auto; padding: var(--s8); border-left: 0; box-shadow: none; overflow: visible; }
.drawer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
.drawer-titles { min-width: 0; display: flex; flex-direction: column; gap: var(--s2); }
.drawer-title { font: 700 24px/32px var(--font-sans); color: var(--ink-primary); overflow-wrap: anywhere; }
.drawer-sub { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.drawer-acts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.drawer-acts a.button { display: inline-flex; align-items: center; height: 32px; padding: 0 var(--s3); border: 1px solid transparent; border-radius: var(--r-lg); background: color-mix(in oklab, var(--surface-invert) 12%, transparent); color: var(--ink-primary); font: 600 12px/1 var(--font-sans); text-decoration: none; transition: border-color var(--t-fast), opacity var(--t-fast); }
.drawer-acts a.button:hover { border-color: var(--ink-muted); }
.drawer-acts a.button:active { opacity: 0.75; }
.drawer-tabs, .drawer-filter { margin-top: 0; }
.drawer-pane { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }
.drawer-pane[hidden] { display: none; }
/* Flow: the pipeline's own canvas, lit by this debate, and its clocks under it. */
.drawer-canvas { flex: none; height: 480px; min-height: 0; border: 1px solid var(--border-subtle); border-radius: var(--r-lg); }
/* Top left, the one corner no step stands in. */
.drawer-canvas .canvas-tools { top: var(--s3); bottom: auto; left: var(--s3); }
.drawer-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--s4); align-items: start; }
.drawer-clock, .drawer-run { display: flex; justify-content: space-between; gap: var(--s3); padding: var(--s2) 0; border-top: 1px solid var(--border-subtle); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.drawer-clocks > :first-child, .drawer-runs > :first-child { border-top: 0; padding-top: 0; }
.drawer-clock b, .drawer-run b { font: 600 14px/20px var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-primary); text-align: right; }
.drawer-run > span:last-child { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
.drawer-run.on b { color: var(--pulse); }
.drawer-run.failed > span:last-child { color: var(--ink-danger); }
/* Log: the totals by step, then each call, opened in place to its whole. */
.drawer-totals td, .drawer-calls td { font-size: 14px; }
.drawer-totals td.mono, .drawer-calls td.mono { white-space: nowrap; }
.drawer-totals td:first-child, .drawer-calls td:nth-child(2), .drawer-calls td:last-child { font-family: var(--font-sans); }
.drawer-sum td { font-weight: 700; color: var(--ink-primary); }
.drawer-call { cursor: pointer; }
.drawer-call:hover td { background: var(--surface-1); }
.drawer-call:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.drawer-call.failed td:last-child { color: var(--ink-danger); }
.drawer-body-row td { padding-top: 0; }
.drawer-whole { display: flex; flex-direction: column; gap: var(--s2); }
.drawer-whole summary { font: 600 14px/20px var(--font-sans); color: var(--ink-primary); }
.drawer-whole pre { margin: var(--s2) 0 0; padding: var(--s3); max-height: 420px; overflow: auto; white-space: pre-wrap; word-break: break-word; border-radius: var(--r-md); background: var(--surface-2); font: 14px/20px var(--font-mono); color: var(--ink-primary); }
/* People and Board. */
.drawer-people td { vertical-align: middle; font-family: var(--font-sans); }
.drawer-people td.end { text-align: right; }
.drawer-people .acts { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); }
.drawer-field { display: flex; flex-direction: column; gap: var(--s2); color: var(--ink-primary); font-size: 14px; line-height: 20px; }
.drawer-field textarea, .drawer-pos textarea { width: 100%; min-height: 0; font: 16px/24px var(--font-sans); }
.drawer-field textarea.drawer-now { min-height: 160px; }
.drawer-save { display: flex; justify-content: flex-end; }
.drawer-topic { display: flex; flex-direction: column; gap: var(--s3); }
.drawer-topic + .drawer-topic { padding-top: var(--s4); border-top: 1px solid var(--border-subtle); }
.drawer-topic h3 { font: 700 18px/26px var(--font-sans); color: var(--ink-primary); }
.drawer-subtopic { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3); border-radius: var(--r-lg); background: var(--surface-2); }
.drawer-subtopic.inner { background: var(--surface-3); }
.drawer-subtopic h4 { font: 700 16px/24px var(--font-sans); color: var(--ink-primary); }
.drawer-pos { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s2) var(--s3); align-items: start; padding: var(--s3); border-radius: var(--r-md); background: var(--surface-1); }
.drawer-pos-who { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3); font-size: 14px; line-height: 20px; color: var(--ink-secondary); }
.drawer-pos-who b { color: var(--ink-primary); }
.drawer-pos-text { max-width: none; color: var(--ink-primary); }
.drawer-pos .acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); }

/* ---------------------------------------------------------------- scoring */
/* The Scoring tab's review: the item and the transcript around it on the
   left, the rubric beside it, one row lit for the keyboard. Stacked under
   1200px, where both columns cannot hold a row's choices on one line. */
.sc-cols { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--s6); }
/* The transcript takes whatever height the rubric leaves beside it, so neither column ends in empty space. */
.sc-item { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.sc-item h3 { margin-top: var(--s2); }
.sc-kind { font: 600 16px/24px var(--font-sans); color: var(--ink-primary); max-width: none; }
.sc-text { margin: 0; padding: var(--s3) var(--s4); border-radius: var(--r-md); background: var(--surface-2); font: 500 18px/28px var(--font-sans); color: var(--ink-primary); white-space: pre-wrap; overflow-wrap: anywhere; }
.sc-statements { margin: 0; padding-left: var(--s5); display: flex; flex-direction: column; gap: var(--s1); color: var(--ink-secondary); }
.sc-lines { flex: 1 1 0; min-height: 240px; margin: 0; padding: var(--s2); list-style: none; overflow-y: auto; border-radius: var(--r-md); background: var(--surface-2); display: flex; flex-direction: column; gap: var(--s1); }
.sc-lines li { padding: var(--s1) var(--s2); border-radius: var(--r-sm); color: var(--ink-secondary); }
.sc-lines b { color: var(--ink-primary); font-weight: 600; }
.sc-lines li.sc-target { background: var(--surface-3); color: var(--ink-primary); box-shadow: inset 2px 0 0 var(--ink-primary); }
.sc-rubric { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.sc-row { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s2) var(--s3); border: 1px solid transparent; border-radius: var(--r-md); cursor: pointer; }
.sc-row[aria-current="true"] { background: var(--surface-2); border-color: var(--border-strong); }
.sc-row-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--s3); }
.sc-name { font: 600 14px/20px var(--font-sans); color: var(--ink-primary); }
.sc-seg { display: inline-flex; flex-wrap: wrap; gap: var(--s1); }
.sc-seg button { min-width: 40px; }
.sc-quote, .sc-note { max-width: none; overflow-wrap: anywhere; }
.sc-note { color: var(--ink-primary); }
.sc-acts { display: flex; flex-wrap: wrap; gap: var(--s3); padding-top: var(--s3); }
@media (max-width: 1200px) {
  .sc-cols { grid-template-columns: minmax(0, 1fr); }
  .sc-lines { flex: none; max-height: 360px; }
}
/* The job's progress beside the buttons: the description gives way to it rather than pushing them to a line of their own. */
#panel-scoring .page-head > div:first-child { flex: 1 1 360px; }
#scoring-results { display: flex; flex-direction: column; gap: var(--s4); }
.sc-table td { font-family: var(--font-sans); vertical-align: middle; border-top: 1px solid var(--border-subtle); }
.sc-table td:not(.sc-measure) { white-space: nowrap; }
.sc-measure { width: 60%; color: var(--ink-primary); }
.sc-gap-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: var(--ink-primary); }
.sc-gap-note { display: block; color: var(--ink-secondary); }
