/* ============================================================
   ZERO SERIES — Shared Theme
   Dark cyberpunk/anime aesthetic for all Zero Series curricula
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap');

/* ── Variables ─────────────────────────────────────────────── */
:root {
  --bg:           #0a0a0f;
  --surface:      #12121a;
  --surface2:     #1a1a26;
  --border:       #2a2a3e;
  --border-bright:#3d3d5c;

  --gold:         #f5a623;
  --gold-dim:     #c4821a;
  --cyan:         #00d4ff;
  --cyan-dim:     #0099bb;
  --red:          #ff4655;
  --green:        #39ff14;
  --purple:       #a855f7;
  --muted:        #6b7280;

  --text:         #e8e8f0;
  --text-dim:     #9998b8;
  --text-muted:   var(--text-dim);

  --font-body:    'Inter', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', 'Fira Code', monospace;

  --radius:       6px;
  --radius-lg:    10px;
}

/* ── Reset ─────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  min-height: 100vh;
}
a { color: var(--cyan); text-decoration: none; }
a:hover { color: var(--gold); }
img { max-width: 100%; display: block; }

/* ── Scrollbar ─────────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--surface); }
::-webkit-scrollbar-thumb { background: var(--border-bright); border-radius: 3px; }

/* ── Typography ────────────────────────────────────────────── */
h1, h2, h3, h4 { font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; }
h1 { font-size: 2rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.08em; }
p  { color: var(--text-dim); line-height: 1.7; }
code, pre { font-family: var(--font-mono); }

/* ── Layout helpers ─────────────────────────────────────────── */
.container { max-width: 1400px; margin: 0 auto; padding: 0 1.5rem; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }

/* ── Badge / chip ──────────────────────────────────────────── */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ── Card ──────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1rem;
}

/* ── Code blocks ───────────────────────────────────────────── */
pre[class*="language-"], pre.code-block {
  background: #0d0d16 !important;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  overflow-x: auto;
  font-size: 12.5px;
  line-height: 1.65;
}
code[class*="language-"] { background: none !important; }

/* ── ===================================================== ── */
/* ── INDEX PAGE                                            ── */
/* ── ===================================================== ── */

.hub-back-link {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  text-decoration: none;
  margin-bottom: 6px;
  transition: color 0.15s;
}
.hub-back-link:hover { color: var(--cyan); }
.lesson-check { margin-left: auto; font-size: 10px; color: var(--green); }
.volume-progress {
  margin-top: 0.8rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 11px;
  color: var(--muted);
}

/* ── ===================================================== ── */
/* ── LESSON PAGE                                           ── */
/* ── ===================================================== ── */

.lesson-page { min-height: 100vh; display: flex; flex-direction: column; }

/* pulse — kept for #mark-complete-btn.checklist-ready (the drawer checklist) */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}
/* "Next up" link — used inside 600+ chapter fragments */
.next-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  padding: 6px 14px;
  background: rgba(0,212,255,0.1);
  border: 1px solid rgba(0,212,255,0.3);
  border-radius: var(--radius);
  color: var(--cyan);
  font-size: 12px;
  font-weight: 600;
  transition: all 0.15s;
}
.next-link:hover { background: rgba(0,212,255,0.2); color: var(--cyan); }

/* ── Auth widget (injected by app.js) ──────────────────────── */
#auth-widget {
  position: fixed;
  top: 12px;
  right: 12px;
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  font-family: var(--font-body);
  font-size: 0.8rem;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
}

#auth-widget .auth-label,
#auth-widget .auth-user {
  color: var(--text-dim);
  white-space: nowrap;
}

#auth-widget .auth-btn {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--border-bright);
  border-radius: var(--radius);
  background: transparent;
  color: var(--cyan);
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

#auth-widget .auth-btn:hover {
  border-color: var(--cyan);
  color: var(--bg);
  background: var(--cyan);
}

@media (max-width: 700px) {
  #auth-widget {
    top: auto;
    bottom: 12px;
    right: 12px;
    font-size: 0.74rem;
  }
  #auth-widget .auth-label { display: none; }
}

/* ── Deep-lesson pedagogy cards ─────────────────────────────────
   Build It Up (staged code), inline run output, collapsible reveals
   (Check Yourself / Exercises), and Worked Failure. Additive — older
   lessons that don't use these classes are unaffected. */

/* Inline run output */
.run-out {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.55;
  background: rgba(0,0,0,0.32); border: 1px solid var(--border); border-radius: 4px;
  padding: 0.5rem 0.7rem; color: var(--green); white-space: pre-wrap; margin-top: 0.6rem;
}
.run-out .run-label { color: var(--text-dim); display: block; margin-bottom: 0.25rem; font-size: 10px; letter-spacing: 0.05em; }

/* Collapsible reveals (Check Yourself + Exercise solutions) */
details.reveal { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 0.6rem; background: var(--surface2); }
details.reveal:last-child { margin-bottom: 0; }
details.reveal > summary {
  cursor: pointer; padding: 0.55rem 0.8rem; font-size: 12.5px; color: var(--text);
  font-weight: 600; list-style: none; line-height: 1.5;
}
details.reveal > summary::-webkit-details-marker { display: none; }
details.reveal > summary::before { content: '▸'; color: var(--cyan); margin-right: 0.5rem; }
details.reveal[open] > summary::before { content: '▾'; }
details.reveal .reveal-body { padding: 0 0.8rem 0.75rem; font-size: 12px; color: var(--text-dim); line-height: 1.65; }
details.reveal .reveal-body strong { color: var(--text); }
details.reveal .reveal-body pre { margin: 0.5rem 0 0; }

/* Worked failure */
.fail-trace {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.55;
  background: rgba(255,70,85,0.06); border: 1px solid rgba(255,70,85,0.25); border-radius: 4px;
  padding: 0.5rem 0.7rem; color: #ff8b96; white-space: pre-wrap; margin-top: 0.6rem;
}

/* ── Keyboard focus visibility ──────────────────────────────────
   Interactive elements get a visible ring for keyboard users only
   (mouse clicks stay clean via :focus-visible). */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
}

/* ── Volume progress label + completed volumes ─────────────────── */
.vol-progress-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ── Continue CTA (curriculum index) ───────────────────────────── */
.continue-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.8rem;
  padding: 0.55rem 0.95rem;
  border-radius: var(--radius);
  border: 1px solid rgba(57,255,20,0.35);
  background: rgba(57,255,20,0.08);
  color: var(--green);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.continue-cta:hover {
  background: rgba(57,255,20,0.14);
  border-color: rgba(57,255,20,0.55);
  transform: translateX(2px);
}
.continue-cta .cta-play { font-size: 0.7rem; }
.continue-cta.all-done {
  border-color: rgba(245,166,35,0.4);
  background: rgba(245,166,35,0.08);
  color: var(--gold);
  cursor: default;
}

/* ── Hub: per-curriculum progress + resume + streak ────────────── */
.hub-card-bar {
  height: 3px;
  border-radius: 2px;
  background: var(--surface2);
  overflow: hidden;
}
.hub-card-bar-fill {
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--green), var(--cyan));
  transition: width 0.4s ease;
}
.hub-card-done.started { color: var(--green); }

.hub-chips {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
}
.hub-chip {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-bright);
  background: var(--surface);
  color: var(--text-dim);
}
.hub-chip.streak {
  border-color: rgba(245,166,35,0.45);
  background: rgba(245,166,35,0.08);
  color: var(--gold);
}
.hub-resume {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  margin-top: 0.9rem;
  padding: 0.6rem 1.2rem;
  border-radius: var(--radius);
  border: 1px solid rgba(57,255,20,0.35);
  background: rgba(57,255,20,0.07);
  color: var(--green);
  font-size: 0.82rem;
  font-weight: 700;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s;
}
.hub-resume:hover {
  background: rgba(57,255,20,0.13);
  border-color: rgba(57,255,20,0.55);
}
.hub-resume-lesson {
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--text-dim);
}

