/* ==========================================================================
   GEM Autocurator, application styles.

   The design system is INSTRUMENT (assets/instrument.css), shared byte-identical
   with MediaDB and PanRoute and loaded before this file. Every colour, type step,
   space, radius, shadow and easing here reads an `--i-` token from it. This file
   holds only what is specific to an approval workspace: the stage rail, the
   proposal row, the stage summary and the intake.

   Theme. Light is the authored surface. Dark is a supported theme with the same
   hierarchy, and a visitor who has asked their operating system for dark gets it
   on the first paint: the boot script in index.html reads the stored choice and
   falls back to `prefers-color-scheme`, and instrument.css carries both palettes.
   The data canvas does not invert. Plotly draws its own light SVG, and a figure
   saved out of a dark page must not arrive in a supplement dark.

   Two rules shape the layout:

   1. The pipeline is never hidden. On a wide screen it is a left rail; below
      1080px the same buttons reflow into a horizontal strip under the header.
      There is no drawer and no handle to find, so every stage is reachable at
      every width down to 390px.

   2. The decision leads. A stage opens on its proposals, each carrying the
      evidence tier it rests on and what approving it writes. Summary figures are
      one dense strip above them; charts, provenance and interpretation follow.
   ========================================================================== */

/* ------------------------------------------------------- token aliases ---
   Transitional. Each line maps a name this file already uses onto the shared
   token, so the system arrives without a rename in every rule at once. A line
   goes when its last use does. Three have no alias because the old value was
   wrong rather than different: `--t-xs` was 12px (the floor is now 12.5px at
   the token), `--ac-info` was a second blue competing with the accent, and the
   site's own dark palette is gone in favour of the shared one.            */
:root {
  --font-ui: var(--i-font);
  --font-data: var(--i-font-data);
  --t-xs: var(--i-t-xs);
  --t-code: var(--i-t-code);
  --t-sm: var(--i-t-sm);
  --t-base: var(--i-t-base);
  --t-md: var(--i-t-md);
  --t-lg: var(--i-t-lg);
  --t-xl: var(--i-t-xl);
  --t-2xl: var(--i-t-2xl);
  --t-num: var(--i-t-num-sm);
  --lh-tight: var(--i-lh-tight);
  --lh: var(--i-lh);
  --lh-loose: 1.7;   /* long reference prose only; no equivalent in the ramp */

  --s1: var(--i-s1); --s2: var(--i-s2); --s3: var(--i-s3); --s4: var(--i-s4);
  --s5: var(--i-s5); --s6: var(--i-s6); --s7: var(--i-s7);

  --r1: var(--i-r1); --r2: var(--i-r2); --r3: var(--i-r3); --rf: var(--i-rf);

  --rail-w: 264px;
  --measure: var(--i-measure);

  --canvas: var(--i-canvas);
  --canvas-line: var(--i-canvas-line);

  --primary: var(--i-accent);
  --primary-2: var(--i-accent-strong);
  --primary-soft: var(--i-accent-wash);

  --bg: var(--i-page);
  --surface: var(--i-surface);
  --surface-2: var(--i-surface-2);
  --surface-3: var(--i-surface-3);

  --rail: var(--i-surface);
  --rail-fg: var(--i-ink);
  --rail-mute: var(--i-ink-3);
  --rail-line: var(--i-line);
  --rail-active-bg: var(--i-accent-wash);

  --ink: var(--i-ink);
  --ink-2: var(--i-ink-2);
  --ink-3: var(--i-ink-3);
  --mute: var(--i-ink-3);
  --line: var(--i-line);
  --line-2: var(--i-line-2);

  --shadow: var(--i-shadow);
  --ring: var(--i-accent);

  --ac-ok: var(--i-ok);     --ac-okbg: var(--i-ok-wash);
  --ac-warn: var(--i-warn); --ac-warnbg: var(--i-warn-wash);
  --ac-bad: var(--i-bad);   --ac-badbg: var(--i-bad-wash);
  --ac-info: var(--i-accent); --ac-infobg: var(--i-accent-wash);
}

/* ------------------------------------------------------------- baseline */
* { box-sizing: border-box; }
html, body { margin: 0; }
/* instrument.css already sets the face, the ground, the leading, the selection
   colour, the caret, the scrollbars and the focus ring. Only the differences
   from it live here: this is a dense instrument, so body copy sits at full ink
   rather than at the prose tier, and headings keep their own margins. */
body { color: var(--ink); }
h1, h2, h3, h4 { margin: 0; }
a { text-decoration: none; }
a:hover { text-decoration: underline; }
.tabular { font-family: var(--font-data); font-variant-numeric: tabular-nums; }
code { overflow-wrap: anywhere; }
/* the UA default for sub/sup is `smaller`, which drops a 12px caption to 10px */
sub, sup { font-size: max(12px, 0.78em); line-height: 0; }
input, select, button, textarea { font-family: inherit; }
input[type='search']::-webkit-search-cancel-button { cursor: pointer; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- shell */
.ac-shell {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  min-height: 100vh;
  align-items: stretch;
}

/* ----------------------------------------------------------------- rail */
.ac-rail {
  background: var(--rail);
  color: var(--rail-fg);
  border-right: 1px solid var(--rail-line);
  position: sticky;
  top: 0;
  height: 100vh;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: var(--s5) var(--s3) var(--s4);
  overflow-y: auto;
}
.ac-brand { display: flex; align-items: center; gap: 11px; padding: 0 var(--s2) var(--s5); }
.ac-logo {
  width: 36px; height: 36px; border-radius: var(--r2); flex: none;
  display: grid; place-items: center;
  background: var(--primary); color: #fff;
}
:root[data-theme='dark'] .ac-logo { color: var(--i-page); }
.ac-tt b { display: block; font-size: var(--t-md); font-weight: 700; letter-spacing: var(--i-track-title); color: var(--rail-fg); }
.ac-tt span { display: block; font-size: var(--t-xs); color: var(--rail-mute); }

.ac-nav { display: block; }
.ac-nav-grp { margin-bottom: var(--s4); }
.ac-lbl {
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--rail-mute); padding: var(--s2) var(--s3) var(--s1);
}
.ac-nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: 1px solid transparent; background: transparent; text-align: left;
  color: var(--rail-fg); font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 500;
  padding: 9px var(--s3); border-radius: var(--r2);
  margin-bottom: 2px; cursor: pointer; position: relative; min-height: 38px;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.ac-nav-item:active:not(:disabled) { transform: scale(.985); }
