/* app.css — layout + components, built on interface/tokens.css variables.
   Editorial look (Option A warmer). Graphics toggle via body[data-gfx="off"]. */
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font-body); background: var(--bg); color: var(--ink);
  line-height: var(--lh-body); transition: background .3s, color .3s;
}
/* Justified body copy, sitewide (2026-07-28, Ashley) — `p` plus the handful of prose
   classes authored on a non-`p` tag (`.sub`, `.rowblurb`, `.tnote`). Deliberately NOT
   applied to buttons, labels, badges, pills, table cells, or form inputs — those are UI
   controls, not sentences, regardless of length. A line short enough to need no wrapping
   is unaffected by `justify` (it only stretches a line that has a following line to justify
   against, and never the paragraph's last line), so this needs no separate "under 5 words"
   exception — short copy already renders identically to left-aligned. */
p, .sub, .rowblurb, .tnote { text-align: justify; }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

/* Flat background, no wash (2026-07-27, Ashley: "the tint is trippy" — was a soft
   claret/ochre radial-gradient wash behind every page, visible on question screens).
   .ambient stays in the markup as an inert, unstyled div rather than removed from
   index.html, so a wash can come back by restyling this rule alone. */
.ambient { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.bar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 18px; background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(8px); border-bottom: var(--border-hairline) solid var(--line);
}
.bar .name { font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.bar .sp { flex: 1; }
.bar .grp { display: inline-flex; border: var(--border-hairline) solid var(--line); border-radius: var(--radius-pill); overflow: hidden; }
.bar .grp button { border: none; background: transparent; color: var(--muted); font: 600 12px/1 var(--font-ui); padding: 7px 12px; cursor: pointer; }
.bar .grp button.on { background: var(--accent); color: var(--on-accent); }
.bar .lbl { font: 700 10px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); }
.bar #brestart, .bar #bsaveExit { border-radius: var(--radius-pill); }
/* Hover-hint captions (spec: First Question.dc.html's barHover()) — every possible caption
   is pre-rendered as its own absolutely-positioned span stacked in the same slot, each at
   opacity 0; hovering a [data-hint-for] button fades its matching [data-hint] span in via
   the .show class (wired in main.js's wireHints()). A cross-fade, not a text swap. */
.hint-slot { position: relative; display: inline-block; }
.hint-slot .hint {
  position: absolute; inset: 0; display: flex; align-items: center;
  font: 13.5px/1.3 var(--font-body); color: var(--muted); opacity: 0; transition: opacity .16s; white-space: nowrap;
}
.hint-slot .hint.show { opacity: 1; }
/* 170px (the spec's value) is too narrow for the longest caption ("keeps your place for
   your private link") at this font — the overflowing, right-aligned text bled left and
   painted over the Theme toggle (2026-07-26 fix). Wide enough to fit every bar caption
   without overflow; a normal-flow flex item this size only pushes later siblings (the
   Restart/Save buttons), it can't overlap the toggle that comes before it. */
.bar .hint-slot { width: 300px; height: 34px; flex: none; }
.bar .hint-slot .hint { justify-content: flex-end; text-align: right; }
/* Bottom nav hint needs its own breathing room from the buttons on both sides — the spec's
   nav row carries gap:16px; .qfoot didn't (2026-07-26 fix: hint text was flush against the
   buttons). */
.qfoot { gap: 16px; }
.qfoot .hint-slot { flex: 1; min-width: 60px; height: 34px; }
.qfoot .hint-slot .hint.left { justify-content: flex-start; padding-left: 2px; }
.qfoot .hint-slot .hint.right { justify-content: flex-end; text-align: right; padding-right: 2px; }

.stage { position: relative; z-index: 1; max-width: 920px; margin: 0 auto; padding: 30px 20px 100px; }
/* Question screen matches the source spec's page width (data-pad="page", max-width:1120px)
   — narrower than the app's default 920px, which was making both source/question columns
   read as much less than half the screen (2026-07-26 fix). Scoped to the question screen
   only; intake/results keep their own tuned widths. */
.stage.question { max-width: 1120px; }
.eyebrow { font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); }
h1 { font-family: var(--font-display); font-weight: 900; font-size: var(--fs-h1); line-height: var(--lh-display); letter-spacing: var(--tracking-display); margin: 10px 0 8px; }
.dek { color: var(--muted); font-size: var(--fs-body); max-width: 600px; }

.card { position: relative; background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-faint); padding: 18px 20px; }
.btn { background: var(--accent); color: var(--on-accent); border: none; border-radius: var(--radius-card); padding: 11px 20px; font: 700 13px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .04em; cursor: pointer; }
.btn:disabled { opacity: .38; cursor: not-allowed; }
.btn.ghost { background: transparent; color: var(--ink); border: var(--border-hairline) solid var(--line); }
input[type=text], input[type=number], select {
  font: 14px var(--font-ui); color: var(--ink); background: var(--surface);
  border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); padding: 9px 12px;
}
input:focus, select:focus { outline: none; border-color: var(--accent); }

/* intake — rebuilt 2026-07-25 from a Claude Design pass ("Finance AI readiness welcome",
   ashley_feedback/); scoped to .stage.intake so the results masthead (which shares
   h1/.dek/.sub with the rest of the app) is untouched. */
.intake { padding-top: var(--intake-pad-page); max-width: var(--intake-explain-w); }
.intake h1 { font-size: var(--intake-fs-h1); font-weight: var(--intake-fw-h1); }
.intake .dek { font-size: var(--intake-fs-dek); max-width: none; }
.intake .pullquote { font-family: var(--font-body); font-style: italic; font-size: var(--intake-fs-body); color: var(--ink); margin: 14px 0 0; }
.intake .sech {
  display: flex; align-items: baseline; gap: 16px;
  font: 700 var(--intake-fs-label)/1 var(--font-ui); text-transform: uppercase;
  letter-spacing: var(--intake-tracking-label); color: var(--ink);
  margin: var(--intake-sec-gap) 0 12px;
}
.intake .sech::after { content: ''; order: 1; flex: 1; height: 1px; background: var(--line); }
.intake .sech .aside { order: 2; font: italic 15px var(--font-body); text-transform: none; letter-spacing: 0; color: var(--muted); white-space: nowrap; }

/* hero: text + compass illustration, two columns down to 940px */
.intake .hero { display: grid; grid-template-columns: minmax(0,1.08fr) minmax(0,.92fr); gap: 56px; align-items: center; }
.intake .metastrip { display: flex; flex-wrap: wrap; margin-top: 30px; border-top: var(--border-hairline) solid var(--line); border-bottom: var(--border-hairline) solid var(--line); }
.intake .metastrip > div { flex: 1 1 140px; padding: 14px 18px; border-right: var(--border-hairline) solid var(--line); }
.intake .metastrip > div:first-child { padding-left: 0; }
.intake .metastrip > div:last-child { border-right: none; }
.intake .metastrip b { display: block; font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1; }
.intake .metastrip span { display: block; font: 500 11px/1.3 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); margin-top: 6px; }
.intake .hero-compass { position: relative; display: flex; align-items: center; justify-content: center; min-height: 340px; }
.intake .hero-compass .ring { position: absolute; border-radius: 50%; }
.intake .hero-compass .ring.outer { width: 340px; height: 340px; border: 1.5px dotted color-mix(in srgb, var(--accent) 28%, transparent); }
.intake .hero-compass .ring.inner { width: 260px; height: 260px; background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.intake .hero-compass .compass-img { position: relative; width: 92%; height: 92%; object-fit: contain; }
.intake .hero-compass .compass-dark { display: none; }
:root[data-theme="dark"] .intake .compass-light { display: none; }
:root[data-theme="dark"] .intake .compass-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .intake .compass-light { display: none; }
  :root:not([data-theme="light"]) .intake .compass-dark { display: block; }
}

.intake .cardrow { display: flex; flex-wrap: wrap; gap: var(--intake-pc-gap); }
.intake .cardrow.pillars .icard { flex: 1 1 calc((100% - (var(--intake-pc-cols) - 1) * var(--intake-pc-gap)) / var(--intake-pc-cols)); min-width: 140px; }
.intake .cardrow.domains .icard { flex: 1 1 calc((100% - 2 * var(--intake-pc-gap)) / 3); min-width: 180px; }
.intake .icard { display: flex; gap: 10px; align-items: flex-start; background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); padding: 12px 14px; }
.intake .icard .chip { flex: none; width: 34px; height: 34px; }
.intake .icard .chip svg { width: 18px; height: 18px; }
.intake .icard-body { display: flex; flex-direction: column; gap: 3px; }
.intake .icard-body b { font: 600 var(--intake-fs-pcname)/1.2 var(--font-ui); }
.intake .icard-body span { font-size: var(--intake-fs-pcdesc); color: var(--muted); line-height: 1.4; }