/* ── Code blocks: copy button + language badge ─────────────────── */
pre { position: relative; }
.copy-btn {
  position: absolute;
  top: 6px; right: 6px;
  font-size: 10px;
  font-weight: 600;
  font-family: var(--font-body);
  padding: 3px 9px;
  border-radius: 4px;
  border: 1px solid var(--border-bright);
  background: var(--surface2);
  color: var(--text-dim);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
pre:hover .copy-btn,
.copy-btn:focus-visible { opacity: 1; }
.copy-btn:hover { color: var(--text); border-color: var(--text-muted); }
.copy-btn.copied { color: var(--green); border-color: rgba(57,255,20,0.5); }
@media (hover: none) {
  .copy-btn { opacity: 0.75; } /* touch devices have no hover */
}
pre[data-lang]::after {
  content: attr(data-lang);
  position: absolute;
  top: 8px; right: 10px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  pointer-events: none;
  transition: opacity 0.15s;
}
pre[data-lang]:hover::after { opacity: 0; } /* yield to the copy button */

/* ── Completion confetti ───────────────────────────────────────── */
.confetti {
  position: fixed;
  width: 8px; height: 8px;
  border-radius: 1px;
  pointer-events: none;
  z-index: 9999;
  animation: confetti-fly 0.9s ease-out forwards;
}
@keyframes confetti-fly {
  to {
    transform: translate(var(--dx), var(--dy)) rotate(var(--rot));
    opacity: 0;
  }
}

/* ── Lab checklist (stages + steps) ────────────────────────────── */
.lab-check {
  margin-left: auto;
  width: 18px; height: 18px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px solid var(--border-bright);
  background: var(--surface2);
  color: var(--green);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.lab-check:hover { border-color: rgba(57,255,20,0.5); }
.lab-check[aria-checked="true"] {
  background: rgba(57,255,20,0.12);
  border-color: rgba(57,255,20,0.5);
}
#lab-progress {
  margin-top: 0.5rem;
  font-size: 10px;
  font-family: var(--font-mono);
  color: var(--text-muted);
  text-align: center;
}
#lab-progress.all-checked { color: var(--green); }
#mark-complete-btn.checklist-ready { animation: pulse 1.6s ease-in-out infinite; }

/* ── Reduced motion ─────────────────────────────────────────────
   Honor the user's OS-level preference: kill animations, smooth
   scrolling, and hover transforms. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── Print ──────────────────────────────────────────────────────
   Lessons print as readable, ink-friendly documents. */
@media print {
  body { background: #fff; color: #111; }
  #auth-widget, .copy-btn, .lab-check, #mark-complete-btn,
  #lab-progress, .next-link,
  .chapter-rail, .width-toggle { display: none !important; }
  .chapter-main { display: block; padding: 0; }
  .chapter { max-width: 100%; }
  pre, code { background: #f7f7f7 !important; color: #111 !important; }
  details.reveal summary { color: #111; }
  a { color: #111; text-decoration: underline; }
}

/* ══════════════════════════════════════════════════════════════
   CHAPTER FORMAT
   Long-form, book-style pages: a narrative spine with boxed
   practice, a single reading column at book measure and book
   typography. Opt in with <main class="chapter-main">.
   ══════════════════════════════════════════════════════════════ */

.chapter-main {
  /* Reading measure stays in the 66–80ch band whatever the screen does:
     past ~85ch the eye loses the line-start on the return sweep, and long
     technical paragraphs are exactly where that hurts. Extra screen width
     is therefore spent on three other things instead — bigger type, a
     breakout track for code and figures, and the outline rail. */
  --ch-measure: 78ch;
  --ch-rail: 0rem;          /* outline rail; 0 until there is room */
  --ch-gap: 2.5rem;

  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--ch-rail);
  column-gap: var(--ch-gap);
  padding: 2rem 2.5rem 4rem;
  overflow-y: auto;
  min-width: 0;
  scroll-behavior: smooth;
}
.chapter {
  max-width: var(--ch-measure);
  margin: 0 auto;
  min-width: 0;
}

/* Wide mode — the reader's choice, persisted. Loosens the measure to the
   top of the readable band rather than abandoning it. */
:root[data-chapter-width="wide"] .chapter-main { --ch-measure: 90ch; }

/* The outline rail claims the right margin once there is room for it.
   (These live here rather than beside .chapter-rail because they set a
   custom property on .chapter-main, the grid that reserves the column.) */
@media (min-width: 1400px) { .chapter-main { --ch-rail: 13rem; } }
@media (min-width: 1650px) { .chapter-main { --ch-rail: 13.5rem; } }
@media (min-width: 1900px) { .chapter-main { --ch-rail: 14.5rem; } }
@media (min-width: 2200px) { .chapter-main { --ch-rail: 15rem; } }

/* Code, figures and tables share the prose measure — a breakout track
   was tried and reverted: mixed widths read as misalignment. Wide
   content scrolls inside its own box instead. */
.chapter pre { overflow-x: auto; max-width: 100%; }
.chapter table { display: block; overflow-x: auto; max-width: 100%; }
.chapter .symtab { display: table; }

/* ── Reading typography ─────────────────────────────────────── */
.chapter p,
.chapter li {
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--text-dim);
}
.chapter p { margin-bottom: 1.05rem; }
.chapter p strong, .chapter li strong { color: var(--text); font-weight: 600; }
.chapter em { color: var(--text); font-style: italic; }
.chapter a { border-bottom: 1px solid rgba(0,212,255,0.3); }

/* ── Section headings ───────────────────────────────────────── */
.chapter-section { margin-top: 2.6rem; }
.chapter-section > h2 {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
  padding-bottom: 0.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}
.chapter-section > h2::before {
  content: counter(chapter-section, decimal) ".";
  counter-increment: chapter-section;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--gold);
  font-weight: 700;
}
.chapter { counter-reset: chapter-section; }
.chapter-section > h3 {
  font-size: 0.95rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--cyan);
  margin: 1.6rem 0 0.7rem;
}

/* ── Boxed practice (shared frame) ──────────────────────────── */
.box {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--surface);
  padding: 1rem 1.15rem;
  margin: 1.6rem 0;
}
.box-label {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.box > p:last-child, .box > div:last-child { margin-bottom: 0; }
.box p, .box li { font-size: 14.5px; line-height: 1.7; }

/* Math Interlude — numbers first, then symbols, then verification */
.box.math      { border-left-color: var(--purple); }
.box.math .box-label { color: var(--purple); }
.math-eq {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.7rem 0.9rem;
  margin: 0.8rem 0;
  overflow-x: auto;
  text-align: center;
}
.math-where {
  font-size: 12.5px;
  color: var(--text-muted);
  border-left: 2px solid var(--border-bright);
  padding-left: 0.7rem;
  margin: 0.6rem 0;
}
.math-where code { color: var(--purple); }

/* Build — a runnable increment */
.box.build     { border-left-color: var(--gold); }
.box.build .box-label { color: var(--gold); }

/* Failure — the thing that goes wrong */
.box.failure   { border-left-color: var(--red); background: rgba(255,70,85,0.04); }
.box.failure .box-label { color: var(--red); }

/* Checkpoint — predict before revealing */
.box.checkpoint { border-left-color: var(--green); }
.box.checkpoint .box-label { color: var(--green); }

/* Practice — exercises with worked solutions */
.box.practice  { border-left-color: var(--green); }
.box.practice .box-label { color: var(--green); }

/* Note / aside */
.box.note      { border-left-color: var(--cyan); }
.box.note .box-label { color: var(--cyan); }

/* Architecture callout — the decoupling thread */
.box.arch      { border-left-color: var(--border-bright); }
.box.arch .box-label { color: var(--text-dim); }

/* ── Figures ────────────────────────────────────────────────── */
.figure { margin: 1.6rem 0; text-align: center; }
.figure svg, .figure img { max-width: 100%; height: auto; margin: 0 auto; }
/* Rendered frames from a game contract: keep the pixels square and crisp
   rather than letting the browser smooth a 160x120 image up to full width. */
.figure img.pixels {
  image-rendering: pixelated;
  width: 100%;
  max-width: 480px;
  border: 1px solid var(--rule, rgba(255,255,255,.12));
  border-radius: 4px;
}
.figure-cap {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 0.6rem;
  text-align: center;
}
.figure-cap strong { color: var(--text-dim); }

.pixel-inspector {
  margin: .75rem auto 0;
  max-width: 100%;
  text-align: left;
  font-size: 12px;
}
.pixel-inspector summary { cursor: pointer; color: var(--cyan); }
.pixel-inspector-toolbar { display: flex; gap: .5rem; margin-top: .75rem; }
.pixel-inspector button {
  font: inherit;
  padding: .3rem .7rem;
  border: 1px solid var(--border-bright);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.pixel-inspector button[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }
.pixel-inspector button:disabled { opacity: .6; cursor: wait; }
.pixel-inspector-status { margin: .5rem 0; }
.pixel-inspector-viewport {
  overflow: auto;
  max-width: 100%;
  max-height: 65vh;
  background: var(--surface2);
  border: 1px solid var(--border-bright);
}
.pixel-inspector .pixel-original {
  display: block;
  max-width: none;
  height: auto;
  image-rendering: pixelated;
}
.pixel-inspector :focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ── Chapter close ──────────────────────────────────────────── */
.chapter-close {
  margin-top: 3rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--border);
}
.chapter-close h2 {
  font-size: 1rem; color: var(--cyan);
  margin-bottom: 0.8rem; border: 0; padding: 0;
}
.chapter-close h2::before { content: none; }

/* ── Outline rail ───────────────────────────────────────────────
   Chapters run 60–70KB with 6–11 sections. Before this there was no
   way to see the shape of one or move inside it — you scrolled and
   hoped. The rail turns the right margin from dead space into the
   navigation the format was missing. Built by app.js from the h2s,
   so no chapter HTML has to change. */
.chapter-rail {
  display: none;
  position: sticky;
  top: 0;
  align-self: start;
  max-height: calc(100vh - 8rem);
  overflow-y: auto;
  padding: 0.4rem 0 1rem;
  font-size: 12px;
  line-height: 1.5;
}
.chapter-main:has(.chapter-rail) { grid-template-columns: minmax(0, 1fr) var(--ch-rail); }
@media (min-width: 1400px) { .chapter-rail { display: block; } }

.chapter-rail-title {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding-bottom: 0.5rem;
  margin-bottom: 0.55rem;
  border-bottom: 1px solid var(--border);
}
.chapter-rail ol { list-style: none; margin: 0; padding: 0; counter-reset: rail; }
.chapter-rail li { margin: 0; }
.chapter-rail a {
  display: flex;
  gap: 0.5rem;
  padding: 0.32rem 0.5rem 0.32rem 0.6rem;
  color: var(--text-muted);
  border-left: 2px solid var(--border);
  border-bottom: 0;
  border-radius: 0 3px 3px 0;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.chapter-rail a::before {
  content: counter(rail);
  counter-increment: rail;
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-muted);
  padding-top: 0.15em;
  flex: none;
}
.chapter-rail a:hover { color: var(--text-dim); background: var(--surface2); border-left-color: var(--border-bright); }
.chapter-rail a.is-current {
  color: var(--gold);
  border-left-color: var(--gold);
  background: rgba(245,166,35,0.06);
}
.chapter-rail a.is-current::before { color: var(--gold); }

/* ── Width toggle ───────────────────────────────────────────────
   Rides at the foot of the rail on wide screens; becomes a compact
   pill in the corner when there is no rail to hold it. */
.width-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.9rem;
  padding: 0.35rem 0.6rem;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.width-toggle:hover { color: var(--gold); border-color: var(--gold); }
.width-toggle svg { width: 11px; height: 11px; flex: none; }
@media (max-width: 1399px) {
  .width-toggle {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 40;
    margin: 0;
    background: var(--surface2);
    box-shadow: 0 2px 10px rgba(0,0,0,0.4);
  }
}
@media (max-width: 900px), (max-height: 500px) { .width-toggle { display: none; } }

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 900px), (max-height: 500px) {
  .chapter-main { padding: 1.5rem 1.2rem 3rem; }
  .chapter p, .chapter li { font-size: 16px; }
}
.box.build.lab-done > .box-label { color: var(--green); }
.box.build.lab-done { border-left-color: var(--green); }

