/* /test — built on the design tokens the scorecard already ships (see /assets/styles.css).
 *
 * TOKENS ONLY, no hardcoded colours. Every colour here resolves through --bg / --surface / --text /
 * --line / --link etc., which the design system redefines under [data-theme="dark"] and under
 * prefers-color-scheme. Hardcoding #fff and #1d1116 (the previous version) produced a page that was
 * light in one half and dark in the other and ignored the theme toggle entirely.
 *
 * There is deliberately no @media (prefers-color-scheme: dark) block: the tokens already handle it,
 * and a second mechanism competing with them is what caused the mixed-theme rendering.
 *
 * Class names are prefixed. `.hero` belongs to the design system and is a DARK band by design
 * (--hero-bg is near-black); reusing it gave the form an unintended dark hero with unreadable
 * controls. Ours is .probe-hero.
 */

.analyzer {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-grotesk, system-ui, sans-serif);
  margin: 0;
  line-height: 1.5;
}

.analyzer__header {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap;
  max-width: var(--maxw, 1040px); margin: 0 auto; padding: 1.25rem var(--pad, 1.5rem);
  border-bottom: 1px solid var(--line);
}
.analyzer__brand { font-weight: 700; text-decoration: none; color: inherit; }
.analyzer__nav { display: flex; align-items: center; gap: 1rem; font-size: .9rem; }
.analyzer__nav a { color: inherit; }
.analyzer__nav a[aria-current] { color: var(--accent); font-weight: 600; }
.analyzer__user { display: inline-flex; flex-direction: column; line-height: 1.2; }
.analyzer__user small { color: var(--text-soft); font-variant-numeric: tabular-nums; }

/* The design system styles .theme-toggle for the scorecard's DARK hero band, so it hardcodes
   color: var(--hero-text) — cream. Our header sits on --bg, where cream on cream renders the
   label invisible: the control looked like a stray red dot. Re-point it at the body text colour,
   scoped to this header so the scorecard's own hero toggle is untouched. */
.analyzer__header .theme-toggle {
  color: var(--text);
  border-color: color-mix(in srgb, var(--text) 32%, transparent);
}
.analyzer__header .theme-toggle:hover { border-color: var(--accent); }

/* Explicit background + colour, never `inherit`. On a tinted panel an inherited colour can land
   the same as the panel behind it — which is how the sign-in button ended up invisible. */
.analyzer__linkbtn {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 999px;
  padding: .35rem .85rem; font: inherit; font-size: .85rem; cursor: pointer;
}
.analyzer__linkbtn:hover { border-color: var(--accent); color: var(--accent); }

.analyzer__main { max-width: var(--maxw, 1040px); margin: 0 auto; padding: 0 var(--pad, 1.5rem) 4rem; }
.analyzer__footer { max-width: var(--measure, 68ch); margin: 0 auto;
  padding: 2rem var(--pad, 1.5rem) 3rem; font-size: .85rem; color: var(--text-soft); }
.analyzer__flash { max-width: var(--maxw, 1040px); margin: 1rem auto 0; padding: .7rem 1rem;
  border-radius: var(--radius, 10px); background: var(--code-bg); color: var(--text); }
.analyzer__flash--warn { border: 1px solid var(--bad); }

/* --- input ------------------------------------------------------------------------------------ */
/* The re-run control, under the status line where "replayed from cache" is read. Button and reason
   on one baseline, wrapping together on a phone. */
.status__again { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin: .5rem 0 0; }
.status__again form { display: inline; }
.status__again small { color: var(--text-soft); font-size: .8rem; max-width: 46ch; }

.probe-hero { padding: 2.5rem 0 1rem; }

/* The address, for a room that is going to type it. Monospace and letter-spaced so it survives a
   projector, and muted so it reads as a caption above the headline rather than competing with it. */
.probe-hero__url { font-family: var(--font-mono, monospace); font-size: .85rem;
  letter-spacing: .04em; color: var(--text-soft); margin: 0 0 .5rem; }

.probe-hero h1 { font-family: var(--font-grotesk); font-weight: 720;
  font-size: clamp(1.8rem, 4vw, 2.6rem); line-height: 1.1; margin: 0 0 .75rem; letter-spacing: -.02em; }
.probe-hero__lead { max-width: var(--measure, 68ch); font-size: 1.05rem; color: var(--text-soft); }

/* Two labelled fields rather than one box that guesses. The grid keeps them side by side on a
   laptop and stacked on a phone, and the submit row spans both so "either may be empty" reads as a
   rule about the pair rather than about the second field. */
.probe-form { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
  margin: 1.5rem 0 .5rem; align-items: start; }
@media (max-width: 46rem) { .probe-form { grid-template-columns: 1fr; } }
.probe-form__field { display: flex; flex-direction: column; gap: .3rem; }
.probe-form__field label { font-size: .85rem; font-weight: 650; }
.probe-form__hint { font-size: .8rem; color: var(--text-soft); line-height: 1.4; }

/* Label on the left, live word count on the right, so the number sits where the eye already is when
   you start typing rather than below the box where it would be hidden by the keyboard on a phone. */
.probe-form__labelrow { display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem; }

/* WORDS, not characters, because words are what the probe requires. Tabular figures so the number
   does not jitter sideways as it counts. Muted until it means something: a count that turns red on
   the first keystroke reads as an error when it is really just "keep going". */
.wordcount { font-size: .78rem; font-family: var(--font-mono, monospace);
  font-variant-numeric: tabular-nums; color: var(--text-soft); white-space: nowrap; }
.wordcount--short { color: var(--warn); }
.wordcount--ok { color: var(--ok); }

/* Why the button is dead, next to the button. A disabled control with its reason somewhere else on
   the page is the same as a broken one. */
.probe-form__reason { font-size: .82rem; color: var(--warn); font-weight: 600; }

/* Disabled says "read the counter", so it stays visible and obviously inert rather than hidden. */
.probe-form input[type="submit"]:disabled { background: var(--line-strong);
  border-color: var(--line-strong); color: var(--bg); cursor: not-allowed; }
.probe-form__submit { grid-column: 1 / -1; display: flex; align-items: center; gap: .8rem;
  flex-wrap: wrap; }

/* Collapsed by default: most visitors are checking a site, and a third box open by default makes
   the form read as three things you must fill in rather than three you may. */
.probe-form__paste { grid-column: 1 / -1; }
.probe-form__paste > summary { cursor: pointer; font-size: .85rem; font-weight: 650;
  color: var(--link); }