.intake .callout {
  margin-top: 28px; display: grid; grid-template-columns: auto minmax(0,1fr); gap: 20px; align-items: center;
  background: color-mix(in srgb, var(--accent) 5.5%, var(--surface)); border: var(--border-hairline) solid var(--line);
  border-left: 3px solid var(--accent); border-radius: var(--radius-card); padding: 22px 26px;
}
.intake .pill {
  font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent);
  border: var(--border-hairline) solid var(--accent); border-radius: var(--radius-pill); padding: 6px 12px; white-space: nowrap;
}
.intake .callout p { margin: 0; font-size: var(--intake-fs-body); }
/* Feedback box (merged with the old .prototype-box 2026-07-28 — one box, not two) is the
   same unscoped .feedback-box the question/results screens use; its own rule (below)
   already carries the right spacing and layout, so .intake adds nothing further. */

.intake .cta-grid { display: grid; grid-template-columns: minmax(0,1fr) 372px; gap: 40px; align-items: start; margin-top: var(--intake-sec-gap); }
.intake .steps { display: grid; border-top: var(--border-hairline) solid var(--line); }
.intake .step { display: grid; grid-template-columns: 26px 1fr; gap: 14px; padding: 15px 0; border-bottom: var(--border-hairline) solid var(--line); align-items: baseline; }
.intake .step .stepno { font: 700 12px/1 var(--font-ui); color: var(--accent); }
.intake .step p { margin: 0; font-size: var(--intake-fs-body); line-height: 1.55; }
.intake .step p.stepnote { margin-top: 7px; font-size: var(--intake-fs-fine); color: var(--muted); }

.intake .cta-card { border-top: 3px solid var(--accent); padding: var(--intake-card-pad); }
.intake .cta-title { font-family: var(--font-display); font-weight: 600; font-size: 21px; line-height: 1.2; letter-spacing: -.01em; }
.intake .cta-card .field { margin-top: var(--intake-wbase-gap); }
.intake .cta-card .field + .field { margin-top: 12px; }
.intake .cta-card label { display: block; font: 500 12px/1 var(--font-ui); letter-spacing: .04em; color: var(--muted); margin-bottom: 6px; }
.intake .cta-card .optional { text-transform: none; letter-spacing: 0; }
.intake .cta-card input, .intake .cta-card select { width: 100%; }
.intake #start { width: 100%; margin-top: 20px; font-size: var(--intake-fs-btn); }
.intake .fineprint { margin-top: 12px; font-size: var(--intake-fs-fine); color: var(--muted); }

.intake .closing { margin-top: 34px; padding-top: 22px; border-top: var(--border-hairline) solid var(--line); font-family: var(--font-body); font-style: italic; font-size: var(--intake-fs-body); color: var(--muted); }

@media (max-width: 940px) {
  .intake .hero { grid-template-columns: 1fr; gap: 34px; }
  .intake .cardrow.pillars .icard { flex: 1 1 calc((100% - var(--intake-pc-gap)) / 2); }
  .intake .cta-grid { grid-template-columns: 1fr; gap: 34px; }
}
@media (max-width: 560px) {
  .intake .cardrow.pillars .icard { flex: 1 1 100%; }
}
.sub { font-size: var(--fs-small); color: var(--muted); }

/* question */
.dots { display: flex; gap: 6px; margin-bottom: 16px; }
.dots i { width: 26px; height: 5px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 12%, transparent); }
.dots i.on { background: var(--accent); }
/* Column split + gap match the source spec exactly (First Question.dc.html:
   grid-template-columns:minmax(0,1.06fr) minmax(0,1fr); gap:48px) — 2026-07-26 fix. The
   near-even 1.06:1 ratio (not a plain 1fr 1fr) gives the source panel a hair more room for
   the source excerpt's longer prose lines. */
.qwrap { display: grid; grid-template-columns: minmax(0,1.06fr) minmax(0,1fr); gap: 48px; align-items: start; }
/* Standalone items (AI Fluency) have no source panel — one centred column, not an empty one. */
.qwrap.solo { grid-template-columns: minmax(0, 720px); justify-content: center; }
@media (max-width: 760px) { .qwrap { grid-template-columns: 1fr; } }
/* Left (source) panel stays pinned while the page scrolls the right column — the source
   itself never scrolls internally (see .clause.verbatim note below); only the panel's
   on-screen position sticks. Offset clears the sticky top .bar. */
.qleft { position: sticky; top: 70px; align-self: start; }
@media (max-width: 760px) { .qleft { position: static; } }
.src { position: relative; background: var(--surface); border: var(--border-hairline) solid var(--line); border-left: 3px solid var(--accent); border-radius: var(--radius-card); padding: 24px 26px; }
.src .cite { font: 600 10px/1.3 var(--font-ui); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin-bottom: 8px; }
.src .cite + .cite { margin-top: 12px; }
/* Excerpt face pinned to Times New Roman at 14.33px — 0.5pt under the shared 15px
   --fs-question token (2026-07-27, Ashley) — scoped to .clause only so option rows,
   field labels and srctable, which also read --fs-question, are unaffected. */
.clause { font-family: 'Times New Roman', Times, serif; font-size: 14.33px; line-height: 1.6; }
.qprompt { position: relative; }

/* Left/right panel headings (interaction-lab mockup, 2026-07-26 feedback pass): a small
   caps label + a trailing rule filling the rest of the row. */
.panelhead { display: flex; align-items: baseline; gap: 14px; margin-bottom: 14px; }
.panelhead.center { align-items: center; }
.panelhead h2 { font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink); margin: 0; }
.panelhead .rule { flex: 1; height: 1px; background: var(--line); }
.qtypepill { display: inline-flex; align-items: center; gap: 9px; border: var(--border-hairline) solid var(--line); border-radius: var(--radius-pill); padding: 4px 12px 4px 4px; flex: none; }
.qtypepill.nochip { padding: 5px 12px; }
.qtypepill .domchip { width: 22px; height: 22px; border-radius: 50%; margin-right: 0; vertical-align: middle; }
.qtypepill .domchip svg { width: 12px; height: 12px; }
.qtypetxt { font: 600 11px/1 var(--font-ui); letter-spacing: .03em; color: var(--muted); white-space: nowrap; }
.qtypetxt .sep { color: var(--line); margin: 0 5px; }
/* The pillar half of the pill, on the results-page reopened question only (2026-07-27,
   Chunk 2) — a second door into that pillar's rail view, so it needs to read as a link
   without changing the pill's own type scale. */
.spokejump { cursor: pointer; text-decoration: underline; text-decoration-color: transparent; transition: text-decoration-color var(--motion-fast), color var(--motion-fast); }
.spokejump:hover, .spokejump:focus-visible { color: var(--accent); text-decoration-color: var(--accent); }
/* The pilljump hint reuses .hint-slot/.hint/wireHints() verbatim (ui/util.js) — only the
   slot's own size/position is re-scoped here, the same way .bar/.qfoot already give that
   shared slot a different box for their own layout. The bar's hint reserves a wide inline
   box beside its trigger; there's no room for that inside this tight pill, so here the slot
   floats as a small bubble below the link instead — same fade, different geometry. */
.pilljump { position: relative; display: inline-block; }
.pilljump .hint-slot {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 7px; width: max-content; max-width: 200px; height: auto; z-index: 6;
}
.pilljump .hint-slot .hint {
  position: static; inset: auto; display: block; white-space: normal; text-align: center;
  background: var(--surface); border: var(--border-hairline) solid var(--line);
  border-radius: 4px; padding: 6px 10px; box-shadow: var(--shadow-faint);
  font: 12px/1.4 var(--font-body); color: var(--muted);
}
/* Stem downsized + lightened — ported 2026-07-25 from the interaction-lab pass: the 7/24
   size/weight read as "taking up too much real estate" per Ashley's note. */
.stem { font-family: var(--font-display); font-weight: var(--fw-stem); font-size: var(--fs-stem); line-height: 1.25; margin: 0 0 14px; }

