/* =====================================================================
   IC Due Diligence — Common Frame

   Visual system re-based on OpenRouter's own (openrouter.ai), 2026-08-07.
   Every value below traces to a token pulled from their live CSS bundle,
   not from memory: surfaces --or-cloud #fcfcfe / --or-ink #03080a, accent
   --or-grape #7624f4 in light and --or-volt #c8ff00 in dark (the accent is
   re-chosen per theme, not inverted), hairlines at 8% ink, a 4/6/8/12
   radius ramp, and tabular figures set once on <body>.

   Two rules that predate this restyle and survive it:
   1. Provenance is never colour alone. Every mark ships a text label.
   2. Both themes are first-class. Light is the demo default — a projector
      with any ambient light crushes #03080a and an 8% hairline to nothing.
   ===================================================================== */

/* ---------- self-hosted faces ----------
   Deliberately not a <link> to fonts.googleapis.com: a lecture-theatre
   wifi hiccup would silently reflow the whole app mid-demo. ~80KB total,
   latin subsets, with the system stack as the fallback. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('fonts/jakarta.woff2') format('woff2');
  font-weight: 400 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('fonts/grotesk.woff2') format('woff2');
  font-weight: 500 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IC Mono';
  src: url('fonts/mono.woff2') format('woff2');
  font-weight: 400 500; font-style: normal; font-display: swap;
}

:root {
  color-scheme: light;

  /* surfaces — the card is LIGHTER than the page, as on OpenRouter */
  --plane:     #fcfcfe;
  --surface-1: #ffffff;
  --surface-2: #ffffff;
  --wash:      rgba(3, 8, 10, 0.031);

  /* ink */
  --ink:       #03080a;
  --ink-prose: #03080a;
  --ink-2:     rgba(3, 8, 10, 0.69);
  --muted:     rgba(3, 8, 10, 0.44);

  /* lines */
  --grid:   rgba(3, 8, 10, 0.05);
  --border: rgba(3, 8, 10, 0.08);
  --rule:   rgba(3, 8, 10, 0.125);

  /* accent — used in exactly two places, as they do */
  --accent:        #7624f4;
  --accent-fg:     #fcfcfe;
  --accent-subtle: #f4eefe;
  --focus-border:  rgba(3, 8, 10, 0.30);
  --focus-shadow:  0 0 0 3px rgba(3, 8, 10, 0.06);

  /* provenance — status ramps, not categorical slots.
     The bright step is the TEXT colour, the mid step is the FILL. */
  --verifiable:      #00bf6f;
  --verifiable-text: #007544;
  --verifiable-wash: #ebfaf4;
  --verifiable-edge: rgba(0, 191, 111, 0.20);
  --asserted:        #e5a000;
  --asserted-text:   #8a6000;
  --absent:          rgba(3, 8, 10, 0.44);
  --track:           rgba(3, 8, 10, 0.10);

  /* severity — four semantics, not five. --serious is gone: it measured
     ΔE 5.8 against --critical for a full-colour reader, i.e. the same
     colour. The severity WORD in .finding .tags is what separates them. */
  --critical:      #ff2d55;
  --critical-text: #bf0024;
  --warning:       #e5a000;
  --warning-text:  #8a6000;
  --good:          #00bf6f;
  --good-text:     #007544;
  --info:          #035ade;
  --info-text:     #0352c9;
  --info-wash:     #eef4fe;

  /* geometry */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius: 12px;
  --radius-full: 9999px;

  /* type */
  --sans:  'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --brand: 'Space Grotesk', var(--sans);
  --mono:  'IC Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --t-hero:    700 36px/1.2   var(--brand);
  --t-display: 700 24px/1.2   var(--sans);
  --t-title:   600 20px/1.2   var(--brand);
  --t-heading: 600 16px/1.35  var(--sans);
  --t-prose:   450 16px/1.7   var(--sans);
  --t-body:    450 14px/1.625 var(--sans);
  --t-ui:      450 14px/1.35  var(--sans);
  --t-button:  500 14px/1     var(--sans);
  --t-meta:    450 12px/1.35  var(--sans);
}