.probe-form__paste[open] > summary { margin-bottom: .5rem; }
.probe-form textarea { width: 100%; padding: .8rem 1rem; font: inherit;
  font-family: var(--font-mono, monospace); font-size: .9rem; line-height: 1.5;
  border: 2px solid var(--line-strong); border-radius: var(--radius, 10px);
  background: var(--surface); color: var(--text); resize: vertical; }
.probe-form textarea:focus { outline: none; border-color: var(--accent); }
.probe-form input[type="text"] {
  width: 100%; padding: .8rem 1rem; font: inherit; font-family: var(--font-mono, monospace);
  font-size: .95rem; border: 2px solid var(--line-strong);
  border-radius: var(--radius, 10px); background: var(--surface); color: var(--text);
}
.probe-form input[type="text"]:focus { outline: none; border-color: var(--accent); }
.probe-form input[type="submit"] {
  padding: .8rem 1.6rem; font: inherit; font-weight: 600; cursor: pointer; color: #fff;
  background: var(--accent); border: 2px solid var(--accent); border-radius: var(--radius, 10px);
}

/* Inline, not flex. As a flex container the <strong> count became its own flex item and wrapped
   onto its own line, rendering as a stray "4" above the sentence. */
.probe-form__quota { font-size: .9rem; color: var(--text-soft); max-width: var(--measure, 68ch); }
.probe-form__quota strong { color: var(--text); }
.probe-form__quota form { display: inline; }
.probe-form__quota .analyzer__linkbtn { margin-left: .4rem; vertical-align: baseline; }

.examples { margin-top: 2.5rem; }
.examples h2 { font-size: 1.1rem; margin-bottom: .6rem; }
.examples__list { list-style: none; padding: 0; display: grid; gap: .5rem; }

/* One row per example since the notes came off: pair on the left, Run it on the right. Grid rather
   than flex-wrap, which gave every row a different height depending on how long its URLs happened
   to be. The pair column wraps INSIDE itself (hence min-width: 0, or a long URL refuses to wrap and
   pushes the button off), so the control stays in one place down the list. */
.examples__list li { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: .5rem 1rem;
  border: 1px solid var(--line); border-radius: var(--radius, 10px); padding: .7rem 1rem;
  background: var(--surface); }
@media (max-width: 46rem) { .examples__list li { grid-template-columns: 1fr; } }

/* Both halves of the pair are shown before anything runs, which is the point of the redesign: the
   tool no longer works one out from the other, so the demo should never look like it did. */
.example__pair { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.example__label { font-weight: 700; }
.example__docs, .example__repo { font-family: var(--font-mono, monospace); font-size: .8rem;
  background: var(--code-bg); border-radius: 4px; padding: .1rem .4rem; color: var(--text-soft); }
.example__docs::before { content: "docs "; opacity: .6; }
.example__repo::before { content: "repo "; opacity: .6; }
.example__go { display: flex; gap: .8rem; align-items: center; justify-content: flex-end; }
.example__go form { display: inline; }
.examples__btn { background: var(--accent); color: #fff; border: 0; border-radius: 999px;
  padding: .3rem .9rem; font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer; }

/* --- the deck ----------------------------------------------------------------------------------
 *
 * Results are walked one slide at a time, like a presentation, and slides ACCUMULATE: advancing
 * reveals the next and keeps everything already shown. The controls are pinned to the bottom of the
 * viewport so the prompt to advance is visible wherever the visitor has scrolled to.
 *
 * padding-bottom on .deck reserves room for that fixed bar, or the last slide's final line sits
 * underneath it and looks truncated.
 */
.deck { padding: 1.5rem 0 7rem; }
.deck__head { display: grid; gap: .6rem; padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--line); }
.deck__back a { font-size: .9rem; }
.deck__target { display: flex; gap: .5rem; flex-wrap: wrap; }

.chip { display: inline-flex; align-items: baseline; gap: .4rem; font-family: var(--font-mono, monospace);
  font-size: .85rem; border: 1px solid var(--line-strong); border-radius: 999px;
  padding: .2rem .8rem; background: var(--surface); max-width: 100%; }
.chip a { color: var(--text); word-break: break-all; }
.chip__key { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-soft); font-family: var(--font-grotesk, sans-serif); }
.chip--docs { border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.chip--repo { border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.chip--passage { border-color: color-mix(in srgb, var(--warn) 45%, transparent); }

/* The pasted text, shown rather than summarised: a probe you cannot see the input to is not
   evidence of anything. */
.deck__passage > summary { cursor: pointer; font-size: .85rem; color: var(--text-soft); }
.deck__passage > summary:hover { color: var(--accent); }
.deck__passage blockquote { margin: .5rem 0 0; padding: .8rem 1rem; background: var(--code-bg);
  border-left: 3px solid var(--warn); border-radius: var(--radius, 10px); font-size: .9rem;
  line-height: 1.6; white-space: pre-wrap; max-width: var(--measure, 68ch); }

.status { padding: .6rem .9rem; border-radius: var(--radius, 10px);
  background: var(--code-bg); color: var(--text); font-size: .9rem; }
.status small { color: var(--text-soft); }

.deck__stages { display: grid; gap: 2.5rem; }
.stage { padding-top: 1.75rem; scroll-margin-top: 1rem; }
.stage + .stage { border-top: 1px solid var(--line); }
.stage__number { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); font-weight: 600; margin: 0 0 .4rem; }
.stage__title { font-family: var(--font-grotesk); font-weight: 720;
  font-size: clamp(1.4rem, 3vw, 2rem); line-height: 1.15; letter-spacing: -.02em; margin: 0; }
.stage__lead { color: var(--text-soft); margin: .35rem 0 1.25rem; max-width: var(--measure, 68ch); }

/* Hidden slides are display:none rather than visibility:hidden, so they take no space and the
   fixed nav never floats over a gap. The reveal controller also pulls their focusables out of the
   tab order, which display:none does for free but the class has to survive a broadcast. */
.stage--hidden { display: none; }
.stage:not(.stage--hidden) { animation: stage-in .28s ease-out both; }
@keyframes stage-in { from { opacity: 0; transform: translateY(.6rem) } to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) { .stage:not(.stage--hidden) { animation: none } }

.deck__nav { position: fixed; left: 50%; transform: translateX(-50%); bottom: 1rem; z-index: 20;
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; justify-content: center;
  padding: .5rem .8rem; border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--surface); box-shadow: 0 6px 24px rgb(0 0 0 / 18%); max-width: calc(100vw - 2rem); }
