/* ============================================================================
   bench.css — the visual system for practicepython.in
   ----------------------------------------------------------------------------
   Ground metaphor: an engineering datasheet, not a course page. Cool paper,
   hairline rules, square corners everywhere, numbered sections, monospace for
   every piece of structural chrome and a humanist sans reserved for prose.
   Depth comes from rules and whitespace only — no shadows, no gradients.
   ========================================================================== */

/* The hidden attribute always wins. Without this, any rule that sets display
   (.row is a grid) quietly beats the browser's own [hidden] rule: the index
   filter hid 121 rows and all of them stayed on screen, while the count said
   "25 of 146". Seven components had each patched it for themselves. */
[hidden] { display: none !important; }

:root {
  color-scheme: light;

  --paper:      #f3f4f1;
  --panel:      #ffffff;
  --ink:        #14161a;
  --ink-2:      #464c55;
  --ink-3:      #696f77;
  --rule:       #d9dbd6;
  --rule-2:     #eceee9;

  --cobalt:     #1449b8;
  /* The logo carries a light and a dark palette; these pick one. */
  --mark-light: inline;
  --mark-dark: none;
  --pass:       #14653c;
  --pass-bg:    #edf5f0;
  --fail:       #ab241d;
  --fail-bg:    #fbf0ef;
  --note:       #6b4a00;
  --note-bg:    #fbf6ea;

  /* Prose sitting on a tinted block — darker than the accent, still on-tone. */
  --on-pass:    #16402c;
  --on-fail:    #4a2320;
  --on-note:    #3f3a2c;

  /* Text on a solid --ink background: always the opposite of --ink. */
  --on-solid:   #ffffff;
  --solid-hover:#2a2f36;

  /* Code blocks invert against the page in both themes. */
  --code-bg:    #14161a;
  --code-fg:    #f2f3f0;
  --code-comment: #9aa3a0;
  --code-border: transparent;

  --grid:       rgba(20, 22, 26, .028);
  --select:     #dbe4f7;

  /* Syntax colours are tokens too, so the editor re-themes with no JS at all. */
  --syn-comment: #7b828b;
  --syn-keyword: #1449b8;
  --syn-string:  #14653c;
  --syn-number:  #ab241d;
  --syn-name:    #14161a;
  --syn-punct:   #464c55;
  --syn-class:   #6b4a00;

  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
  --sans: "IBM Plex Sans", -apple-system, "Segoe UI", Roboto, sans-serif;

  --gap: 28px;
  --rail-h: 46px;
}

/* ── Dark: a blueprint, not a dark IDE ────────────────────────────────────────
   The drafting metaphor survives the inversion — the quadrille ruling becomes
   faint light lines on a cool dark ground, exactly like a blueprint. The two
   blocks below are deliberate duplicates: one follows the system setting, the
   other an explicit choice. Keep them in sync.

   There is no transition on any of this, on purpose. A hairline that flips
   polarity has to pass through the background colour while it interpolates,
   which makes every rule on the page blink mid-change. Snapping avoids the
   entire class of bug.
   ------------------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper:      #14171c;
    --panel:      #1a1e25;
    --ink:        #e7eaee;
    --ink-2:      #a9b1bb;
    --ink-3:      #828c97;
    --rule:       #2c323b;
    --rule-2:     #232830;
    --cobalt:     #7aa4ff;
    --mark-light: none;
    --mark-dark: inline;
    --pass:       #52c08a;
    --pass-bg:    #14261d;
    --fail:       #ff8177;
    --fail-bg:    #2b1a19;
    --note:       #d7b264;
    --note-bg:    #262016;
    --on-pass:    #c8e6d6;
    --on-fail:    #f2cfcb;
    --on-note:    #e8dcc2;
    --on-solid:   #14171c;
    --solid-hover:#cfd6dd;
    --code-bg:    #0e1116;
    --code-fg:    #dfe4e8;
    --code-comment: #6f7982;
    --code-border: #272d35;
    --grid:       rgba(180, 200, 220, .05);
    --select:     #2a3550;
    --syn-comment: #6f7982;
    --syn-keyword: #8ab4ff;
    --syn-string:  #7fd6a4;
    --syn-number:  #ff9d92;
    --syn-name:    #e7eaee;
    --syn-punct:   #a9b1bb;
    --syn-class:   #e0be74;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --paper:      #14171c;
  --panel:      #1a1e25;
  --ink:        #e7eaee;
  --ink-2:      #a9b1bb;
  --ink-3:      #828c97;
  --rule:       #2c323b;
  --rule-2:     #232830;
  --cobalt:     #7aa4ff;
  --mark-light: none;
  --mark-dark: inline;
  --pass:       #52c08a;
  --pass-bg:    #14261d;
  --fail:       #ff8177;
  --fail-bg:    #2b1a19;
  --note:       #d7b264;
  --note-bg:    #262016;
  --on-pass:    #c8e6d6;
  --on-fail:    #f2cfcb;
  --on-note:    #e8dcc2;
  --on-solid:   #14171c;
  --solid-hover:#cfd6dd;
  --code-bg:    #0e1116;
  --code-fg:    #dfe4e8;
  --code-comment: #6f7982;
  --code-border: #272d35;
  --grid:       rgba(180, 200, 220, .05);
  --select:     #2a3550;
  --syn-comment: #6f7982;
  --syn-keyword: #8ab4ff;
  --syn-string:  #7fd6a4;
  --syn-number:  #ff9d92;
  --syn-name:    #e7eaee;
  --syn-punct:   #a9b1bb;
  --syn-class:   #e0be74;
}

/* ── Eye saver: the same drafting paper, under a warmer lamp ────────────────
   Not a dimmed light theme and not sepia nostalgia. The ground keeps its
   quadrille ruling and its square corners; what changes is the light falling
   on it. Every colour loses blue energy — paper is #f4ecd9, whose blue channel
   sits 27 points under its red — and the accents warm to match, so nothing on
   the page glows at the eye after an hour.

   It has no system-preference equivalent, so unlike dark there is only one
   block: nobody's operating system asks for this, you do.

   Every pair here was measured rather than eyeballed. Worst ratio 4.95:1,
   which is better than the light theme manages, and verify_dark.js re-measures
   all three themes from the computed styles on a real page.
   ------------------------------------------------------------------------- */