.ac-nav-item .ni { width: 18px; display: grid; place-items: center; color: var(--i-ink-3); flex: none; }
.ac-nav-item .nt { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (hover: hover) and (pointer: fine) {
  .ac-nav-item:hover:not(:disabled) { background: var(--surface-3); }
}
/* You are here: the wash, the full 1px accent border and the weight say it together.
   The 3px coloured stripe this carried is gone; no surface in the system wears one. */
.ac-nav-item.active {
  background: var(--rail-active-bg); border-color: var(--i-accent-line);
  color: var(--ink); font-weight: 700;
}
.ac-nav-item.active .ni { color: var(--primary); }
.ac-nav-item:disabled { color: var(--i-ink-3); cursor: default; }
.ac-nav-item:disabled .ni { opacity: .55; }
.ac-nav-item .cnt {
  margin-left: auto; font-size: var(--t-xs); font-weight: 700; padding: 1px 7px;
  border-radius: var(--rf); font-family: var(--font-data);
  font-variant-numeric: tabular-nums; flex: none;
  background: var(--surface-3); color: var(--ink-2);
}
.ac-nav-item .cnt.bad { background: var(--ac-badbg); color: var(--ac-bad); }
.ac-nav-item .cnt.warn { background: var(--ac-warnbg); color: var(--ac-warn); }
.ac-nav-item .cnt.ok { background: var(--ac-okbg); color: var(--ac-ok); }
/* A stage that has not run yet. Not a numeral, not a glyph, not a colour: the words,
   in the prose face, at the muted tier. The same rendering the whole system uses. */
.ac-nav-item .cnt.txt { font-family: var(--font-ui); font-weight: 600; }
.ac-nav-item .cnt.na {
  background: none; padding: 1px 0; font-family: var(--font-ui); font-weight: 500;
  color: var(--i-ink-3);
}
.ac-rail-foot { margin-top: auto; padding: var(--s4) var(--s3) 0; border-top: 1px solid var(--rail-line); }
.ac-refline { font-size: var(--t-xs); color: var(--rail-mute); line-height: var(--lh-loose); }
/* The badge column carries two quantities: findings on a pipeline stage, approvals on
   Deliver. Every badge also names its own quantity in a title and an aria-label, and the
   review strip under the header states the same ratio in words at every width. */
.ac-nav-key { font-size: var(--t-xs); color: var(--rail-mute); line-height: var(--lh-loose); margin: var(--s3) 0 0; }
.ac-nav-key b { color: var(--rail-fg); font-weight: 600; }
.ac-refline b { color: var(--rail-fg); font-weight: 600; }
/* inline-block with vertical padding so the short label still clears the 24px tap-target floor */
.ac-refline a { color: var(--primary); display: inline-block; padding: 5px 0; }

/* ----------------------------------------------------------------- main */
.ac-main { min-width: 0; display: flex; flex-direction: column; }
.ac-top {
  min-height: 56px; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s5); border-bottom: 1px solid var(--line);
  background: var(--surface); position: sticky; top: 0; z-index: 20; flex-wrap: wrap;
}
/* The stage's name, printed once. Above 1080px the sticky header carries it, so it stays
   on screen while a long queue is scrolled; below 1080px the strip is the breadcrumb and
   the stage prints it instead. The two used to appear a few pixels apart, which cost about
   40px directly above the first proposal on the screen where the fold is tightest.

   The header copy is chrome, not a heading. The stage's own h2 stays in the document and in
   the accessibility tree at every width, so the section keeps exactly one heading and a
   reader navigating by headings still lands on it; above 1080px it is only taken out of the
   visual flow. */