/* The UA rule for [hidden] is `display: none` at element specificity, so the class above wins and a
   hidden nav keeps rendering. Restate it. */
.deck__nav[hidden] { display: none; }
.deck__btn { font: inherit; font-size: .85rem; cursor: pointer; border-radius: 999px;
  border: 1px solid var(--line-strong); background: var(--bg); color: var(--text);
  padding: .3rem .8rem; }
.deck__btn:disabled { opacity: .35; cursor: default; }
.deck__btn--go { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.deck__dots { display: inline-flex; gap: .3rem; }
.dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--line-strong); opacity: .5; }
.dot--on { background: var(--accent); opacity: 1; }
.deck__hint { font-size: .78rem; color: var(--text-soft); }
.deck__hint.is-spent { display: none; }
.deck__hint kbd { font-family: var(--font-mono, monospace); font-size: .72rem;
  border: 1px solid var(--line-strong); border-radius: 4px; padding: 0 .25rem; }
.deck__all { font: inherit; font-size: .78rem; background: none; border: 0; color: var(--link);
  cursor: pointer; text-decoration: underline; }
@media (max-width: 34rem) { .deck__hint { display: none; } }

.deck__evidence { margin-top: 1.5rem; border-top: 1px solid var(--line); padding-top: .8rem; }
.deck__evidence > summary { cursor: pointer; font-size: .85rem; color: var(--text-soft);
  text-transform: uppercase; letter-spacing: .04em; }
.deck__evidence > summary:hover { color: var(--accent); }

.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }

/* --- the answer, above the evidence ------------------------------------------------------------
 *
 * Two cards, one per question the visitor came with. They are deliberately the largest type on the
 * page: the four detail boxes are the working, and the working is not an answer.
 *
 * Tone is carried by a left rule and the headline colour, never by colour alone — `--unknown` and
 * `--mixed` differ in wording too, so a red/green-blind reader loses nothing.
 */
.answer { display: block; border: 1px solid var(--line); border-left: 4px solid var(--line-strong);
  border-radius: var(--radius, 10px); padding: 1rem 1.2rem; background: var(--surface);
  margin: 0 0 1.25rem; }
.answer > * { display: block; }
.answer__q { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-soft); margin: 0 0 .4rem; }
.answer__headline { font-family: var(--font-grotesk); font-weight: 700;
  font-size: clamp(1.1rem, 2.2vw, 1.35rem); line-height: 1.25; margin: 0 0 .5rem;
  letter-spacing: -.01em; }
.answer__detail { font-size: .92rem; margin: 0; color: var(--text); }
.answer__caveat { font-size: .82rem; color: var(--text-soft); margin: .6rem 0 0; }

.answer--yes { border-left-color: var(--ok); }
.answer--yes .answer__headline { color: var(--ok); }
.answer--no { border-left-color: var(--bad); }
.answer--no .answer__headline { color: var(--bad); }
.answer--mixed { border-left-color: var(--warn); }
.answer--unknown { border-left-color: var(--line-strong); }
.answer--unknown .answer__headline { color: var(--text-soft); }

/* The progressive part: a card with nothing in it yet reads as unfinished rather than as a null
   answer, and stops pulsing the moment real evidence lands. */