/* New Tool — the first time a library or tool is introduced, it gets a
   proper welcome: why this one, how to install it, the smallest use. */
.box.tool { border-left-color: var(--cyan); background: rgba(0,212,255,0.035); }
.box.tool .box-label { color: var(--cyan); }
.box.tool .tool-why { font-size: 13px; color: var(--text-muted); margin-top: 0.5rem; }

/* ── Inline SVG diagrams ────────────────────────────────────────
   Diagrams are inline SVG so they inherit the theme exactly, stay
   crisp at any zoom, and diff in git. Use these classes rather than
   hard-coded fills so a palette change carries automatically. */
.figure svg { display: block; margin: 0 auto; max-width: 100%; height: auto; }
.figure svg text { font-family: var(--font-body); }
.dg-panel   { fill: var(--surface);  stroke: var(--border); }
.dg-box     { fill: var(--surface2); stroke: var(--border-bright); }
.dg-box-hi  { fill: rgba(245,166,35,0.10); stroke: var(--gold); }
.dg-box-bad { fill: rgba(255,70,85,0.08);  stroke: var(--red); }
.dg-box-ok  { fill: rgba(57,255,20,0.08);  stroke: var(--green); }
.dg-title   { fill: var(--text);      font-size: 12px; font-weight: 700; }
.dg-label   { fill: var(--text-dim);  font-size: 11px; }
.dg-mono    { fill: var(--cyan);      font-size: 11px; font-family: var(--font-mono); }
.dg-sub     { fill: var(--text-muted); font-size: 9.5px; letter-spacing: 0.08em; text-transform: uppercase; }
.dg-line    { stroke: var(--border-bright); fill: none; }
.dg-flow    { stroke: var(--gold);  fill: none; stroke-width: 1.5; }
.dg-flow-x  { stroke: var(--red);   fill: none; stroke-width: 1.5; stroke-dasharray: 4 3; }
.dg-fill-gold  { fill: var(--gold); }
.dg-fill-red   { fill: var(--red); }
.dg-fill-green { fill: var(--green); }

/* ── Symbol table ───────────────────────────────────────────────
   Every Math Interlude that introduces notation carries one of
   these: what the symbol means in words, what it is called in the
   code, and a real value from the run on the page. Reading a
   formula is a skill; this is the decoder ring. */