.ac-crumbs { font-size: var(--t-md); font-weight: 700; color: var(--ink); margin: 0; letter-spacing: var(--i-track-title); }
@media (min-width: 1080px) {
  .ac-sh h2 {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}
.ac-modelchip {
  font-size: var(--t-xs); font-family: var(--font-data);
  font-variant-numeric: tabular-nums; color: var(--ink-2);
  background: var(--surface-3); border-radius: var(--r1);
  padding: 4px 10px; overflow-wrap: anywhere;
}
.ac-modelchip b { color: var(--primary); }
.ac-topacts { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
.ac-toplink { font-size: var(--t-sm); color: var(--ink-2); padding: 6px 10px; border-radius: var(--r1); }
.ac-toplink .sm { display: none; }
.theme-toggle {
  width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid var(--line-2);
  background: var(--surface); color: var(--ink-2); border-radius: var(--r1); cursor: pointer; flex: none;
  transition: color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.theme-toggle:active { transform: scale(.97); }
.theme-toggle .i-sun { display: none; }
:root[data-theme='dark'] .theme-toggle .i-sun { display: block; }
:root[data-theme='dark'] .theme-toggle .i-moon { display: none; }

/* Switching stage is the main verb of this product and is fired tens of times in a
   session, so it does not animate. The stage appears. */
/* The review strip's own rule separates the header from the stage, so the stage does not
   pay for that separation twice. */
.ac-stage { display: none; padding: var(--s4) var(--s5) var(--s5); max-width: 1180px; margin: 0 auto; width: 100%; }
.ac-stage.active { display: block; }

/* ------------------------------------------------------- review progress --
   The one thing this page exists to report: how much of what it proposed has been
   decided. Under the header at every width, so position and what is still
   unreviewed are legible without opening a stage. */
.ac-review {
  display: flex; align-items: center; gap: var(--s3) var(--s5); flex-wrap: wrap;
  max-width: 1180px; width: 100%; margin: 0 auto;
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--line);
}
.ac-review[hidden] { display: none; }
.ac-review p { margin: 0; max-width: none; }
.ac-review .fig { display: flex; align-items: baseline; gap: var(--s2); }
.ac-review .fig .n {
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: var(--i-t-num-sm); font-weight: 700; line-height: 1.1;
  letter-spacing: var(--i-track-display); color: var(--ink);
}
.ac-review .fig .of { font-size: var(--t-sm); color: var(--ink-2); }
.ac-review .of b { font-family: var(--font-data); font-variant-numeric: tabular-nums; font-weight: 600; }
.ac-review .split { font-size: var(--t-sm); color: var(--ink-3); }
.ac-review .split b { font-family: var(--font-data); font-variant-numeric: tabular-nums; color: var(--ink-2); font-weight: 600; }
.ac-review .split .a { color: var(--ac-ok); }
.ac-review .split .r { color: var(--ac-bad); }
/* A partition of one total, drawn on the data canvas in the composition ramp:
   a share of the answer is part of the answer, never a status colour. */
.ac-revbar {
  display: flex; height: 10px; overflow: hidden; flex: 1 1 180px; min-width: 140px;
  max-width: 420px; border: 1px solid var(--canvas-line); border-radius: var(--r1);
  background: var(--canvas);
}
.ac-revbar > span { display: block; height: 100%; }
.ac-revbar .seg-a { background: var(--i-seq-1); }
.ac-revbar .seg-r { background: var(--i-seq-3); }
.ac-revbar .seg-p { background: var(--i-seq-0); }

/* ------------------------------------------------------- error and status */
/* One composed, persistent error region. A native alert() cannot be re-read,
   is suppressed by some browsers, and leaves the page looking untouched. */
.ac-error {
  margin: var(--s4) var(--s5) 0; padding: var(--s4);
  border: 1px solid var(--ac-bad);
  background: var(--ac-badbg); border-radius: var(--r2); max-width: 1180px;
  align-self: center; width: calc(100% - 2 * var(--s5));
}
.ac-error[hidden] { display: none; }
.ac-error h2 { font-size: var(--t-md); margin: 0 0 var(--s1); color: var(--ac-bad); }
.ac-error p { font-size: var(--t-sm); margin: 0 0 var(--s2); color: var(--ink-2); line-height: var(--lh); max-width: var(--measure); }
.ac-error p:last-child { margin-bottom: 0; }
/* The reader's message runs to several lines. An inline background breaks across every
   one of them and reads as a patchwork, so the quoted text is set in the data face at full
   ink and carries no fill of its own. */
.ac-error code { background: none; padding: 0; color: var(--ink); }
.ac-error p b { color: var(--ink); font-weight: 600; }
.ac-error .ac-btn { margin-top: var(--s2); }

/* -------------------------------------------------------- upload and hero */
/* Before a model is loaded the intake IS the tool, so it comes first in the document
   and leads the first screen at every width. On a wide screen it takes the right
   column and the description sits beside it; below 1000px the description follows it. */
.ac-lede { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(340px, .95fr); gap: var(--s5) var(--s7); align-items: start; }
.ac-hero { max-width: 58ch; grid-column: 1; grid-row: 1; }
.ac-hero h1 { font-size: var(--t-2xl); letter-spacing: var(--i-track-display); margin: 0 0 var(--s3); }
.ac-hero p { font-size: var(--t-base); color: var(--ink-2); line-height: var(--lh); margin: 0 0 var(--s4); }
.ac-hero p b { color: var(--ink); font-weight: 600; }
.ac-hero p.ac-back { font-size: var(--t-sm); color: var(--ink-3); margin-bottom: 0; }
.ac-intake { min-width: 0; grid-column: 2; grid-row: 1; }
.ac-intake .ac-drop { margin-top: 0; }
.ac-privacy { font-size: var(--t-xs); color: var(--ink-3); margin: var(--s3) 0 0; line-height: var(--lh); max-width: var(--i-measure-tight); }
/* What the tool does with the file, stated as a fact about the flow, in the place
   where the reader is about to hand it over. */
.ac-promise { font-size: var(--t-sm); color: var(--ink-2); margin: var(--s3) 0 0; max-width: var(--i-measure-tight); }
.ac-promise b { color: var(--ink); font-weight: 600; }

.ac-drop {
  margin: 0 0 var(--s3); border: 1px dashed var(--line-2); border-radius: var(--r2);
  background: var(--surface); padding: var(--s6) var(--s4); text-align: center; cursor: pointer;
  transition: border-color var(--i-d-hover) ease, background-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.ac-drop:active { transform: scale(.99); }
@media (hover: hover) and (pointer: fine) {
  .ac-drop:hover { border-color: var(--primary); background: var(--primary-soft); }
}
.ac-drop.drag { border-color: var(--primary); background: var(--primary-soft); }
.ac-drop svg { color: var(--primary); }
.ac-drop-t { font-size: var(--t-md); font-weight: 600; margin-top: var(--s2); color: var(--ink); }
/* not a control of its own: the whole drop zone is the control, and this is the part of it
   that reads as clickable */
.ac-drop-browse { font-weight: 600; color: var(--primary); text-decoration: underline; text-underline-offset: 3px; }
.ac-drop-s { font-size: var(--t-xs); color: var(--mute); margin-top: var(--s1); font-family: var(--font-data); }
.ac-examples { font-size: var(--t-sm); color: var(--ink-2); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.ac-ex {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink);
  font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 600;
  padding: 8px 13px; border-radius: var(--r1); cursor: pointer; min-height: 34px;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.ac-ex:active { transform: scale(.97); }
.ac-ex i { color: var(--primary); }
.ac-load { display: flex; align-items: center; gap: var(--s3); margin: var(--s4) 0; font-size: var(--t-sm); color: var(--ink-2); }
.ac-spin {
  width: 20px; height: 20px; border: 3px solid var(--line-2); border-top-color: var(--primary);
  border-radius: 50%; animation: acspin .9s linear infinite; flex: none;
}
@keyframes acspin { to { transform: rotate(360deg); } }

/* What each stage checks. One panel of ordered rows, not six containers of the same
   size: the rail already carries the order, and this only has to say what each step
   looks at. */
.ac-pp-h { font-size: var(--t-lg); margin: var(--s6) 0 var(--s3); }
.ac-pipeline-preview {
  border: 1px solid var(--line); border-radius: var(--r2); background: var(--surface);
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 0 var(--s5); padding: var(--s2) var(--s4);
}
.ac-pp-card { display: grid; grid-template-columns: 1.6em 1fr; gap: 0 var(--s2); padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.ac-pp-card:last-child { border-bottom: 0; }
.ac-pp-card i {
  grid-row: 1 / span 2; font-style: normal; font-family: var(--font-data);
  font-variant-numeric: tabular-nums; font-size: var(--t-sm); font-weight: 500; color: var(--ink-3);
  padding-top: 1px;
}
.ac-pp-card b { font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
.ac-pp-card span { font-size: var(--t-xs); font-weight: 400; letter-spacing: 0; color: var(--ink-2); line-height: var(--lh); display: block; }
@media (min-width: 820px) {
  /* Two columns of three, filled column by column, so the last row is always full
     and no cell is ever left facing an empty one. */
  .ac-pipeline-preview { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-flow: column; grid-template-rows: repeat(3, auto); }
  .ac-pp-card:nth-child(3), .ac-pp-card:nth-child(6) { border-bottom: 0; }
}

/* --------------------------------------------- stage headers, KPIs, cards */
.ac-sh { margin-bottom: var(--s4); }
.ac-sh h2 { font-size: var(--t-xl); margin: 0 0 var(--s2); }
.ac-sh p { font-size: var(--t-sm); color: var(--ink-2); margin: 0 0 var(--s2); max-width: var(--measure); line-height: var(--lh); }
.ac-sh p:last-child { margin-bottom: 0; }
/* The stage definition. Wide: open, and its own summary is not drawn, so it reads as a
   paragraph. Narrow: a closed disclosure with a real control, so the queue leads the
   screen and the definition is one press away rather than a screen of scroll. */
.ac-def > summary {
  display: none; align-items: center; gap: var(--s2);
  font-size: var(--t-sm); font-weight: 600; color: var(--primary);
  cursor: pointer; padding: var(--s1) 0; list-style: none; width: max-content;
}
.ac-def > summary::-webkit-details-marker { display: none; }
.ac-def[open] > summary .ac-caret { transform: rotate(90deg); }
@media (max-width: 1079px) {
  .ac-def > summary { display: inline-flex; }
  .ac-def[open] .ac-defbody { padding-top: var(--s2); }
}
/* Provenance: which reference release produced these numbers. One line, at the foot
   of the stage, in the muted tier. No coloured rule beside it. */
.ac-prov {
  font-size: var(--t-xs); color: var(--ink-3); line-height: var(--lh-loose);
  margin: var(--s5) 0 0; max-width: var(--measure);
}
.ac-prov b { color: var(--ink-2); font-weight: 600; }
/* colour key for the evidence rings, so a downloaded PNG's colours can still be read */
.ac-figkey { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); margin-top: var(--s3); font-size: var(--t-xs); color: var(--ink-2); }
.ac-figkey span { display: inline-flex; align-items: center; gap: 6px; }
.ac-figkey i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
/* caption under a figure row: describes the display and its denominators */
.ac-figcap { font-size: var(--t-xs); color: var(--ink-3); line-height: var(--lh-loose); margin-top: var(--s3); max-width: var(--measure); }
.ac-figcap b { color: var(--ink-2); font-weight: 600; }
/* One dense strip of figures, not a grid of tiles. Cells grow to fill the last line,
   so a set of nine never leaves a ragged row of holes, and each one is a value with
   its denominator rather than a card with a number in the corner.

   Colour rule, and the reason this is a strip and not nine coloured tiles: a MEASURED
   ZERO is a real number and renders in ink. Only a non-zero count that carries a
   verdict takes a verdict colour, and no cell wears a coloured stripe. Seven green
   zeros on this screen is what that rule exists to prevent; the number itself is
   untouched. A value that is not a number at all ("not run", "not measured") renders
   in the prose face at the muted tier, never as a numeral. */
.ac-kpis {
  display: flex; flex-wrap: wrap; gap: var(--s4) var(--s5);
  margin: var(--s4) 0 var(--s5); padding: var(--s4);
  border: 1px solid var(--line); border-radius: var(--r2); background: var(--surface);
}
.ac-kpi { flex: 1 1 190px; max-width: 340px; min-width: 0; }
.ac-kpi .v {
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: var(--t-num); font-weight: 700; letter-spacing: var(--i-track-display);
  line-height: 1.15; color: var(--ink); overflow-wrap: anywhere;
}
.ac-kpi .v.wide { font-size: var(--t-lg); }
.ac-kpi .v.na {
  font-family: var(--font-ui); font-variant-numeric: normal; font-size: var(--t-md);
  font-weight: 400; letter-spacing: 0; color: var(--ink-3);
}
.ac-kpi .l { font-size: var(--t-xs); letter-spacing: .01em; color: var(--ink-3); margin-top: var(--s1); font-weight: 500; line-height: 1.4; }
/* `info` is a neutral fact, not a verdict, so it keeps the ink the default gives it. */
.ac-kpi.ok .v { color: var(--ac-ok); }
.ac-kpi.warn .v { color: var(--ac-warn); }
.ac-kpi.bad .v { color: var(--ac-bad); }
.ac-kpi .v.na { color: var(--ink-3); }

.ac-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r2);
  padding: var(--s4) var(--s4) var(--s5); margin-bottom: var(--s4); min-width: 0;
}
.ac-card h3 { font-size: var(--t-md); margin: 0 0 var(--s1); }
.ac-card h3 .note { font-weight: 400; color: var(--ink-3); }
.ac-card .sub { font-size: var(--t-sm); color: var(--ink-3); margin: 0 0 var(--s3); line-height: var(--lh); max-width: var(--measure); }
/* Card title and its one-line note share a row where there is room, for the same reason the
   stage head does: every line above the first proposal is a line the decision sits lower by. */
@media (min-width: 1000px) {
  .ac-cardhead { display: grid; grid-template-columns: minmax(0, 15em) minmax(0, 1fr); gap: var(--s5); align-items: baseline; margin-bottom: var(--s3); }
  .ac-cardhead h3 { margin: 0; }
  .ac-cardhead .sub { margin: 0; }
}
.ac-card .sub:last-child { margin-bottom: 0; }
.ac-plot { width: 100%; background: var(--canvas); border: 1px solid var(--canvas-line); border-radius: var(--r1); overflow: hidden; }
.ac-vizgrid { display: grid; grid-template-columns: 1fr 1fr 1.4fr; gap: var(--s3); }

/* Native controls take the accent too: an unthemed range or checkbox is the one
   surface on the page still painted by the browser. */
input[type='range'], input[type='checkbox'], input[type='radio'], progress { accent-color: var(--primary); }
.ac-phrow { display: flex; align-items: center; gap: var(--s4); margin-top: var(--s3); }
.ac-phrow input[type='range'] { flex: 1; min-width: 0; }
.ac-phrow .end { font-size: var(--t-xs); color: var(--ink-2); font-family: var(--font-data); }
.ac-phrow .val {
  font-size: var(--i-t-num-sm); font-weight: 700; color: var(--ink);
  letter-spacing: var(--i-track-display); min-width: 56px; text-align: right;
}

.ac-interp {
  font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh); margin-top: var(--s4);
  padding: var(--s4); background: var(--primary-soft);
  border: 1px solid var(--i-accent-line); border-radius: var(--r2);
  max-width: var(--measure);
}
.ac-interp b { color: var(--ink); font-weight: 600; }

/* ---------------------------------------- findings, approve and reject UI */
/* An approval is pressed hundreds of times in a session, so its only feedback is the
   press itself: 120ms, scale(.97), and the row's own state changing under it.
   Nothing here animates on hover except the fill, and nothing moves a row. */
/* The batch bar now renders UNDER the rows it acts on, so its breathing room
   is above it. */
.ac-batchbar { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }
.ac-btn {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink);
  font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 600;
  padding: 8px 13px; border-radius: var(--r1); cursor: pointer; min-height: 34px;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.ac-btn:active:not(:disabled) { transform: scale(.97); }
.ac-btn:disabled { opacity: .55; cursor: not-allowed; }
.ac-btn:disabled:active { transform: none; }
.ac-btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
:root[data-theme='dark'] .ac-btn.primary { color: var(--i-page); }
.ac-btn.ok { border-color: var(--ac-ok); color: var(--ac-ok); }
.ac-btn.bad { border-color: var(--ac-bad); color: var(--ac-bad); }
/* The batch APPROVE control carries the caution outline: approving is the act
   that writes to the exported model, so the red rides on the writer, not on
   Reject, which keeps the reader's own file untouched. */
.ac-btn.write { border-color: var(--ac-bad); color: var(--ac-bad); }

/* review queue: facets by evidence, a filter, and both numbers on the page count */
/* The facets and the filter narrow the same list, so they share one row wherever they fit. */
.ac-queuehead { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); margin-bottom: var(--s3); }
.ac-queuehead .ac-facets { margin-bottom: 0; flex: 1 1 auto; min-width: 0; }
.ac-queuehead .ac-filterwrap { margin-bottom: 0; flex: 0 1 240px; min-width: 180px; }
.ac-queuehead .ac-filter { max-width: none; padding: 6px 12px; min-height: 32px; }
.ac-facets { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s2); }
.ac-facet {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: var(--t-sm); font-weight: 500; padding: 6px 12px; border-radius: var(--r1);
  cursor: pointer; min-height: 32px;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              color var(--i-d-hover) ease, transform var(--i-d-press) var(--i-ease-out);
}
.ac-facet:active { transform: scale(.97); }
.ac-facet b { font-family: var(--font-data); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); margin-left: var(--s1); }
.ac-facet-hint { font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh); margin-bottom: var(--s3); max-width: var(--measure); }
.ac-facet-hint.warn { color: var(--ac-warn); font-weight: 600; }
.ac-filterwrap { margin-bottom: var(--s3); }
.ac-inlab { display: block; font-size: var(--t-xs); font-weight: 600; color: var(--ink-3); margin-top: var(--s3); }
.ac-filter {
  width: 100%; max-width: 520px; padding: 9px 12px; border: 1px solid var(--line-2);
  border-radius: var(--r1); background: var(--surface); color: var(--ink); font-size: var(--t-sm);
}
.ac-filter::placeholder { color: var(--ink-3); }
.ac-listcount { font-size: var(--t-sm); color: var(--ink-3); margin-bottom: var(--s2); }
.ac-listcount b { color: var(--ink); font-family: var(--font-data); }
.ac-more { margin-top: var(--s3); }
.ac-progress { font-size: var(--t-sm); color: var(--ink-2); margin-top: var(--s3); min-height: 1.4em; }
.ac-progress b { font-family: var(--font-data); color: var(--ink); }
.ac-progress .bad { color: var(--ac-bad); }
.ac-batchinfo { font-size: var(--t-sm); color: var(--ink-3); margin-right: auto; }
.ac-batchinfo b { color: var(--ink); font-family: var(--font-data); font-variant-numeric: tabular-nums; }
.ac-batchinfo b.ok { color: var(--ac-ok); }
.ac-batchinfo b.bad { color: var(--ac-bad); }
/* What approving and rejecting on this list do, directly above the rows they do it to,
   so the consequence of either decision is on screen at the moment of every click. */