.answer--pending .answer__headline { color: var(--text-soft); animation: answer-breathe 1.6s ease-in-out infinite; }
@keyframes answer-breathe { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
@media (prefers-reduced-motion: reduce) { .answer--pending .answer__headline { animation: none } }

/* --- slide 1: agent experience -----------------------------------------------------------------
 *
 * Two columns of boxes, docs on the left and repo on the right, because the two are separately
 * fixable and a visitor usually owns one of them and not the other.
 *
 * A box that is not ticked carries its fix inline. That is the whole design: a checklist that only
 * reports leaves the reader to work out what any of it is worth.
 */
.ax__scope { font-size: .88rem; color: var(--text-soft); border-left: 3px solid var(--line-strong);
  padding-left: .8rem; margin: 0 0 1.25rem; max-width: var(--measure, 68ch); }
.ax__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
@media (max-width: 52rem) { .ax__cols { grid-template-columns: 1fr; } }

.axcol { border: 1px solid var(--line); border-radius: var(--radius, 10px);
  background: var(--surface); padding: 1rem 1.1rem; }
.axcol__head { margin-bottom: .75rem; }
.axcol__head h3 { font-size: 1rem; margin: 0; }
.axcol__subject { font-family: var(--font-mono, monospace); font-size: .8rem;
  color: var(--text-soft); margin: .15rem 0 0; word-break: break-all; }
.axcol__empty { font-size: .9rem; color: var(--text-soft); margin: 0; }
.axcol--missing { border-style: dashed; }

/* The packaged fix: full width under the tally, not inside a column. Nested in the docs card, an
   open panel stretched that card to twice the height of the repo card next to it and left a
   column of white space; across the full width it opens downward and moves nothing sideways. */
.axskill { margin: 1rem 0 0; border: 1px dashed var(--line-strong);
  border-radius: var(--radius, 10px); padding: .8rem 1rem; background: var(--surface); }
.axskill > summary { cursor: pointer; font-size: .9rem; font-weight: 650; color: var(--accent); }
.axskill > summary:hover { text-decoration: underline; }
.axskill[open] > summary { margin-bottom: .5rem; }

.axskill__what { font-size: .88rem; line-height: 1.6; margin: .6rem 0 0;
  max-width: var(--measure, 68ch); }
.axskill__what code { font-size: .95em; }
.axskill__covers { list-style: none; padding: 0; margin: 0; font-size: .85rem;
  display: grid; gap: .2rem; }
.axskill__covers li::before { content: "\2192\00a0"; color: var(--accent); }

/* The install line is a command someone copies, so it never wraps mid-flag: it scrolls instead. */
.axskill__install { margin: .8rem 0 0; padding: .55rem .7rem; overflow-x: auto;
  border-radius: 6px; background: var(--code-bg); }
.axskill__install code { font-family: var(--font-mono, monospace); font-size: .8rem;
  white-space: pre; color: var(--text); }
.axskill__links { font-size: .82rem; margin: .55rem 0 0; }

.ax__tally { margin: 1rem 0 0; font-size: .92rem; }
.ax__tally strong { color: var(--bad); font-size: 1.1rem; }
.ax__tally--clear { color: var(--ok); }

/* The inline fix under an unticked box. Indented under the label so the column still scans as a
   list of boxes rather than as prose. */
.check__action { display: block; font-size: .85rem; margin-top: .3rem; padding-left: .1rem;
  color: var(--text); border-left: 2px solid color-mix(in srgb, var(--accent) 50%, transparent);
  padding-left: .6rem; }
.check__action--info { border-left-color: var(--line-strong); }
.check__why-link { white-space: nowrap; font-weight: 600; }
.check--warn .check__mark { color: var(--warn); }
.check--waiting { opacity: .6; }
.check--waiting .check__mark { color: var(--text-soft); }

/* Placeholder rows while a column's check is still running, so the slide has its final shape
   before the data lands and nothing jumps when it does. */
.checks--ghost .check__body { flex: 1; }
.ghostbar { display: block; height: .7rem; width: 70%; border-radius: 4px;
  background: var(--line); animation: ghost 1.4s ease-in-out infinite; }
@keyframes ghost { 0%, 100% { opacity: .35 } 50% { opacity: .8 } }
@media (prefers-reduced-motion: reduce) { .ghostbar { animation: none } }

/* --- slide 2: the two funnels ------------------------------------------------------------------
 *
 * Two wide bases narrowing into one small apex. The widths are the argument: every tier keeps a
 * fraction of what arrives at it, and verbatim recall is rare even for text that cleared them all.
 *
 * Drawn with plain boxes at percentage widths rather than clip-path trapezoids, because the labels
 * have to stay readable at 320px and a real trapezoid clips its own text.
 */
.funnel { display: grid; gap: .5rem; justify-items: center; }
.funnel__apex { width: 100%; display: flex; justify-content: center; }
.funnel__apex .tier { width: min(26rem, 60%); }

.funnel__connector { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  justify-content: center; font-size: .85rem; color: var(--text-soft); margin: 0;
  text-align: center; }
.funnel__arrow { color: var(--accent); font-size: 1.2rem; line-height: 1; }
.funnel__mechanism { font-weight: 650; color: var(--text); }

/* One grid for BOTH channels, with each tile placed explicitly, so the two funnels share their row
   heights. As two independent grids they did not: "Archived and permissively licensed" wraps to
   three lines and "Quality filter" to two, and the middle tier of one channel floated half a tile
   above the other, which reads as a rendering fault rather than as a comparison.

   `display: contents` on .fchan lets its children join the parent grid while the channel keeps its
   class for placement. */
.funnel__channels { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem 1.25rem; width: 100%;
  align-items: end; }
.fchan { display: contents; }
.fchan--web .tier:nth-of-type(1) { grid-area: 1 / 1; }
.fchan--web .tier:nth-of-type(2) { grid-area: 2 / 1; }
.fchan--web .fchan__foot { grid-area: 3 / 1; }
.fchan--code .tier:nth-of-type(1) { grid-area: 1 / 2; }
.fchan--code .tier:nth-of-type(2) { grid-area: 2 / 2; }
.fchan--code .fchan__foot { grid-area: 3 / 2; }
.funnel__channels .tier { justify-self: center; }

/* Stacked, the two funnels run one after the other rather than side by side, so the placement has
   to be re-declared or both channels land in the same three rows on top of each other. */
@media (max-width: 46rem) {
  .funnel__channels { grid-template-columns: 1fr; }
  .fchan--web .tier:nth-of-type(1) { grid-area: 1 / 1; }
  .fchan--web .tier:nth-of-type(2) { grid-area: 2 / 1; }
  .fchan--web .fchan__foot { grid-area: 3 / 1; }
  .fchan--code .tier:nth-of-type(1) { grid-area: 4 / 1; }
  .fchan--code .tier:nth-of-type(2) { grid-area: 5 / 1; }
  .fchan--code .fchan__foot { grid-area: 6 / 1; }
}
.fchan__foot { font-size: .8rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-soft); margin: .2rem 0 0; text-align: center; }
.fchan__subject { display: block; text-transform: none; letter-spacing: 0;
  font-family: var(--font-mono, monospace); font-size: .78rem; word-break: break-all; }
.fchan__subject--none { font-style: italic; }

.tier { width: var(--tier-w, 100%); display: grid;
  grid-template-columns: 1.4rem 1fr auto; gap: .1rem .5rem; align-items: baseline;
  border: 1px solid var(--line-strong); border-radius: var(--radius, 10px);
  padding: .6rem .8rem; background: var(--surface); text-align: left; }
.tier__mark { grid-row: 1 / span 2; font-weight: 700; font-size: 1rem; align-self: center; }
.tier__label { font-weight: 650; font-size: .95rem; }
.tier__detail { grid-column: 2; font-size: .8rem; color: var(--text-soft); }
.tier__why { grid-column: 3; grid-row: 1; font-size: .78rem; white-space: nowrap; }

.tier--pass { border-color: color-mix(in srgb, var(--ok) 55%, transparent);
  background: color-mix(in srgb, var(--ok) 10%, var(--surface)); }
.tier--pass .tier__mark { color: var(--ok); }
.tier--fail { border-color: color-mix(in srgb, var(--bad) 55%, transparent);
  background: color-mix(in srgb, var(--bad) 8%, var(--surface)); }
.tier--fail .tier__mark { color: var(--bad); }
.tier--unknown { border-color: color-mix(in srgb, var(--warn) 55%, transparent); }
.tier--unknown .tier__mark { color: var(--warn); }
.tier--waiting, .tier--missing { border-style: dashed; opacity: .65; }

.tier--apex { border-width: 2px; }
.tier--apex .tier__label { font-family: var(--font-grotesk); font-weight: 750; font-size: 1.05rem; }

/* justify-self overrides the centring the funnel grid applies to its children: a paragraph capped
   at the reading measure and centred under two columns hangs in the middle of the page with no
   edge to start from. */
.funnel__note { font-size: .85rem; color: var(--text-soft); margin: 1rem 0 0;
  max-width: var(--measure, 68ch); justify-self: start; }

/* --- slide 3: the recall grid ------------------------------------------------------------------
 *
 * Models down the side, your text and the reference pages across the top. One shared scale across
 * the whole grid, because per-row scaling would make a 2-word run and a 31-word run look alike.
 */
/* --- waiting on the probe ----------------------------------------------------------------------
 *
 * The one wait on this page long enough to look like a hangup: 9 to 12 real model calls, 60 to 140
 * seconds. It gets a spinner, a running clock and a bar, because a static sentence for that long is
 * indistinguishable from a page that has died.
 *
 * Sized to roughly the height the grid will occupy, so the answer landing does not shove the rest of
 * the page down.
 */
.recall__waiting { font-size: .92rem; color: var(--text-soft); border: 1px solid var(--line);
  border-radius: var(--radius, 10px); padding: 1rem 1.1rem; background: var(--surface); }