:root[data-theme="eyesaver"] {
  color-scheme: light;
  --paper:      #f4ecd9;
  --panel:      #fcf6e9;
  --ink:        #2a231a;
  --ink-2:      #544a3b;
  --ink-3:      #6f6355;
  --rule:       #ddd0b6;
  --rule-2:     #ece2cd;
  --cobalt:     #1a4b96;
  --mark-light: inline;
  --mark-dark: none;
  --pass:       #2c6135;
  --pass-bg:    #e7efd9;
  --fail:       #9c3319;
  --fail-bg:    #f8e6dc;
  --note:       #75500d;
  --note-bg:    #f5ead0;
  --on-pass:    #23402a;
  --on-fail:    #46231a;
  --on-note:    #3c3422;
  --on-solid:   #faf4e6;
  --solid-hover:#453a2c;
  --code-bg:    #2a231a;
  --code-fg:    #f1e8d6;
  --code-comment: #a08f79;
  --code-border: transparent;
  --grid:       rgba(90, 70, 40, .05);
  --select:     #e4d6b4;
  --syn-comment: #8a7b68;
  --syn-keyword: #1a4b96;
  --syn-string:  #2c6135;
  --syn-number:  #9c3319;
  --syn-name:    #2a231a;
  --syn-punct:   #544a3b;
  --syn-class:   #75500d;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background-color: var(--paper);
  /* Faint quadrille ruling — drafting paper, not decoration. */
  background-image:
    linear-gradient(to right, var(--grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid) 1px, transparent 1px);
  background-size: 26px 26px;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

code, kbd, pre { font-family: var(--mono); }

/* ── Rail ─────────────────────────────────────────────────────────────────── */

.rail {
  position: sticky;
  top: 0;
  z-index: 20;
  height: var(--rail-h);
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 22px;
  background: var(--panel);
  border-bottom: 1px solid var(--ink);
}

.rail-mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  white-space: nowrap;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: .02em;
}
.rail-mark .mark { flex: none; }

.rail-meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.rail-status {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
}
.rail-status::before {
  content: "";
  width: 7px; height: 7px;
  background: var(--ink-3);
  border-radius: 50%;
}
.rail-status[data-state="ready"] { color: var(--pass); }
.rail-status[data-state="ready"]::before { background: var(--pass); }
.rail-status[data-state="busy"]::before { animation: pulse 1s steps(2) infinite; }
.rail-status[data-state="failed"] { color: var(--fail); }
.rail-status[data-state="failed"]::before { background: var(--fail); }

@keyframes pulse { 50% { opacity: .25; } }

/* The download hairline sits on the rail's own bottom rule, so progress reads
   as the rule filling in rather than as a new widget. scaleX, not width: the
   update arrives every 100ms and should not relayout the page each time. */
.boot-bar {
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--cobalt);
  transform-origin: left center;
  transform: scaleX(var(--done, 0));
  transition: transform .15s linear;
  pointer-events: none;
}
.boot-bar[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .boot-bar { transition: none; } }

