/* ============================================================================
   RETRIVIUM — components
   Load after tokens.css and base.css.

   Naming: block / block--modifier / block__element.
   Class names here are PRODUCTION names. The approved comp in
   reference/retrivium-design-v1.html uses short prototype names; the mapping
   table is in COMPONENTS.md. Build against these, not against the comp.
   ============================================================================ */

/* ============================================================================
   1 · APP SHELL
   The session surface is phone-shaped at every viewport. It never exceeds
   --app-max, because the cue has to survive a phone and a session that looks
   different on desktop is a different repetition (§9.2, context consistency).
   ============================================================================ */
.app-shell {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: var(--app-max);
  margin-inline: auto;
  min-height: 100dvh;
  background: var(--color-surface);
  color: var(--color-text);
}

/* Framed presentation — used on Records/Map/marketing surfaces, never in the PWA. */
.app-shell--framed {
  min-height: 31rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-app);
  box-shadow: var(--shadow-2), var(--shadow-hairline);
  overflow: hidden;
}

.page-shell {
  width: min(100% - 2rem, var(--page-max));
  margin-inline: auto;
  padding-block: var(--space-6);
}
.page-header {
  display: grid;
  grid-template-columns: minmax(8rem, 2fr) minmax(0, 7fr) minmax(0, 3fr);
  gap: var(--space-5);
  align-items: start;
}
.page-header > div { grid-column: 2; }
.page-header h1 { margin-top: var(--space-2); font-size: clamp(var(--text-2xl), 4vw, 2.4rem); }
.page-actions { max-width: 30rem; margin: var(--space-8) auto 0; }

/* The map's own rules now live in map.css: the surface renders a frontier
   rather than 308 nodes at once, so the node grid these described is gone. */

.concept-record { margin-block: var(--space-5); min-height: calc(100dvh - (2 * var(--space-5))); }
.evidence-heading { margin-top: var(--space-6); }
.dependency-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
.dependency-link { display: block; margin-top: var(--space-2); font-family: var(--font-mono); font-size: var(--text-sm); }

.criterion-card {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(8rem, 2fr) minmax(0, 5fr);
  gap: var(--space-5);
  align-items: center;
  margin-top: var(--space-8);
  padding: var(--space-6);
  border: 1px solid var(--color-state);
  border-radius: var(--radius-xl);
  background: var(--color-state-wash);
}
.criterion-card__value {
  font-family: var(--font-mono);
  font-size: 2.5rem;
  font-weight: var(--weight-bold);
  color: var(--color-state);
  text-align: center;
}

@media (max-width: 60rem) {
  .page-header { grid-template-columns: 8rem minmax(0, 1fr); }
  .page-header > div { grid-column: 2; }
}
@media (max-width: 36rem) {
  .page-shell { width: min(100% - 1rem, var(--page-max)); padding-block: var(--space-3); }
  .page-header { grid-template-columns: 1fr; }
  .page-header > div { grid-column: 1; }
  .page-header .logo { display: none; }
  .dependency-list, .criterion-card { grid-template-columns: minmax(0, 1fr); }
  .criterion-card__value { text-align: left; }
  .concept-record { margin-block: 0; min-height: 100dvh; border-radius: 0; }
}

.app-status {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.55rem var(--space-5) 0.35rem;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.04em;
  color: var(--color-text-subtle);
}

/* ============================================================================
   2 · BANDS
   Exactly one band is live per screen state. The rest recede but stay
   readable — they hold information the learner may need to check, and
   opacity below ~.55 pushes body text under AA.
   ============================================================================ */
.logo { display: inline-flex; align-items: center; gap: 0.6em; }
.logo__word {
  text-transform: uppercase;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wordmark);
  line-height: 1;
}
.logo--sm .logo__word { font-size: var(--text-md); }
.logo--md .logo__word { font-size: var(--text-xl); }
.logo--lg .logo__word { font-size: var(--text-2xl); }
.logo__lift { color: var(--color-action); }