.recall__waithead { display: flex; align-items: center; gap: .6rem; }
.recall__waittitle { font-weight: 650; color: var(--text); }
/* Tabular figures, or the whole line jitters sideways once a second as the digits change. */
.recall__clock { margin-left: auto; font-family: var(--font-mono, monospace); font-size: .85rem;
  font-variant-numeric: tabular-nums; color: var(--text); }

.recall__progress { height: .35rem; border-radius: 999px; background: var(--code-bg);
  margin: .8rem 0 .6rem; overflow: hidden; }
.recall__progress::after { content: ""; display: block; height: 100%; width: var(--progress, 0%);
  background: var(--accent); border-radius: 999px; transition: width 1s linear; }
/* Amber past the expected time: still running, no longer typical. */
.recall__progress--over::after { background: var(--warn); }

.recall__waitnote { font-size: .85rem; margin: 0; }
.recall__waitmodels { list-style: none; padding: 0; margin: .7rem 0 0; display: flex;
  flex-wrap: wrap; gap: .4rem .9rem; font-size: .8rem; }
.recall__waitmodels li { display: inline-flex; align-items: center; gap: .35rem; }
.recall__waitmodels code { font-size: .72rem; background: var(--code-bg); border: 0;
  border-radius: 4px; padding: .05rem .35rem; color: var(--text-soft); }
.recall__waitdot { width: .4rem; height: .4rem; border-radius: 50%; background: var(--accent);
  opacity: .5; animation: recall-pulse 1.4s ease-in-out infinite; }

.spinner { width: 1rem; height: 1rem; border-radius: 50%; flex: none;
  border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-top-color: var(--accent); animation: spin .8s linear infinite; }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes recall-pulse { 0%, 100% { opacity: .25; } 50% { opacity: .9; } }

/* Motion here is decoration, and a spinner is the classic trigger. The clock still counts, so
   nothing that carries information is lost. */
@media (prefers-reduced-motion: reduce) {
  .spinner, .recall__waitdot { animation: none; }
  .recall__progress::after { transition: none; }
}
.recall__scroll { overflow-x: auto; margin: 0 0 .8rem; }
.recall__grid { border-collapse: collapse; width: 100%; min-width: 40rem; }
.recall__grid th, .recall__grid td { padding: .5rem .6rem; border-bottom: 1px solid var(--line);
  vertical-align: middle; }
.recall__corner { text-align: left; font-size: .75rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-soft); font-weight: 500; }
.recall__col { text-align: left; vertical-align: bottom; min-width: 6.5rem; }
.recall__collabel { display: block; font-size: .85rem; font-weight: 650; }
.recall__colsub { display: block; font-size: .72rem; color: var(--text-soft); font-weight: 400; }
.recall__col--yours { border-bottom: 2px solid var(--accent); }
/* Family name over the exact model id. The id is what makes a number reproducible: "Claude Opus"
   will point at different weights in six months. */
.recall__model { text-align: left; white-space: nowrap; padding-right: .9rem; }
.recall__modelname { display: block; font-size: .9rem; font-weight: 650; }
/* border: 0 is load-bearing. The design system gives every <code> a 1px border, which on a block
   element stretched a box the full width of the column and read as an empty input. */
.recall__modelid { display: block; font-family: var(--font-mono, monospace); font-size: .68rem;
  font-weight: 400; color: var(--text-soft); background: none; border: 0; padding: 0;
  border-radius: 0; }

/* Bar and number on ONE line, with the bar in a fixed-width track. Stacked, the number sat under
   its own bar and every cell read as two separate facts. The track is what lets the bar keep a
   percentage width while still sitting beside the figure. */
.recall__cell { white-space: nowrap; }
.bar-track { display: inline-block; width: 4.5rem; vertical-align: middle; margin-right: .5rem;
  border-bottom: 1px solid var(--line); }
.bar { display: block; height: .5rem; border-radius: 3px; width: var(--bar, 0%); min-width: 2px;
  background: var(--line-strong); }
.recall__cell--yours .bar { background: var(--accent); }
.bar--none { opacity: .35; }
.bar__value { font-family: var(--font-mono, monospace); font-size: .8rem;
  font-variant-numeric: tabular-nums; }
.bar__value--muted { color: var(--text-soft); font-size: .72rem; }

.recall__legend { font-size: .85rem; color: var(--text-soft); margin: 0;
  max-width: var(--measure, 68ch); }
.recall__legend strong { color: var(--text); }

.recall__controls { font-size: .85rem; margin: .6rem 0 0; padding: .5rem .8rem;
  border-radius: var(--radius, 10px); background: var(--code-bg); }
.recall__controls--ok { color: var(--text-soft); }
.recall__controls--bad { border: 1px solid var(--bad); color: var(--bad); }
.recall__caveat { font-size: .85rem; color: var(--text-soft); margin: .8rem 0 0;
  max-width: var(--measure, 68ch); }

.tag--source { border-color: var(--accent); color: var(--accent); }

.steps { display: grid; gap: 1rem; margin-top: 1.25rem; }
.step { border: 1px solid var(--line); border-radius: var(--radius, 10px);
  padding: 1rem 1.2rem; background: var(--surface); }
.step--pending { opacity: .55; }
.step__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; }
.step__head h2 { font-size: 1.05rem; margin: 0; }
.step__hint, .step__note { font-size: .88rem; color: var(--text-soft); }
.step__error { color: var(--bad); font-size: .92rem; }

.tag { font-size: .75rem; padding: .15rem .55rem; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--text-soft); white-space: nowrap; }
.tag--cached { background: var(--code-bg); }
.tag--waiting { opacity: .7; }
.tag--ok { border-color: var(--ok); color: var(--ok); }
.tag--muted { opacity: .6; }

.checks { list-style: none; padding: 0; margin: .75rem 0 0; display: grid; gap: .5rem; }
.check { display: flex; gap: .6rem; align-items: flex-start; }
.check__mark { font-weight: 700; width: 1.2rem; flex: none; }
.check--pass .check__mark { color: var(--ok); }
.check--fail .check__mark { color: var(--bad); }
.check--unknown .check__mark { color: var(--text-soft); }
.check--info { opacity: .8; }
.check__body { display: flex; flex-direction: column; }
.check__detail { font-size: .9rem; }
.check__why { font-size: .82rem; color: var(--text-soft); }
.check__why--caveat { font-style: italic; }