.ac-consequence { font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh); margin: 0 0 var(--s3); max-width: var(--measure); }
.ac-consequence[hidden] { display: none; }
/* how the hold control is used, beside it and constant: nothing above the control moves
   while it is being held */
.ac-holdnote { font-size: var(--t-xs); color: var(--ink-3); line-height: var(--lh); flex: 1 1 220px; min-width: 180px; }
.ac-consequence b { color: var(--ink); font-weight: 600; }

/* THE ONE AUTHORED MOMENT ON THIS SITE, and the only place its motion budget is spent.
   Approving a batch that rests on weak evidence is the act that writes the most into a
   model on the least evidence, and a double click used to complete it. It is now hold
   to confirm: a fill reports the hold over 1.2s LINEAR, because a fill that reports
   progress must not ease, and it snaps back in 180ms ease-out on release. Asymmetric on
   purpose: slow where the scientist is deciding, fast where the system responds.
   Keyboard activation and reduced motion both take the two-press path instead, which
   asks for the same deliberate second act without asking anyone to hold a key down. */
.ac-btn.hold { position: relative; overflow: hidden; }
.ac-btn.hold .lb { position: relative; }
.ac-btn.hold .fill {
  position: absolute; inset: 0; background: var(--ac-warnbg);
  clip-path: inset(0 100% 0 0);
  transition: clip-path 180ms var(--i-ease-out);
}
.ac-btn.hold.holding .fill { clip-path: inset(0); transition: clip-path 1200ms linear; }