/* Verbatim filed text: paragraph rhythm. The source ALWAYS shows its full content — no
   scrollbar on the source panel, ever. The old `max-height: 46vh; overflow-y: auto`
   scroller was removed (ported 2026-07-25 from the interaction-lab pass): it silently
   truncated the clause mid-sentence, which is how FK-E2 once read as unanswerable. The
   page scrolls; the source panel does not. */
/* Justified, with hyphenation to keep the ragged-edge gaps from getting wide — matches the
   spec's excerpt block (text-align:justify;hyphens:auto) exactly (2026-07-26 fix). */
.clause.verbatim { text-align: justify; hyphens: auto; }
.clause.verbatim p { margin: 0 0 0.85em; }
.clause.verbatim p:last-child { margin-bottom: 0; }
/* Provenance line under the source (2026-07-24 citation convention). */
.provenance { font: 11.5px/1.5 var(--font-ui); color: var(--muted); margin: 7px 2px 0; }
.provenance .citelink { color: var(--accent); text-decoration: none; border-bottom: 1px dotted currentColor; }

/* General-purpose external link (intake attribution, feedback box LinkedIn) — same quiet
   dotted-underline treatment as .citelink, unscoped since it's used outside .provenance. */
.ext-link { color: var(--accent); text-decoration: none; border-bottom: 1px dotted currentColor; }
.ext-link:hover, .ext-link:focus-visible { border-bottom-style: solid; }

/* multiselect — "click all that apply" */
/* Long-prose option sets stack full-width, one per line — see optsClass() in question.js.
   The tag grid is for tags; at 83-163 characters an option is a sentence and needs a line. */
.opts.wide  { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.opts.stack { grid-template-columns: minmax(0, 1fr); gap: 7px; }
.opts.stack .opt { justify-content: flex-start; text-align: justify; align-items: flex-start; padding: 9px 14px; line-height: 1.5; }
.opts.multi.stack .opt::before { flex: none; line-height: 1.5; }
.opts.multi { gap: 6px; }
.opts.multi .opt::before { content: '＋'; margin-right: 6px; opacity: .45; font-weight: 700; }
.opts.multi .opt.sel::before { content: '✓'; opacity: 1; }

/* Wraps every row-based control (classify/highlight/critique/click/multiselect) — the top
   rule opening the list, matching the interaction-lab mockup's data-list="rows". */
.rowlist { border-top: 1px solid var(--ink); }

/* Option-major multiselect (2026-07-27, Ashley) — replaces reading the same long option
   sentence up to 3 times (once per purpose row) with reading it once, with a compact
   A/B/C toggle per purpose beside it. Purpose text itself moves to a one-time legend. */
.mlegend { margin-bottom: 14px; }
.mleg { font-size: var(--fs-question); line-height: 1.5; color: var(--muted); margin-bottom: 5px; }
.mleg:last-child { margin-bottom: 0; }
.mleg .rowltr { font-family: var(--font-body); color: var(--accent); font-weight: 600; margin-right: 10px; }
.mgrid { border-top: 1px solid var(--ink); }
.mrow {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 11px 0; border-bottom: var(--border-hairline) solid var(--line);
}
.mrow:last-child { border-bottom: none; }
.mlbl { font-size: var(--fs-question); line-height: 1.5; flex: 1 1 auto; min-width: 0; }
.mtoggles { display: flex; gap: 6px; flex: none; }
.mtoggle {
  min-width: 30px; height: 30px; padding: 0 8px; text-align: center; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: var(--border-hairline) solid var(--line); background: var(--surface); color: var(--muted);
  border-radius: var(--radius-pill); font: 700 12px/1 var(--font-ui); letter-spacing: .02em;
  transition: border-color var(--motion-fast), background var(--motion-fast), color var(--motion-fast);
}
.mtoggle:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); color: var(--ink); }
.mtoggle.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.mtoggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mtoggle.correct { border-color: var(--good); color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.mtoggle.wrong { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); text-decoration: line-through; }
@media (max-width: 560px) {
  .mrow { flex-wrap: wrap; }
  .mlbl { flex-basis: 100%; }
}

/* Row padding tightened 9->11px; question label gets a touch more line-height + a
   medium weight — ported 2026-07-25 from the interaction-lab pass. */
.row { padding: 11px 0; border-bottom: var(--border-hairline) solid var(--line); }
.row:last-child { border-bottom: none; }
.row .q { font-size: var(--fs-question); line-height: 1.5; margin-bottom: 10px; font-weight: 500; }
.row .rowltr { font-family: var(--font-body); color: var(--accent); font-weight: 600; margin-right: 12px; }

/* Dropdown rows — classify/highlight/critique/click's per-row single answer, a lettered
   label beside a select rather than a stacked list of tag buttons. Column width (113px)
   and gap (28px) match the source spec (First Question.dc.html) exactly; the reveal state
   (its own extension beyond the static spec, which only shows a fresh/unanswered row)
   widens the second column so the ✓/✗ note has room without wrapping. */
.row.dd { display: grid; grid-template-columns: minmax(0,1fr) 113px; column-gap: 28px; row-gap: 8px; align-items: center; }
/* A revealed wrong answer names the correct option in full, which never fits the 113px
   answer track — give it its own full-width line instead of letting it overflow. */
.row.dd > .ans { grid-column: 1 / -1; white-space: normal; margin-left: 0; }
/* Revealed rows swap the (now inert) select for the pick as text, so the answer column can
   size to its content rather than clipping it. */
/* Bound the answer track as a SHARE of the row, not by its content (2026-07-27). Both
   `max-content` and `auto` size to the longest pick, which is fine in the single-column
   sitting and starves the statement in the results drill-down, where the same row renders
   inside a half-width panel — FK-A1 wrapped "Numerator of the Senior Secured First Lien
   Net Leverage Ratio" to five lines beside a half-empty answer column. A percentage track
   resolves against the row, so the statement keeps ~60% at every width and the pick wraps
   instead of pushing. `fit-content()`, not `minmax(_, 40%)`: a percentage MAX is a definite
   size, so the answer column would take its 40% even for a two-word pick — fit-content
   sizes to the content and only clamps at the cap. `--dd-answer-w` is the one knob. */
:root { --dd-answer-w: 40%; }
.row.dd.revealed { grid-template-columns: minmax(0,1fr) fit-content(var(--dd-answer-w)); }
.ddpick { font: 500 var(--fs-option)/1.4 var(--font-option); color: var(--ink); text-align: right; }
/* The taker's own pick, once graded, is marked the way every other control marks a wrong
   pick — struck through and receded (cf. .opt.wrong/.mc.wrong) — so on a missed row the eye
   separates "what I chose" from the "Answer" line below it without reading either label. */
.ddpick.bad { color: var(--muted); text-decoration: line-through; }
.ddpick.ok { color: var(--good); }
/* `.okmark`, not `.tick` — `.tick` is already the results page's cutoff marker on a pillar
   bar (an absolutely-positioned 1px rule), and reusing the name rendered this ✓ as a
   1px-wide, 1775px-tall hairline instead of a glyph. */
.ddpick .okmark { margin-right: 6px; font-weight: 700; }
/* An unanswered row is neither a wrong pick nor a struck-out one — there is nothing to
   strike. Last, so it wins over .bad. */
.ddpick.none { color: var(--muted-3); font-style: italic; text-decoration: none; }
.reviewing .row.dd { grid-template-columns: minmax(0,1fr) fit-content(var(--dd-answer-w)); }
/* Verdict on the row's left edge — the only part of a five-row list that can be scanned in
   one pass. Padding is applied in both states so revealing cannot shift the text sideways
   (the "a graded question must not re-flow" rule). */