.boot-note {
  margin: 10px 0 0;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.boot-note[hidden] { display: none; }

/* ── Theme control ────────────────────────────────────────────
   A peripheral tool on the right edge, the same placement pythonmastery.io
   uses — one switcher pattern across both sites. Vertical rather than
   horizontal because stacked along an edge reads as "a control that lives
   here", while a horizontal bar at the corner reads as "click me".

   Ghosted until you go near it: a theme is set once, so it should be visible
   enough to find and quiet enough to forget. The chosen tile stays legible
   even while the group is faded, which is why the opacity is per-tile rather
   than on the container — a parent opacity fades its children with it and no
   child can opt out.

   Opacity is the only thing that animates anywhere on this site. It is safe
   where a colour is not: nothing has to cross the background colour to fade.
   ------------------------------------------------------------------------ */

.theme-fab {
  position: fixed;
  right: 16px;
  bottom: 56px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  border: 1px solid transparent;
  background: transparent;
}
.theme-fab:hover, .theme-fab:focus-within {
  border-color: var(--ink);
  background: var(--panel);
}

.theme-chip {
  position: relative;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  cursor: pointer;
  opacity: .35;
  transition: opacity .15s linear;
}
.theme-chip:last-child { border-bottom: 0; }
.theme-chip[aria-pressed="true"],
.theme-fab:hover .theme-chip,
.theme-fab:focus-within .theme-chip { opacity: 1; }
.theme-chip:focus-visible { outline: 2px solid var(--cobalt); outline-offset: -2px; }

/* The swatch is the theme's own paper, so the control shows the page it will
   produce. These are literals because they must not follow the current theme. */
.theme-chip::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1px solid var(--ink-3);
}
.theme-chip[data-theme="light"]::before {
  background: linear-gradient(to bottom, #f3f4f1 0 60%, #1449b8 60% 100%);
}
.theme-chip[data-theme="dark"]::before {
  background: linear-gradient(to bottom, #14171c 0 60%, #7aa4ff 60% 100%);
}
.theme-chip[data-theme="eyesaver"]::before {
  background: linear-gradient(to bottom, #f4ecd9 0 60%, #a8730f 60% 100%);
}
.theme-chip[data-theme="auto"]::before {
  background: linear-gradient(135deg, #f3f4f1 0 50%, #14171c 50% 100%);
}

/* The current choice keeps a cobalt frame at any opacity. */
.theme-chip[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid var(--cobalt);
}

/* ── Page frame ───────────────────────────────────────────────────────────── */

.bench {
  display: grid;
  grid-template-columns: minmax(300px, 370px) minmax(0, 1fr);
  align-items: start;
  max-width: 1440px;
  margin: 0 auto;
  padding: var(--gap) 22px 90px;
  gap: var(--gap);
}

.section-label {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding-bottom: 7px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--ink);
}
.section-label .num { color: var(--ink); font-weight: 600; }
.section-label .tail { margin-left: auto; letter-spacing: .08em; text-transform: none; }

/* ── Brief (left spine) ───────────────────────────────────────────────────── */

.brief { position: sticky; top: calc(var(--rail-h) + var(--gap)); }

.panel {
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: 20px;
}
.panel + .panel { border-top: 0; }

.ex-title {
  font-size: 25px;
  line-height: 1.2;
  font-weight: 600;
  letter-spacing: -.015em;
  margin: 0 0 14px;
}

/* Datasheet block — the metadata reads as a spec table, not as pills. */
.spec { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.spec th, .spec td {
  text-align: left;
  padding: 6px 0;
  border-bottom: 1px solid var(--rule-2);
  vertical-align: top;
}
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 0; }
.spec th {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
  width: 96px;
  padding-right: 12px;
}
.spec td { font-family: var(--mono); color: var(--ink-2); }
/* The download note under a package name: present but not competing with it. */
.spec td .quiet { color: var(--ink-3); font-size: 11px; line-height: 1.45; }

.difficulty { display: inline-flex; gap: 3px; vertical-align: -1px; }
.difficulty i { width: 7px; height: 7px; background: var(--rule); display: block; }
.difficulty i.on { background: var(--ink); }

.prose p { margin: 0 0 12px; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { font-weight: 600; }

.contract { margin: 0; padding: 0; list-style: none; counter-reset: rule; }
.contract li {
  counter-increment: rule;
  position: relative;
  padding: 9px 0 9px 30px;
  border-bottom: 1px solid var(--rule-2);
  font-size: 14px;
}
.contract li:last-child { border-bottom: 0; padding-bottom: 0; }
.contract li::before {
  content: counter(rule, decimal-leading-zero);
  position: absolute;
  left: 0; top: 10px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}

.why { font-size: 14px; color: var(--ink-2); }

/* ── Ladder (study → build → extend) ──────────────────────────────────────── */

.ladder { display: flex; border: 1px solid var(--ink); background: var(--panel);
  scroll-margin-top: calc(var(--rail-h) + 12px); /* clear of the sticky rail */ }

.rung {
  flex: 1;
  min-width: 0;   /* let a long label shrink the row rather than widen the page */
  display: block;
  padding: 11px 16px;
  border: 0;
  border-right: 1px solid var(--rule);
  background: transparent;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-align: left;
  cursor: pointer;
}
.rung:last-child { border-right: 0; }
.rung .n { color: var(--ink); font-weight: 600; margin-right: 8px; }
.rung .sub {
  display: block;
  margin-top: 2px;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-3);
}
.rung[aria-selected="true"] { background: var(--ink); color: var(--on-solid); }
.rung[aria-selected="true"] .n,
.rung[aria-selected="true"] .sub { color: var(--on-solid); }
.rung[disabled] { cursor: not-allowed; opacity: .45; }
.rung:not([disabled]):not([aria-selected="true"]):hover { background: var(--rule-2); }

.step { margin-top: var(--gap); }
.step[hidden] { display: none; }

/* ── Worked example ───────────────────────────────────────────────────────── */

.worked-intro { font-size: 15px; color: var(--ink-2); margin: 0 0 18px; }

pre.code {
  margin: 0;
  padding: 18px 20px;
  background: var(--code-bg);
  color: var(--code-fg);
  border: 1px solid var(--code-border);
  font-size: 13.5px;
  line-height: 1.72;
  overflow-x: auto;
  tab-size: 4;
}
pre.code .cm { color: var(--code-comment); font-style: italic; }

.points { margin: 22px 0 0; padding: 0; list-style: none; }
.points li { padding: 16px 0; border-top: 1px solid var(--rule); }
.points .label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cobalt);
  margin-bottom: 6px;
}
.points p { margin: 0; font-size: 14.5px; color: var(--ink-2); }

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 18px;
  border: 1px solid var(--ink);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
}
.btn:hover { background: var(--rule-2); }
.btn:active { transform: translateY(1px); }
.btn--solid { background: var(--ink); color: var(--on-solid); }
.btn--solid:hover { background: var(--solid-hover); }
.btn--solid:disabled { background: var(--ink-3); border-color: var(--ink-3); cursor: not-allowed; }
.btn--quiet { border-color: var(--rule); color: var(--ink-2); }
.btn:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }

.kbd {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .04em;
  padding: 2px 5px;
  border: 1px solid currentColor;
  opacity: .6;
}

/* ── Editor ───────────────────────────────────────────────────────────────── */

.editor-shell { border: 1px solid var(--ink); background: var(--panel); }

.editor-head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-2);
}
.editor-head .file::before { content: "\25A0"; margin-right: 8px; color: var(--ink-3); font-size: 9px; vertical-align: 2px; }
.editor-head .spacer { margin-left: auto; }

.cm-host { min-height: 300px; }
.cm-host .cm-editor { height: 100%; }
.cm-host .cm-scroller {
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.7;
}
.cm-host .cm-gutters {
  background: var(--panel);
  border-right: 1px solid var(--rule-2);
  color: var(--ink-3);
}
.cm-host .cm-activeLine { background: rgba(20,73,184,.035); }
.cm-host .cm-activeLineGutter { background: transparent; color: var(--ink); }
.cm-host .cm-content { padding: 14px 0; }
.cm-host .cm-cursor { border-left-color: var(--ink); }
.cm-host .cm-line.line-error { background: var(--fail-bg); box-shadow: inset 3px 0 0 var(--fail); }

.actions { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.actions .spacer { margin-left: auto; }

/* ── Report — the hero ────────────────────────────────────────────────────── */

.report { margin-top: var(--gap); }

.verdict {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 15px 18px;
  border: 1px solid var(--ink);
  background: var(--panel);
  font-family: var(--mono);
}
.verdict .score { font-size: 19px; font-weight: 600; }
.verdict .headline { font-family: var(--sans); font-size: 14.5px; color: var(--ink-2); }
.verdict .elapsed { margin-left: auto; font-size: 11px; color: var(--ink-3); }
.verdict[data-tone="pass"] { border-color: var(--pass); background: var(--pass-bg); }
.verdict[data-tone="pass"] .score { color: var(--pass); }
.verdict[data-tone="fail"] { border-color: var(--fail); background: var(--fail-bg); }
.verdict[data-tone="fail"] .score { color: var(--fail); }

.cases { border: 1px solid var(--rule); border-top: 0; background: var(--panel); }

.case { border-bottom: 1px solid var(--rule-2); }
.case:last-child { border-bottom: 0; }

.case-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 18px;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--ink);
}
.case-head:hover { background: var(--rule-2); }
.case-head .mark { width: 15px; font-weight: 600; }
.case-head .idx { color: var(--ink-3); font-size: 11px; }
.case-head .name { font-family: var(--sans); font-size: 14px; }
.case-head .chev { margin-left: auto; color: var(--ink-3); font-size: 11px; }
.case[data-passed="true"] .mark { color: var(--pass); }
.case[data-passed="false"] .mark { color: var(--fail); }
.case[data-passed="false"] .case-head { background: var(--fail-bg); }