/* What the decision just made does to the objective the model predicts. It sits under the approve
   buttons because that is where the decision is made; it states a number or the reason there is
   none, and never renders an uncomputed value as 0 or as "unchanged". */
.ac-pheno {
  font-size: var(--t-sm); line-height: var(--lh); color: var(--ink-2);
  border: 1px solid var(--line); padding: var(--s3) var(--s4);
  background: var(--surface-2); border-radius: var(--r2);
  margin: 0 0 var(--s3); max-width: var(--measure);
}
.ac-pheno b { color: var(--ink); font-weight: 600; }
.ac-pheno.ok { border-color: var(--ac-ok); background: var(--ac-okbg); }
.ac-pheno.warn { border-color: var(--ac-warn); background: var(--ac-warnbg); }
.ac-pheno.bad { border-color: var(--ac-bad); background: var(--ac-badbg); }
/* the same verdict, stated once at the top of the report card */
.ac-verdict {
  font-size: var(--t-base); line-height: var(--lh); color: var(--ink);
  border: 1px solid var(--line); padding: var(--s4);
  background: var(--surface-2); border-radius: var(--r2);
  margin: 0 0 var(--s3); max-width: var(--measure);
}
.ac-verdict.ok { border-color: var(--ac-ok); background: var(--ac-okbg); }
.ac-verdict.warn { border-color: var(--ac-warn); background: var(--ac-warnbg); }
.ac-verdict.bad { border-color: var(--ac-bad); background: var(--ac-badbg); }
.ac-verdict.info { border-color: var(--i-accent-line); background: var(--primary-soft); }

/* ------------------------------------------------------------ the proposal row
   The product IS this row. It has to carry, without the reader leaving it: what
   changes, why, the evidence tier the change rests on, what approving writes, and
   the two decision controls. Semantic colour appears only on a row that carries a
   decision, and nothing here wears a coloured side stripe. */
.ac-issues { display: flex; flex-direction: column; gap: var(--s2); }
.ac-issue {
  display: flex; align-items: flex-start; gap: var(--s3); background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r2); padding: var(--s3) var(--s4); min-width: 0;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease;
}
/* The row's own state lives in its BORDER and in its toggled control, not in a wall of
   wash. A wash of the same hue swallows the evidence chip sitting on it, and the evidence
   tier has to stay legible after the decision as well as before it: an approved row whose
   chip has disappeared no longer says what the approval rested on. Rejected rows drop to
   the inset ground so a set-aside proposal reads as set aside, and keep full text
   contrast, because a faded row is not a record of a decision. */