.row.dd { padding-left: 11px; border-left: 3px solid transparent; }
.row.dd.ok { border-left-color: var(--good); }
.row.dd.bad { border-left-color: var(--accent); }
.row.dd .q { margin-bottom: 0; }
.row.dd select { width: 100%; }
.reviewing .row.dd select { width: 170px; max-width: 100%; }
.ddwrap { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.ddwrap .ans { margin-left: 0; }
/* Select restyle to match spec: serif body font (not the app-wide sans UI font), a custom
   chevron in place of the native arrow, and a "filled" state — text darkens and the field
   tints claret once a row is answered (spec's Component.pick(), reproduced here in JS by
   toggling this class on change — see question.js's select-change wiring). */
.ddsel {
  font-family: var(--font-body); font-size: 15px; line-height: 1.3; color: var(--muted);
  background-color: var(--surface); border: var(--border-hairline) solid var(--line);
  border-radius: var(--radius-card); padding: 11px 26px 11px 11px; cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0.5 5 5.5 10 0.5' fill='none' stroke='%238A7A6C' stroke-width='1.2'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 9px 5.4px;
  transition: color .12s, border-color .12s, background-color .12s;
}
.ddsel.filled { color: var(--ink); border-color: var(--accent); background-color: color-mix(in srgb, var(--accent) 5%, var(--surface)); }
.ddsel:disabled { opacity: .75; cursor: not-allowed; }
:root[data-theme="dark"] .ddsel { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0.5 5 5.5 10 0.5' fill='none' stroke='%23A89A8C' stroke-width='1.2'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ddsel { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0.5 5 5.5 10 0.5' fill='none' stroke='%23A89A8C' stroke-width='1.2'/%3E%3C/svg%3E"); }
}
@media (max-width: 560px) {
  .row.dd, .row.dd.revealed, .reviewing .row.dd { grid-template-columns: 1fr; row-gap: 8px; }
  .row.dd select { width: 100%; }
  .ddpick { text-align: left; }
}

/* Gap widened 6->10px; padding tightened; font switched to --font-option at --fs-option
   (12px), down from --fs-question (15px) — ported 2026-07-25 from the interaction-lab
   pass, applied to every interaction type. `flex: 1 1 120px` forces equal-width option
   buttons in a row so a long option can't balloon beside a short one. */
/* Grid, not flex-wrap: the option row must keep the SAME layout before and after Submit.
   With `flex: 1 1 120px` + wrap, reveal's `font-weight: 600` on the picked option changed
   its intrinsic width and could push the row onto a different number of lines, so a graded
   answer re-flowed under the taker (2026-07-26). Fixed tracks can't re-wrap. */
.opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; align-items: stretch; }
.opt {
  min-width: 0; text-align: center; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border: var(--border-hairline) solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: var(--radius-card);
  padding: 6px 12px; font: 400 var(--fs-option)/1.4 var(--font-option);
  transition: border-color var(--motion-fast), background var(--motion-fast);
}
.opt .l { display: none; }
.mc {
  display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 11px;
  width: 100%; text-align: justify; cursor: pointer; margin: 7px 0;
  border: var(--border-hairline) solid var(--line); border-left: 3px solid transparent;
  background: var(--surface); color: var(--ink); border-radius: var(--radius-card);
  padding: 8px 14px; font: 400 var(--fs-option)/1.5 var(--font-option);
  transition: border-color var(--motion-fast), background var(--motion-fast);
}
.mc .l { font: 700 12px/1.5 var(--font-ui); color: var(--accent); min-width: 15px; letter-spacing: .02em; }
.opt:hover, .mc:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); background: color-mix(in srgb, var(--accent) 4%, var(--surface)); }
.opt.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.opts .opt { font-weight: 500; }   /* one weight in every state — see .opts note above */
.mc.sel { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); border-left-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.opt:focus-visible, .mc:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.opt.correct { border-color: var(--good); color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.opt.wrong { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); text-decoration: line-through; }
.mc.correct { border-color: var(--good); color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.mc.wrong { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); text-decoration: line-through; }

/* match: statement / select split evenly in half (2026-07-27 fix, Ashley — the select
   used to size to its own content via grid's `auto` column, which on a long option
   ("After the expiration of that debt's own grace period") ballooned the box and
   squeezed the statement text into a narrow, cramped column). Two even columns now;
   the select is width:100% of its column rather than sized to its longest option. */
.match .pair { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 24px; align-items: start; padding: 10px 0; border-bottom: var(--border-hairline) solid var(--line); }
.match .pair:last-child { border-bottom: none; }
.match .pair .lft { font-size: var(--fs-question); line-height: 1.5; padding-top: 2px; }
.match .pair .rgt { min-width: 0; }
.match select { width: 100%; }
.match .ans { display: block; margin-left: 0; margin-top: 6px; }
@media (max-width: 560px) {
  .match .pair { grid-template-columns: 1fr; gap: 6px; }
}

/* calc / extract fields */
.field-row { display: grid; grid-template-columns: 1fr 130px; gap: 10px; align-items: center; padding: 7px 0; }
.field-row label { font-size: var(--fs-question); }
.field-row .unit { color: var(--muted); font: 12px var(--font-ui); }
.numwrap { display: flex; align-items: center; gap: 6px; }
.numwrap input { width: 100%; text-align: right; font-family: var(--font-ui); }
/* typed entry: dates and free text read left-aligned, and need a wider column */
.field-row.wide { grid-template-columns: 1fr 200px; align-items: start; }
.field-row.wide label { padding-top: 7px; }
.numwrap input.txt { text-align: left; }

/* click passages */
.passage { display: block; width: 100%; text-align: left; border: var(--border-hairline) solid var(--line); background: var(--surface); color: var(--ink); border-radius: var(--radius-card); padding: 11px 14px; margin: 7px 0; font: var(--fs-question)/1.5 var(--font-body); cursor: pointer; }
.passage.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.passage.correct { border-color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.passage.wrong { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); text-decoration: line-through; }

.qfoot { display: flex; justify-content: space-between; align-items: center; margin-top: 18px; }

/* reveal (submit -> correct/wrong + explanation; also the permanent state of any
   answered question viewed via Back or the results-page drill-down) */
/* The explanation is the reason the sitting reveals at all (§8, v24) — it was set at 13px
   under a hairline with no label, the register of a footnote (2026-07-27 design pass).
   Now: a small-caps heading in the page's own label style, and the prose in the body serif
   at reading size with real leading. A heading and a rule, deliberately NOT a box — a
   question page shows exactly three things, and every past breach began as a panel here. */
.reveal {
  margin-top: 18px; border-top: var(--border-hairline) solid var(--line); padding-top: 14px;
  font: 400 15px/1.65 var(--font-body); color: var(--ink); text-align: justify;
}
.revhead {
  font: 700 var(--fs-label) / 1 var(--font-ui); text-transform: uppercase;
  letter-spacing: var(--tracking-label); color: var(--muted); margin-bottom: 9px;
}
.reveal b { font-weight: 600; color: var(--ink); }
.reveal ul { margin: 0; padding: 0; list-style: none; }
.reveal li { position: relative; padding-left: 15px; margin-bottom: 7px; }
.reveal li:last-child { margin-bottom: 0; }
.reveal li::before { content: "—"; position: absolute; left: 0; color: var(--accent); }
.reveal .tag { font: 700 10px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .05em; padding: 2px 7px; border-radius: var(--radius-pill); }
.reveal .flag { color: var(--warn); margin-top: 8px; font-style: italic; }
.scorepill { font: 700 11px/1 var(--font-ui); color: var(--good); }
/* inline correctness marker for select/input-based types (match/calc/extract/entry),
   which have no button to mark .correct/.wrong on directly — mirrors the review
   console's .ent pattern but built on the app's own tokens. */
.ans { font: 700 12px/1 var(--font-ui); margin-left: 8px; }
.ans.ok { color: var(--good); }
.ans.bad { color: var(--accent); }
/* A correction, typeset as one: a quiet small-caps label, then the correct option in the
   option face at option size — the same type the taker read it in when choosing. It was
   one 12px UI-font run ("Answer: Consolidated Senior Secured Net Indebtedness"), which
   made the label and the answer indistinguishable at a glance (2026-07-27). */
.ans .want { display: inline-flex; align-items: baseline; gap: 7px; margin-left: 7px; }
.ans .wlbl { font: 700 10px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); flex: none; }
.ans .wval { font: 500 var(--fs-option)/1.45 var(--font-option); color: var(--ink); }

/* results */
.res { display: grid; grid-template-columns: 1fr 300px; gap: 22px; align-items: start; margin-top: 16px; }
/* The rail's max-height is set in JS (results.js's syncRailHeight), matched to the radar
   card's own rendered height — CSS grid has no way to cap one item's height to a sibling's
   without a fixed-height ancestor, so this is just the overflow half of that fix. Below the
   820px breakpoint the JS clears the inline max-height (the two cards no longer share a
   row), so this is inert there and the rail flows at its natural height instead. */