/* Dark is a re-choice, not an inversion — different accent hue, dimmed
   provenance fills (OpenRouter's own bright steps measure OKLCH L 0.71+
   and glow as large fills on #03080a), and prose set at 90% cloud rather
   than pure white. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme='light'])) { color-scheme: dark; }
}
:root[data-theme='dark'],
:root:where(:not([data-theme='light'])):is(.dark-capable) { color-scheme: dark; }

:root[data-theme='dark'] {
  color-scheme: dark;
  --plane:     #03080a;
  --surface-1: #080d0f;
  --surface-2: #0a1113;
  --wash:      rgba(252, 252, 254, 0.039);

  --ink:       #fcfcfe;
  --ink-prose: #e4e5e7;
  --ink-2:     rgba(252, 252, 254, 0.627);
  --muted:     rgba(252, 252, 254, 0.44);

  --grid:   rgba(252, 252, 254, 0.05);
  --border: rgba(252, 252, 254, 0.09);
  --rule:   rgba(252, 252, 254, 0.125);

  --accent:        #c8ff00;
  --accent-fg:     #03080a;
  --accent-subtle: #17200e;
  --focus-border:  rgba(252, 252, 254, 0.30);
  --focus-shadow:  0 0 0 3px rgba(252, 252, 254, 0.06);

  --verifiable:      #00a05e;
  --verifiable-text: #34dfaa;
  --verifiable-wash: #0b1d1b;
  --verifiable-edge: rgba(52, 223, 170, 0.20);
  --asserted:        #c08600;
  --asserted-text:   #ffab00;
  --absent:          rgba(252, 252, 254, 0.44);
  --track:           rgba(252, 252, 254, 0.10);

  --critical:      #ff2d55;
  --critical-text: #ff2d55;
  --warning:       #c08600;
  --warning-text:  #ffab00;
  --good:          #00a05e;
  --good-text:     #34dfaa;
  --info:          #4d8dff;
  --info-text:     #4d8dff;
  --info-wash:     #0c1524;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme='light'])) {
    --plane: #03080a; --surface-1: #080d0f; --surface-2: #0a1113;
    --wash: rgba(252,252,254,.039);
    --ink: #fcfcfe; --ink-prose: #e4e5e7;
    --ink-2: rgba(252,252,254,.627); --muted: rgba(252,252,254,.44);
    --grid: rgba(252,252,254,.05); --border: rgba(252,252,254,.09);
    --rule: rgba(252,252,254,.125);
    --accent: #c8ff00; --accent-fg: #03080a; --accent-subtle: #17200e;
    --focus-border: rgba(252,252,254,.30); --focus-shadow: 0 0 0 3px rgba(252,252,254,.06);
    --verifiable: #00a05e; --verifiable-text: #34dfaa;
    --verifiable-wash: #0b1d1b; --verifiable-edge: rgba(52,223,170,.20);
    --asserted: #c08600; --asserted-text: #ffab00;
    --absent: rgba(252,252,254,.44); --track: rgba(252,252,254,.10);
    --critical: #ff2d55; --critical-text: #ff2d55;
    --warning: #c08600; --warning-text: #ffab00;
    --good: #00a05e; --good-text: #34dfaa;
    --info: #4d8dff; --info-text: #4d8dff; --info-wash: #0c1524;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--plane);
  color: var(--ink);
  font: var(--t-ui);
  /* Set once, for the whole document, exactly as OpenRouter does — every
     IRR, MOIC, DPI, fee and date column aligns without further thought. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: inherit; }
button { font: inherit; cursor: pointer; }

/* One focus treatment for everything. There was none before. */
:where(a, button, select, input, summary, [tabindex]):focus-visible {
  outline: none;
  border-color: var(--focus-border);
  box-shadow: var(--focus-shadow);
  border-radius: var(--radius-lg);
}