.symtab { width: 100%; border-collapse: collapse; margin: 0.9rem 0; font-size: 12.5px; }
.symtab th {
  text-align: left; font-size: 9.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-muted);
  border-bottom: 1px solid var(--border); padding: 0 0.6rem 0.4rem 0;
}
.symtab td { padding: 0.42rem 0.6rem 0.42rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.symtab tr:last-child td { border-bottom: 0; }
.symtab .sym  { font-family: var(--font-mono); color: var(--purple); white-space: nowrap; font-weight: 600; }
.symtab .said { color: var(--text-dim); }
.symtab .code { font-family: var(--font-mono); color: var(--cyan); white-space: nowrap; }
.symtab .val  { font-family: var(--font-mono); color: var(--text); white-space: nowrap; }
@media (max-width: 620px) { .symtab, .symtab tbody, .symtab tr, .symtab td { display: block; width: 100%; } .symtab thead { display: none; } .symtab td { border: 0; padding: 0.15rem 0; } .symtab tr { border-bottom: 1px solid var(--border); padding: 0.5rem 0; } }

/* ── Data table ─────────────────────────────────────────────────
   A measured table that is a synthesis across chapters rather than
   one program's output. Anything a single program printed belongs
   in a .run-out; this is for the rare case where the numbers come
   from several of them and the page is doing the joining. */
.datatable { width: 100%; border-collapse: collapse; margin: 0.9rem 0; font-size: 12.5px; font-family: var(--font-mono); }
.datatable th {
  text-align: right; font-size: 9.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-muted);
  font-family: var(--font-body);
  border-bottom: 1px solid var(--border); padding: 0 0.7rem 0.4rem 0;
}
.datatable th:first-child, .datatable td:first-child { text-align: left; }
.datatable td { padding: 0.4rem 0.7rem 0.4rem 0; border-bottom: 1px solid var(--border); text-align: right; color: var(--text); white-space: nowrap; }
.datatable tr:last-child td { border-bottom: 0; }
.datatable tbody tr:hover td { background: var(--surface); }

/* Sub-headings inside a chapter section. Without this rule writers reach for
   inline styles — Chapter 02 grew five identical style="" attributes before
   the gap was spotted. */
.chapter-section h3 {
  font-size: 15px;
  margin-top: 1.6rem;
  margin-bottom: 0.6rem;
  color: var(--cyan);
  text-transform: none;
  letter-spacing: 0;
}
/* Notation the maths primers pronounce: the map arrow and function
   application read as operators, not multiplication. */
.mapsto { font-family: var(--font-mono); color: var(--gold); padding: 0 0.15em; }

/* ══════════════════════════════════════════════════════════════
   BOOK INDEX — "The Lit Station"
   A book's volumes as one journey down a spine. The volume you are
   reading becomes a lit station carrying its own instruments; the
   volumes still to be written stay quiet stops further down the line.
   Generated by tools/gen from book.json; progress filled by app.js.
   ══════════════════════════════════════════════════════════════ */
.bk-hero {
  text-align: center; padding: 2.4rem 2rem 1.6rem;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #0d0d18 0%, var(--bg) 100%);
}
.bk-hero .hub-back-link { justify-content: center; }
.bk-label { font-size: 10px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--cyan-dim); }
.bk-title { font-size: 2.2rem; font-weight: 800; letter-spacing: -.02em; color: var(--text); margin-top: .35rem; }
.bk-sub { font-size: 12.5px; color: var(--text-dim); margin-top: .15rem; }
.bk-intro { max-width: 66ch; margin: 1rem auto 0; font-size: 13.5px; line-height: 1.7; color: var(--text-dim); }
.bk-intro > p { margin-bottom: .8rem; }
.game-projects { width: 100%; border-collapse: collapse; text-align: left; }
.game-projects th, .game-projects td { padding: .65rem .35rem; border-bottom: 1px solid var(--border); vertical-align: top; overflow-wrap: anywhere; }
.game-projects th { color: var(--text); }
.game-projects thead th { overflow-wrap: normal; }
.game-projects th span { font-weight: 400; color: var(--text-dim); }
.game-projects td { width: 25%; }
.bk-stats { display: flex; justify-content: center; gap: 2.6rem; margin-top: 1.4rem; flex-wrap: wrap; }
.bk-stats div { text-align: center; }
.bk-stats b { display: block; font-family: var(--font-mono); font-size: 1.25rem; color: var(--gold); }
.bk-stats span { font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }
.bk-reading { gap: 1.8rem; margin-top: 1rem; }
.bk-reading b { font-size: 1rem; color: var(--text-dim); }
.bk-cta {
  display: inline-flex; align-items: center; gap: .5rem; margin-top: 1.3rem; padding: .7rem 1.4rem;
  border-radius: var(--radius); border: 1px solid rgba(57,255,20,.35); background: rgba(57,255,20,.08);
  color: var(--green); font-weight: 700; font-size: 13px;
}
.bk-cta:hover { background: rgba(57,255,20,.16); color: var(--green); }

/* ── The spine ── */
.journey { max-width: 940px; margin: 2.2rem auto 4rem; padding: 0 2rem; position: relative; }
.journey::before {
  content: ''; position: absolute; left: calc(2rem + 15px); top: 16px; bottom: 64px; width: 2px;
  background: linear-gradient(180deg, var(--gold) 0%, var(--gold) 12%, var(--border-bright) 26%, var(--border) 100%);
}
.vol { position: relative; padding-left: 3.4rem; margin-bottom: 1.5rem; }
.vol-dot {
  position: absolute; left: 6px; top: 8px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--bg); border: 2px solid var(--border-bright); display: flex; align-items: center;
  justify-content: center; font-family: var(--font-mono); font-size: 8px; color: var(--text-muted); z-index: 1;
}
.vol.current .vol-dot { border-color: var(--gold); color: var(--gold); box-shadow: 0 0 14px rgba(245,166,35,.55); }
.vol.locked { opacity: .6; }
.vol.locked .vol-dot { border-style: dashed; }
/* a volume finished end to end stops being "here" and turns green */
.vol.volume-complete .vol-dot { border-color: var(--green); color: var(--green); box-shadow: 0 0 14px rgba(57,255,20,.4); }
.vol.volume-complete .station { border-color: rgba(57,255,20,.5); }
.vol.volume-complete .st-here { display: none; }

/* ── The lit station: the volume you are reading ── */
.station {
  border: 1px solid var(--border-bright); border-radius: var(--radius-lg); overflow: hidden;
  background: var(--surface);
}
.vol.current .station {
  border-color: var(--gold);
  background: radial-gradient(ellipse at 12% 0%, rgba(245,166,35,.11), transparent 62%), var(--surface);
}
.st-here { display: none; }
.vol.current .st-here { display: inline; }
.station-head { padding: 1.1rem 1.3rem .9rem; border-bottom: 1px solid var(--border); }
.st-kicker { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .2em; color: var(--gold); }
.st-t { font-size: 1.4rem; font-weight: 800; color: var(--text); letter-spacing: -.02em; margin-top: .1rem; }
.st-s { font-size: 11.5px; color: var(--text-muted); margin-top: .15rem; }
.st-p { font-size: 13px; color: var(--text-dim); line-height: 1.7; margin-top: .7rem; max-width: 62ch; }
.st-build { font-family: var(--font-mono); font-size: 10.5px; color: var(--cyan); margin-top: .5rem; }
.st-build span { color: var(--text-muted); }
.asset-downloads {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem 1rem;
  font-size: 11px; line-height: 1.6; margin-top: .8rem;
}
.asset-downloads a { color: var(--cyan); text-decoration: underline; text-underline-offset: .2em; }
.asset-downloads span { color: var(--text-muted); }
.asset-downloads {
  padding: .7rem .9rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); font-size: 12px; overflow-wrap: anywhere;
}
.st-prog { padding: .9rem 1.3rem; border-bottom: 1px solid var(--border); background: rgba(0,0,0,.16); }
.st-bar { height: 6px; border-radius: 3px; background: var(--bg); border: 1px solid var(--border); overflow: hidden; }
.st-bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--gold), var(--cyan)); transition: width .4s ease; }
.st-l {
  display: flex; justify-content: space-between; gap: 1rem; font-family: var(--font-mono); font-size: 9.5px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); margin-top: .45rem;
}
.st-l b { color: var(--gold); font-weight: 400; }