.band {
  padding: var(--band-inset);
  border-top: 1px solid var(--color-border-soft);
  transition: opacity var(--dur-base) var(--ease-out);
}
.band:first-of-type { border-top: 0; }

.band--live  { background: var(--color-surface-sunk); }

/* Receded by TOKEN REMAP, not by opacity.
   Opacity was the obvious implementation and it is the wrong one: at the .6
   needed to read as receded, body text lands at 2.8:1. Shifting the text down
   one step of the ramp instead reads as just as quiet and stays above 4.5:1,
   because the floor (--color-text-subtle) is itself an AA colour. */
.band--quiet {
  --color-text: var(--color-text-muted);
  --color-text-muted: var(--color-text-subtle);
  color: var(--color-text);
}

/* After commit the prompt stops being the demand and becomes the thing the
   correction refers to. It stays pinned so feedback is never correlated from
   memory — this is the §10.2 requirement, and it is not optional. */
.band--ref {
  opacity: 0.78;
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--color-surface);
}

/* ============================================================================
   3 · ACTION BAR
   One primary action per screen state, pinned to the bottom, and the only
   garnet thing on screen. Making it structural is what makes the rule
   impossible to violate by accident.
   ============================================================================ */
.action-bar {
  margin-top: auto;
  padding: var(--action-inset);
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  position: sticky;
  bottom: 0;
  z-index: var(--z-action);
}

.btn {
  display: block;
  width: 100%;
  text-align: center;
  padding: 0.82rem var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-action);
  color: var(--color-action-text);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  letter-spacing: -0.006em;
  box-shadow: var(--shadow-1);
  min-height: 44px;                       /* touch target floor */
  transition: filter var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn:hover  { filter: brightness(1.07); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .5; cursor: not-allowed; filter: none; transform: none; }

/* Ghost — for actions that are not the session's forward motion
   (Open the map, Done, Back to the item). */
.btn--ghost {
  background: none;
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  box-shadow: none;
}
.btn--ghost:hover { border-color: var(--color-text-muted); filter: none; }

/* State — for stepping the trace. Never for a session action. */
.btn--state { background: var(--color-state); color: var(--color-state-text); }

.btn-link {
  display: block;
  width: 100%;
  margin-top: var(--space-2);
  text-align: center;
  font-size: var(--text-md);
  color: var(--color-text-muted);
  text-decoration: underline;
  text-decoration-color: var(--color-border);
  text-underline-offset: 3px;
  min-height: 32px;
}
.btn-link:hover { color: var(--color-text); text-decoration-color: var(--color-text-muted); }

.auth-form {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}
.field-label {
  display: block;
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-semi);
  color: var(--color-text-muted);
}
.flash { margin-top: var(--space-3); }

/* ============================================================================
   4 · TYPE ROLES
   Each of these owns one size from the scale. Do not mix.
   ============================================================================ */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-subtle);
}

/* The if–then plan. The largest type in the product — larger than any number.
   That is the hierarchy the evidence supports (d = 0.65 vs everything else). */
.plan {
  margin-top: var(--space-2);
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-semi);
  text-wrap: balance;
}
.plan em { font-style: normal; color: var(--color-action); }

/* The item prompt. Same size as .plan — they never appear together. */
.prompt {
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
  text-wrap: balance;
}

/* The session's learning goal, and capability statements at close. */
.goal {
  margin-top: var(--space-2);
  font-size: var(--text-base);
  line-height: var(--leading-snug);
}

/* Capability statement on the concept page. */
.capability {
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-tight);
}

.note {
  margin-top: var(--space-2);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--color-text-muted);
}
.note strong, .note b { color: var(--color-text); font-weight: var(--weight-semi); }

/* Inline code inside prose. */
.mono { font-family: var(--font-mono); font-size: 0.92em; }