.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;
}

/* ---------- synthetic-data banner ----------
   Still unmistakable, no longer the loudest object in the room for three
   hours: the alarm moves into a solid pill, the bar becomes a warning tint. */
.synthetic-banner {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 20px;
  background: var(--asserted-wash, #fdf8eb);
  color: var(--asserted-text);
  border-bottom: 1px solid rgba(229, 160, 0, 0.22);
  font: var(--t-meta);
}
:root[data-theme='dark'] .synthetic-banner { background: #1b190e; }
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme='light'])) .synthetic-banner { background: #1b190e; }
}
.synthetic-banner .pill {
  flex: none;
  background: var(--asserted); color: #03080a;
  font: 600 11px/1 var(--sans); letter-spacing: 0.04em;
  padding: 4px 8px; border-radius: var(--radius-full);
}

/* ---------- header ---------- */
header.app {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 14px 22px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
}
.brand { display: flex; flex-direction: column; gap: 3px; margin-right: auto; }
.brand h1 { margin: 0; font: var(--t-title); letter-spacing: -0.015em; }
.brand p { margin: 0; font: var(--t-meta); color: var(--muted); }

.control { display: flex; align-items: center; gap: 8px; font: var(--t-meta); color: var(--muted); }
select, input[type='text'] {
  font: var(--t-ui);
  color: var(--ink);
  background: var(--surface-1);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 7px 10px;
  max-width: 340px;
}
.btn {
  border: 1px solid var(--rule);
  background: var(--surface-1);
  color: var(--ink);
  border-radius: var(--radius-lg);
  padding: 8px 14px;
  font: var(--t-button);
}
.btn:hover:not(:disabled) { border-color: var(--focus-border); background: var(--wash); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn.primary {
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
}
.btn.primary:hover:not(:disabled) { filter: brightness(1.07); background: var(--accent); }
.btn.small { padding: 5px 10px; font: var(--t-meta); font-weight: 500; }

/* segmented theme control, replacing an unlabelled ◐ glyph */
.seg-control {
  display: inline-flex; padding: 2px; gap: 2px;
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  background: var(--plane);
}
.seg-control button {
  border: 0; background: none; color: var(--muted);
  font: var(--t-meta); font-weight: 500;
  padding: 4px 9px; border-radius: var(--radius-md);
}
.seg-control button[aria-pressed='true'] { background: var(--surface-1); color: var(--ink); }

/* ---------- stability controls (v2) ----------
   Its own strip rather than two more items crammed into header.app, because
   the whole point is that a grader can find it without being told where to
   look. #stability-effect is a live region: it names which of temperature
   and reasoning is actually in force, so the pair can never silently
   contradict each other on screen. */
.stability {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 10px 22px;
  border-bottom: 1px solid var(--border);
  background: var(--plane);
}
.stability-label {
  font: var(--t-meta); font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ink-2);
}
/* Wide enough for the locked form ("0.0 → 1.0") so the row does not jump
   sideways every time Reasoning is toggled. */
.stability output {
  font: var(--t-meta); font-family: var(--mono);
  color: var(--ink); min-width: 5.4em;
}
.stability input[type='range'] { width: 128px; accent-color: var(--accent); }

/* Locked = Reasoning is On and the model discards temperature anyway. The
   slider is genuinely disabled rather than merely annotated, so it cannot be
   dragged into a position that has no effect.

   The dimming is applied to the SLIDER only, never to .control — an opacity
   on the parent creates a stacking context that a child cannot climb back
   out of, which would fade the readout too. The readout is the one part
   still telling you something true, so it keeps full contrast. */
.stability .control.is-locked input[type='range'] {
  opacity: 0.4; cursor: not-allowed;
}
.stability output.is-forced { color: var(--warning-text); font-weight: 600; }