.res .card.railcard { overflow-y: auto; }
/* Themed scrollbar — the native default is a light-mode-only widget on most platforms/browsers
   (it doesn't follow the app's own dark/light toggle), so left alone it looks like a stray
   light-UI element sitting inside a dark card. `scrollbar-color` covers Firefox; the
   `::-webkit-scrollbar-*` rules cover Chrome/Safari/Edge. Track is transparent so it reads as
   part of the card, not a separate lane. */
.res .card.railcard { scrollbar-color: var(--muted) transparent; scrollbar-width: thin; }
.res .card.railcard::-webkit-scrollbar { width: 10px; }
.res .card.railcard::-webkit-scrollbar-track { background: transparent; }
.res .card.railcard::-webkit-scrollbar-thumb { background-color: var(--muted); border-radius: 6px; border: 2px solid var(--surface); }
.res .card.railcard::-webkit-scrollbar-thumb:hover { background-color: var(--ink); }
@media (max-width: 820px) { .res { grid-template-columns: 1fr; } }
.radar-wrap { display: flex; flex-direction: column; align-items: center; }
/* Score-on-hover tooltip (2026-07-27, Chunk 1 — replaces the number a deleted pillar bar
   used to show). Pure CSS, no JS state: radar.js always emits the tooltip markup, hidden
   until `.pspoke:hover` reveals it, matching how the rest of this SVG is a re-issued string
   on every redraw rather than a stateful widget. `pointer-events: none` keeps the bubble from
   stealing the hover/click that .pspoke itself handles. */
.pspoke .ptip { opacity: 0; transition: opacity var(--motion-fast); pointer-events: none; }
.pspoke:hover .ptip, .pspoke:focus-within .ptip { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .pspoke .ptip { transition: none; } }
.toggle { display: inline-flex; border: var(--border-hairline) solid var(--line); border-radius: var(--radius-pill); overflow: hidden; margin-bottom: 6px; }
.toggle button { border: none; background: transparent; color: var(--muted); font: 600 12.5px/1 var(--font-ui); padding: 7px 14px; cursor: pointer; }
.toggle button.on { background: var(--accent); color: var(--on-accent); }
.legend { display: flex; gap: 16px; justify-content: center; font: 11px var(--font-ui); color: var(--muted); margin-top: 8px; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; }
.lvl { font-family: var(--font-display); font-weight: 700; font-size: 20px; margin-top: 2px; }
.badge { display: inline-block; font: 700 11px/1 var(--font-ui); letter-spacing: .03em; padding: 5px 12px; border-radius: var(--radius-pill); border: var(--border-hairline) solid var(--accent); color: var(--accent); margin-top: 8px; }
.field-claret { background: var(--accent); color: var(--on-accent); border-radius: var(--radius-card); padding: 12px 14px; }
.field-claret .lvl { color: var(--on-accent); }
.ribbon { display: inline-block; font: 700 10px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .06em; background: var(--accent); color: var(--on-accent); padding: 4px 10px; border-radius: var(--radius-pill); }
.pill-list { margin-top: 14px; display: grid; gap: 8px; }
.pl { font-size: 12.5px; }
.pl .track { height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 10%, transparent); margin-top: 3px; overflow: hidden; }
.pl .track i { display: block; height: 100%; background: var(--data-current); width: 0; transition: width .8s ease; }
.note { font-size: 11.5px; color: var(--muted); margin-top: 18px; border-top: var(--border-hairline) solid var(--line); padding-top: 10px; }
.sharebar { display: flex; gap: 10px; align-items: center; margin-top: 14px; flex-wrap: wrap; }

/* End-of-sitting feedback box (PRD §14, added 2026-07-27) — the same visual language as
   the intake's .prototype-box (accent-tinted surface, small pill label), reproduced here
   unscoped since the results page doesn't carry the `.intake` class. */
.feedback-box {
  margin-top: 28px; display: grid; grid-template-columns: auto minmax(0,1fr); gap: 20px; align-items: start;
  background: color-mix(in srgb, var(--accent) 5.5%, var(--surface)); border: var(--border-hairline) solid var(--line);
  border-left: 3px solid var(--accent); border-radius: var(--radius-card); padding: 22px 26px;
}
.feedback-box .pill {
  font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent);
  border: var(--border-hairline) solid var(--accent); border-radius: var(--radius-pill); padding: 6px 12px; white-space: nowrap;
}
.feedback-box p { margin: 0 0 8px; font-size: 15px; line-height: 1.5; }
.feedback-box p.sub { font-size: 12.5px; color: var(--muted); margin-bottom: 14px; }
.feedback-box textarea {
  display: block; width: 100%; resize: vertical; min-height: 80px; font: 15px/1.5 var(--font-body); color: var(--ink);
  background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card);
  padding: 10px 12px; margin-bottom: 12px;
}
.feedback-box textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 560px) {
  .feedback-box { grid-template-columns: 1fr; }
}

/* radar draw-in */
.draw { animation: draw var(--motion-reveal); transform-origin: center; }
@keyframes draw { from { opacity: .2; transform: scale(.92); } to { opacity: 1; transform: scale(1); } }

/* ===== graphics layer ===== */
body[data-gfx="off"] .gfx { display: none !important; }
.ill { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ill .f-surface { fill: var(--surface); }
.ill .f-accent { fill: var(--accent); }
.ill .f-ink { fill: var(--ink); }
.ill .f-line { fill: var(--line); }
.ill .s-none { stroke: none; }
.ill .s-accent { stroke: var(--accent); stroke-width: 3.4; }
.hero-ill { position: absolute; top: 4px; right: 8px; z-index: 0; width: 232px; height: 194px; }
.spot-ill { position: absolute; top: 2px; right: 10px; z-index: 0; width: 140px; height: 120px; }
.hero-ill svg, .spot-ill svg { width: 100%; height: 100%; display: block; }
.chip { display: inline-flex; align-items: center; justify-content: center; background: var(--accent); color: var(--on-accent); border-radius: var(--chip-radius); flex: none; }
.chip svg { stroke: #fff; fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; display: block; }
.domchip { width: 34px; height: 34px; border-radius: 10px; margin-right: 10px; vertical-align: -11px; }
.domchip svg { width: 18px; height: 18px; }
.pl .pchip { width: 24px; height: 24px; border-radius: 7px; margin-right: 9px; vertical-align: -6px; }
.pl .pchip svg { width: 14px; height: 14px; }
.qbg { position: absolute; top: -24px; right: -14px; width: 300px; height: 200px; z-index: 0; color: var(--accent); opacity: var(--gfx-faint-opacity); pointer-events: none; }
.qbg svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.card > *:not(.cardbg) { position: relative; z-index: 1; }
.hasbg { overflow: hidden; }
.cardbg { position: absolute; right: -16px; bottom: -16px; width: 140px; height: 140px; z-index: 0; color: var(--accent); opacity: var(--gfx-faint-opacity); pointer-events: none; }
.cardbg svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }

/* ===== progress bar (domain-labeled) + review-mode nav ===== */
.progress { margin-bottom: 16px; }
.pmeta { font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 8px; }
.pmeta b { color: var(--ink); }
/* Restyled as one continuous rail (interaction-lab mockup, 2026-07-26 feedback pass) —
   still one button per question, still clickable to jump back to that answer, still
   domain-colored; just drawn edge-to-edge as slim contiguous slices instead of separate
   pill/dot buttons, with the whole rail's un-reached remainder showing as the base line. */
.segs { display: flex; gap: 0; height: 4px; border-radius: 999px; overflow: hidden; background: var(--line); min-width: 160px; }
.seg {
  flex: 1 1 0; height: 100%; min-width: 3px; padding: 0; margin: 0; font-size: 0; color: transparent;
  border: none; border-radius: 0; background: color-mix(in srgb, var(--ink) 18%, transparent); cursor: default;
}
.seg.done { cursor: pointer; }
.seg.dom-FK { background: var(--accent); }
.seg.dom-PI { background: var(--warn); }
.seg.dom-AIF { background: var(--good); }
.seg.on { box-shadow: inset 0 0 0 1.5px var(--ink); }
.review-banner { display: flex; align-items: center; gap: 8px; font: 600 12px/1.3 var(--font-ui); color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, transparent); border: var(--border-hairline) solid color-mix(in srgb, var(--warn) 40%, var(--line)); border-radius: var(--radius-card); padding: 8px 12px; margin-bottom: 12px; }
/* Submitting is a confirmation, not a caution — it read in the same ochre as the
   locked-answer notice until 2026-07-27, so the two banners said the same thing in colour
   while saying opposite things in words. Ochre stays with the warning. */