/* ============================================================================
   5 · CODE
   Code is the most legible element on the page. Syntax classes live in code.css.
   ============================================================================ */
.code-box {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-code-bg);
  border-radius: var(--radius-lg);
  overflow-x: auto;
}

/* ============================================================================
   6 · ANSWER INPUT
   No peek-before-commit path exists. The field is monospace because what is
   typed is usually a value, not prose.
   ============================================================================ */
.field {
  width: 100%;
  margin-top: var(--space-3);
  padding: 0.78rem 0.85rem;
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  min-height: 44px;
}
.field::placeholder { color: var(--color-text-subtle); }
.field--committed {
  border-color: var(--color-text-muted);
  background: var(--color-surface-sunk);
}
.field[readonly] { cursor: default; }

/* Instrumentation (§14). Deliberately unglamorous: this is where the system is
   held to account, and it should not look like a scoreboard. */
.instrumentation h2 {
  margin-top: var(--space-6);
  font-size: var(--text-xl);
}
.instrumentation section + section { margin-top: var(--space-5); }

.metric-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  margin-top: var(--space-5);
}
.metric {
  padding: var(--space-3);
  background: var(--color-surface-sunk);
  border-radius: var(--radius-lg);
}
.metric__value {
  margin-top: var(--space-1);
  font-size: var(--text-xl);
  font-variant-numeric: tabular-nums;
}

/* Columns are capped rather than stretched: at a wide viewport a 1fr track
   pushes each label and its value to opposite ends of the row, and a number
   you have to track across 20rem of whitespace is a number you misread. */
.stat-list {
  margin-top: var(--space-3);
  display: grid;
  gap: var(--space-2) var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 18rem));
  justify-content: start;
}
.stat-list > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-md);
}
.stat-list dd { font-variant-numeric: tabular-nums; }

.monitor-list { list-style: none; margin-top: var(--space-3); }
.monitor {
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
}
.monitor__question { font-size: var(--text-md); }
.monitor__value {
  margin-top: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
/* A firing monitor is marked by its label, not by colour alone. */
.monitor--firing .monitor__value { color: var(--color-loss); }

.experiment-list { list-style: none; margin-top: var(--space-5); }
.experiment {
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--color-border);
}
.experiment__hypothesis { margin-top: var(--space-2); font-size: var(--text-lg); }
.experiment__removal,
.experiment__decision {
  margin-top: var(--space-2);
  font-size: var(--text-md);
  color: var(--color-text-muted);
}
.experiment__form { margin-top: var(--space-3); }
.rung-row + .rung-row { margin-top: var(--space-4); }

/* The boss challenge (§7.7). Its specification is running prose, not a single
   retrieval demand, so it takes the prose step rather than the prompt step. */
.challenge-spec {
  margin-top: var(--space-4);
  font-size: var(--text-xl);
  line-height: var(--leading-body);
}
.challenge-spec p + p { margin-top: var(--space-3); }

.criteria {
  margin: var(--space-2) 0 var(--space-4);
  padding-left: var(--space-4);
  font-size: var(--text-md);
  color: var(--color-text-muted);
}
.criteria li + li { margin-top: var(--space-2); }