/* Wraps to its own full-width line once the controls run out of room, so a
   long sentence never squeezes the slider. */
.stability-effect {
  flex: 1 1 100%; margin: 0;
  font: var(--t-meta); color: var(--muted);
}
.stability-effect.is-overridden {
  color: var(--warning-text); font-weight: 500;
}
.stability-effect.is-deterministic { color: var(--good-text); }

/* ---------- tabs ---------- */
nav.tabs {
  display: flex; gap: 2px; overflow-x: auto;
  padding: 0 22px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
}
nav.tabs button {
  border: 0; background: none; color: var(--muted);
  padding: 12px 14px; white-space: nowrap;
  font: var(--t-ui); font-weight: 500;
  border-bottom: 2px solid transparent;
}
nav.tabs button:hover { color: var(--ink-2); }
nav.tabs button[aria-selected='true'] { color: var(--accent); border-bottom-color: var(--accent); }

main { padding: 24px 22px 72px; max-width: 1240px; margin: 0 auto; }
.panel[hidden] { display: none; }

h2.sec { font: var(--t-title); margin: 0 0 5px; }
.card h2.sec { font: var(--t-heading); }
p.sub { margin: 0 0 18px; font: var(--t-body); color: var(--ink-2); max-width: 68ch; }

.seed-note {
  display: none;
  background: var(--info-wash);
  border: 1px solid var(--border);
  border-left: 2px solid var(--info);
  border-radius: var(--radius-lg);
  padding: 10px 14px; margin-bottom: 14px;
  font: var(--t-meta); color: var(--ink-2);
}

/* ---------- containers ----------
   Three tiers, not one. A .card wraps a real object (a table, a document
   set, a KPI cluster). Prose gets a hairline and space, no box. */
.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 22px;
  margin-bottom: 16px;
}
.section { border-top: 1px solid var(--grid); padding-top: 20px; margin-top: 28px; }
.section > h2 { font: var(--t-heading); margin: 0 0 6px; }
.section > p { font: var(--t-body); color: var(--ink-2); max-width: 68ch; margin: 0; }

/* ---------- provenance ----------
   Three weights, one hue vocabulary. ~85% of cells are "Asserted"; a mark
   that fires on 85% of observations carries no signal, so only the rare,
   decision-relevant "verifiable" gets pill treatment. The word is always
   printed — the rule is never colour ALONE, not always colour. */
.prov {
  display: inline-flex; align-items: center; gap: 6px;
  font: var(--t-meta); font-weight: 500; white-space: nowrap;
  color: var(--ink-2);
}
.prov::before { content: ''; width: 6px; height: 6px; border-radius: 50%; flex: none; }
.prov.verifiable {
  color: var(--verifiable-text);
  background: var(--verifiable-wash);
  border: 1px solid var(--verifiable-edge);
  border-radius: var(--radius-full);
  padding: 2px 8px 2px 7px;
}
.prov.verifiable::before { background: var(--verifiable); }
.prov.asserted { color: var(--muted); font-weight: 450; }
.prov.asserted::before { background: var(--asserted); opacity: 0.85; }
.prov.absent { color: var(--muted); font-style: italic; }
.prov.absent::before { display: none; }

.legend { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; font: var(--t-meta); }

/* ---------- flag dots (4P rubric) ---------- */
.flagdot { display: inline-flex; align-items: center; gap: 7px; font: var(--t-meta); font-weight: 500; text-transform: capitalize; white-space: nowrap; }
.flagdot::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none; }
.flagdot.red::before { background: var(--critical); }
.flagdot.amber::before { background: var(--warning); }
.flagdot.green::before { background: var(--good); }
.flagdot.red { color: var(--critical-text); }
.flagdot.amber { color: var(--warning-text); }
.flagdot.green { color: var(--good-text); }