.review-banner.ok { color: var(--good); background: color-mix(in srgb, var(--good) 10%, transparent); border-color: color-mix(in srgb, var(--good) 40%, var(--line)); }
.reviewing #ctl, .reviewing .passage, .reviewing select, .reviewing input, .reviewing .opt, .reviewing .mc { pointer-events: none; }
.disclaimer { font-size: 12.5px; line-height: 1.5; color: var(--muted); border-left: 3px solid var(--warn); background: color-mix(in srgb, var(--warn) 8%, transparent); border-radius: 0 5px 5px 0; padding: 8px 11px; margin-bottom: 14px; }

/* Both illustrations are currently unused — hero-ill dropped from intake 2026-07-25,
   spot-ill from the results drill-down 2026-07-27 (the live question screen had already
   dropped its graphic on 7/26; that path was missed). Their positioning rules stay, paired,
   for when either returns. The `.spot-ill ~ .eyebrow/h1/.dek` right-padding that kept the
   headline out from under the mascot went WITH the call: it existed only to clear an
   illustration, so leaving it behind would have indented a heading against nothing. */
@media (max-width: 900px) {
  .hero-ill, .spot-ill { display: none; }
}
/* ?dev only — the bank item id, so walkthrough notes can name a question exactly */
.devid { color: var(--accent); font-family: var(--font-ui); letter-spacing: .02em; }

/* ============================================================================
   Results explainer (PRD §9.2) — reconciled from the Claude Design dashboard
   pass, 2026-07-26. Four surfaces: the profile additions below, the pillar
   panel, "What this measured", and "Show the arithmetic".
   Design rule held here: cutoff marks live on the BARS, never on the radar —
   the radar carries shape, the bars carry position against a threshold.
   ============================================================================ */

.stage.results { max-width: 1120px; }

/* --- hero --- */
.rhero { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; padding-bottom: 22px; border-bottom: var(--border-hairline) solid var(--line); }
.rhero h1 { font-size: clamp(28px, 3vw, 38px); font-weight: 700; margin: 0; flex: none; }
.rrule { flex: 1; min-width: 20px; height: 1px; background: var(--line); }
.rwho { text-align: right; }
.rwho .sub { margin-top: 6px; }
/* One knob for the whole hero mark — discs and artwork scale together off --lantern-mark,
   so resizing it never leaves the lantern bursting out of its backdrop. Doubled 76 -> 152
   on 2026-07-26 (Ashley). The trimmed artwork is 221x327, so at this size it is still
   rendering under 1:1 and stays crisp on a retina screen. */
.lantern { --lantern-mark: 152px; position: relative; width: var(--lantern-mark); height: var(--lantern-mark); flex: none; display: flex; align-items: center; justify-content: center; color: var(--accent); }
.lantern .lring { position: absolute; border-radius: 50%; }
.lantern .lring.o { width: var(--lantern-mark); height: var(--lantern-mark); background: var(--ring-outer); }
.lantern .lring.i { width: calc(var(--lantern-mark) * 0.79); height: calc(var(--lantern-mark) * 0.79); background: var(--ring-inner); }
.lantern .lantern-img { position: relative; width: auto; height: calc(var(--lantern-mark) * 0.76); object-fit: contain; }
.lantern .lantern-dark { display: none; }
:root[data-theme="dark"] .lantern .lantern-light { display: none; }
:root[data-theme="dark"] .lantern .lantern-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .lantern .lantern-light { display: none; }
  :root:not([data-theme="light"]) .lantern .lantern-dark { display: block; }
}

/* --- card headings shared by every explainer surface --- */
.chead { display: flex; align-items: baseline; gap: 16px; }
.chead h2 { font: 700 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--ink); margin: 0; }
.sub.i { font-family: var(--font-body); font-style: italic; font-size: 14px; color: var(--muted); }

/* --- Surface 1: pillar bars with cutoff ticks --- */
/* `transition` here would be a no-op and was one (2026-07-27, third pass): draw() replaces
   #stage's innerHTML wholesale on every state change, so .res is a brand-new element on every
   redraw with no "before" value for a transition to interpolate from — it can only ever jump
   straight to whatever grid-template-columns says for that render. Only `@keyframes` animation
   plays correctly on a freshly-inserted node, which is why the fix below is animation-based,
   not transition-based, for both the rail and the radar. */
.res { grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr); gap: 34px; }
/* The page opens on the radar alone, full width (2026-07-27) — read the shape first, then
   pick a domain to open the pillar rail beside it. */
.res.solo { grid-template-columns: minmax(0, 1fr); }
.res.solo .radar-wrap { max-width: 620px; margin-inline: auto; }
/* Every open/close of the rail gives the radar card a quick settle cue (opacity+scale) timed
   with the rail's own slide, so the radar's instant width snap doesn't read as a bare glitch
   next to an animated neighbour — .enter is added by the JS on the single draw where the rail
   state actually flips either way (open or closed), never on redraws that merely change what's
   showing inside an already-open rail. */
.res .card:first-child.settle { animation: radarSettle var(--motion-fast); }
@keyframes radarSettle { from { opacity: .55; transform: scale(.99); } to { opacity: 1; transform: scale(1); } }
/* The pillar rail and the question drawer are freshly-mounted nodes on every render (this
   page does a full innerHTML rebuild on every state change, not a targeted DOM patch), so a
   plain mount-triggered animation on `.railcard` replayed every time ANYTHING redrew it —
   e.g. picking a different pillar bar inside an already-open rail, or opening a question from
   one of its rows — even though the rail itself hadn't just opened. `.enter` is only added by
   the JS for the one draw where the rail actually transitions closed→open, so the slide-in
   plays on real opens and stays out of the way otherwise. The question drawer has no such
   false-positive case (every open is a genuine reveal of a — possibly different — question),
   so it keeps the unconditional mount animation. */
.res .card.railcard.enter, #qslot .card.qdrawer { animation: railIn var(--motion-reveal); }
@keyframes railIn { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: translateX(0); } }
/* The exit side of the same pattern: JS holds the actual state change (and the redraw that
   would delete these nodes) until this animation's `animationend` fires, so the rail/question
   visibly leaves instead of vanishing the instant something is clicked (2026-07-27, third
   pass). `forwards` holds the end state for that brief hand-off window. */
.res .card.railcard.leaving, #qslot .card.qdrawer.leaving { animation: railOut var(--motion-fast) forwards; }
@keyframes railOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(18px); } }
/* .tick and .pscale stay bare (not scoped under a now-deleted .prow/.plist ancestor) —
   explain.js's cutoff strip (Chunk 3, untouched) still uses both. */
.tick { position: absolute; top: -3px; bottom: -3px; width: 1px; background: var(--line); }
.pscale { display: flex; margin-top: 9px; font: 500 9.5px/1.2 var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--muted-3); }
.pscale span { border-left: 1px solid var(--grid-line); padding-left: 5px; }
.ptrend { margin: 18px 0 0; font-family: var(--font-body); font-size: 15px; color: var(--muted); }

/* --- the condensed question grid (FK/PI domain card click, replaces the deleted pillar
   progress bars, 2026-07-27 Chunk 1) — every question in the domain as a small square,
   grouped under its pillar. */