.ac-issue.sev-bad { border-color: var(--ac-bad); }
.ac-issue.approved { border-color: var(--ac-ok); }
.ac-issue.rejected { background: var(--surface-2); border-color: var(--line-2); }
.ac-issue .txt { flex: 1; min-width: 0; }
.ac-issue .ttl { font-size: var(--t-sm); font-weight: 600; line-height: 1.45; color: var(--ink); overflow-wrap: anywhere; }
.ac-issue .ttl code, .ac-issue .fix code { background: var(--surface-3); padding: 1px 5px; border-radius: var(--r1); }
.ac-issue .fix { font-size: var(--t-sm); color: var(--ink-2); margin-top: var(--s1); line-height: var(--lh); overflow-wrap: anywhere; }
.ac-issue .fix .to { color: var(--ac-ok); font-weight: 600; font-family: var(--font-data); }
.ac-issue .fix .from { color: var(--ac-bad); text-decoration: line-through; font-family: var(--font-data); }
.ac-issue .note { font-size: var(--t-xs); color: var(--ink-2); line-height: var(--lh); margin-top: var(--s1); }
/* the chip line: evidence tier first, then what approving this one writes */
.ac-chips { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); margin-top: var(--s2); align-items: center; }

/* The evidence tier rides on the row the user approves, drawn from the shared
   ordinal scale, so a structural match and a name guess can never be read as peers
   at the instant of the click. `derived` is not weaker evidence, it is a different
   kind of thing (an identifier built from a name, matched to nothing), so it keeps
   its own hue and the dashed rule the whole system gives that class. */
.ac-tier {
  display: inline-flex; align-items: center; vertical-align: middle;
  padding: 3px var(--s2); border-radius: var(--r1);
  font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--i-track-label);
  white-space: nowrap;
  background: var(--surface-3); color: var(--ink-2);
}
.ac-tier.ev1 { background: var(--i-ev-1-wash); color: var(--i-ev-1); }
.ac-tier.ev2 { background: var(--i-ev-2-wash); color: var(--i-ev-2); }
.ac-tier.ev3 { background: var(--i-ev-3-wash); color: var(--i-ev-3); }
.ac-tier.ev4 { background: var(--i-ev-4-wash); color: var(--i-ev-4); }
.ac-tier.ev5 { background: var(--i-ev-5-wash); color: var(--i-ev-5); }
.ac-tier.evd {
  background: var(--i-ev-d-wash); color: var(--i-ev-d);
  border: 1px dashed currentColor; padding: 2px calc(var(--s2) - 1px);
}
/* what approving this row writes: a category, never a verdict, so never a verdict colour */
.ac-outcome {
  display: inline-flex; align-items: center; padding: 3px var(--s2);
  border-radius: var(--r1); font-size: var(--t-xs); font-weight: 500;
  background: var(--surface-3); color: var(--ink-2); white-space: nowrap;
}
/* a finding the file's own curation ledger already records: continuity, not a verdict,
   so it takes the accent wash and never an evidence colour */
.ac-outcome.ac-prior { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.ac-tierkey {
  display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center;
  margin: var(--s1) 0 var(--s3); font-size: var(--t-xs); color: var(--ink-2);
}
.ac-acts { display: flex; gap: var(--s2); flex: none; }
.ac-acts button {
  min-height: 34px; padding: 0 var(--s3); border-radius: var(--r1);
  border: 1px solid var(--line-2);
  background: var(--surface); cursor: pointer; display: inline-flex; align-items: center;
  color: var(--ink-2); font-family: var(--font-ui); font-size: var(--t-xs); font-weight: 600;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              color var(--i-d-hover) ease, transform var(--i-d-press) var(--i-ease-out);
}
.ac-acts button:active { transform: scale(.97); }

/* Empty state, composed rather than blank: a stage that raised nothing says what it
   compared, and a stage that has not run says that instead. The tick that used to stand
   at the top of this block claimed a verdict the sentence underneath sometimes withheld. */
.ac-empty {
  color: var(--ink-2); padding: var(--s5) var(--s4); font-size: var(--t-sm);
  max-width: 62ch; margin: 0 auto; line-height: var(--lh);
  border: 1px dashed var(--line-2); border-radius: var(--r2); background: var(--surface);
}
.ac-empty b { color: var(--ink); font-weight: 600; }

.ac-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs);
  padding: 4px 10px; border-radius: var(--r1); background: var(--surface-3);
  color: var(--ink-2);
}
/* an inset note beside the thing it qualifies: wash, full 1px border, no side stripe */
.ac-callout {
  font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh);
  margin: var(--s2) 0; padding: var(--s3) var(--s4);
  border: 1px solid var(--line); border-radius: var(--r2); background: var(--surface-2);
  max-width: var(--measure);
}
.ac-callout b { color: var(--ink); font-weight: 600; }
.ac-callout.warn { background: var(--ac-warnbg); border-color: var(--ac-warn); }
.ac-callout.warn b { color: var(--ac-warn); }
.ac-strain { color: var(--primary); font-family: var(--font-data); }
/* a one-line note on the value beside it, at the label step, in the shared verdict inks */
.ac-flag { font-size: var(--t-xs); color: var(--ink-3); }
.ac-flag.ok { color: var(--ac-ok); }
.ac-flag.warn { color: var(--ac-warn); }
.ac-flag b { font-weight: 600; }
/* the composite grade letter: the display step, at the ramp's top weight */
.ac-grade { font-size: var(--i-t-num); font-weight: 700; line-height: var(--i-lh-tight); letter-spacing: var(--i-track-display); }
.ac-secrow { display: inline-flex; align-items: baseline; gap: var(--s2); margin: 0 var(--s3) var(--s2) 0; font-size: var(--t-sm); color: var(--ink-2); }
.ac-secrow b { color: var(--ink); font-family: var(--font-data); font-weight: 500; }
.ac-n { color: var(--ink-3); font-weight: 400; font-size: var(--t-xs); }
/* a collapsible group of experimental records: a real control, with a drawn caret */
.ac-grouphdr {
  display: flex; align-items: center; gap: var(--s2); width: 100%;
  background: none; border: 0; padding: var(--s1) 0; cursor: pointer;
  font: inherit; text-align: left; color: var(--ink);
}
.ac-grouptitle { font-size: var(--t-sm); font-weight: 700; letter-spacing: var(--i-track-label); flex: 1; min-width: 0; }
.ac-caret {
  display: inline-flex; color: var(--ink-3); flex: none;
  transition: transform var(--i-d-press) var(--i-ease-out);
}
.ac-caret.open { transform: rotate(90deg); }
.ac-removebtn {
  background: none; border: 1px solid var(--line-2); border-radius: var(--r1);
  color: var(--ink-2); cursor: pointer; font: inherit; font-size: var(--t-xs);
  font-weight: 600; padding: 5px var(--s2); min-height: 28px;
  transition: background-color var(--i-d-hover) ease, border-color var(--i-d-hover) ease,
              color var(--i-d-hover) ease, transform var(--i-d-press) var(--i-ease-out);
}
.ac-removebtn:active { transform: scale(.97); }