/* --- the memorization probe ------------------------------------------------------------------- */
.verdict { padding: .8rem 1rem; border-radius: var(--radius, 10px); margin: .75rem 0;
  background: var(--code-bg); }
.verdict small { display: block; margin-top: .35rem; font-size: .85rem; color: var(--text-soft); }
.verdict--partial { border-left: 3px solid var(--warn); }
.verdict--strong { border: 1px solid var(--ok); }

/* The "show exactly what we tested" panel. Renders in two places, so it is styled by its own class
   rather than by the step tile it used to live inside. On the recall slide it is a standalone
   panel; inside the working appendix it sits within a tile that already has a border, hence the
   border only in the first case. */
.probe-evidence { margin-top: .5rem; font-size: .9rem; }
.probe-evidence > summary { cursor: pointer; font-weight: 600; }
.recall .probe-evidence { margin-top: 1.5rem; border: 1px solid var(--line);
  border-radius: var(--radius, 10px); padding: .75rem 1rem; background: var(--surface); }
.recall .probe-evidence > summary { color: var(--text-soft); font-weight: 650; }
.recall .probe-evidence[open] > summary { margin-bottom: .6rem;
  border-bottom: 1px solid var(--line); padding-bottom: .5rem; }
.probe { border-top: 1px solid var(--line); padding: .8rem 0; }
.probe__label { font-weight: 600; font-size: .85rem; margin: 0 0 .4rem; }
.probe__prefix, .probe__truth { font-family: var(--font-mono, monospace); font-size: .78rem;
  line-height: 1.5; background: var(--code-bg); padding: .5rem .7rem;
  border-radius: 6px; margin: .3rem 0; }
.probe__prefix em, .probe__truth em { font-family: var(--font-grotesk, sans-serif);
  color: var(--text-soft); font-size: .8rem; display: block; }
.probe__models { width: 100%; border-collapse: collapse; margin-top: .4rem; font-size: .85rem; }
.probe__models th { text-align: left; font-weight: 600; padding: .25rem .5rem .25rem 0; }
.probe__models td { padding: .25rem .5rem; }
.probe__row--strong td, .probe__row--strong th { color: var(--ok); font-weight: 600; }
.probe__row--partial td, .probe__row--partial th { color: var(--warn); }
.probe__matched { font-family: var(--font-mono, monospace); font-size: .75rem; color: var(--text-soft); }
.probe__controls { margin-top: .8rem; display: flex; gap: .4rem; flex-wrap: wrap; align-items: center; }
.probe__controls small { flex-basis: 100%; color: var(--text-soft); font-size: .8rem; }

.recent { margin-top: 2.5rem; font-size: .9rem; }
.recent h2 { font-size: 1.1rem; }
.recent ul { list-style: none; padding: 0; }
.recent li { padding: .25rem 0; }
.recent small { color: var(--text-soft); }

/* --- /learn ------------------------------------------------------------------------------------
 *
 * A reading page inside the app rather than a generated document, because every result on /test
 * deep-links into its anchors and needs the shared header and theme to come with it.
 *
 * scroll-margin-top on every anchor target: without it a #fragment lands with the heading flush
 * against the viewport edge, which reads as "the link went to the wrong place".
 */
.learn { max-width: var(--measure, 68ch); margin: 0 auto; padding: 2.5rem 0 4rem; }
.learn section { margin-top: 3rem; }
.learn [id] { scroll-margin-top: 1.5rem; }

.learn__kicker { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); font-weight: 600; margin: 0 0 .75rem; }
.learn h1 { font-family: var(--font-grotesk); font-weight: 750;
  font-size: clamp(1.9rem, 4vw, 2.6rem); line-height: 1.1; letter-spacing: -.02em; margin: 0 0 1rem; }
.learn h2 { font-family: var(--font-grotesk); font-weight: 720; font-size: 1.5rem; line-height: 1.2;
  letter-spacing: -.01em; margin: 0 0 1rem; padding-top: .5rem; border-top: 1px solid var(--line); }
.learn h3 { font-family: var(--font-grotesk); font-weight: 700; font-size: 1.1rem;
  margin: 2rem 0 .5rem; }
.learn p, .learn li { font-size: 1rem; line-height: 1.65; }
.learn__lead { font-size: 1.15rem; color: var(--text-soft); }
.learn__meta { font-size: .88rem; color: var(--text-soft); }
.learn__note { font-size: .92rem; color: var(--text-soft); border-left: 3px solid var(--line-strong);
  padding-left: .9rem; }
.learn code { font-family: var(--font-mono, monospace); font-size: .88em;
  background: var(--code-bg); padding: .1rem .3rem; border-radius: 4px; }

.learn__toc { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius, 10px); padding: 1rem 1.2rem 1rem 2.2rem; margin-top: 2rem; }
.learn__toc ol { margin: 0; padding-left: .5rem; }
.learn__toc li { font-size: .95rem; padding: .15rem 0; }

.learn__split { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.25rem 0; }
@media (max-width: 40rem) { .learn__split { grid-template-columns: 1fr; } }
.learn__col { border: 1px solid var(--line); border-radius: var(--radius, 10px);
  padding: 1rem 1.2rem; background: var(--surface); }
.learn__col h3 { margin: 0; }
.learn__colmeta { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-soft); margin: .2rem 0 .6rem; }
.learn__col ul { margin: 0; padding-left: 1.1rem; }
.learn__col li { font-size: .95rem; margin-bottom: .35rem; }

.learn__steps li { margin-bottom: .75rem; }

/* Wide content scrolls inside its own box; the page body never scrolls sideways. */
.learn__tablewrap { overflow-x: auto; margin: 1.25rem 0; }
.learn__table { border-collapse: collapse; width: 100%; font-size: .9rem; min-width: 34rem; }
.learn__table th, .learn__table td { text-align: left; vertical-align: top;
  padding: .5rem .7rem; border-bottom: 1px solid var(--line); }
.learn__table thead th { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-soft); }
.learn__table--outcomes td { font-size: .92rem; }
.learn__table--outcomes th[scope="row"] { width: 9rem; font-weight: 700; }

.learn__glossary dt { font-weight: 700; margin-top: 1.2rem; font-family: var(--font-grotesk); }
.learn__glossary dd { margin: .3rem 0 0; font-size: .95rem; line-height: 1.6; }

.learn__cta { display: inline-block; margin: .5rem 1rem .5rem 0; font-weight: 600; }
.learn__cta--quiet { color: var(--text-soft); font-weight: 500; }

/* --- the checklist -------------------------------------------------------------------------
 *
 * The page opens with what to do, because that is what a visitor arriving from a result wants.
 * Each item is one action, one reason, and a link to the section that shows the working.
 */