.case-body { padding: 4px 18px 20px 45px; }
.case-body[hidden] { display: none; }

.ledger { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12.5px; }
.ledger th, .ledger td { text-align: left; padding: 5px 0; vertical-align: top; }
.ledger th {
  width: 84px;
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-right: 14px;
}
.ledger td { color: var(--ink); word-break: break-word; }
.ledger tr.got td { color: var(--fail); }
.ledger tr.want td { color: var(--pass); }

.ok-inline, .bad-inline {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: .01em;
}
.ok-inline { color: var(--pass); }
.bad-inline { color: var(--fail); }

.linkish {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: var(--cobalt);
  text-decoration: underline;
  cursor: pointer;
}

.case-why {
  margin: 12px 0 0;
  padding-left: 13px;
  border-left: 2px solid var(--rule);
  font-size: 13.5px;
  color: var(--ink-3);
}

/* The margin note — the whole reason this product exists. */
.note {
  margin-top: 14px;
  padding: 13px 16px;
  background: var(--note-bg);
  border-left: 3px solid var(--note);
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--on-note);
}
.note + .note { margin-top: 8px; }
.note .note-label {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--note);
  margin-bottom: 5px;
}

.blocker {
  padding: 20px;
  border: 1px solid var(--fail);
  background: var(--fail-bg);
}
.blocker h3 {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fail);
}
.blocker p { margin: 0 0 10px; font-size: 14.5px; }
.blocker pre.code { margin-top: 12px; }

/* ── Hints ────────────────────────────────────────────────────────────────── */

.hints { margin-top: var(--gap); }
.hint {
  border: 1px solid var(--rule);
  border-bottom: 0;
  background: var(--panel);
  padding: 14px 18px;
}
.hint:last-of-type { border-bottom: 1px solid var(--rule); }
.hint .level {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--cobalt);
}
.hint p { margin: 7px 0 0; font-size: 14.5px; color: var(--ink-2); white-space: pre-wrap; }
.hint p.mono { font-family: var(--mono); font-size: 13px; }
.hint-more { margin-top: 14px; }
.hint-note { margin: 10px 0 0; font-size: 13px; color: var(--ink-3); }

/* ── Extend ───────────────────────────────────────────────────────────────── */

.sol-note { padding: 16px 0; border-top: 1px solid var(--rule); }
.sol-note .label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cobalt);
  margin-bottom: 6px;
}
.sol-note p { margin: 0; font-size: 14.5px; color: var(--ink-2); }

.ext { margin: 0; padding: 0; list-style: none; counter-reset: ext; }
.ext li {
  counter-increment: ext;
  position: relative;
  padding: 14px 0 14px 34px;
  border-top: 1px solid var(--rule);
  font-size: 14.5px;
}
.ext li::before {
  content: "\2192";
  position: absolute; left: 0; top: 14px;
  font-family: var(--mono);
  color: var(--cobalt);
}

.locked { padding: 26px 20px; border: 1px dashed var(--rule); text-align: center; color: var(--ink-3); font-size: 14px; }

/* ── Prerequisite graph ───────────────────────────────────────────────────── */

.graph { margin: 0; padding: 0; list-style: none; }
.graph li {
  position: relative;
  padding: 9px 0 9px 24px;
  border-bottom: 1px solid var(--rule-2);
  font-size: 14px;
}
.graph li:last-child { border-bottom: 0; }
.graph li::before {
  content: "\25A1";  /* unmet: the same square as the editor tab, unfilled */
  position: absolute;
  left: 0; top: 9px;
  color: var(--ink-3);
}
.graph li.done::before { content: "\2713"; color: var(--pass); }
.graph li.done a { color: var(--ink-3); }
.graph a { color: var(--cobalt); text-decoration: none; }
.graph a:hover { text-decoration: underline; }
.graph-note { margin: 12px 0 0; font-size: 13px; color: var(--ink-3); }

/* ── Debug exercises + cross-links ────────────────────────────────────────── */

.symptom {
  margin-top: 16px;
  padding: 14px 16px;
  background: var(--fail-bg);
  border-left: 3px solid var(--fail);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--on-fail);
}
.symptom-label {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--fail);
  margin-bottom: 5px;
}

.symptom.smell {
  background: var(--note-bg);
  border-left-color: var(--note);
  color: var(--on-note);
}
.symptom.smell .symptom-label { color: var(--note); }

/* The bar — refactor constraints, in the spine before you start */
.rules { margin: 0; padding: 0; list-style: none; }
.rules li {
  position: relative;
  padding: 9px 0 9px 22px;
  border-bottom: 1px solid var(--rule-2);
  font-size: 14px;
}
.rules li:last-child { border-bottom: 0; }
.rules li::before {
  content: "\25AA";
  position: absolute;
  left: 0; top: 9px;
  color: var(--cobalt);
}
.rules-note { margin: 12px 0 0; font-size: 13px; color: var(--ink-3); }

/* The bar — as reported after a run */
.rules-report {
  border: 1px solid var(--rule);
  border-top: 0;
  background: var(--panel);
  padding: 14px 18px 16px;
}
.rules-head {
  display: flex;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--rule-2);
}
.rules-head span { margin-left: auto; letter-spacing: .08em; }
.rule {
  display: flex;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--rule-2);
  font-size: 14.5px;
}
.rule:last-of-type { border-bottom: 0; }
.rule .mark { font-family: var(--mono); font-weight: 600; }
.rule[data-ok="true"] .mark { color: var(--pass); }
.rule[data-ok="false"] .mark { color: var(--fail); }
.rule[data-ok="false"] .rule-text { color: var(--ink); }
.rule[data-ok="true"] .rule-text { color: var(--ink-3); }
.rules-foot { margin: 10px 0 0; font-size: 13.5px; color: var(--ink-2); }