/* -------------------------------------------------------------- roadmap */
.ac-roadmap { border: 1px dashed var(--line-2); border-radius: var(--r2); padding: var(--s4) var(--s5); background: var(--surface-2); }
.ac-roadmap h3 { margin: 0 0 var(--s1); }
.ac-roadmap .tag {
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  background: var(--ac-infobg); color: var(--ac-info); padding: 2px 8px; border-radius: var(--r1); margin-left: var(--s2);
}
.ac-roadmap ul { margin: var(--s2) 0 0; padding-left: 20px; }
.ac-roadmap li { font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh); }

/* --------------------------------------------------------------- export */
.ac-export { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s3); margin-top: var(--s2); }
.ac-dl {
  display: flex; align-items: center; gap: var(--s3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r2); padding: var(--s3) var(--s4);
  cursor: pointer; text-align: left; width: 100%; font: inherit; color: inherit;
  transition: border-color var(--i-d-hover) ease, background-color var(--i-d-hover) ease,
              transform var(--i-d-press) var(--i-ease-out);
}
.ac-dl:active { transform: scale(.99); }
.ac-dl .ic {
  width: 40px; height: 40px; border-radius: var(--r1); flex: none; display: grid; place-items: center;
  background: var(--primary-soft); color: var(--primary); font-weight: 700;
  font-family: var(--font-data); font-size: var(--t-xs);
}
.ac-dl .tx { min-width: 0; }
.ac-dl b { font-size: var(--t-sm); display: block; font-weight: 600; color: var(--ink); }
.ac-dl .tx span { font-size: var(--t-xs); color: var(--ink-3); display: block; line-height: 1.4; overflow-wrap: anywhere; }