.check-list { margin-top: var(--space-4); }
.check { list-style: none; }
.check__glyph { margin-right: var(--space-2); }
/* Colour is never the only carrier: the glyph changes shape too. */
.check--failed { color: var(--color-loss); }
.check__message {
  display: block;
  margin-top: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.btn--waiting { opacity: 0.55; pointer-events: none; }

/* What the hidden checks reported. This is the concrete discrepancy for a
   runner-graded item, so it sits above the elaborated feedback that explains
   it — never in place of it. */
.runner-output {
  margin-top: var(--space-4);
  padding: var(--space-3);
  background: var(--color-surface-sunk);
  border-radius: var(--radius-lg);
}
.runner-output__stream {
  margin: var(--space-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--leading-code);
  color: var(--color-text-muted);
  white-space: pre-wrap;
  overflow-x: auto;
}
.runner-output__stream--error { color: var(--color-loss); }

/* Code production. The submission is code, so it obeys the code rules: the
   most legible element on the page, structure never broken by wrapping. */
.field--code {
  font-size: var(--text-md);
  line-height: var(--leading-code);
  white-space: pre;
  overflow-x: auto;
  -moz-tab-size: 2;
  tab-size: 2;
}

.practice-form {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}
.choice-field {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  border: 0;
}
.choice-option {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  cursor: pointer;
}
.choice-option:has(input:checked) {
  border-color: var(--color-state);
  background: var(--color-state-wash);
}
.choice-option input { margin-top: 0.22em; accent-color: var(--color-state); }
.parsons-field {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  border: 0;
}
.parsons-field legend {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.parsons-slot {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: var(--space-3);
  align-items: center;
}
.parsons-slot label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.parsons-select {
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 0.65rem 2.2rem 0.65rem 0.75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.parsons-select:focus-visible { outline: 2px solid var(--color-state); outline-offset: 2px; }
.reveal-pending { visibility: hidden; }

/* Optional pre-commit confidence tap. One tap, removable if it slows sessions
   without producing calibration insight. */
.confidence { display: flex; gap: 0.35rem; margin-top: var(--space-2); }
.confidence button {
  flex: 1 1 0;
  padding: 0.32rem 0.3rem;
  min-height: 32px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.confidence button:hover { border-color: var(--color-text-muted); color: var(--color-text); }
.confidence button[aria-pressed="true"] {
  border-color: var(--color-state);
  color: var(--color-state);
  font-weight: var(--weight-semi);
}

/* ============================================================================
   7 · BLOCK PLAN
   Progress is shown at BLOCK granularity only. There is no item count and no
   shrinking remainder — nothing to sprint toward at the end of a session.
   ============================================================================ */
.block-plan { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: var(--space-2); }
.block-chip {
  padding: 0.14rem 0.55rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.04em;
  color: var(--color-text-subtle);
}
.block-chip--done { border-color: var(--color-state); color: var(--color-state); }
.block-chip--now  { border-color: var(--color-text); color: var(--color-text); font-weight: var(--weight-semi); }

/* ============================================================================
   8 · CONSISTENCY STRIP
   A trailing window, never a chain. There is no state here that can "break",
   and no repair to buy. Four day-states, each distinguishable without colour.
   Always give the strip role="img" and an aria-label with the counts.
   ============================================================================ */
.consistency { display: flex; gap: 0.22rem; margin-top: var(--space-2); }
.consistency__day {
  flex: 1 1 0;
  height: 0.5rem;
  border: 1px solid var(--color-text-subtle);
  border-radius: var(--radius-pill);
}
.consistency__day--cue  { background: var(--color-state); border-color: var(--color-state); }
.consistency__day--off  {                       /* done, outside the cue window */
  background: linear-gradient(to right, var(--color-state) 0 50%, transparent 50% 100%);
  border-color: var(--color-state);
}
.consistency__day--miss { background: none; }   /* hollow. Never red. Never a warning. */
.consistency__day--rest { border-style: dashed; } /* planned rest is first-class */

/* ============================================================================
   9 · RUNG LADDER
   Six rungs. State is encoded three ways — fill, hatch, and numeral — so it
   survives greyscale, colour-blindness, and a screenshot.
   The ladder MUST be able to render a lost rung. A display that only rises
   is a fiction.
   ============================================================================ */
.rung-ladder { display: flex; gap: 0.18rem; margin-top: var(--space-3); }
.rung {
  flex: 1 1 0;
  height: 1.7rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--color-text-subtle);
}
.rung--held {
  background: var(--color-state);
  border-color: var(--color-state);
  color: var(--color-state-text);
}
.rung--lost {
  border-color: var(--color-loss);
  color: var(--color-loss);
  background: repeating-linear-gradient(
    135deg,
    light-dark(rgba(142,36,56,.22), rgba(232,139,156,.22)) 0 2px,
    transparent 2px 6px
  );
}
.rung--target { border-style: dashed; border-color: var(--color-text-muted); color: var(--color-text-muted); }
.rung--asserted {                            /* manual override — never counts (§4.2 r6) */
  border-style: dotted;
  color: var(--color-text-subtle);
  background: none;
}

/* Retrievability sparkline wrapper. The line must be able to go down, and the
   failed-check marker is drawn in --color-loss. */
.retrievability { margin-top: var(--space-3); color: var(--color-text-muted); }
.retrievability svg { width: 100%; height: auto; }

/* ============================================================================
   10 · EVIDENCE LEDGER
   The refusals matter more than the passes — they are the reason the claim
   above them means anything. Render both lists, always.
   ============================================================================ */
.evidence { margin-top: var(--space-3); }
.evidence__row {
  display: grid;
  grid-template-columns: 0.9rem 1fr;
  gap: var(--space-2);
  align-items: baseline;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--color-border-soft);
  font-size: var(--text-sm);
}
.evidence__glyph { font-family: var(--font-mono); color: var(--color-counted); }
.evidence__row--refused { color: var(--color-text-subtle); }
.evidence__row--refused .evidence__glyph { color: var(--color-text-subtle); }
/* §4.5 requires the exact family, delay and support state on every row; the row
   used to be nothing else, so it read as a field dump. The sentence leads and
   the identifying detail sits under it, still complete and still checkable. */
.evidence__family {
  display: block;
  margin-top: 1px;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--color-text-subtle);
}
.evidence__reason { font-style: italic; }

/* ============================================================================
   11 · VERDICT AND FEEDBACK
   Task-directed, never person-directed. The struck-through committed answer
   beside the real one makes the DISCREPANCY the object of attention.
   ============================================================================ */
.verdict {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
}
.verdict--incorrect { color: var(--color-loss); }
.verdict--correct   { color: var(--color-text); }   /* no colour. No celebration. */
/* A pre-instruction guess is never marked. It used to be rendered in the
   correct-answer style, which said "right" about a thing nobody scored. */
.verdict--neutral   { color: var(--color-text-muted); }
.verdict__glyph { font-family: var(--font-mono); font-size: 1.05rem; }

.answer-pair { display: flex; flex-wrap: wrap; gap: var(--space-6); margin-top: var(--space-2); }
.answer-pair > div { min-width: 0; }
.answer-pair__label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-subtle);
}
.answer-pair__value {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-weight: var(--weight-semi);
  font-variant-numeric: tabular-nums;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.answer-pair__value--given {
  color: var(--color-loss);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
/* A pre-instruction guess was never marked, so it is never struck through: the
   strike says "wrong" about a thing the verdict directly above it says was not
   scored. */
.answer-pair__value--unmarked { color: var(--color-text-muted); }
/* Most answers are a literal, so the pair is set in a code face. Once the
   fallback chain began resolving whole sentences out of `terminal_hint`, that
   face was being applied to the most important prose on the screen. */
.answer-pair__value--prose {
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-normal);
  line-height: var(--leading-normal);
  max-width: var(--measure);
}
.answer-pair__value--actual { color: var(--color-state); }

/* Elaborated feedback. All four authored terms are still required by the content
   linter — goal · discrepancy · why-it-failed · next-step — and all four are
   still shown on a MISS. What changed is the shape: they were rendered as a
   definition list of engine vocabulary, on hits and misses alike, so a correct
   answer was told why it failed and the one sentence worth acting on came last.
   Here the miss reads as prose, led by what went wrong and closed by what to do;
   a hit gets the explanation on demand instead. */
.feedback { margin-top: var(--space-4); }
.feedback__heading {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-subtle);
}
.feedback__heading--next { margin-top: var(--space-4); }
.feedback__body {
  margin-top: 0.3rem;
  max-width: var(--measure);
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
}
.feedback__body + .feedback__body { margin-top: var(--space-2); }