.learn__do, .learn__skip, .learn__limits { list-style: none; padding: 0; margin: 1rem 0 0;
  display: grid; gap: .6rem; counter-reset: none; }
.learn__do { counter-reset: doitem; }
.learn__do > li, .learn__skip > li, .learn__limits > li {
  border: 1px solid var(--line); border-radius: var(--radius, 10px);
  background: var(--surface); padding: .75rem 1rem .8rem 2.6rem; position: relative; }
.learn__do > li { border-left: 3px solid var(--accent); }

/* Numbered squares on the do-lists, an unchecked box on the skip-list: the shape says which list
   you are reading even when the heading has scrolled off. */
.learn__do > li::before { counter-increment: doitem; content: counter(doitem);
  position: absolute; left: .8rem; top: .8rem; width: 1.2rem; height: 1.2rem;
  border-radius: 4px; background: var(--accent); color: #fff; font-size: .72rem;
  font-weight: 700; display: grid; place-items: center; }
.learn__skip > li::before { content: "✕"; position: absolute; left: .8rem; top: .75rem;
  width: 1.2rem; height: 1.2rem; border-radius: 4px; font-size: .78rem; font-weight: 700;
  display: grid; place-items: center;
  color: var(--bad); border: 1px solid color-mix(in srgb, var(--bad) 45%, transparent); }
.learn__limits > li { padding-left: 1rem; border-left: 3px solid var(--line-strong); }

/* Fact lists: the page's default body copy. One claim per line, tighter than a paragraph and
   scannable in a way running prose is not. */
.learn__facts { margin: .6rem 0 1rem; padding-left: 1.1rem; }
.learn__facts li { font-size: .95rem; line-height: 1.55; margin-bottom: .3rem; }

.learn__why { display: block; font-size: .92rem; color: var(--text-soft); margin-top: .25rem; }
.learn__tag { display: inline-block; font-size: .68rem; text-transform: uppercase;
  letter-spacing: .05em; border: 1px solid var(--line-strong); border-radius: 999px;
  padding: .05rem .5rem; margin-left: .35rem; color: var(--text-soft); vertical-align: .1em; }
.learn__tag--high { color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent); }

/* --- collapsed evidence ---------------------------------------------------------------------
 *
 * Every measured claim keeps its table, one click from the sentence it supports. Closed by
 * default so the page reads as a checklist; open, it is the same evidence the old /guide printed
 * inline.
 */
.learn__ev { margin: 1rem 0 0; border: 1px solid var(--line); border-radius: var(--radius, 10px);
  background: var(--surface); }
.learn__ev > summary { cursor: pointer; padding: .6rem .9rem; font-size: .9rem; font-weight: 600;
  color: var(--text-soft); list-style-position: inside; }
.learn__ev > summary:hover { color: var(--accent); }
.learn__ev[open] > summary { border-bottom: 1px solid var(--line); }
.learn__ev > *:not(summary) { margin-left: .9rem; margin-right: .9rem; }
.learn__ev > *:last-child { margin-bottom: .9rem; }
.learn__evnote { font-size: .88rem; line-height: 1.6; color: var(--text-soft); }
.learn__sources { padding-left: 1.1rem; }
.learn__sources li { font-size: .88rem; line-height: 1.7; margin-bottom: .3rem; }

/* --- diagrams --------------------------------------------------------------------------------
 *
 * Hand-authored inline SVG: no external asset, and every colour is a design token, so the figures
 * follow the theme toggle like the rest of the page.
 *
 * Figures bleed wider than the reading measure, because 720 units squeezed into 68ch renders the
 * labels below legibility. Below that width they scroll inside their own box, the same bargain
 * .learn__tablewrap makes, so the page body never scrolls sideways.
 */
.learn__fig { --bleed: clamp(0rem, calc((100vw - var(--measure, 68ch)) / 2 - 2rem), 7rem);
  margin: 1.75rem calc(-1 * var(--bleed)); overflow-x: auto; }
.learn__svg { display: block; width: 100%; min-width: 34rem; height: auto; }
.learn__fig figcaption { font-size: .88rem; line-height: 1.55; color: var(--text-soft);
  margin: .6rem calc(var(--bleed)) 0; }

.svg-cap { font-family: var(--font-grotesk); font-size: 9.5px; font-weight: 700;
  letter-spacing: .09em; fill: var(--text-soft); }
.svg-cap--keep { fill: var(--accent); }
.svg-t { font-family: var(--font-grotesk); font-size: 13px; font-weight: 650; fill: var(--text); }
.svg-t--head { font-size: 13.5px; font-weight: 750; }
.svg-t--inv { fill: var(--bg); font-size: 15px; font-weight: 750; }
.svg-t--ok { fill: var(--ok); }
.svg-t--warn { fill: var(--warn); }
.svg-t--bad { fill: var(--bad); }
.svg-s { font-family: var(--font-grotesk); font-size: 11.5px; font-weight: 450;
  fill: var(--text-soft); }
.svg-s--strong { font-weight: 700; fill: var(--text); }
.svg-v { font-family: var(--font-mono, monospace); font-size: 11px; fill: var(--text-soft); }

.svg-box { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1; }
.svg-box--ok   { fill: color-mix(in srgb, var(--ok) 12%, var(--surface));
  stroke: color-mix(in srgb, var(--ok) 55%, transparent); }
.svg-box--warn { fill: color-mix(in srgb, var(--warn) 12%, var(--surface));
  stroke: color-mix(in srgb, var(--warn) 55%, transparent); }
.svg-box--bad  { fill: color-mix(in srgb, var(--bad) 12%, var(--surface));
  stroke: color-mix(in srgb, var(--bad) 55%, transparent); }