/* ---------- comparison grid ----------
   The scroll container needs an explicit max-height or `position:sticky`
   never activates, and border-collapse must be `separate` because Chrome
   and Safari drop collapsed borders on sticky cells. Rules are drawn with
   inset box-shadows instead. */
.table-scroll {
  padding: 0;
  max-height: calc(100vh - 280px);
  overflow: auto;
  overscroll-behavior: contain;
}
.compare-grid {
  width: 100%; table-layout: fixed;
  border-collapse: separate; border-spacing: 0;
  font: var(--t-ui);
}
.compare-grid th, .compare-grid td {
  text-align: left; vertical-align: top;
  padding: 10px 14px;
  box-shadow: inset 0 -1px 0 var(--grid);
}
.compare-grid thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--surface-2);
  font: var(--t-heading);
  box-shadow: inset 0 -1px 0 var(--rule);
}
.compare-grid tbody th {
  position: sticky; left: 0; z-index: 2;
  width: 210px;
  background: var(--surface-1);
  font: var(--t-ui); font-weight: 450; color: var(--ink-2);
  box-shadow: inset -1px 0 0 var(--grid), inset 0 -1px 0 var(--grid);
}
.compare-grid thead th:first-child { left: 0; z-index: 4; background: var(--surface-2); }
.compare-grid tbody tr:hover th, .compare-grid tbody tr:hover td { background: var(--wash); }
.compare-grid tbody th.is-critical {
  font-weight: 600; color: var(--ink);
  box-shadow: inset 2px 0 0 var(--accent), inset -1px 0 0 var(--grid), inset 0 -1px 0 var(--grid);
}
.compare-grid tr.group-head th {
  position: sticky; top: 46px; left: 0; z-index: 2;
  background: var(--plane);
  font: 500 12px/1 var(--sans);
  text-transform: none; letter-spacing: 0;
  color: var(--ink-2); padding: 12px 14px;
  box-shadow: inset 0 1px 0 var(--grid), inset 0 -1px 0 var(--grid);
}
/* Flags, transparency, per-candidate lists: same cell styling, but no fixed
   layout and no sticky first column — those exist for the 50-row scrolling
   comparison grid only, and applying them here made the "Status" column as
   wide as the reason text. */
.compare-grid.plain { table-layout: auto; }
.compare-grid.plain tbody th { position: static; width: auto; box-shadow: inset 0 -1px 0 var(--grid); }
.compare-grid.plain thead th { position: static; }
.compare-grid.plain td.narrow, .compare-grid.plain th.narrow { width: 130px; }

.compare-grid .col-sub { display: block; font-weight: 450; color: var(--muted); font-size: 12px; margin-top: 2px; }
.cell-value { display: block; }
.cell-value.empty { color: var(--muted); font-style: italic; }

/* One metadata line per cell, OpenRouter's pattern — the provenance mark,
   the source document, the note, separated by 1px hairlines. Replaces
   three stacked block elements and cuts cell height by roughly a third. */
.cell-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px;
  margin-top: 5px; font: var(--t-meta); color: var(--muted);
}
.cell-meta > * + *::before {
  content: ''; display: inline-block; width: 1px; height: 10px;
  margin-right: 10px; vertical-align: -1px; background: var(--rule);
}
.cell-meta .src { font-family: var(--mono); font-size: 11.5px; }

/* ---------- findings ---------- */
.finding {
  border: 1px solid var(--border);
  border-left: 2px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 13px 15px; margin-bottom: 10px;
  background: var(--surface-1);
}
.finding.critical { border-left-color: var(--critical); }
.finding.serious, .finding.warning { border-left-color: var(--warning); }
.finding h4 { margin: 0 0 5px; font: var(--t-heading); }
.finding p { margin: 0 0 8px; font: var(--t-body); color: var(--ink-2); }
.finding .tags { display: flex; gap: 8px; flex-wrap: wrap; font: var(--t-meta); color: var(--muted); margin-bottom: 6px; }
.tag { border: 1px solid var(--border); border-radius: var(--radius-full); padding: 2px 9px; }
blockquote.ev {
  margin: 6px 0; padding: 8px 12px;
  border-left: 2px solid var(--grid);
  font: 400 12.5px/1.6 var(--mono);
  color: var(--ink-2); white-space: pre-wrap;
}
blockquote.ev cite { display: block; font: var(--t-meta); font-style: normal; color: var(--muted); margin-top: 5px; }
.ask { font: var(--t-body); color: var(--ink); background: var(--wash); border-radius: var(--radius-md); padding: 8px 11px; }