/* ── Chapters as steps in sequence ── */
.steps { padding: .5rem .7rem .8rem; }
.step {
  display: flex; gap: .9rem; align-items: flex-start; padding: .6rem .7rem; border-radius: var(--radius);
  color: inherit; text-decoration: none; border: 1px solid transparent; transition: background .15s, border-color .15s;
}
.step:hover { background: var(--surface2); border-color: var(--border); }
.step + .step { border-top: 1px solid rgba(255,255,255,.04); border-radius: 0; }
.step-n { font-family: var(--font-mono); font-size: 10.5px; color: var(--gold); padding-top: .2rem; min-width: 1.5rem; }
.step-body { min-width: 0; }
.step-t { display: block; font-weight: 600; font-size: 13.5px; color: var(--text); }
.step-s { display: block; font-size: 11.5px; color: var(--text-muted); line-height: 1.5; margin-top: .12rem; }
.step-tag {
  margin-left: auto; align-self: center; font-family: var(--font-mono); font-size: 8px;
  letter-spacing: .12em; padding: 2px 6px; border-radius: 3px; border: 1px solid transparent; flex: none;
}
.step.completed .step-tag { color: var(--green); border-color: rgba(57,255,20,.3); }
.step.is-next .step-tag { color: var(--gold); border-color: rgba(245,166,35,.4); background: rgba(245,166,35,.08); }

/* ── Volumes not yet written ── */
.vol-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; padding-top: .15rem; }
.vol-n { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); letter-spacing: .12em; }
.vol-t { font-size: 1.05rem; font-weight: 700; color: var(--text-dim); }
.vol-badge {
  font-family: var(--font-mono); font-size: 8px; letter-spacing: .14em; padding: 2px 6px;
  border-radius: 3px; border: 1px solid var(--border); color: var(--text-muted);
}
.vol-promise { font-size: 12.5px; color: var(--text-muted); margin-top: .25rem; line-height: 1.6; }
.vol-build { font-family: var(--font-mono); font-size: 10px; color: var(--cyan-dim); margin-top: .35rem; }
.vol-build span { color: var(--text-muted); }

@media (max-width: 640px) {
  .journey { padding: 0 1rem; }
  .journey::before { left: calc(1rem + 15px); }
  .vol { padding-left: 2.8rem; }
  .bk-stats { gap: 1.6rem; }
}

/* On a phone the sign-in pill was pinned over the bottom-right of the
   page, where it covered whatever you were reading. Give it the top-left
   instead: out of the thumb's way, clear of the reading column, and it
   scrolls off as soon as you start reading rather than following you. */
@media (max-width: 700px) {
  body:not(.lesson-page) #auth-widget {
    position: absolute; top: 8px; right: 8px; bottom: auto;
    padding: 4px 8px; gap: 5px;
  }
  body:not(.lesson-page) #auth-widget .auth-btn { padding: 3px 7px; }
}

/* Inline code in prose — a path or a passwd line has no spaces to
   break at, so a long one pushes past the measure (and off a phone
   screen entirely). Let it break only when it otherwise would not fit. */
.chapter p code, .chapter li code, .chapter td code,
.chapter .box p code, .chapter .box li code {
  overflow-wrap: break-word;
  word-break: break-word;
}

/* ══════════════════════════════════════════════════════════════
   READING ON A PHONE
   This block owns the phone layout. It is last in the file, and
   its selectors match or exceed the desktop rules they must
   override.

   The `max-height` half of the query is not decoration. A phone in
   LANDSCAPE is wider than 900px — an iPhone 15/16 Pro Max is 932 —
   so a width-only breakpoint would hand a phone the desktop grid.
   No phone is 500px tall in landscape; no desk is. Ask both.
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 900px), (max-height: 500px) {

  /* The measure must never exceed the screen. `min()` keeps the
     book measure on tablets and yields to the viewport on phones. */
  body.lesson-page .chapter-main {
    display: block;
    padding: 1.1rem 1.05rem 6.5rem;   /* bottom room for the action bar */
    overflow: visible;
    /* `viewport-fit=cover` lets the page run under the notch, which in
       landscape is on the SIDE. Keep the prose clear of it. */
    padding-left: max(1.05rem, env(safe-area-inset-left));
    padding-right: max(1.05rem, env(safe-area-inset-right));
  }
  body.lesson-page .chapter {
    max-width: min(var(--ch-measure), 100%);
    margin: 0;
  }

  /* Reading type: slightly larger than desktop, because a phone is
     held closer and the line is shorter. */
  body.lesson-page .chapter p,
  body.lesson-page .chapter li { font-size: 17px; line-height: 1.72; }
  body.lesson-page .chapter-section > h2 { font-size: 1.08rem; }
  body.lesson-page .chapter-section { margin-top: 2rem; }

  /* Code: readable, and scrollable on its own rather than pushing
     the page sideways. */
  body.lesson-page .chapter pre[class*="language-"],
  body.lesson-page .chapter pre.code-block,
  body.lesson-page .chapter pre {
    font-size: 12.5px;
    padding: .8rem .85rem;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  body.lesson-page .chapter .box { padding: .85rem .9rem; }
  body.lesson-page .chapter .box p,
  body.lesson-page .chapter .box li { font-size: 15px; }
  body.lesson-page .figure svg { width: 100%; height: auto; }

  /* The fixed sign-in pill sat on top of the prose. It belongs to
     the hub and the book index, not to a page you are reading. */
  body.lesson-page #auth-widget { display: none; }

  body.lesson-page #lab-progress { display: none; }
  body.lesson-page #mark-complete-btn {
    width: auto; flex: 0 0 auto; padding: 8px 11px; font-size: 10.5px; white-space: nowrap;
  }
}

/* Very narrow phones: give the prose every pixel. */
@media (max-width: 400px) {
  body.lesson-page .chapter-main { padding-left: .8rem; padding-right: .8rem; }
  body.lesson-page .chapter p,
  body.lesson-page .chapter li { font-size: 16.5px; }
}

/* ── The book index and hub on a phone ── */
@media (max-width: 720px) {
  .journey { padding: 0 1rem; }
  .journey::before { left: calc(1rem + 15px); }
  .vol { padding-left: 2.9rem; }
  .station-head, .st-prog { padding-left: .9rem; padding-right: .9rem; }
  .steps { padding: .35rem .4rem .6rem; }
  .step { padding: .55rem .5rem; }
  .step-tag { display: none; }          /* the colour of the row already says it */
  .step.completed .step-n::after { content: ' ✓'; color: var(--green); }
  .bk-title { font-size: 1.7rem; }
  .bk-intro { font-size: 13px; }
  .bk-stats { gap: 1.4rem; }
  .bk-cta { width: 100%; justify-content: center; }
}

/* ══════════════════════════════════════════════════════════════
   ROADMAPS — curated study paths as a lit spine.
   Same visual language as the book index's "journey": a numbered
   node column, per-stage stations, resources as steps in sequence.
   The one addition is a per-stage accent (--rm-accent / --rm-glow /
   --rm-tint) set by an .rm-accent-* class — never an inline style.
   Data lives in roadmaps.json; the generator owns the markup.
   ══════════════════════════════════════════════════════════════ */

.roadmaps-page, .roadmap-page { background: var(--bg); }