.svg-box--ink  { fill: var(--text); stroke: none; }
.svg-arrow { stroke: var(--line-strong); stroke-width: 1.5; fill: none;
  marker-end: url(#svg-arrowhead); }

.svg-lane { fill: var(--surface); stroke: var(--line); stroke-width: 1; }
.svg-lane--ok   { fill: color-mix(in srgb, var(--ok) 8%, var(--surface)); }
.svg-lane--warn { fill: color-mix(in srgb, var(--warn) 8%, var(--surface)); }
.svg-lane--bad  { fill: color-mix(in srgb, var(--bad) 8%, var(--surface)); }
.svg-pip { fill: var(--line-strong); }
.svg-pip--ok { fill: var(--ok); } .svg-pip--warn { fill: var(--warn); }
.svg-pip--bad { fill: var(--bad); }

.svg-axis { stroke: var(--line-strong); stroke-width: 1; }
.svg-keep { stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 4 3; }
.svg-bar--a { fill: var(--accent); }
.svg-bar--b { fill: color-mix(in srgb, var(--text-soft) 55%, transparent); }

.svg-quad { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1; }
.svg-quad--best { fill: color-mix(in srgb, var(--ok) 10%, var(--surface));
  stroke: color-mix(in srgb, var(--ok) 55%, transparent); }
.svg-quad--warn { fill: color-mix(in srgb, var(--warn) 10%, var(--surface));
  stroke: color-mix(in srgb, var(--warn) 55%, transparent); }
.svg-quad--bad  { fill: color-mix(in srgb, var(--bad) 10%, var(--surface));
  stroke: color-mix(in srgb, var(--bad) 55%, transparent); }

/* --- action items on a result ------------------------------------------------------------------
 *
 * The results are the finding; these are what a visitor can do about it. Ordered by impact, and
 * every one links to the part of /learn that explains why it is the lever.
 */
.actions { margin: 1.5rem 0 0; }
.actions__title { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-soft); margin: 0 0 .75rem; }
.actions__list { list-style: none; padding: 0; margin: 0; display: grid; gap: .75rem;
  counter-reset: action; }
.action { border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--radius, 10px); padding: .85rem 1.1rem; background: var(--surface); }
.action--low { border-left-color: var(--line-strong); }
.action__head { display: flex; gap: .6rem; align-items: baseline; flex-wrap: wrap; }
.action__title { font-weight: 700; font-size: 1rem; }
.action__tag { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-soft); border: 1px solid var(--line-strong); border-radius: 999px;
  padding: .05rem .5rem; }
.action__why { font-size: .92rem; margin: .35rem 0 0; }
.action__link { font-size: .85rem; margin: .4rem 0 0; }

.actions__settled { margin-top: .9rem; font-size: .9rem; }
.actions__settled summary { cursor: pointer; color: var(--text-soft); }
.actions__settled ul { margin: .5rem 0 0; padding-left: 1.1rem; color: var(--text-soft); }
.actions__settled li { font-size: .9rem; margin-bottom: .25rem; }

/* Glossary links inside a check row: present enough to be found, quiet enough not to turn the
   evidence into a wall of blue. */
.learn-term { color: inherit; text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 2px; }
.learn-term:hover { color: var(--accent); }

/* --- why the models have it --------------------------------------------------------------------
 *
 * Shown only when something fired. Recall on its own is a fact with no handle on it; duplication is
 * the part a visitor can act on, and it is what the study found predicts recall.
 */
.why { margin: 1rem 0 0; padding: .9rem 1.1rem; border: 1px solid var(--line);
  border-left: 3px solid var(--accent); border-radius: var(--radius, 10px);
  background: var(--surface); }
.why__title { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-soft); margin: 0 0 .5rem; }
.why__lead { margin: 0; font-size: 1rem; }
.why__lead strong { font-size: 1.15rem; color: var(--accent); }
.why__repos { list-style: none; padding: 0; margin: .6rem 0 0; display: flex; flex-wrap: wrap;
  gap: .35rem .75rem; font-family: var(--font-mono, monospace); font-size: .82rem; }
.why__note { font-size: .85rem; color: var(--text-soft); margin: .6rem 0 0;
  max-width: var(--measure, 68ch); }
.why__phrase { font-size: .8rem; color: var(--text-soft); margin: .6rem 0 0; }
.why__phrase code { font-family: var(--font-mono, monospace); background: var(--code-bg);
  padding: .1rem .35rem; border-radius: 4px; word-break: break-word; }

/* --- check another paragraph, from a result ----------------------------------------------------
 *
 * Sits under the recall grid because that is where the question occurs to you: a null row invites
 * "would anything of mine fire?", and until now answering it meant navigating back to the form.
 *
 * Deliberately quieter than the hero form. It is a follow-up, not the main event, so it borrows the
 * field styling and drops the emphasis.
 */
.recheck { margin: 1.5rem 0 0; padding: 1rem 1.1rem; border: 1px solid var(--line);
  border-radius: var(--radius, 10px); background: var(--surface); }
.recheck__title { font-family: var(--font-grotesk); font-size: 1rem; font-weight: 700;
  margin: 0 0 .6rem; }
.recheck__label { font-size: .85rem; font-weight: 650; }
.recheck__form textarea { width: 100%; margin-top: .3rem; padding: .7rem .85rem; font: inherit;
  font-size: .92rem; line-height: 1.5; border: 1px solid var(--line-strong);
  border-radius: var(--radius, 10px); background: var(--bg); color: var(--text); resize: vertical; }
.recheck__form textarea:focus { outline: none; border-color: var(--accent); }
.recheck__go { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-top: .6rem; }
.recheck__go input[type="submit"] { padding: .5rem 1.1rem; font: inherit; font-size: .9rem;
  font-weight: 600; cursor: pointer; color: #fff; background: var(--accent);
  border: 1px solid var(--accent); border-radius: var(--radius, 10px); }
/* Disabled says "the counter above is the reason", which is why the button stays visible rather
   than being hidden until the paragraph is long enough. */
.recheck__go input[type="submit"]:disabled { background: var(--line-strong);
  border-color: var(--line-strong); color: var(--bg); cursor: not-allowed; }

/* --- form validation ---------------------------------------------------------------------------
 *
 * Server-rendered, next to the field that caused them. The Stimulus counter is enhancement on top;
 * these are what a visitor sees with JavaScript off, and what they see when the client and the
 * server ever disagree.
 */
.form-errors { border: 1px solid var(--bad); border-left-width: 3px;
  border-radius: var(--radius, 10px); background: color-mix(in srgb, var(--bad) 8%, var(--surface));
  padding: .7rem 1rem; margin: 1.25rem 0 0; }
.form-errors p { margin: 0; font-size: .9rem; color: var(--text); }
.field-error { display: block; font-size: .82rem; color: var(--bad); font-weight: 600;
  margin-top: .1rem; }

/* The probe fell back to another page on the same site. Amber rather than red: it is a caveat about
   which page the number came from, not a failure. */
.recall__substituted { font-size: .85rem; margin: .5rem 0 0; padding: .5rem .8rem;
  border-left: 3px solid var(--warn); border-radius: var(--radius, 10px);
  background: color-mix(in srgb, var(--warn) 7%, var(--surface)); color: var(--text-soft); }
.recall__substituted a { word-break: break-all; }