/* A confirmation on a correct answer is one sentence and stays ink. Nothing
   fires here (C6) — no colour change, no motion, no mark of achievement. */
.verdict-line {
  margin-top: var(--space-2);
  max-width: var(--measure);
  font-size: var(--text-lg);
  color: var(--color-text-muted);
}

.explainer--feedback { margin-top: var(--space-4); border-top: 1px solid var(--color-border-soft); }

.misconception {
  margin-top: var(--space-3);
  padding: 0.42rem 0.65rem;
  border: 1px solid var(--color-loss);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-loss);
}

.inline-correction {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}
.inline-correction h2 { margin-top: var(--space-1); font-size: var(--text-lg); }


/* The close screen. It used to end the app: one link, and no way to learn
   anything else until the local day rolled over. It now answers what happened,
   what can be done now, and what is waiting — in that order. */
.outcome-headline { font-size: var(--text-2xl); letter-spacing: var(--tracking-tight); }
.goal--recap { margin-top: var(--space-4); font-size: var(--text-lg); color: var(--color-text-muted); }

.next-list { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.next-list__item {
  position: relative;
  padding-left: var(--space-5);
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
}
.next-list__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 7px;
  height: 7px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-strong);
}
/* Available now versus scheduled later, encoded by fill as well as by wording. */
.next-list__item--now::before { background: var(--color-state); border-color: var(--color-state); }
.next-list__item--later { color: var(--color-text-muted); font-size: var(--text-md); }
.next-list__item--later::before { top: 0.5em; }