/* ---------- KPI row (dashboard) ----------
   A single hairline-divided cluster rather than five competing cards, so
   the one number the product exists to produce reads as the hero. */
.kpi-row {
  display: grid; grid-template-columns: 1.4fr repeat(4, 1fr);
  gap: 1px; background: var(--grid);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; margin-bottom: 16px;
}
.kpi { background: var(--surface-1); padding: 18px 20px; }
.kpi .label { font: var(--t-meta); color: var(--muted); }
.kpi .value {
  font: var(--t-display); letter-spacing: -0.015em; margin-top: 7px;
  font-variant-numeric: proportional-nums;
}
.kpi.hero .value { font: var(--t-hero); }
.kpi .unit { font: 450 16px/1 var(--sans); color: var(--muted); }
.kpi .why {
  font: var(--t-meta); line-height: 1.55; color: var(--ink-2); margin-top: 10px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.kpi details { margin-top: 7px; }
.kpi details summary { font: var(--t-meta); color: var(--muted); cursor: pointer; }
.kpi details p { font: var(--t-meta); line-height: 1.55; color: var(--ink-2); margin: 7px 0 0; }
.meter { height: 6px; border-radius: var(--radius-full); background: var(--track); margin-top: 12px; overflow: hidden; }
.meter > i { display: block; height: 100%; border-radius: var(--radius-full); background: var(--accent); }
/* The 7.0 committee bar was previously encoded in colour alone. */
.gate-line { display: inline-flex; align-items: center; gap: 7px; margin-top: 10px; font: var(--t-meta); font-weight: 500; color: var(--critical-text); }
.gate-line::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--critical); flex: none; }
.gate-line.pass { color: var(--good-text); }
.gate-line.pass::before { background: var(--good); }

/* ---------- score provenance (Dashboard) ----------
   Which model produced the number, sitting under the number. The baked scores
   are a mixed Haiku/Gemini set and the two models disagree by 1.8 points on the
   same manager, so a reader comparing two candidates against one 7.0 bar needs
   to see this without going looking for it. Small, but not muted to the point
   of being decorative. */
.score-prov { margin-top: 10px; max-width: 52ch; font: var(--t-meta); color: var(--muted); line-height: 1.45; }
.score-prov b { color: var(--ink-2); font-weight: 600; }
.score-prov .warn { color: var(--warning-text); font-weight: 600; }

/* ---------- out-of-scope notice (Dashboard) ----------
   A withheld score is a decision, not an absence, so it gets a real block:
   an amber rule, a stated reason, and the asset class as the headline. */
.out-of-scope { border-left: 2px solid var(--asserted); }
.oos-label {
  font: var(--t-meta); font-weight: 600; color: var(--asserted-text);
  display: inline-flex; align-items: center; gap: 7px;
}
.oos-label::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--asserted); flex: none; }
.out-of-scope h3 { font: var(--t-title); margin: 9px 0 10px; }
.out-of-scope p { font: var(--t-body); color: var(--ink-2); max-width: 72ch; margin: 0 0 10px; }
.out-of-scope p.oos-foot { font: var(--t-meta); color: var(--muted); margin: 0; }