.concept-link {
  display: inline-block;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--cobalt);
  text-decoration: none;
}
.concept-link:hover { text-decoration: underline; }
.concept-note { margin: 10px 0 0; font-size: 13px; color: var(--ink-3); }

.crumb {
  margin-bottom: 26px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.crumb a { color: inherit; text-decoration: none; }
.crumb a:hover { color: var(--cobalt); text-decoration: underline; }
.crumb .sep { margin: 0 9px; }

a.track-link { color: inherit; text-decoration: none; }
a.track-link:hover { color: var(--cobalt); text-decoration: underline; }

.row-name .kind {
  margin-left: 9px;
  padding: 1px 6px;
  border: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
  vertical-align: 2px;
}

/* ── The practice record ──────────────────────────────────────────────────── */

.trail {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 18px;
  border: 1px solid var(--rule);
  border-top: 0;
  background: var(--panel);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.trail-note { margin-left: auto; }
.pips { display: flex; gap: 3px; }
.pip {
  display: block;
  width: 9px; height: 9px;
  background: var(--rule);
}
.pip[data-state="part"] { background: var(--note); }
.pip[data-state="pass"] { background: var(--pass); }

.resume-note {
  margin: 0;
  padding: 13px 18px;
  border: 1px solid var(--rule);
  border-top: 0;
  background: var(--panel);
  font-size: 14px;
  color: var(--ink-2);
}

.solved {
  padding: 18px 20px;
  border: 1px solid var(--pass);
  border-bottom: 0;
  background: var(--pass-bg);
}
.solved-line { margin: 0; font-size: 15.5px; color: var(--on-pass); }
.solved-patterns {
  margin: 12px 0 0;
  font-size: 13.5px;
  color: var(--ink-2);
}
.solved-patterns span {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--pass);
  margin-bottom: 5px;
}
.solved-patterns b { font-family: var(--mono); font-weight: 500; }
.solved-next { margin: 12px 0 0; font-size: 13.5px; color: var(--ink-3); }

/* ── Continue card ────────────────────────────────────────────────────────── */

.continue {
  padding: 22px;
  border: 1px solid var(--ink);
  background: var(--panel);
  margin-bottom: 46px;
}
.continue-eyebrow {
  margin: 0 0 10px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.continue-title {
  display: inline-block;
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--ink);
  text-decoration: none;
}
.continue-title:hover { text-decoration: underline; }
.continue-meta {
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
}
.continue-why {
  margin: 12px 0 18px;
  max-width: 60ch;
  font-size: 14.5px;
  color: var(--ink-2);
}
.continue .btn { text-decoration: none; }

/* ── Filters ──────────────────────────────────────────────────────────────── */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  padding: 14px 16px;
  margin-bottom: 34px;
  border: 1px solid var(--rule);
  background: var(--panel);
}
.filter-search { flex: 1 1 220px; }
.filter-search input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
}
.filter-search input:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 1px; }

.chips { display: flex; gap: 0; }
.chip {
  padding: 7px 11px;
  border: 1px solid var(--rule);
  border-right-width: 0;
  background: var(--panel);
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
}
.chip:last-child { border-right-width: 1px; }
.chip:hover { background: var(--rule-2); }
.chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-solid); }
.chip[aria-pressed="true"] + .chip { border-left-color: var(--ink); }

.filter-count {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.no-results {
  padding: 30px 16px;
  border: 1px dashed var(--rule);
  text-align: center;
  color: var(--ink-3);
  font-size: 14.5px;
}

/* ── Alternatives ─────────────────────────────────────────────────────────── */

.alt-intro { margin: 0 0 18px; font-size: 14.5px; color: var(--ink-2); }

.alt { margin-bottom: 22px; }
.alt:last-child { margin-bottom: 0; }
.alt-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--rule);
  font-size: 15px;
  font-weight: 500;
}
.alt-tone {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: 2px 7px;
  border: 1px solid currentColor;
}
.alt[data-tone="better"] .alt-tone { color: var(--pass); }
.alt[data-tone="fine"] .alt-tone { color: var(--ink-3); }
.alt[data-tone="worse"] .alt-tone { color: var(--note); }
.alt-verdict { margin: 12px 0 0; font-size: 14.5px; color: var(--ink-2); }

/* ── Pattern report ───────────────────────────────────────────────────────── */

.patterns { margin-top: 8px; }
.pattern {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) minmax(0, 1fr);
  align-items: baseline;
  gap: 14px;
  padding: 12px 8px;
  border-bottom: 1px solid var(--rule-2);
}
.pattern-count {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 600;
  color: var(--fail);
}
.pattern-label { font-size: 15px; }
.pattern-where { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }

.pattern-advice {
  margin: 18px 0 0;
  padding: 15px 18px;
  background: var(--note-bg);
  border-left: 3px solid var(--note);
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--on-note);
}
.pattern-advice span {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--note);
  margin-bottom: 5px;
}
.patterns-foot { margin: 14px 0 0; font-size: 12.5px; color: var(--ink-3); }

.track-bar {
  display: inline-block;
  width: 54px;
  height: 4px;
  margin-left: 10px;
  background: var(--rule);
  vertical-align: 1px;
}
.track-bar i { display: block; height: 100%; background: var(--pass); }

.row-name .tag {
  margin-left: 9px;
  padding: 1px 6px;
  border: 1px solid var(--note);
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--note);
  vertical-align: 2px;
}

/* ── Stepper (previous / index / next) ────────────────────────────────────── */

.stepper {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: var(--gap);
  border: 1px solid var(--rule);
  background: var(--panel);
}
.step-link {
  padding: 14px 18px;
  border-right: 1px solid var(--rule);
  color: var(--ink);
  text-decoration: none;
  font-size: 14px;
}
.step-link:last-child { border-right: 0; }
.step-link:hover { background: var(--rule-2); }
.step-link span {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 3px;
}
.step-link.mid { text-align: center; }
.step-link.next { text-align: right; }

/* ── Index ────────────────────────────────────────────────────────────────── */

a.rail-mark { color: inherit; text-decoration: none; }