/* --------------------------------------------------------------- tables */
.ac-tbl { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.ac-tbl th {
  text-align: left; font-size: var(--t-xs); letter-spacing: var(--i-track-label); color: var(--ink-2);
  padding: var(--s2); border-bottom: 1px solid var(--line); position: sticky; top: 0;
  background: var(--surface-3); font-weight: 600;
}
.ac-tbl td { padding: var(--s2); border-bottom: 1px solid var(--line); color: var(--ink-2); }
/* not computed: the words, in the prose face, at the muted tier, never a numeral */
.ac-tbl td.na, .ac-tbl .na { color: var(--ink-3); }
.ac-scroll { max-height: 460px; overflow: auto; border: 1px solid var(--line); border-radius: var(--r1); }

/* ---------------------------------------------- standalone document page */
.ac-dochead {
  display: flex; align-items: center; gap: var(--s3); min-height: 56px;
  padding: var(--s2) var(--s5); border-bottom: 1px solid var(--line);
  background: var(--surface); position: sticky; top: 0; z-index: 20;
}
.ac-docbrand { display: flex; align-items: center; gap: var(--s2); color: var(--ink); }
.ac-docbrand b { font-size: var(--t-md); font-weight: 700; letter-spacing: var(--i-track-title); white-space: nowrap; }
.ac-dochead .ac-logo { width: 28px; height: 28px; border-radius: var(--r1); }
/* One column, one measure: the container carries it, so the prose does not sit narrower
   than the cards beside it. */
.ac-doc { max-width: 72ch; margin: 0 auto; padding: var(--s6) var(--s5) var(--s7); }
.ac-doc p, .ac-doc li { max-width: none; }
.ac-toc {
  display: flex; flex-direction: column; gap: var(--s1); margin: var(--s5) 0 var(--s6);
  padding: var(--s4); border: 1px solid var(--line); border-radius: var(--r2); background: var(--surface);
}
.ac-toc b { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-bottom: var(--s1); }
.ac-toc a { font-size: var(--t-sm); padding: 3px 0; }
.ac-doc h1 { font-size: var(--t-2xl); letter-spacing: var(--i-track-display); margin: 0 0 var(--s4); }
.ac-doc h2 { font-size: var(--t-xl); margin: var(--s7) 0 var(--s3); }
.ac-doc h3 { font-size: var(--t-md); margin: var(--s5) 0 var(--s2); }
.ac-doc p, .ac-doc li { font-size: var(--t-base); color: var(--ink-2); line-height: var(--lh); }
.ac-doc p { margin: 0 0 var(--s3); }
.ac-doc ul, .ac-doc ol { margin: 0 0 var(--s3); padding-left: var(--s5); }
.ac-doc li { margin-bottom: var(--s2); }
.ac-doc li b, .ac-doc p b { color: var(--ink); font-weight: 600; }
.ac-doc code { background: var(--surface-3); padding: 1px 5px; border-radius: var(--r1); }
.ac-doc p.ac-doc-lede { font-size: var(--t-md); color: var(--ink); }
.ac-doc-stamps { margin-top: var(--s4); }
.ac-doc-stamps .ac-tbl td { vertical-align: top; }
.ac-doc-warn { color: var(--ac-warn); font-size: var(--t-sm); }
.ac-back-link { font-size: var(--t-sm); }
@media (max-width: 700px) { .ac-doc { padding: var(--s5) var(--s3) var(--s6); } }

/* --------------------------------------------------------------- footer */
.ac-footer {
  text-align: center; padding: var(--s5) var(--s4); font-size: var(--t-xs);
  color: var(--ink-3); border-top: 1px solid var(--line); background: var(--surface);
  line-height: var(--lh-loose);
}
.ac-footer a { color: var(--primary); display: inline-block; padding: 5px 2px; }


/* Hover is a pointer state. Every one of these is colour only and none of them moves
   a data row a reader is reading, and they are collected here so a touch reader never
   gets one stuck on the last thing they tapped. */
@media (hover: hover) and (pointer: fine) {
  .ac-toplink:hover { color: var(--primary); text-decoration: none; background: var(--surface-2); }
  .theme-toggle:hover { color: var(--ink); border-color: var(--primary); }
  .ac-drop:hover .ac-drop-browse { color: var(--primary-2); }
  .ac-ex:hover { background: var(--surface-3); border-color: var(--primary); }
  .ac-btn:hover { background: var(--surface-3); }
  .ac-btn.primary:hover { background: var(--primary-2); border-color: var(--primary-2); }
  .ac-btn.ok:hover { background: var(--ac-okbg); }
  .ac-btn.bad:hover { background: var(--ac-badbg); }
  .ac-btn.write:hover { background: var(--ac-badbg); }
  .ac-facet:hover { border-color: var(--primary); }
  .ac-acts button.yes:hover { background: var(--ac-okbg); border-color: var(--ac-ok); color: var(--ac-ok); }
  .ac-acts button.no:hover { background: var(--ac-badbg); border-color: var(--ac-bad); color: var(--ac-bad); }
  .ac-removebtn:hover { background: var(--ac-badbg); border-color: var(--ac-bad); color: var(--ac-bad); }
  .ac-dl:hover { border-color: var(--primary); background: var(--surface-2); }
  .ac-docbrand:hover { text-decoration: none; color: var(--primary); }
}

/* CHOSEN STATES, declared once and last.
   A state a reader has put a control into outranks a hover of equal specificity, so the
   decision they made stays visible while the pointer is over it. The pressed control is
   filled: white on the evidence-scale green measures 6.56:1 and on the red 6.54:1. */
.ac-acts button.yes.on { background: var(--ac-ok); border-color: var(--ac-ok); color: #fff; }
.ac-acts button.no.on { background: var(--ac-bad); border-color: var(--ac-bad); color: #fff; }
.ac-facet.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.ac-facet.on b { color: #fff; }
.ac-btn.arm { background: var(--ac-warnbg); border-color: var(--ac-warn); color: var(--ac-warn); }
.ac-btn.hold.holding { border-color: var(--ac-warn); color: var(--ac-warn); }
:root[data-theme='dark'] .ac-acts button.yes.on,
:root[data-theme='dark'] .ac-acts button.no.on,
:root[data-theme='dark'] .ac-facet.on,
:root[data-theme='dark'] .ac-facet.on b { color: var(--i-page); }

/* ============================== responsive ===============================
   The pipeline reflows; it is never hidden. Below 1080px the rail becomes a
   horizontal strip pinned under the top of the page, so all eight stages and
   the export tiles inside the last one stay reachable down to 390px.
   ======================================================================== */
@media (max-width: 1079px) {
  .ac-shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .ac-rail {
    position: sticky; top: 0; z-index: 30; height: auto;
    border-right: 0; border-bottom: 1px solid var(--rail-line);
    padding: var(--s2) 0 0; overflow: visible;
  }
  .ac-brand { padding: 0 var(--s4) var(--s2); }
  .ac-logo { width: 30px; height: 30px; border-radius: var(--r1); }
  .ac-logo svg { width: 17px; height: 17px; }
  /* The strip scrolls, and it has to look like it scrolls. Each edge fades only while there
     are stages past it, so the cue is never a lie: at the start of the list nothing fades on
     the left, and at the end nothing fades on the right. */
  /* The strip is a row of stage buttons and nothing else. The badge key used to sit
     inside it as a third flex child, so at 390px it became a tall narrow column of
     wrapped text and stretched every stage button to about 400px high: half the first
     screen, empty, above the one control the page exists for. The key now lives in the
     rail foot, and `align-items: flex-start` keeps any future sibling from doing it
     again. */
  .ac-nav {
    display: flex; align-items: flex-start; gap: var(--s1);
    overflow-x: auto; overscroll-behavior-x: contain;
    padding: 0 var(--s4) var(--s2); scroll-padding-inline: var(--s4);
  }
  .ac-nav[data-fade='both'] { mask-image: linear-gradient(to right, transparent 0, #000 26px, #000 calc(100% - 26px), transparent 100%); }
  .ac-nav[data-fade='end']  { mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 26px), transparent 100%); }
  .ac-nav[data-fade='start']{ mask-image: linear-gradient(to right, transparent 0, #000 26px, #000 100%); }
  /* the breadcrumb repeats the highlighted chip a few pixels above it: at this width the
     strip is the breadcrumb, and the row is better spent on the model it applies to */
  .ac-crumbs { display: none; }
  .ac-nav-grp { display: flex; gap: var(--s1); margin: 0; }
  .ac-lbl { display: none; }
  .ac-nav-item { width: auto; white-space: nowrap; margin-bottom: 0; border: 1px solid var(--line); background: var(--surface); }
  .ac-nav-item.active { border-color: var(--i-accent-line); }
  .ac-nav-item .nt { overflow: visible; }
  .ac-rail-foot { display: none; }
  .ac-review { padding: var(--s3) var(--s4) 0; }
  .ac-top { position: static; padding: var(--s2) var(--s4); }
  .ac-stage { padding: var(--s4); }
  .ac-error { margin: var(--s3) var(--s4) 0; width: calc(100% - 2 * var(--s4)); }
  .ac-vizgrid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 1000px) {
  /* One column, and the intake keeps the lead it has in the document: the drop zone is
     the first thing under the header, not a screen and a half below a description. */
  .ac-lede { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .ac-hero, .ac-intake { grid-column: 1; grid-row: auto; }
  .ac-hero { max-width: var(--measure); }
}
@media (max-width: 700px) {
  /* The display step already clamps; nothing below it shrinks. */
  /* one header row, not three: the chip shrinks with an ellipsis and keeps its full text in
     its tooltip, and the counts it abbreviates are on the stage itself */
  .ac-top { flex-wrap: nowrap; gap: var(--s2); }
  .ac-modelchip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .ac-toplink { padding: 6px 6px; white-space: nowrap; }
  .ac-dochead { padding: var(--s2) var(--s3); gap: var(--s2); }
  .ac-docbrand b { display: none; }
  .ac-toplink .lg { display: none; }
  .ac-toplink .sm { display: inline; }
  .ac-vizgrid { grid-template-columns: 1fr; }
  .ac-drop { padding: var(--s5) var(--s3); }
  .ac-stage { padding: var(--s4) var(--s3); }
  .ac-error { margin: var(--s3) var(--s3) 0; width: calc(100% - 2 * var(--s3)); }
  .ac-issue { flex-wrap: wrap; }
  .ac-acts { margin-left: auto; }
  .ac-kpis { gap: var(--s4); padding: var(--s3); }
  .ac-kpi { flex: 1 1 130px; }
  .ac-pp-h { margin-top: var(--s6); }
  .ac-review { padding: var(--s3); gap: var(--s2) var(--s4); }
  /* the bar and the split share a line at this width rather than taking one each */
  .ac-revbar { flex: 1 1 110px; min-width: 90px; max-width: 150px; }
}

/* instrument.css carries the global reduced-motion block. The two exceptions this
   page needs are here: the loading spinner still has to turn, slower, because it
   reports that work is in flight; and the hold-to-confirm control is not offered at
   all under reduced motion, so its fill never has to be animated (autocurator.js
   takes the two-press path instead). */
@media (prefers-reduced-motion: reduce) {
  .ac-spin { animation-duration: 1.6s !important; animation-iteration-count: infinite !important; }
}