/* ---------- coverage bar (heads the extracted-frame card) ----------
   Replaced four evaluation tiles (raw coverage / answerable-cell recall /
   fabrication gate / provenance mix). Recall and fabrications measure US
   against an answer key; that belongs in GA2 and on the deck. What stays
   is the product fact: how many of the frame's questions this pack
   answers, and who stands behind each. The key doubles as the legend. */
.coverage { margin-bottom: 20px; }
.coverage-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.coverage-head h3 { font: var(--t-heading); margin: 0; }
.coverage-figure { font: var(--t-display); font-variant-numeric: proportional-nums; color: var(--ink); }
.coverage-figure .of { font: 450 16px/1 var(--sans); color: var(--muted); }
.coverage-bar {
  display: flex; gap: 2px; height: 8px; margin: 12px 0 11px;
  border-radius: var(--radius-full); overflow: hidden;
}
.coverage-bar > span { display: block; min-width: 4px; border-radius: 1px; }
.coverage-bar > span:first-child { border-radius: var(--radius-full) 1px 1px var(--radius-full); }
.coverage-bar > span:last-child { border-radius: 1px var(--radius-full) var(--radius-full) 1px; }
.coverage-bar .s-verifiable { background: var(--verifiable); }
.coverage-bar .s-asserted { background: var(--asserted); }
.coverage-bar .s-absent { background: var(--track); }
.coverage-key { display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px; font: var(--t-meta); color: var(--ink-2); }
.coverage-key > * + *::before {
  content: ''; display: inline-block; width: 1px; height: 10px;
  margin-right: 12px; vertical-align: -1px; background: var(--rule);
}
.coverage-key b { color: var(--ink); font-weight: 600; }
.coverage-key i { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; }
@media (prefers-reduced-motion: no-preference) {
  .coverage-bar > span { transition: flex-grow 0.28s ease; }
}

/* ---------- documents ---------- */
.doclist { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }
.doc { border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px 14px; background: var(--surface-1); }
.doc h5 { margin: 0 0 4px; font: var(--t-heading); }
.doc .meta { font: var(--t-meta); color: var(--muted); }
.doc pre {
  margin: 9px 0 0; padding-top: 9px;
  font: 400 11.5px/1.6 var(--mono);
  white-space: pre-wrap; max-height: 220px; overflow: auto;
  color: var(--ink-2); border-top: 1px solid var(--grid);
}
.doc[dir='rtl'] pre { text-align: right; }
.xlate { font: var(--t-meta); color: var(--ink-2); background: var(--wash); border-radius: var(--radius-md); padding: 8px 10px; margin-top: 8px; }

/* ---------- memo + chat ---------- */
.memo { font: var(--t-prose); color: var(--ink-prose); max-width: 74ch; }
.memo h2 { font: var(--t-title); margin: 26px 0 8px; }
.memo h3 { font: var(--t-heading); margin: 18px 0 6px; }
.memo table { border-collapse: collapse; font: var(--t-ui); margin: 12px 0; }
.memo th, .memo td { border: 1px solid var(--grid); padding: 7px 11px; text-align: left; }
.memo th { background: var(--wash); font-weight: 600; }
.memo code { font: 400 13px var(--mono); background: var(--wash); padding: 1px 5px; border-radius: var(--radius-sm); }

.chat-log { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; }
.msg { max-width: 74ch; font: var(--t-body); }
.msg .who { font: var(--t-meta); text-transform: none; letter-spacing: 0; color: var(--muted); margin-bottom: 4px; }
.msg.user .body { background: var(--wash); border-radius: var(--radius-lg); padding: 9px 12px; }
.chat-form { display: flex; gap: 9px; }
.chat-form input { flex: 1; max-width: none; }

/* ---------- status / empty states ---------- */
.status { font: var(--t-meta); color: var(--ink-2); min-height: 18px; }
.status.err { color: var(--critical-text); }
.spinner {
  display: inline-block; width: 11px; height: 11px;
  border: 2px solid var(--grid); border-top-color: var(--ink-2);
  border-radius: 50%; animation: spin 0.7s linear infinite; vertical-align: -1px;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 3s; } }