.home { max-width: 1000px; margin: 0 auto; padding: 52px 22px 90px; }

.hero { margin-bottom: 56px; }
.hero h1 {
  margin: 0 0 20px;
  font-size: clamp(30px, 4.6vw, 46px);
  line-height: 1.12;
  font-weight: 600;
  letter-spacing: -.025em;
}
.lede {
  max-width: 62ch;
  margin: 0;
  font-size: 16.5px;
  line-height: 1.68;
  color: var(--ink-2);
}
.lede code {
  font-size: 14.5px;
  padding: 1px 4px;
  background: var(--rule-2);
}
.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  margin-top: 26px;
  padding-top: 16px;
  border-top: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.track { margin-bottom: 44px; }

.row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1.3fr) minmax(0, 1fr) 62px 74px;
  align-items: center;
  gap: 16px;
  padding: 13px 14px 13px 8px;
  border-bottom: 1px solid var(--rule-2);
  color: var(--ink);
  text-decoration: none;
}
.row:hover { background: var(--panel); }
.row-tick {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px; height: 14px;
  border: 1px solid var(--rule);
  background: var(--panel);
}
.row.done .row-tick { border-color: var(--pass); background: var(--pass); }
.row.done .row-tick::after {
  content: "✓";
  color: var(--on-solid);
  font-size: 10px;
  line-height: 1;
}
.row-name { font-size: 15.5px; font-weight: 500; }
.row-concepts { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.row-diff { text-align: right; }
.row-time { font-family: var(--mono); font-size: 12px; color: var(--ink-3); text-align: right; }

.foot-note {
  margin: 56px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
  font-size: 14px;
  color: var(--ink-3);
}
.foot-note a { color: var(--cobalt); }

/* ── Who it is for, and the way in ────────────────────────────────── */

.hero-note {
  max-width: 62ch;
  margin: 18px 0 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}
.hero-note code { font-size: 13.5px; padding: 0; background: none; color: var(--ink); }
.hero-note a { color: var(--cobalt); }

.start-list { margin: 18px 0 0; padding: 0; list-style: none; }
.start-list li {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  padding: 11px 0;
  border-top: 1px solid var(--rule);
}
.start-list a { color: var(--cobalt); text-decoration: none; font-size: 15.5px; }
.start-list a:hover { text-decoration: underline; }
.start-meta {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
}

/* The one-sentence statement of the problem, read before the contract rather
   than alongside it. Everything below it in the brief is detail. */
.ex-brief {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
}

@media (max-width: 520px) and (max-height: 480px) {
  .theme-fab { bottom: auto; top: 50%; transform: translateY(-50%); }
  /* The theme stack is 122px tall and centred, so its bottom edge sits 61px
     below the middle; 10px under that is where this goes. */
  .feedback { bottom: auto; top: calc(50% + 71px); }
}

/* ── Feedback ──────────────────────────────────────────────────
   Directly under the theme control, same edge, same square idiom, same ghost:
   two peripheral tools reading as one column rather than two floating
   widgets. The theme stack is anchored 56px up, is 122px tall and leaves a
   10px gap, which is where these numbers come from.
   ------------------------------------------------------------------------ */

.feedback {
  position: fixed;
  right: 16px;
  bottom: 10px;   /* 10px under the theme stack, which ends 56px up */
  z-index: 30;
}

.feedback-button {
  position: relative;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  opacity: .35;
  transition: opacity .15s linear;
}
.feedback-button:hover,
.feedback-button:focus-visible,
.feedback-button[aria-expanded="true"] { opacity: 1; }
.feedback-button:hover,
.feedback-button[aria-expanded="true"] { border-color: var(--ink); background: var(--panel); }
.feedback-button:focus-visible { outline: 2px solid var(--cobalt); outline-offset: -2px; }

/* A speech bubble, drawn square: the site has no rounded corners to lend it. */
.feedback-button::before {
  content: "";
  position: absolute;
  left: 7px; top: 7px;
  width: 14px; height: 10px;
  border: 1px solid var(--ink);
}
.feedback-button::after {
  content: "";
  position: absolute;
  left: 9px; top: 17px;
  width: 0; height: 0;
  border-left: 4px solid var(--ink);
  border-bottom: 4px solid transparent;
}

/* Beside the column, not above it: anchoring the panel over the stack would
   hide the theme control every time someone opened this. */
.feedback-panel {
  position: absolute;
  right: 38px;
  bottom: 0;
  width: 340px;
  padding: 18px;
  border: 1px solid var(--ink);
  background: var(--panel);
}
.feedback-panel[hidden] { display: none; }
.feedback-panel .section-label { margin-bottom: 12px; }

.feedback-close {
  margin-left: auto;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--ink-3);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.feedback-close:hover { color: var(--ink); }

.feedback-panel textarea {
  width: 100%;
  padding: 10px;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.55;
  resize: vertical;
}
.feedback-field { display: block; margin-top: 12px; }
.feedback-field span {
  display: block;
  margin-bottom: 5px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.feedback-field input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
}
.feedback-panel textarea:focus-visible,
.feedback-field input:focus-visible { outline: 2px solid var(--cobalt); outline-offset: -1px; }

.feedback-status { font-size: 13px; color: var(--ink-2); }
.feedback-status[data-tone="pass"] { color: var(--pass); }
.feedback-status[data-tone="fail"] { color: var(--fail); }
.feedback-note { margin: 14px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-3); }
.feedback-note a { color: var(--cobalt); }

/* ── Site footer ─────────────────────────────────────────────── */

/* A measure for running prose. .prose was written for the narrow panels on an
   exercise page and has no width of its own; on a 1000px text page that is a
   110-character line, which nobody reads twice. */
.home .prose { max-width: 68ch; }
.home .points { max-width: 74ch; }
.lede code { white-space: nowrap; }

.site-foot { margin-top: 56px; }
.site-foot .foot-note { margin-top: 0; }

/* On an exercise page the footer sits OUTSIDE <main>, and carries the grid's
   own measurements so its edges still line up with the brief and the report.
   Inside the grid it was overlapped by the brief: a sticky element is held by
   its containing block, which is <main> — not by the row it was placed in. */
.site-foot--wide { max-width: 1440px; margin: 0 auto; padding: 0 22px 20px; }
main.bench { padding-bottom: 34px; }

.foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.foot-links a { color: var(--ink-3); text-decoration: none; }
.foot-links a:hover { color: var(--cobalt); text-decoration: underline; }

/* ── Consent bar ────────────────────────────────────────────── */

.consent {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 20px;
  padding: 14px 22px;
  background: var(--panel);
  border-top: 1px solid var(--ink);
}
.consent p {
  margin: 0;
  max-width: 78ch;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-2);
}
.consent a { color: var(--cobalt); }
.consent-actions { display: flex; gap: 8px; margin-left: auto; }

/* ── Privacy controls ──────────────────────────────────────── */

.privacy-controls { display: grid; gap: 18px; margin-top: 18px; }
.privacy-control { border: 1px solid var(--rule); background: var(--panel); padding: 18px 20px; }
.privacy-control .actions { margin-top: 12px; }
.privacy-state { margin: 0; font-size: 14.5px; color: var(--ink-2); }

/* ── 404 ────────────────────────────────────────────────────── */

.track-list { margin: 0; padding: 0; list-style: none; columns: 2; column-gap: 40px; }
.track-list li { break-inside: avoid; border-bottom: 1px solid var(--rule-2); }
.track-list a {
  display: block;
  padding: 12px 2px;
  color: var(--ink);
  text-decoration: none;
  font-size: 15px;
}
.track-list a:hover { color: var(--cobalt); }

.hero .actions { margin-top: 28px; }
.hero .actions .btn { text-decoration: none; }

/* ── Responsive ───────────────────────────────────────────────────────────── */

@media (max-width: 1040px) {
  .bench { grid-template-columns: minmax(0, 1fr); }
  .brief { position: static; }
}
@media (max-width: 760px) {
  .row { grid-template-columns: 20px minmax(0, 1fr) 62px; gap: 12px; }
  .row-concepts, .row-time { display: none; }
  .stepper { grid-template-columns: minmax(0, 1fr); }
  .step-link { border-right: 0; border-bottom: 1px solid var(--rule); text-align: left; }
  .step-link.mid, .step-link.next { text-align: left; }
  .step-link:last-child { border-bottom: 0; }
}
@media (max-width: 760px) {
  .theme-fab { right: 10px; bottom: 10vh; bottom: calc(10dvh + env(safe-area-inset-bottom, 0px)); }
  /* Collapsed to the current theme's chip until tapped (assets/theme.js): the full
     stack floated over the text column and covered a strip of every line that
     scrolled past it. Two squares (theme, feedback) instead of five. */
  .theme-fab:not(.open) .theme-chip:not([aria-pressed="true"]) { display: none; }
  .theme-fab:not(.open) .theme-chip { border-bottom: 0; }
  .theme-fab.open { border-color: var(--ink); background: var(--panel); }
  .theme-fab.open .theme-chip { opacity: 1; }
  .feedback { right: 10px; bottom: calc(10vh - 40px); bottom: calc(10dvh + env(safe-area-inset-bottom, 0px) - 40px); }
  .feedback-panel {
    position: fixed;
    right: 10px;
    left: 10px;
    bottom: 54px;
    width: auto;
  }
  .track-list { columns: 1; }
  .start-meta { margin-left: 0; }
  .consent { padding: 14px; }
  .consent-actions { margin-left: 0; }
  .consent p { font-size: 13px; }
}
/* The name is 17 characters of mono; below this the status would squeeze it
   onto two lines. The mark stays: it is the logo. */
@media (max-width: 380px) {
  .rail-mark { font-size: 13px; gap: 7px; }
  /* "02 REFACTOR" is the longest step label; at 320px the three steps needed
     307px of a 292px ladder and pushed the page 2px wider than the screen. */
  .rung { padding: 11px 10px; }
  .rung .n { margin-right: 5px; }
}

@media (max-width: 620px) {
  :root { --gap: 18px; }
  /* The rail carries four things; at this width the tagline is the one
     nobody needs, and dropping it is what makes room for the theme control. */
  .rail { padding: 0 14px; gap: 12px; }
  .rail-meta { display: none; }
  .bench { padding: 18px 14px 70px; }
  .home { padding: 32px 14px 70px; }
  .rung .sub { display: none; }
  .case-body { padding-left: 18px; }
  .ledger th { width: 70px; }
  .hero { margin-bottom: 38px; }
}

/* Touch screens only: the datasheet's small mono links measured 14-21px tall on a
   phone, under the 24px a fingertip needs (WCAG 2.2 target size). Padding grows
   the hit area without moving the design; a mouse gets the page exactly as before. */
@media (pointer: coarse) {
  .foot-links a, .crumb a { display: inline-block; padding-block: 6px; }
  .track-link { display: inline-block; padding-block: 4px; }
  .concept-link { display: inline-block; padding-block: 3px; }
  .rail-status, .rail-meta, .crumb { font-size: 12px; }
}

/* Tablets: the content reaches the right edge, where the theme and feedback
   controls float, and rows ran under them. Keep their 46px lane clear. Desktop
   (wider than the 1000px content plus margins) already has it; phones collapse
   the controls to two ghosted squares instead (see the 760px rules). */
@media (min-width: 621px) and (max-width: 1080px) {
  .home, .bench { padding-right: 60px; }
}

/* ── Daily puzzle ─────────────────────────────────────────────────────────── */