.band--orientation { padding-block: var(--space-3); }
.capability-list { display: grid; gap: var(--space-2); margin-top: var(--space-2); }
.capability-list li { padding-left: var(--space-3); border-left: 2px solid var(--color-state); }
.capability-list__lost { margin-top: var(--space-5); }
.capability-list--lost li { border-left-color: var(--color-loss); color: var(--color-text-muted); }
.xp-boundary { margin-top: var(--space-1); font-variant-numeric: tabular-nums; }

/* ============================================================================
   12 · HINT LADDER
   Four ordered levels. Level 1 is a QUESTION, not an answer. Level 4 is always
   reachable and always ends the attempt as aided — state the cost, never
   punish the choice.
   ============================================================================ */
.hint-ladder {
  margin-top: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.hint {
  display: grid;
  grid-template-columns: 1.4rem 1fr auto;
  gap: var(--space-2);
  align-items: baseline;
  padding: 0.42rem 0.6rem;
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.hint:first-child { border-top: 0; }
.hint__level { font-family: var(--font-mono); color: var(--color-text-subtle); }
.hint--taken { background: var(--color-surface-sunk); color: var(--color-text); }

/* Revealed in place. The ladder was its own screen, so taking a hint threw away
   whatever the learner had typed — a real cost attached to support they are
   explicitly told is free to take. */
.hint-ladder-inline { margin-top: var(--space-5); }
.hint-ladder-inline .hint-ladder { display: none; }
.hint-ladder-inline--open .hint-ladder { display: block; }
.hint-ladder-inline .hint { grid-template-columns: 1.4rem 1fr; }
.hint-ladder-inline__open {
  display: inline-block;
  min-height: 2.75rem;
  padding-block: var(--space-2);
}
.hint-ladder-inline__open[disabled] { opacity: .5; }
.hint-ladder-inline .note:empty { display: none; }

/* ============================================================================
   13 · SCAFFOLD PANEL (worked example / explanation)
   Support fades as a function of demonstrated rung. At rung 4+ this element is
   REMOVED FROM THE DOM — do not render it hidden, do not render it collapsed.
   A panel you can re-open is a panel you will re-open.
   ============================================================================ */
.scaffold-panel {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--color-code-bg);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--color-text-muted);
}
.scaffold-panel__subgoal { display: block; }
.scaffold-panel__blank { color: var(--color-action); }