/* ── Index hero ── */
.rm-hero { max-width: 820px; margin: 0 auto; padding: 3rem 1.5rem 1.4rem; text-align: center; }
.rm-hero .hub-back-link { display: inline-block; margin-bottom: 1.2rem; }
.rm-hero-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--cyan-dim); margin-bottom: 0.5rem;
}
.rm-hero-title { font-size: 2.2rem; font-weight: 800; letter-spacing: -0.02em; color: var(--text); }
.rm-hero-title span { color: var(--cyan); }
.rm-hero p {
  color: var(--text-dim); font-size: 13.5px; max-width: 62ch; margin: 0.8rem auto 0; line-height: 1.7;
}

/* ── Index grid + hub-panel cards ── */
.rm-index {
  max-width: 960px; margin: 0.6rem auto 0; padding: 1rem 1.5rem 4rem;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem;
}
.rm-card {
  display: block; position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 1.1rem 1.2rem; transition: border-color 0.15s, transform 0.15s;
}
.rm-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, var(--gold), transparent);
}
.rm-card:hover { border-color: var(--border-bright); transform: translateY(-2px); }
.rm-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem; }
.rm-card-title { font-size: 1.05rem; font-weight: 700; color: var(--text); }
.rm-card-done { font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: var(--muted); }
.rm-card-done.started { color: var(--green); }
.rm-card-tagline { font-size: 12px; color: var(--text-dim); line-height: 1.5; margin: 0.35rem 0 0.7rem; }
.rm-card .hub-card-bar { margin-bottom: 0.5rem; }
.rm-card-meta { font-family: var(--font-mono); font-size: 10px; color: var(--muted); letter-spacing: 0.05em; }
.rm-card.curriculum-complete { border-color: rgba(57,255,20,0.4); }

/* ── Per-stage accent tokens (solid / glow / tint) ── */
.rm-accent-green    { --rm-accent: var(--green);    --rm-glow: rgba(57,255,20,0.45);  --rm-tint: rgba(57,255,20,0.10); }
.rm-accent-cyan     { --rm-accent: var(--cyan);     --rm-glow: rgba(0,212,255,0.45);  --rm-tint: rgba(0,212,255,0.10); }
.rm-accent-cyan-dim { --rm-accent: var(--cyan-dim); --rm-glow: rgba(0,153,187,0.45);  --rm-tint: rgba(0,153,187,0.10); }
.rm-accent-gold     { --rm-accent: var(--gold);     --rm-glow: rgba(245,166,35,0.45); --rm-tint: rgba(245,166,35,0.11); }
.rm-accent-red      { --rm-accent: var(--red);      --rm-glow: rgba(255,70,85,0.45);  --rm-tint: rgba(255,70,85,0.10); }
.rm-accent-purple   { --rm-accent: var(--purple);   --rm-glow: rgba(168,85,247,0.45); --rm-tint: rgba(168,85,247,0.10); }
.rm-accent-muted    { --rm-accent: var(--muted);    --rm-glow: rgba(107,114,128,0.4); --rm-tint: rgba(107,114,128,0.10); }

/* ── The spine (mirrors .journey) ── */
.rm-spine { max-width: 940px; margin: 2.2rem auto 4rem; padding: 0 2rem; position: relative; }
.rm-spine::before {
  content: ''; position: absolute; left: calc(2rem + 15px); top: 16px; bottom: 40px; width: 2px;
  background: linear-gradient(180deg, var(--border-bright) 0%, var(--border) 100%);
}
.rm-stage { position: relative; padding-left: 3.4rem; margin-bottom: 1.5rem; }
.rm-stage .vol-dot {
  position: absolute; left: 4px; top: 6px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--bg); border: 2px solid var(--rm-accent); display: flex; align-items: center;
  justify-content: center; font-family: var(--font-mono); font-size: 9px; font-weight: 700;
  color: var(--rm-accent); box-shadow: 0 0 14px var(--rm-glow); z-index: 1;
}

/* Station carries the stage's accent (mirrors .station's lit look). */
.rm-station {
  border: 1px solid var(--rm-accent); border-radius: var(--radius-lg); overflow: hidden;
  background: radial-gradient(ellipse at 12% 0%, var(--rm-tint), transparent 62%), var(--surface);
}
.rm-station .station-head { padding: 1.1rem 1.3rem 0.9rem; border-bottom: 1px solid var(--border); }
.rm-station .st-kicker { color: var(--rm-accent); }
.rm-kicker-tag { color: var(--text-muted); }
.rm-station .st-t { font-size: 1.25rem; }
.rm-station .st-build { color: var(--cyan); margin-top: 0.5rem; }
.rm-station .st-prog { padding: 0.8rem 1.3rem; border-bottom: 1px solid var(--border); background: rgba(0,0,0,0.16); }
.rm-station .st-bar i { background: linear-gradient(90deg, var(--rm-accent), var(--cyan)); }
.rm-station .st-next b { color: var(--rm-accent); font-weight: 600; }
.rm-stage.volume-complete .rm-station { border-color: rgba(57,255,20,0.5); }
.rm-stage.volume-complete .vol-dot { border-color: var(--green); color: var(--green); box-shadow: 0 0 14px rgba(57,255,20,0.4); }

/* ── Resources as steps (mirrors .step) ── */
.rm-steps { padding: 0.5rem 0.7rem 0.8rem; }
.rm-step {
  display: grid; grid-template-columns: 22px 54px 1fr auto; gap: 0.75rem; align-items: start;
  padding: 0.6rem 0.7rem; border-radius: var(--radius); cursor: pointer;
  border: 1px solid transparent; transition: background 0.15s, border-color 0.15s;
}
.rm-step:hover { background: var(--surface2); border-color: var(--border); }
.rm-step + .rm-step { border-top: 1px solid rgba(255,255,255,0.04); border-radius: 0; }
.rm-step:hover + .rm-step, .rm-step:hover { border-radius: var(--radius); }

.rm-res-check {
  margin-top: 1px; width: 20px; height: 20px; border-radius: 5px;
  border: 1px solid var(--border-bright); background: var(--surface2);
  color: var(--green); font-size: 12px; font-weight: 700; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: all 0.15s; font-family: var(--font-body); flex: none;
}
.rm-res-check:hover { border-color: var(--green); }
.rm-step.completed .rm-res-check { background: rgba(57,255,20,0.15); border-color: rgba(57,255,20,0.5); }
.rm-step.completed .step-t { color: var(--text-dim); }

.rm-res-badge {
  font-family: var(--font-mono); font-size: 8.5px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; text-align: center; padding: 3px 0; border-radius: 4px;
  margin-top: 1px; border: 1px solid; align-self: start;
}
.rm-b-book { color: var(--cyan);   border-color: rgba(0,212,255,0.35);  background: rgba(0,212,255,0.08); }
.rm-b-htb  { color: var(--purple); border-color: rgba(168,85,247,0.35); background: rgba(168,85,247,0.08); }
.rm-b-web  { color: var(--green);  border-color: rgba(57,255,20,0.3);   background: rgba(57,255,20,0.08); }
.rm-b-lab  { color: var(--gold);   border-color: rgba(245,166,35,0.35); background: rgba(245,166,35,0.08); }
.rm-b-done { color: var(--muted);  border-color: var(--border-bright);  background: var(--surface2); }

.rm-step .step-body { min-width: 0; }
.rm-step .step-t { font-size: 13px; }
.rm-step .step-t a { color: var(--text); }
.rm-step .step-t a:hover { color: var(--gold); }
.rm-res-seq { font-family: var(--font-mono); color: var(--muted); font-weight: 600; margin-right: 0.4rem; }
.rm-ext { font-family: var(--font-mono); font-size: 0.66rem; color: var(--green); margin-left: 0.35rem; font-weight: 600; }
.rm-step .step-s { color: var(--text-dim); }
.rm-step .step-tag { align-self: center; }