.daily-hero { margin-bottom: 30px; }
.daily { margin-bottom: 52px; }
.daily-note { color: var(--ink-2); }
.daily-card {
  padding: 22px;
  border: 1px solid var(--ink);
  background: var(--panel);
}
.daily-title { margin: 0; font-size: 23px; font-weight: 600; letter-spacing: -.015em; }
/* Easy / Medium / Hard: a label, not a warning, so it stays quiet. */
.daily-level {
  display: inline-block; vertical-align: 4px; margin-left: 6px; padding: 2px 8px;
  font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid currentColor;
}
.daily-level[data-level="easy"] { color: var(--pass); }
.daily-level[data-level="medium"] { color: var(--cobalt); }
.daily-level[data-level="hard"] { color: var(--fail); }
.daily-ask { margin: 6px 0 14px; color: var(--ink-2); font-size: 15px; }
.daily-code { margin-bottom: 18px; white-space: pre; }
.daily-options { display: grid; gap: 8px; }
.daily-option {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 46px; padding: 10px 14px;
  text-align: left; font: inherit; color: var(--ink);
  background: var(--panel); border: 1px solid var(--rule); cursor: pointer;
}
.daily-option:hover:not([disabled]) { border-color: var(--ink); background: var(--rule-2); }
.daily-option:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }
.daily-option[disabled] { cursor: default; }
.daily-option code { font-family: var(--mono); font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.daily-letter {
  flex: 0 0 auto; width: 24px; height: 24px; display: inline-grid; place-items: center;
  font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--ink-2);
  border: 1px solid var(--rule);
}
.daily-option[data-result="wrong"] { background: var(--fail-bg); border-color: var(--fail); color: var(--on-fail); }
.daily-option[data-result="wrong"] .daily-letter { border-color: var(--fail); color: var(--fail); }
.daily-option[data-result="right"] { background: var(--pass-bg); border-color: var(--pass); color: var(--on-pass); }
.daily-option[data-result="right"] .daily-letter { border-color: var(--pass); color: var(--pass); }
.daily-tries { margin: 14px 0 0; font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); }
.daily-result { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--rule); }
.daily-verdict { margin: 0; font-size: 18px; font-weight: 600; outline: none; }
.daily-grid { margin: 6px 0 14px; font-size: 20px; letter-spacing: .08em; }
.daily-why { font-size: 15px; }
.daily-links { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 14px 0 18px; font-size: 14.5px; }
.daily-links a { color: var(--cobalt); }
.daily-share-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.daily-copied { font-size: 13.5px; color: var(--pass); }
.daily-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  margin: 20px 0 0; padding: 14px 0 0; border-top: 1px solid var(--rule);
}
.daily-stats div { text-align: center; }
.daily-stats dt { font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.daily-stats dd { margin: 4px 0 0; font-size: 20px; font-weight: 600; }
.daily-next { margin: 14px 0 0; font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); }
@media (max-width: 520px) {
  .daily-card { padding: 16px; }
  .daily-code { font-size: 12.5px; padding: 14px; }
}

/* The way in from the index: today's puzzle, one line. */
.daily-promo {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  padding: 14px 18px; margin: 0 0 30px;
  border: 1px solid var(--cobalt); background: var(--panel); text-decoration: none; color: var(--ink);
}
.daily-promo:hover { background: var(--rule-2); }
.daily-promo:focus-visible { outline: 2px solid var(--cobalt); outline-offset: 2px; }
.daily-promo-eyebrow {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--cobalt);
}
.daily-promo strong { font-weight: 600; }
.daily-promo .go { margin-left: auto; font-family: var(--mono); font-size: 12.5px; color: var(--cobalt); }

/* Past puzzles: the archive list, and a past puzzle's page. */
.daily-row { grid-template-columns: 44px minmax(0, 1fr) auto 150px; }
.daily-row .row-num, .daily-row .row-meta { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.daily-row .row-title { font-size: 15.5px; font-weight: 500; }
.daily-row .row-meta { text-align: right; }
.daily-row .daily-level { margin-left: 0; vertical-align: 0; }
@media (max-width: 560px) {
  .daily-row { grid-template-columns: 36px minmax(0, 1fr) auto; }
  .daily-row .row-meta { display: none; }
}
.daily-past-options { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 8px; }
.daily-past-options li {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border: 1px solid var(--rule); background: var(--panel);
}
.daily-past-options code { font-family: var(--mono); font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.daily-reveal summary { display: inline-flex; list-style: none; cursor: pointer; }
.daily-reveal summary::-webkit-details-marker { display: none; }
.daily-reveal[open] summary { display: none; }
.daily-reveal .daily-verdict { margin-top: 4px; }
.daily-reveal .daily-verdict code { font-family: var(--mono); }
.daily-today { margin: 24px 0 0; }
.daily-today .btn, .daily-archive-link a { text-decoration: none; }
.daily-archive-link { margin: -14px 0 18px; font-family: var(--mono); font-size: 13px; }
.daily-archive-link a { color: var(--cobalt); }

/* ── Coding keys for phones (bench.js buildKeybar) ───────────────────────── */
.keybar { display: none; }
@media (pointer: coarse) {
  .keybar {
    display: flex; gap: 6px; padding: 7px 8px;
    position: sticky; bottom: 0; z-index: 5;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    border-top: 1px solid var(--rule); background: var(--paper);
  }
  .keybar::-webkit-scrollbar { display: none; }
  .keybar-key {
    flex: 0 0 auto; min-width: 40px; height: 40px; padding: 0 10px;
    font: 600 17px var(--mono); color: var(--ink);
    background: var(--panel); border: 1px solid var(--rule);
    touch-action: manipulation; -webkit-user-select: none; user-select: none;
  }
  .keybar-key:active { background: var(--rule-2); }
}

/* The file picker is a label styled as a button (privacy page, load a saved copy). */
.backup-load { cursor: pointer; }
.backup-load:focus-within { outline: 2px solid var(--cobalt); outline-offset: 2px; }

/* ── Review your mistakes (index.js reviewPanel) ─────────────────────────── */
.review { padding: 20px 22px; border: 1px solid var(--note); background: var(--note-bg); margin-bottom: 46px; }
.review--quiet { border-color: var(--rule); background: var(--panel); padding: 14px 18px; }
.review .continue-eyebrow { color: var(--note); }
.review--quiet .continue-eyebrow { color: var(--ink-3); }
.review .continue-why { color: var(--on-note); margin-bottom: 12px; }
.review-list { margin: 0; padding-left: 22px; }
.review-list li { padding: 7px 0; }
.review-list a { font-weight: 600; color: var(--ink); }
.review-meta { display: block; font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.review-next { margin: 0; font-size: 14.5px; color: var(--ink-2); }
.review-next a { color: var(--cobalt); }
.review-more { margin: 8px 0 0; font-size: 13.5px; color: var(--ink-3); }

/* A real traceback inside a debug exercise's report (build.py verify_traceback). */
.trace-panel { margin-bottom: var(--gap); }
.symptom-trace { font-size: 13px; line-height: 1.65; white-space: pre; }