.qgrid { margin-top: 14px; }
.qgroup { padding: 13px 0; border-bottom: var(--border-hairline) solid var(--line); }
.qgroup:last-child { border-bottom: none; }
.qglabel { display: flex; align-items: center; gap: 8px; font: 600 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.qsquares { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-top: 10px; }
.qsq { width: 22px; height: 22px; border-radius: 4px; padding: 0; cursor: pointer; transition: transform var(--motion-fast); }
.qsq:hover { transform: scale(1.12); }
.qsq.ok { background: var(--accent); border: none; }
.qsq.no { background: transparent; border: 1.5px solid var(--faint-x); }
/* The hover caption for a square lands in the empty space beside the row, not a bubble over
   the square (2026-07-27, second pass, Ashley's correction) — reuses .hint-slot/.hint/
   wireHints() verbatim, same as the top bar's "Copy result link"/"Take again" captions and
   the pilljump hint. One shared slot per pillar's row: every "ok" square in it says the same
   thing, every "no" square says the same thing, so they share one pair of hint spans. */
.qsquares .hint-slot { width: 200px; height: 22px; flex: none; margin-left: 4px; }
/* Font/color deliberately NOT overridden here (2026-07-27, third pass, Ashley's call) — the
   base .hint-slot .hint rule above (13.5px/1.3 var(--font-body), --muted) is what the bar's
   "Copy result link"/"Take again" captions render in, so this hint matches them and the
   pilljump hint (which only re-scopes size/position for its bubble, not the font) instead of
   carrying its own bolder, --font-ui, --ink-colored look. */
.qsquares .hint-slot .hint { justify-content: flex-start; }
.legend .ln { width: 14px; height: 0; border-radius: 0; }
.legend .ln.you { border-top: 2.2px solid var(--data-current); }
.legend .ln.bm { border-top: 1.6px dashed var(--data-benchmark); }

/* --- Surface 1: the three band cards, each with its provenance caption --- */
/* Columns come from the number of cards actually rendered, not a hardcoded 3: partner
   mode has no Finance Knowledge card (PRD §5), and a fixed 3-track grid left an empty
   third column that read as a score deleted rather than one never offered. */
.tracks { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); margin-top: 26px; border-top: var(--border-hairline) solid var(--line); border-bottom: var(--border-hairline) solid var(--line); }
.tcard { padding: 15px 16px; border-right: var(--border-hairline) solid var(--line); }
.tcard:last-child { border-right: none; padding-right: 0; }
/* The first card used to sit flush against the container's own left edge (padding-left:0)
   — reversed 2026-07-27 (Ashley's call): it read as misaligned against the page's other
   left-edge content, not intentionally flush. Now every card gets the same 16px inset,
   first or not, so the old partner-only override (which existed only to undo the zero for
   whichever card happened to land first when FK is absent) is redundant and removed. */
.tlabel {
  font: 500 10.5px/1.3 var(--font-ui); text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); white-space: nowrap;
}
/* nowrap + tighter tracking (was .08em) so "Practical Integration" fits on one line like its
   neighbors — a wrapped label pushed everything below it in that column down a full line,
   reading as the three cards being misaligned rather than one label being long (2026-07-27). */
.badge.solid { background: var(--accent); color: var(--on-accent); border-radius: var(--radius-card); }
/* Practical Integration / AI Fluency level badges (2026-07-27, Chunk 1) — filled with that
   tier's ramp color, the radar ring label's color inverted (figure/ground swapped) into a
   solid chip. Border matches the fill (the `.badge.solid` pattern above already does this
   for the plain accent case) so there's no mismatched outline color. White badge text was
   chosen per-step against BOTH ramps in both themes (validated 4.5:1+ WCAG, dataviz skill) —
   see tokens.css's --lvl-fill-* / --aif-fill-* comment for why the dark-mode fill steps are a
   separate, darker set of the same hue rather than literally the ring label's own color. */
.badge.lvl-1, .badge.lvl-2, .badge.lvl-3, .badge.lvl-4,
.badge.aif-1, .badge.aif-2, .badge.aif-3 { color: var(--lvl-badge-ink); border-radius: var(--radius-card); }
.badge.lvl-1 { background: var(--lvl-fill-1); border-color: var(--lvl-fill-1); }
.badge.lvl-2 { background: var(--lvl-fill-2); border-color: var(--lvl-fill-2); }
.badge.lvl-3 { background: var(--lvl-fill-3); border-color: var(--lvl-fill-3); }
.badge.lvl-4 { background: var(--lvl-fill-4); border-color: var(--lvl-fill-4); }
.badge.aif-1 { background: var(--aif-fill-1); border-color: var(--aif-fill-1); }
.badge.aif-2 { background: var(--aif-fill-2); border-color: var(--aif-fill-2); }
.badge.aif-3 { background: var(--aif-fill-3); border-color: var(--aif-fill-3); }
.tsub { font-family: var(--font-body); font-size: 13.5px; color: var(--muted); margin-top: 7px; }
.tnote { font-family: var(--font-body); font-style: italic; font-size: 12.5px; line-height: 1.4; color: var(--muted-3); margin-top: 5px; }
@media (max-width: 640px) { .tracks { grid-auto-flow: row; } .tcard { border-right: none; border-bottom: var(--border-hairline) solid var(--line); padding: 15px 0; } }

/* --- the pillar / AI-Fluency panel --- */
.rlinks { margin-top: 20px; text-align: right; }
.rlinks a { font: 600 12px/1 var(--font-ui); color: var(--accent); text-decoration: none; }
.rlinks a:hover { color: var(--ink); }
.pqs { margin-top: 10px; border-top: var(--border-hairline) solid var(--ink); }
.pqbody { min-width: 0; }
.atitle { display: block; }
/* What the question ASKED, under its internal handle. "BRP nested caps — prompt
   construction" names the item for the bank, not for the person who answered it. */
.pqasked { display: block; margin-top: 3px; font-family: var(--font-body); font-size: 13px; line-height: 1.45; color: var(--muted); }
.pparts em { display: block; font-style: normal; margin-top: 3px; color: var(--muted-3); }
/* The per-pillar working, folded away behind its own summary — it was a bare formula
   sitting under the question list with nothing saying what it was. */
.pcalcwrap { margin-top: 18px; border-top: var(--border-hairline) solid var(--line); padding-top: 14px; }
.pcalcwrap > summary { font: 600 12px/1 var(--font-ui); color: var(--accent); cursor: pointer; list-style: none; }
.pcalcwrap > summary::-webkit-details-marker { display: none; }
.pcalcwrap > summary::before { content: "+ "; }
.pcalcwrap[open] > summary::before { content: "− "; }
.pcalcwrap > summary:hover { color: var(--ink); }
/* Every question row is a door (2026-07-27) — it was inert text beside a clickable copy of
   the same list further down the page, which is the duplication this restructure removed. */
.pq {
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; gap: 10px 14px; align-items: start;
  width: 100%; text-align: left; padding: 9px 8px 9px 2px; border: none;
  border-bottom: var(--border-hairline) solid var(--line);
  background: transparent; color: inherit; font: inherit; cursor: pointer;
  transition: background var(--motion-fast);
}
.pq:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.pq:last-child { border-bottom: none; }
.pparts { font: 500 11px/1.4 var(--font-ui); color: var(--muted-3); white-space: nowrap; }
.pcalc, .calc { margin-top: 16px; background: var(--bg); border: var(--border-hairline) solid var(--line); border-radius: 4px; padding: 14px 18px; font: 13.5px/1.7 var(--font-ui); font-variant-numeric: tabular-nums; color: var(--muted); white-space: pre-wrap; }
.amark { font: 600 13px/1.44 var(--font-ui); }
.amark.ok { color: var(--accent); }
.amark.no { color: var(--faint-x); }
.atitle { font-size: 15px; line-height: 1.44; }
@media (max-width: 640px) { .pq { grid-template-columns: 20px minmax(0, 1fr); } .pparts { display: none; } }

/* --- the open question --- */
/* One slot, directly under the charts and above "What this measured", fed by a pillar row,
   an AI-Fluency row or a coverage-map cell. It needs a visible edge: a question is a tall
   two-column layout, and dropped between a bar chart and a coverage map with no boundary it
   reads as the page having changed rather than a drawer having opened. */
.qdrawer { margin-top: 18px; padding: 22px 26px 26px; border-left: 3px solid var(--accent); }
.qdhead { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 14px; margin-bottom: 4px; }
.qdhead .eyebrow { grid-column: 1; }
.qdhead h2 { grid-column: 1; font-size: 22px; margin: 4px 0 0; }
.qclose { grid-column: 2; grid-row: 1 / span 2; align-self: start; font: 600 11px/1 var(--font-ui); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--muted); background: transparent; border: var(--border-hairline) solid var(--line); border-radius: var(--radius-pill); padding: 7px 12px; cursor: pointer; transition: color var(--motion-fast), border-color var(--motion-fast); }
.qclose:hover { color: var(--ink); border-color: var(--ink); }
.qdrawer .qwrap, .qdrawer #qwrap { margin-top: 16px; }

/* --- the AI Fluency card, the one band card that is also a door --- */
/* Finance Knowledge and Practical Integration are NOT doors: the five pillar bars already
   reach their questions. AI Fluency has no pillar, so without this its questions have no
   way in at all. */