/* ── Lab setup block ── */
.rm-res-setup {
  margin-top: 0.5rem; border: 1px solid var(--border); border-left: 2px solid var(--gold);
  background: var(--surface2); border-radius: var(--radius); padding: 0.55rem 0.7rem;
}
.rm-setup-h {
  font-family: var(--font-mono); font-size: 8.5px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 0.35rem;
}
.rm-res-setup ul { list-style: none; display: flex; flex-direction: column; gap: 0.28rem; }
.rm-res-setup li {
  font-size: 0.75rem; color: var(--text-dim); line-height: 1.45; padding-left: 0.9rem; position: relative;
}
.rm-res-setup li::before { content: '▹'; position: absolute; left: 0; color: var(--gold); font-size: 0.7rem; }
.rm-res-setup li b { color: var(--text); font-weight: 600; }
.rm-res-setup li code {
  font-family: var(--font-mono); font-size: 0.72rem; background: var(--bg);
  padding: 0.05rem 0.3rem; border-radius: 3px; color: var(--cyan);
}

@media (max-width: 640px) {
  .rm-hero-title { font-size: 1.8rem; }
  .rm-spine { padding: 0 1rem; }
  .rm-spine::before { left: calc(1rem + 15px); }
  .rm-stage { padding-left: 2.8rem; }
  .rm-step { grid-template-columns: 20px 48px 1fr; gap: 0.5rem; }
  .rm-step .step-tag { display: none; }
}

/* ══════════════════════════════════════════════════════════════
   UI RESET (2026-08) — Hub G "Library × Console" + Chapter D
   The hub is a cover grid over console chrome; the chapter page is
   a reading column with the volume map behind a ☰ drawer.
   ══════════════════════════════════════════════════════════════ */

/* ── Hub: frame ── */
.hg-wrap { max-width: 1080px; margin: 0 auto; padding: 1.8rem 1.2rem 4rem; }
.hg-head { display: flex; align-items: baseline; gap: 1rem; border-bottom: 1px solid var(--border); padding-bottom: 1.1rem; flex-wrap: wrap; }
.hg-logo { font-family: var(--font-mono); font-weight: 700; font-size: 1.05rem; color: var(--gold); }
.hg-logo::before { content: "▞ "; color: var(--cyan); }
.hg-tag { font-family: var(--font-mono); font-size: .64rem; color: var(--muted); letter-spacing: .1em; }
.hg-stats { margin-left: auto; display: flex; gap: 1.3rem; font-family: var(--font-mono); font-size: .64rem; color: var(--text-dim); }
.hg-stats b { color: var(--green); font-weight: 600; }
.hg-sec { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .22em; text-transform: uppercase; color: var(--text-dim); margin: 2rem 0 .9rem; display: flex; gap: .8rem; align-items: center; }
.hg-sec b { color: var(--text); }
.hg-sec::after { content: ""; flex: 1; height: 1px; background: var(--border); order: 9; }
.hg-sec-n { color: var(--muted); letter-spacing: 0; }
.hg-sec-link { color: var(--cyan); letter-spacing: 0; text-decoration: none; }
.hg-foot { margin-top: 3rem; font-family: var(--font-mono); font-size: .62rem; color: var(--muted); line-height: 1.8; }

/* ── Hub: resume panel (filled by app.js into #hub-continue) ── */
#hub-continue:empty { display: none; }
#hub-continue { margin: 1.4rem 0 0; }
#hub-continue .hub-chips { display: flex; gap: .5rem; margin-bottom: .6rem; flex-wrap: wrap; }
#hub-continue .hub-resume {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  border: 1px solid var(--border); border-left: 3px solid var(--gold); border-radius: var(--radius-lg);
  background: var(--surface); padding: .9rem 1.1rem; text-decoration: none; color: var(--text);
  font-size: .9rem; font-weight: 600;
}
#hub-continue .hub-resume:hover { background: var(--surface2); }
#hub-continue .hub-resume .cta-play { color: var(--gold); }
#hub-continue .hub-resume-lesson { font-family: var(--font-mono); font-size: .68rem; color: var(--text-dim); font-weight: 400; }