/* ============================================================================
   14 · TRACE PLAYER
   The entire motion budget. Nothing else in RETRIVIUM animates.
   At rung 1 the learner predicts each next state before it is revealed, so the
   step control is the interaction — never autoplay into a learning surface.
   ============================================================================ */
.trace {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-2), var(--shadow-hairline);
  overflow: hidden;
}
.trace__head {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  justify-content: space-between; align-items: center;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface-sunk);
}
.trace__body { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.05fr); }
@media (max-width: 56rem) { .trace__body { grid-template-columns: minmax(0,1fr); } }
.trace__code {
  padding: var(--space-5);
  background: var(--color-code-bg);
  border-right: 1px solid var(--color-border);
}
@media (max-width: 56rem) {
  .trace__code { border-right: 0; border-bottom: 1px solid var(--color-border); }
}
.trace__stage { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; }

.trace__sequence { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.trace__item {
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunk);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  color: var(--color-text-muted);
  transition: background var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.trace__item--past { opacity: 0.52; }
.trace__item--now {
  background: var(--color-state);
  border-color: var(--color-state);
  color: var(--color-state-text);
  transform: translateY(-2px);
}

.trace__memo { display: flex; flex-direction: column; gap: var(--space-2); }
.trace__entry {
  display: grid; grid-template-columns: 1fr auto;
  align-items: center; gap: var(--space-3);
  padding: 0.42rem 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunk);
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  transition: border-color var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out);
}
.trace__entry--hit { border-color: var(--color-state); background: var(--color-state-wash); }
.trace__key   { color: var(--color-code-string); }
.trace__value { font-variant-numeric: tabular-nums; font-weight: var(--weight-semi); }

.trace__caption {
  padding-left: var(--space-3);
  border-left: 2px solid var(--color-state);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-muted);
  min-height: 3.4rem;
}
.trace__caption strong { color: var(--color-text); font-weight: var(--weight-semi); }
.trace__caption .discard { color: var(--color-action); }

.trace__controls {
  display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center;
  padding: var(--space-3) var(--space-5) var(--space-5);
}
.trace__position {
  margin-inline-start: auto;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
}
.trace__btn {
  padding: 0.42rem 0.9rem;
  min-height: 36px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.trace__btn:hover { border-color: var(--color-text-muted); color: var(--color-text); }
.trace__btn--primary {
  background: var(--color-state);
  border-color: var(--color-state);
  color: var(--color-state-text);
}

.fresh-start {
  margin: 0 0 var(--space-4);
  color: var(--color-action);
  font-size: var(--text-xl);
  font-weight: var(--weight-semi);
}

/* The trailing-window *section* on Records and Close. `.consistency` itself is
   the design system's day strip and is a different component — sharing the name
   made this section inherit `display: flex` and lay its header, dots and note
   out as three columns. */
.consistency-window {
  padding: var(--space-6);
  border-block: 1px solid var(--color-border);
}

.consistency-window__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
}

.consistency-window__dots {
  display: grid;
  grid-template-columns: repeat(14, minmax(0, 1fr));
  gap: var(--space-2);
  margin-block: var(--space-4);
}

.consistency-window__dot {
  aspect-ratio: 1;
  border: 1px solid var(--color-border-strong);
  border-radius: 50%;
}

.consistency-window__dot--complete { background: var(--color-state); border-color: var(--color-state); }
.consistency-window__dot--open { background: transparent; }
.consistency-window__dot--rest { border-style: dashed; opacity: 0.4; }

@media (max-width: 44rem) {
  .consistency-window__header { display: block; }
}