/* Explicit flex column, top-anchored (2026-07-27, Ashley's report) — a <button> that is a
   stretched grid item keeps Chrome's internal content layout centered vertically (its
   default `justify-content` for that internal box) even once `display: block` is set on it
   directly; only an explicit `display: flex` + `justify-content: flex-start` on the button
   itself overrides it. `align-items: flex-start` keeps the badge pill hugging its own text
   width instead of stretching to the column's full width (flex's cross-axis default).
   Invisible when a card's content already fills its box top-to-bottom (Finance Knowledge,
   Practical Integration — both wrap onto a multi-line qualifier), but AI Fluency's shorter,
   unwrapped qualifier left the extra room this was quietly centering into, so its whole
   content block sat visibly lower than the other two cards' top-anchored content. */
.tcard.door {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start;
  text-align: left; font: inherit; color: inherit; background: transparent; cursor: pointer;
  transition: background var(--motion-fast); border-top: none; border-left: none; border-bottom: none;
}
.tcard.door:hover, .tcard.door.on { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.tcard.door.on { box-shadow: inset 0 -3px 0 var(--accent); }
.respick { margin: 14px 0 0; font-family: var(--font-body); font-style: italic; font-size: 14px; color: var(--muted); }

/* --- "What this measured", now a section of the results page --- */
/* Rewritten 2026-07-28 (Ashley) — was a four-part masthead (eyebrow/h1/pull-quote/dek)
   over three tall single-column lists with per-domain "X of Y seen" tallies. Now one
   heading line, no coverage counts, and a dense two-column grid per domain. */
.measured { display: block; margin-top: 52px; padding-top: 8px; border-top: var(--border-hairline) solid var(--ink); }
.measured .mhero { margin-top: 26px; }
.mhero { margin-bottom: 28px; }
/* One line, one typeface choice — a serif heading sized to read as a section title
   without competing with the dashboard's own "Your bearings" h1 above it. */
.msingle { font-family: var(--font-display); font-weight: 600; font-size: clamp(23px, 2.6vw, 29px); letter-spacing: -.01em; margin: 0; }
.mapsec { margin-top: 30px; }
/* Size + color swapped with the domain name (2026-07-28): the domain name now carries the
   accent, this descriptor sits in plain ink underneath it. Sentence case, not all-caps. */
.measured .chead h2 { font-size: 12px; color: var(--accent); }
.msub { font: 600 11px/1.3 var(--font-ui); letter-spacing: .04em; color: var(--ink); margin: 8px 0 0; }
/* Two columns, one row per pillar/skill — replaced the full-width stacked list
   (2026-07-27 dropped the clickable coverage cells; 2026-07-28 dropped the row-per-line
   height, name + blurb now one compact block). */
.mgrid { margin-top: 14px; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); padding: 4px 20px; }
.mrow { padding: 11px 0; border-top: var(--border-hairline) solid var(--line); }
.mgrid .mrow:nth-child(1), .mgrid .mrow:nth-child(2) { border-top: none; }
@media (max-width: 640px) {
  .mgrid { grid-template-columns: 1fr; }
  .mgrid .mrow:nth-child(2) { border-top: var(--border-hairline) solid var(--line); }
}
.rowname { font: 600 13.5px/1 var(--font-ui); }
.rowblurb { font-family: var(--font-body); font-style: italic; font-size: 13px; color: var(--muted); margin-top: 2px; }
/* AI Fluency's Foundational grid + the source footnote share this one box, not two
   (2026-07-28) — .sources supplies the outer card; a nested .mgrid drops its own chrome. */
.card.sources { margin-top: 14px; padding: 14px 20px; }
.sources .mgrid { background: none; border: none; padding: 0; margin-top: 0; }
.sources .lead { font-size: 12px; color: var(--muted); margin: 14px 0 0; padding-top: 12px; border-top: var(--border-hairline) solid var(--line); }
.sources .lead a { color: var(--accent); text-decoration: none; border-bottom: 1px dotted currentColor; }

/* ============================================================================
   Source tables (PRD §12, fixed 2026-07-26). Excerpts that ARE tables in the
   filing now render as tables: FK-D3/E3/E3-PI are authored as markdown pipe
   tables, and FK-D1/D4/D1-PI are financial statements parsed by value-peeling
   (see excerptHtml in question.js). Verbatim text is untouched — this is
   presentation only. Column alignment is most of what makes a filing readable,
   and on the calculation items the taker works figures straight out of it.
   ============================================================================ */
.srctable { width: 100%; border-collapse: collapse; font-size: var(--fs-question); line-height: 1.45; }
.srctable th, .srctable td { padding: 5px 8px; vertical-align: top; text-align: left; }
.srctable thead th { font: 600 11px/1.3 var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); border-bottom: 1px solid var(--ink); }
.srctable tbody tr { border-bottom: var(--border-hairline) solid var(--line); }
.srctable tbody tr:last-child { border-bottom: none; }
/* financial statements: label left, figures right, tabular numerals so digits line up */
.srctable.fin th[scope="row"] { font-weight: 400; padding-left: 0; }
.srctable.fin td { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; padding-right: 0; }
.srctable.fin td:not(:last-child) { padding-right: 14px; }
/* section captions ("Operating expenses:") and blank spacers keep the statement's shape */
.srctable.fin tr.cap { border-bottom: none; }
.srctable.fin tr.cap td { text-align: left; font-weight: 600; padding-left: 0; white-space: normal; }
.srctable.fin tr.sp { border-bottom: none; }
.srctable.fin tr.sp td { padding: 4px 0; }
.src .srctable { margin: 2px 0; }
@media (max-width: 700px) { .srctable { font-size: 12.5px; } }

/* Bullet-list excerpts (FK-C8, 2026-07-28): disjunctive provisions stitched together from
   different sections, given a visual break between them instead of reading as one run-on
   paragraph. Inherits .clause's serif/justify (see excerptHtml's isBulletBlock). */
.clause.verbatim .srclist { margin: 0 0 0.85em; padding-left: 1.3em; }
.clause.verbatim .srclist:last-child { margin-bottom: 0; }
.clause.verbatim .srclist li { margin-bottom: 0.6em; }
.clause.verbatim .srclist li:last-child { margin-bottom: 0; }

/* ============================================================================
   Content-review chrome (?review). Sits ABOVE #stage, never inside it — the
   question canvas must stay byte-identical to what a test-taker sees, which is
   the whole reason this is a mode and not a separate console.
   ============================================================================ */
#reviewbar { position: sticky; top: 0; z-index: 19; background: var(--bar-bg); backdrop-filter: blur(8px); border-bottom: var(--border-hairline) solid var(--line); }
.rvline { display: flex; align-items: center; gap: 10px; padding: 8px 22px; flex-wrap: wrap; }
.rvline.second { border-top: var(--border-hairline) solid var(--line); }
.rvline .sp { flex: 1; }
.rvcount { font: 500 12px/1 var(--font-ui); color: var(--muted); font-variant-numeric: tabular-nums; }
.rvcount b { color: var(--ink); font-size: 14px; }
.rvid { font: 700 11px/1 var(--font-ui); letter-spacing: .04em; color: var(--accent); }
.rvid .rvdom { color: var(--muted-3); font-weight: 500; letter-spacing: .06em; margin-left: 8px; text-transform: uppercase; }
.rvdone { font-family: var(--font-body); font-style: italic; font-size: 13px; color: var(--muted); }
.rvlbl { font: 600 10.5px/1 var(--font-ui); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
#reviewbar select { font: 500 12px/1 var(--font-ui); color: var(--ink); background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); padding: 6px 8px; max-width: 330px; }
#reviewbar #rvFilter { max-width: 190px; }
.rvnote { flex: 1; min-width: 200px; font: 400 13px/1.4 var(--font-body); color: var(--ink); background: var(--surface); border: var(--border-hairline) solid var(--line); border-radius: var(--radius-card); padding: 7px 11px; }
.rvnote:focus { outline: none; border-color: var(--accent); }
#rvVerdict button { border: none; background: transparent; color: var(--muted); font: 600 12px/1 var(--font-ui); padding: 7px 12px; cursor: pointer; }
#rvVerdict button.on { background: var(--accent); color: var(--on-accent); }
.btn.ghost.sm.on { border-color: var(--accent); color: var(--accent); }
@media (max-width: 820px) { #reviewbar select { max-width: 150px; } }