/* ── Hub: cover grid ── */
.hg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)); gap: 1rem; }
.hg-book { min-width: 0; text-decoration: none; color: inherit; display: block; }
.hg-cover {
  aspect-ratio: 5 / 7; border-radius: 5px; position: relative; overflow: hidden;
  border: 1px solid var(--border); display: flex; flex-direction: column;
  justify-content: space-between; padding: .65rem .6rem;
  transition: transform .15s, box-shadow .15s, border-color .15s;
}
a.hg-book:hover .hg-cover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0,0,0,.55); border-color: var(--hg-ac); }
.hg-series { font-family: var(--font-mono); font-size: .48rem; letter-spacing: .18em; color: rgba(232,232,240,.55); text-transform: uppercase; position: relative; z-index: 1; }
.hg-cv-foot { position: relative; z-index: 1; display: block; }
.hg-bt { font-weight: 800; font-size: .92rem; line-height: 1.14; color: #fff; text-shadow: 0 1px 6px rgba(0,0,0,.5); display: block; }
.hg-vt { font-family: var(--font-mono); font-size: .5rem; color: rgba(232,232,240,.7); margin-top: .18rem; display: block; }
.hg-motif { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .5; pointer-events: none; }
.hg-meta { margin-top: .5rem; font-family: var(--font-mono); font-size: .6rem; color: var(--text-dim); display: flex; justify-content: space-between; gap: .4rem; }
.hg-st { color: var(--hg-ac, var(--muted)); }
.hg-st.started { color: var(--green); }
.hg-prog { display: block; height: 3px; border-radius: 99px; background: var(--surface2); overflow: hidden; margin-top: .35rem; }
.hg-prog .hub-card-bar-fill { display: block; height: 100%; width: 0; background: var(--hg-ac, var(--gold)); }
.hg-book.plan .hg-cover { opacity: .45; filter: saturate(.5); }
.hg-book.plan .hg-meta { color: var(--muted); }

/* accents + cover gradients */
.ac-gold   { --hg-ac: var(--gold); }
.ac-cyan   { --hg-ac: var(--cyan); }
.ac-green  { --hg-ac: var(--green); }
.ac-red    { --hg-ac: var(--red); }
.ac-purple { --hg-ac: var(--purple); }
.cv-gold   { background: linear-gradient(160deg, #3b2a10, #14100a 70%); }
.cv-cyan   { background: linear-gradient(160deg, #083344, #0a1016 70%); }
.cv-green  { background: linear-gradient(160deg, #123a1a, #0a140c 70%); }
.cv-red    { background: linear-gradient(160deg, #4a1220, #160a0e 70%); }
.cv-purple { background: linear-gradient(160deg, #331a52, #120a1c 70%); }
.cv-plain  { background: linear-gradient(160deg, #20202e, #101018 70%); }

/* ── Hub: project book cards ── */
.hg-projrow { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.hg-projrow + .hg-grid { margin-top: 1rem; }
.hg-proj {
  display: flex; gap: 1rem; border: 1px solid var(--border); border-left: 3px solid var(--hg-ac);
  border-radius: var(--radius-lg); background: var(--surface); padding: .9rem;
  text-decoration: none; color: inherit; transition: border-color .14s;
}
a.hg-proj:hover { border-color: var(--hg-ac); }
.hg-pcover { width: 86px; min-width: 86px; height: 120px; border-radius: 4px; overflow: hidden; border: 1px solid var(--border-bright); position: relative; display: flex; flex-direction: column; justify-content: space-between; padding: .55rem .5rem; }
.hg-pcover .hg-bt { font-size: .8rem; }
.hg-pbody { min-width: 0; display: block; }
.hg-pcap { font-family: var(--font-mono); font-size: .56rem; letter-spacing: .2em; text-transform: uppercase; color: var(--hg-ac); display: block; }
.hg-pt { font-weight: 800; font-size: 1.05rem; margin: .25rem 0 .3rem; display: block; }
.hg-pd { font-size: .76rem; color: var(--text-dim); line-height: 1.55; display: block; }
.hg-pfoot { font-family: var(--font-mono); font-size: .6rem; color: var(--muted); margin-top: .5rem; display: block; }

@media (max-width: 720px) { .hg-projrow { grid-template-columns: 1fr; } .hg-stats { display: none; } }
@media (max-width: 520px) { .hg-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: .75rem; } }

/* The old chrome made body a flex column; under Chapter D the page is a
   normal document flow (a flex item's min-width:auto let long <pre> lines
   widen .page-grid past the viewport on phones). */
body.lesson-page { display: block; }

/* ── Chapter D: topbar ── */
.toc-toggle { position: absolute; opacity: 0; pointer-events: none; }
.tb { position: sticky; top: 0; background: rgba(10,10,15,.93); backdrop-filter: blur(8px); border-bottom: 1px solid var(--border); z-index: 120; }
.tb-in { max-width: 1160px; margin: 0 auto; display: flex; align-items: center; gap: .9rem; padding: .6rem 1.2rem; font-family: var(--font-mono); font-size: .7rem; }
.tb-in a { color: var(--text-dim); text-decoration: none; white-space: nowrap; }
.tb-in a:hover { color: var(--text); }
.tb-book { color: var(--gold) !important; }
.tb-vol { color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.tb-toc { border: 1px solid var(--border); background: var(--surface); color: var(--text-dim); border-radius: var(--radius); padding: .35rem .6rem; cursor: pointer; white-space: nowrap; }
.tb-toc:hover { border-color: var(--gold); color: var(--gold); }
.tb-prog { margin-left: auto; display: flex; align-items: center; gap: .55rem; color: var(--text-dim); white-space: nowrap; }
.tb-bar { width: 90px; height: 4px; border-radius: 99px; background: var(--surface2); overflow: hidden; display: inline-block; }
.tb-bar i { display: block; height: 100%; width: 0; background: var(--gold); }

/* ── Chapter D: drawer ── */
.drawer {
  position: fixed; top: 0; bottom: 0; left: 0; width: min(320px, 86vw);
  background: var(--surface); border-right: 1px solid var(--border);
  transform: translateX(-102%); transition: transform .22s ease; z-index: 140;
  padding: 1.2rem; overflow-y: auto;
}
.toc-toggle:checked ~ .drawer { transform: none; }
.drawer-scrim { position: fixed; inset: 0; background: rgba(0,0,0,.5); opacity: 0; pointer-events: none; transition: opacity .2s; z-index: 130; }
.toc-toggle:checked ~ .drawer-scrim { opacity: 1; pointer-events: auto; }
.dr-book { font-weight: 800; margin-bottom: .15rem; }
.dr-sub { font-family: var(--font-mono); font-size: .62rem; color: var(--text-dim); margin-bottom: 1rem; line-height: 1.5; }
.dr-vol { margin-bottom: .3rem; }
.dr-vol summary { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); cursor: pointer; padding: .45rem .3rem; list-style: none; display: flex; justify-content: space-between; gap: .6rem; }
.dr-vol summary::-webkit-details-marker { display: none; }
.dr-vol[open] summary { color: var(--gold); }
.dr-vol .volume-progress { color: var(--muted); }
.dr-vol a { display: flex; gap: .5rem; align-items: baseline; font-size: .8rem; color: var(--text-dim); text-decoration: none; padding: .3rem .3rem .3rem .8rem; border-radius: 4px; }
.dr-vol a:hover { background: var(--surface2); color: var(--text); }
.dr-vol a.now { color: var(--text); background: var(--surface2); border-left: 2px solid var(--gold); }
.dr-tick { font-family: var(--font-mono); font-size: .64rem; color: var(--green); width: .9rem; min-width: .9rem; display: inline-block; }
.dr-vol a:not(.completed) .dr-tick::before { content: "○"; color: var(--border-bright); }
.dr-vol a.completed .dr-tick::before { content: none; }

/* ── Chapter D: page ── */
.page-grid { max-width: 1160px; margin: 0 auto; padding: 0 1.2rem; }
.chapter-col { display: block; }
.ch-head { max-width: var(--ch-measure, 78ch); margin: 2.4rem auto 0; padding: 0 2.5rem; }
.ch-num { font-family: var(--font-mono); font-size: .68rem; letter-spacing: .25em; color: var(--gold); text-transform: uppercase; }
.ch-title { font-size: clamp(1.55rem, 4.5vw, 2.15rem); font-weight: 800; letter-spacing: -.02em; margin: .5rem 0 .4rem; line-height: 1.16; color: var(--text); }

/* the reading column now scrolls with the page, not inside itself */
.lesson-page .chapter-main { overflow-y: visible; padding-top: 1.2rem; }
.lesson-page .chapter-rail { position: sticky; top: 4rem; align-self: start; max-height: calc(100vh - 5rem); overflow-y: auto; }

/* ── Chapter D: complete + pager + foot ── */
.ch-done { max-width: var(--ch-measure, 78ch); margin: 2rem auto 0; padding: 0 2.5rem; }
#mark-complete-btn {
  width: 100%; padding: .8rem; border-radius: var(--radius);
  border: 1px solid rgba(57,255,20,.35); background: rgba(57,255,20,.06);
  color: var(--green); font-family: var(--font-mono); font-size: .72rem; letter-spacing: .08em;
  font-weight: 600; cursor: pointer; transition: background .15s;
}
#mark-complete-btn:hover { background: rgba(57,255,20,.14); }
#mark-complete-btn.done { background: rgba(57,255,20,.15); border-color: rgba(57,255,20,.5); }
#mark-complete-btn:disabled { opacity: .5; cursor: default; }
#lab-progress { margin-top: .5rem; font-family: var(--font-mono); font-size: .66rem; color: var(--text-dim); text-align: center; }
.pager { max-width: 1160px; margin: 2.6rem auto 0; padding: 0 1.2rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.pager a { border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 1rem 1.2rem; text-decoration: none; color: var(--text); min-width: 0; display: block; }
.pager a:hover { border-color: var(--gold); }
.pg-dir { font-family: var(--font-mono); font-size: .6rem; color: var(--muted); letter-spacing: .15em; text-transform: uppercase; display: block; }
.pg-t { font-weight: 700; margin-top: .3rem; font-size: .9rem; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg-next { text-align: right; }
.ch-foot { text-align: center; font-family: var(--font-mono); font-size: .62rem; color: var(--muted); margin: 3rem 0 2.5rem; }

@media (max-width: 640px) {
  .tb-vol, .tb-toc-word, .tb-home { display: none; }
  .tb-in { gap: .6rem; }
  .ch-head, .ch-done { padding: 0 1.2rem; }
  .lesson-page .chapter-main { padding-left: 1.2rem; padding-right: 1.2rem; }
  .pager { grid-template-columns: 1fr; }
  .pg-next { text-align: left; }
}
@media print {
  .tb, .drawer, .drawer-scrim, .pager, .ch-done, #auth-widget { display: none !important; }
  .ch-title, .ch-num { color: #111; }
}

/* The auth widget used to float top-right; under the new chrome that corner
   belongs to the topbar progress / hub stats, so it lives bottom-right. */
#auth-widget { top: auto; bottom: 12px; }