.empty-state { color: var(--muted); font: var(--t-body); padding: 28px 0; text-align: center; }
/* An outcome that is genuinely empty must not look like one that broke.
   This matters more here than elsewhere: the product's own thesis is that
   an empty cell is information. */
.t-empty { padding: 20px 14px; font: var(--t-ui); color: var(--ink-2); text-align: left; }
.t-empty.clean::before { content: '✓'; color: var(--good-text); margin-right: 9px; font-weight: 600; }
.t-empty.na { color: var(--muted); font-style: italic; }
.t-empty.err { color: var(--critical-text); }
.t-empty.err::before { content: '!'; margin-right: 9px; font-weight: 700; }

details.tableview { margin-top: 12px; }
details.tableview summary { font: var(--t-meta); color: var(--muted); cursor: pointer; }
details.tableview table { border-collapse: collapse; font: var(--t-meta); margin-top: 9px; width: 100%; }
details.tableview th, details.tableview td { border: 1px solid var(--grid); padding: 6px 9px; text-align: left; }

.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.grow { flex: 1; }

/* ---------- upload tab ---------- */
.upload-form { display: flex; flex-direction: column; gap: 15px; max-width: 560px; }
.upload-form label { display: flex; flex-direction: column; gap: 6px; font: var(--t-meta); color: var(--ink-2); }
.upload-form input[type='text'] { background: var(--surface-1); border: 1px solid var(--rule); }
.upload-form input[type='file'] { font: var(--t-meta); }
.upload-file-list { list-style: none; font: var(--t-meta); color: var(--ink-2); margin: 0; padding: 0; }
.upload-file-list li { padding: 3px 0; }
.upload-step { border-left: 2px solid var(--grid); padding: 5px 0 5px 13px; margin: 11px 0; font: var(--t-body); color: var(--ink-2); }
.upload-step.done { border-left-color: var(--good); color: var(--ink); }
.upload-step.active { border-left-color: var(--accent); color: var(--ink); }
.upload-step.error { border-left-color: var(--critical); color: var(--critical-text); }

/* ---------- print-to-PDF (memo export) ----------
   Re-tokened to the light theme. This is the only artefact that leaves the
   room, and it used to be set in a purple-tinted palette belonging to
   nothing else in the product. */
#memo-print-root { display: none; }
@media print {
  body > *:not(#memo-print-root) { display: none !important; }
  #memo-print-root {
    display: block !important;
    font-family: var(--sans);
    color: #03080a;
    max-width: 720px; margin: 0 auto; line-height: 1.6;
  }
  #memo-print-root .pf-banner {
    background: #fdf8eb; border: 1px solid rgba(229, 160, 0, 0.35);
    border-radius: 6px; padding: 9px 13px; font-size: 11px; margin-bottom: 20px;
    color: #8a6000;
  }
  #memo-print-root .pf-meta { font-size: 11px; color: rgba(3, 8, 10, 0.55); margin-bottom: 24px; }
  #memo-print-root h1 { font-family: var(--brand); font-size: 22px; margin-bottom: 5px; }
  #memo-print-root h2 { font-size: 15px; margin: 20px 0 7px; border-top: 1px solid rgba(3, 8, 10, 0.10); padding-top: 11px; }
  #memo-print-root h3 { font-size: 13px; margin: 13px 0 5px; }
  #memo-print-root table { border-collapse: collapse; width: 100%; font-size: 11.5px; margin: 9px 0; }
  #memo-print-root th, #memo-print-root td { border: 1px solid rgba(3, 8, 10, 0.12); padding: 5px 8px; text-align: left; }
  #memo-print-root th { background: rgba(3, 8, 10, 0.04); }
  #memo-print-root code { font-family: var(--mono); font-size: 11px; }
  #memo-print-root p, #memo-print-root li { orphans: 3; widows: 3; }
}
