/* ═══════════════════════════════════════════════════════════════════════════
   ATENA LESSON SYSTEM — shared token layer + component recipes.

   Every lesson file imports ONLY this sheet and shared/lesson.js. Lessons may
   add ≤120 lines of lesson-specific CSS in a local <style> block; anything a
   second lesson would want belongs here instead.

   Tokens mirror the ATENA design system (css/design-system.css) so a lesson
   dropped next to the app reads as the same product. Values are re-declared
   rather than imported because lessons must render standalone and offline.

   ⚠️  THAT MIRROR IS MANUAL, AND IT DRIFTED. This sheet sat on the PRE-2026-08-15
   palette (#22c55e accent, pure-red negative, 8/12/16 radii, the 11-16px type
   scale) for the whole platform refresh, so all 320 lesson files rendered the
   old product while every other page rendered the new one. Re-synced
   2026-08-15. When css/design-system.css §1 changes, THIS BLOCK CHANGES TOO —
   nothing enforces it.

   No webfont network request: the stacks below degrade to system faces so a
   lesson opened with no connection still sets correctly.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ─────────────────────────────────────────────────────────── */
:root {
  /* colour — ONE green, semantic reds/ambers only where meaning is real */
  --bg:            #030f0a;
  --bg-elevated:   #05140d;
  --surface:       linear-gradient(155deg, rgba(255,255,255,0.14), rgba(255,255,255,0.035) 46%, rgba(255,255,255,0.06));
  --surface-raised:linear-gradient(155deg, rgba(255,255,255,0.18), rgba(255,255,255,0.055) 46%, rgba(255,255,255,0.08));
  /* --surface-inset is the design-system NAME; --surface-inner is this sheet's
     older alias for it. The alias is kept (and kept canonical-by-value) because
     416 declarations across the 320 lesson files already say
     var(--surface-inner) — renaming would break every one of them. New rules
     here should use --surface-inset so the mirror reads like the real sheet. */
  --surface-inset: rgba(2,12,8,0.34);
  --surface-inner: var(--surface-inset);
  --border:        rgba(150,255,205,0.20);
  --border-strong: rgba(150,255,205,0.40);
  --hairline:      rgba(150,255,205,0.11);

  --text:           #e9f6ef;
  --text-secondary: #bfdfd0;
  --text-muted:     #8fab9e;

  --accent:        #19e07f;
  --accent-bright: #7ff5c0;
  --accent-dim:    rgba(25,224,127,0.13);
  --positive:      #19e07f;
  --negative:      #ff5f7a;
  --warning:       #ffc857;

  /* space — 4px scale, nothing off-scale */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px;
  --s6:24px; --s8:32px; --s10:40px; --s12:48px; --s16:64px;

  /* radius — three values + pill. --r-xl is an alias of --r-lg, exactly as in
     css/design-system.css, so a recipe copied across in either direction keeps
     resolving. */
  --r-sm:10px; --r-md:14px; --r-lg:20px; --r-xl:20px; --r-full:999px;

  /* type */
  --fs-xs:12px; --fs-sm:13px; --fs-base:14px; --fs-md:15px; --fs-lg:17px;
  --fs-xl:21px; --fs-2xl:26px; --fs-3xl:34px; --fs-display:42px;
  --lh-tight:1.25; --lh-snug:1.4; --lh-base:1.55; --lh-loose:1.7;
  --font-sans:'Outfit','Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'SFMono-Regular',Menlo,monospace;
  --caps-tracking:0.12em;

  /* elevation */
  --e1:0 2px 8px rgba(0,0,0,0.34);
  --e2:0 18px 50px rgba(0,0,0,0.42);
  --e3:0 36px 100px rgba(0,0,0,0.56);
  --glass:blur(22px) saturate(180%) brightness(1.08);
  /* The signature Verdant bevel + gleam. These were MISSING from the mirror,
     which is why .ds-card here (same class name as the app's) rendered with a
     single flat white hairline instead of the specular-top / shaded-bottom /
     green-haze edge every card in the app has. A lesson opened next to the app
     read as a different, older product — the exact drift this sheet warns about. */
  --glass-bevel:
    inset 0 1px 1px rgba(255,255,255,0.30),
    inset 0 -1px 1px rgba(0,0,0,0.18),
    inset 0 0 56px rgba(127,245,192,0.035);
  --glass-glow:0 0 48px rgba(25,224,127,0.16);
  --glass-pane:linear-gradient(180deg, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0.05) 34%, rgba(255,255,255,0) 55%);
  --ds-title-glow:0 0 16px rgba(127,245,192,0.55);

  /* motion — four durations, two easings. Also missing from the mirror: the
     lesson components had invented .12s/.18s/.3s/.42s/.45s/.5s/.55s/.6s with
     three different easing curves, so a hover in a lesson had a different
     rhythm from the identical hover in the app. */
  --d1:120ms; --d2:220ms; --d3:380ms; --d4:800ms;
  --ease:cubic-bezier(.2,.8,.2,1);
  --ease-out:cubic-bezier(.16,1,.3,1);

  /* reading measure */
  --measure:68ch;
  --shell:940px;
}

/* ── 1b. LIGHT THEME ───────────────────────────────────────────────────────
   Lessons had NO light theme at all. The toggle worked and set
   html[data-theme="light"] exactly as it does everywhere else — there was
   simply nothing here listening for it, so every one of the 320 lesson pages
   stayed on the dark palette while the rest of the site flipped around them.

   This sheet is the mirror of css/design-system.css and uses the same token
   NAMES, so the fix is a straight transcription of that file's light block
   (LIGHT V2). Values are written out as literals rather than as var(--emerald)
   / var(--frost) / var(--stroke), because those primitives live in the design
   system and are not defined here — an alias would have resolved to nothing
   and silently fallen back to the dark value.

   --surface-inner is deliberately absent: :root already defines it as
   var(--surface-inset), and custom properties resolve at computed-value time,
   so overriding --surface-inset below carries the alias with it.

   Known limit, measured rather than guessed: the 319 lesson-local <style>
   blocks hold 4,774 hardcoded colour literals (4,317 rgba, 457 hex), mostly
   white-over-dark overlays in the decorative "signature" illustrations. Those
   do not read these tokens and are unaffected by this block. Page chrome,
   prose, cards, quiz and nav all flip; individual lesson artwork may still
   assume a dark canvas. That tail is item M6b, not silently "done". */
html[data-theme="light"] {
  --bg:             #dde4de;
  --bg-elevated:    #f4f7f4;
  --surface:        linear-gradient(155deg, #fbfcfa, #f5f8f5 55%, #f2f5f2);
  --surface-raised: linear-gradient(155deg, #fdfefc, #f8faf7 55%, #f5f8f5);
  --surface-inset:  rgba(6,35,26,0.055);
  --border:         rgba(0,80,54,0.24);
  --border-strong:  rgba(0,80,54,0.36);
  --hairline:       rgba(0,70,46,0.13);

  --text:           #0a2419;
  --text-secondary: #2b4a3d;
  --text-muted:     #3f6154;

  --accent:         #00734b;
  --accent-bright:  #005f40;
  --accent-dim:     #e8f4ee;
  --positive:       #00734b;
  --negative:       #ba2d4b;
  --warning:        #7d5a00;

  /* Short + tight. A large soft shadow over a tinted ground reads as grime. */
  --e1: 0 1px 2px rgba(6,35,26,0.07);
  --e2: 0 2px 6px rgba(6,35,26,0.07), 0 8px 24px rgba(6,35,26,0.06);
  --e3: 0 4px 12px rgba(6,35,26,0.09), 0 20px 56px rgba(6,35,26,0.09);

  /* The brightness(1.08) lift is dropped: it exists to make a translucent pane
     glow against near-black. On paper it just washes the page out. */
  --glass: blur(18px) saturate(120%);
  --glass-bevel:
    inset 0 1px 1px rgba(255,255,255,0.92),
    inset 0 -1px 1px rgba(6,35,26,0.10),
    inset 0 0 60px rgba(0,121,79,0.025);
  /* A 48px bloom of dark green on paper is a smudge, not a glow. */
  --glass-glow: 0 2px 10px rgba(0,121,79,0.14), 0 0 0 1px rgba(0,121,79,0.10);
  /* The white top-film over every pane is white-on-white here — removed. */
  --glass-pane: none;
  --ds-title-glow: none;
}

/* ── 2. RESET + PAGE ───────────────────────────────────────────────────── */
*,*::before,*::after { box-sizing:border-box; }
html { -webkit-text-size-adjust:100%; }
body {
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--font-sans);
  font-size:var(--fs-lg);
  line-height:var(--lh-base);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,svg { max-width:100%; }
button { font:inherit; color:inherit; }

/* page glow — fixed radial greens, top + corner, subtle */
body::before,body::after {
  content:''; position:fixed; pointer-events:none; z-index:0;
}
body::before {
  inset:0;
  background:radial-gradient(1100px 560px at 62% -12%, rgba(25,224,127,0.09), transparent 62%);
}
body::after {
  right:-10%; bottom:-18%; width:70vw; height:60vh;
  background:radial-gradient(closest-side, rgba(25,224,127,0.055), transparent 72%);
}

/* ── 3. SHELL + BEAT RHYTHM ────────────────────────────────────────────── */
.lx-shell {
  position:relative; z-index:1;
  max-width:var(--shell);
  margin:0 auto;
  padding:var(--s8) var(--s5) var(--s16);
}
.lx-beat { margin-top:var(--s16); }
.lx-beat:first-of-type { margin-top:var(--s12); }

/* kicker: mono step number + green-caps label */
.lx-kicker {
  display:flex; align-items:center; gap:var(--s3);
  margin-bottom:var(--s3);
}
.lx-step {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-sm); font-weight:600;
  color:var(--accent); opacity:0.85;
}
.lx-step::after {
  content:''; display:inline-block; width:18px; height:1px;
  background:var(--border-strong); vertical-align:middle; margin-left:var(--s3);
}

/* the two title roles — nothing else */
/* fs-sm → fs-md and 600 → 700, plus the title glow: css/design-system.css made
   exactly this change platform-wide (its Round 2 note — uppercase letter-spaced
   titles read lighter than the values under them) and the mirror never got it,
   so lesson widget titles were a step smaller and a weight lighter than the
   identical titles in the app. */
.ds-title {
  font-family:var(--font-sans); font-size:var(--fs-md); font-weight:700;
  color:var(--accent-bright); text-transform:uppercase;
  letter-spacing:var(--caps-tracking); margin:0;
  text-shadow:var(--ds-title-glow);
}
.ds-title--plain {
  font-family:var(--font-sans); font-size:var(--fs-md); font-weight:700;
  color:var(--text); text-transform:none; letter-spacing:normal; margin:0;
}

.lx-h2 {
  font-size:var(--fs-2xl); font-weight:700; line-height:var(--lh-snug);
  margin:0 0 var(--s3); text-wrap:balance; letter-spacing:-0.01em;
}
.lx-sub {
  max-width:64ch; margin:0 0 var(--s5);
  color:var(--text-secondary); font-size:var(--fs-lg); line-height:var(--lh-base);
}
.lx-prose { max-width:var(--measure); line-height:var(--lh-loose); }
.lx-prose p { margin:0 0 var(--s4); }

/* every number is mono + tabular */
/* text-shadow added to match css/design-system.css §4 — "numbers representing
   money/data carry a soft glow". font-size is deliberately NOT copied from the
   app recipe: lesson files set their own sizes on .ds-value in their local
   <style> blocks and a size here would fight 320 of them for no visual gain. */
.ds-value,.lx-num {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  letter-spacing:-0.01em;
  text-shadow:0 0 24px rgba(127,245,192,0.25);
}
.ds-pos{color:var(--positive);} .ds-neg{color:var(--negative);} .ds-warn{color:var(--warning);}
.lx-em { color:var(--accent-bright); font-style:normal; }

/* ── 4. CARD RECIPES ───────────────────────────────────────────────────── */
/* Kept byte-for-byte in step with the .ds-card recipe in css/design-system.css:
   two background layers (the top gleam over the glass pane), the signature
   bevel, the brighter lit top edge, and the hover bloom. It previously had the
   pane but no gleam, a single flat `inset 0 1px 0` instead of the bevel, a
   dimmer top edge and NO hover state at all — so the same class name rendered
   two visibly different cards depending on whether you were in the app or in
   one of the 320 lesson files. */
.ds-card {
  background:var(--glass-pane), var(--surface);
  backdrop-filter:var(--glass); -webkit-backdrop-filter:var(--glass);
  border:1px solid var(--border);
  border-top-color:rgba(255,255,255,0.30);
  border-radius:var(--r-md);
  box-shadow:var(--e2), var(--glass-bevel);
  padding:var(--s4);
  min-width:0;
  transition:box-shadow var(--d3) var(--ease), border-color var(--d3) var(--ease);
}
.ds-card:hover { box-shadow:var(--e2), var(--glass-bevel), var(--glass-glow); border-color:var(--border-strong); }
.ds-card--lg { border-radius:var(--r-xl); padding:var(--s5); box-shadow:var(--e3), var(--glass-bevel); }
.ds-card--dense { padding:var(--s3); }
.ds-card-inner {
  background:var(--surface-inner);
  border:1px solid var(--hairline);
  border-radius:var(--r-sm);
  box-shadow:inset 0 2px 6px rgba(0,0,0,0.35);
  padding:var(--s3); min-width:0;
}
.ds-card-head {
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--s3); margin-bottom:var(--s3); flex-wrap:wrap;
}

/* ── 5. BUTTONS + CHIPS ────────────────────────────────────────────────── */
.lx-btn {
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
  min-height:44px; padding:0 var(--s5);
  border-radius:var(--r-full); border:1px solid var(--border-strong);
  background:var(--surface-raised); color:var(--text);
  font-size:var(--fs-md); font-weight:600; cursor:pointer;
  transition:background var(--d2) var(--ease), border-color var(--d2) var(--ease), transform var(--d1) var(--ease);
}
.lx-btn:hover { border-color:var(--accent); }
.lx-btn:active { transform:translateY(1px); }
.lx-btn--primary { background:var(--accent); border-color:var(--accent); color:#04140a; }
.lx-btn--primary:hover { background:var(--accent-bright); border-color:var(--accent-bright); }
.lx-btn--ghost { background:transparent; }
.lx-btn[disabled] { opacity:.45; cursor:not-allowed; }

.lx-chip {
  display:inline-flex; align-items:center; gap:var(--s2);
  min-height:44px; padding:0 var(--s4);
  border-radius:var(--r-full); border:1px solid var(--border);
  background:var(--surface-inner); color:var(--text-secondary);
  font-size:var(--fs-md); font-weight:500; cursor:pointer;
  transition:color var(--d2) var(--ease), border-color var(--d2) var(--ease), background var(--d2) var(--ease);
}
.lx-chip:hover { color:var(--text); border-color:var(--border-strong); }
/* THE one active look (css/design-system.css §5): solid emerald→mint gradient,
   dark ink, glow. This was the accent-dim wash + accent text that the design
   system calls out by name as "the platform's second competing active look" and
   removed from every selection control in the app — .lx-chip was the last place
   still rendering it, and only because this mirror is hand-maintained.
   .lx-opt (the quiz answer) is deliberately NOT touched: its is-right/is-wrong
   states carry correctness, and a green fill on mere selection would pre-empt
   the grading. */
.lx-chip[aria-pressed="true"] {
  color:#03140c; font-weight:700; border-color:transparent;
  background:linear-gradient(120deg, var(--accent), var(--accent-bright));
  box-shadow:0 0 20px rgba(25,224,127,0.45), inset 0 1px 1px rgba(255,255,255,0.6);
}
.lx-chip-row { display:flex; flex-wrap:wrap; gap:var(--s2); }

/* ── 6. ROWS, BADGES, BARS ─────────────────────────────────────────────── */
.lx-row {
  display:flex; align-items:center; justify-content:space-between; gap:var(--s3);
  padding:var(--s3) 0; border-bottom:1px solid var(--hairline);
}
.lx-row:last-child { border-bottom:0; }
.lx-row-label { color:var(--text-secondary); font-size:var(--fs-md); min-width:0; }

.lx-badge {
  display:inline-flex; align-items:center; gap:var(--s1);
  padding:var(--s1) var(--s2); border-radius:var(--r-sm);
  border:1px solid var(--border); background:var(--accent-dim);
  font-family:var(--font-mono); font-size:var(--fs-xs); font-variant-numeric:tabular-nums;
  color:var(--accent-bright); text-transform:uppercase; letter-spacing:.04em;
}
.lx-badge--neg { color:var(--negative); border-color:rgba(255,95,122,0.34); background:rgba(255,95,122,0.10); }
.lx-badge--warn{ color:var(--warning);  border-color:rgba(245,158,11,0.34); background:rgba(245,158,11,0.10); }

.lx-bar {
  position:relative; height:8px; border-radius:var(--r-full);
  background:rgba(255,255,255,0.05); overflow:hidden;
}
.lx-bar-fill {
  position:absolute; inset:0 auto 0 0; width:0;
  border-radius:var(--r-full); background:var(--accent);
  transition:width .5s var(--ease), background var(--d3) var(--ease);
}
.lx-bar-fill.is-warn { background:var(--warning); }
.lx-bar-fill.is-neg  { background:var(--negative); }

/* ── 7. STAT GRID (hero stats + sim readouts) ──────────────────────────── */
.lx-stats { display:flex; flex-wrap:wrap; gap:var(--s5) var(--s8); }
.lx-stat-label {
  display:block; font-size:var(--fs-xs); color:var(--text-muted);
  text-transform:uppercase; letter-spacing:var(--caps-tracking); margin-bottom:var(--s1);
}
.lx-stat-value {
  display:block; font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-xl); font-weight:600; color:var(--text); line-height:1.1;
}
.lx-stat-value.is-accent { color:var(--accent-bright); }

/* ── 8. RANGE INPUT ────────────────────────────────────────────────────── */
.lx-range {
  -webkit-appearance:none; appearance:none;
  width:100%; height:44px; background:transparent; cursor:pointer; margin:0;
}
.lx-range::-webkit-slider-runnable-track {
  height:6px; border-radius:var(--r-full);
  background:linear-gradient(90deg,var(--accent) var(--pct,0%),rgba(255,255,255,0.07) var(--pct,0%));
}
.lx-range::-moz-range-track {
  height:6px; border-radius:var(--r-full);
  background:linear-gradient(90deg,var(--accent) var(--pct,0%),rgba(255,255,255,0.07) var(--pct,0%));
}
.lx-range::-webkit-slider-thumb {
  -webkit-appearance:none; appearance:none;
  width:22px; height:22px; margin-top:-8px; border-radius:50%;
  background:var(--accent-bright); border:2px solid #04140a;
  box-shadow:0 0 0 1px var(--accent), 0 2px 8px rgba(0,0,0,0.5);
}
.lx-range::-moz-range-thumb {
  width:22px; height:22px; border-radius:50%;
  background:var(--accent-bright); border:2px solid #04140a;
  box-shadow:0 0 0 1px var(--accent), 0 2px 8px rgba(0,0,0,0.5);
}
.lx-range:focus-visible { outline:2px solid var(--accent-bright); outline-offset:4px; }

/* ── 9. FLIP CARDS (definition beat) ───────────────────────────────────── */
.lx-flips { display:grid; gap:var(--s4); grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); }
/* display:grid (not block) so .lx-flip-in stretches to the button's own height.
   .lx-flips stretches every button in a row to the tallest one, and without
   this the three cards in a row would draw three different card heights inside
   three equal-height buttons. No percentage height is involved, so there is no
   circular sizing to get wrong. */
.lx-flip {
  position:relative; display:grid; width:100%; padding:0; border:0; background:none;
  cursor:pointer; perspective:1200px; text-align:left;
}
/* ⚠️ Round 4 #46 — the revealed text used to run out of the bottom of the card
   and over whatever sat under it (client screenshot P2-13, reproduced at
   1400px: back faces measured 239 / 260 / 302px of content inside a 168px box,
   i.e. 71 / 92 / 134px spilling past the border and across the next heading).
   The cause was structural, not a missing overflow rule: BOTH faces were
   `position:absolute; inset:0`, so neither contributed height, and the card's
   only height source was the flat `min-height:170px` below. The back face —
   title + payoff + a full paragraph — is always taller than that, and 319
   lesson files use this component, so every one of them carried the defect.

   Fix: stack the two faces in the SAME grid cell instead of taking them out of
   flow. A grid row is as tall as its tallest item, so the card now sizes to
   whichever face needs more room, both faces stretch to that height (so the
   flip does not resize mid-turn), and min-height survives as a floor rather
   than as the only measurement. Clipping the overflow instead would have been
   the wrong fix — it hides the sentence rather than showing it. */
.lx-flip-in {
  display:grid; position:relative; width:100%; min-height:170px;
  transition:transform .55s var(--ease); transform-style:preserve-3d;
}
.lx-flip[aria-pressed="true"] .lx-flip-in { transform:rotateY(180deg); }
.lx-flip-face {
  grid-area:1 / 1; min-width:0;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
  display:flex; flex-direction:column; justify-content:space-between; gap:var(--s3);
  border-radius:var(--r-md); padding:var(--s4);
  background:var(--surface); border:1px solid var(--border);
  box-shadow:var(--e2), var(--glass-bevel);
}
/* A single unbroken token (a hash, a long contract address) in a note is the
   one thing left that could still push a face wider than its column. */
.lx-flip-claim, .lx-flip-note, .lx-flip-payoff { overflow-wrap:anywhere; }
.lx-flip-face--back { transform:rotateY(180deg); background:var(--surface-raised); border-color:var(--accent); }
.lx-flip-claim { font-size:var(--fs-lg); font-weight:600; line-height:var(--lh-snug); text-wrap:balance; }
.lx-flip-payoff {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-2xl); font-weight:600; color:var(--accent-bright); line-height:1.1;
}
.lx-flip-note { font-size:var(--fs-md); color:var(--text-secondary); line-height:var(--lh-snug); }
.lx-flip-hint {
  font-size:var(--fs-xs); color:var(--text-muted);
  text-transform:uppercase; letter-spacing:var(--caps-tracking);
}
.lx-flip:focus-visible { outline:2px solid var(--accent-bright); outline-offset:4px; border-radius:var(--r-md); }

/* ── 10. SCROLL STRIP (context beat) ───────────────────────────────────── */
.lx-strip {
  display:flex; gap:var(--s4); overflow-x:auto; padding-bottom:var(--s3);
  scroll-snap-type:x mandatory; scrollbar-width:thin;
}
.lx-strip > * { scroll-snap-align:start; flex:0 0 min(78vw,260px); }
.lx-strip::-webkit-scrollbar { height:6px; }
.lx-strip::-webkit-scrollbar-thumb { background:var(--border); border-radius:var(--r-full); }

/* ── 11. QUIZ ──────────────────────────────────────────────────────────── */
.lx-quiz-head {
  display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--s3); margin-bottom:var(--s4); flex-wrap:wrap;
}
.lx-quiz-score {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-md); color:var(--text-secondary);
}
.lx-quiz-q { font-size:var(--fs-xl); font-weight:600; line-height:var(--lh-snug); margin:0 0 var(--s4); text-wrap:balance; }
.lx-quiz-opts { display:grid; gap:var(--s2); }
.lx-opt {
  display:flex; align-items:center; gap:var(--s3);
  width:100%; min-height:44px; padding:var(--s3) var(--s4);
  border-radius:var(--r-sm); border:1px solid var(--border);
  background:var(--surface-inner); color:var(--text);
  font-size:var(--fs-md); text-align:left; cursor:pointer;
  transition:border-color var(--d2) var(--ease), background var(--d2) var(--ease), color var(--d2) var(--ease);
}
.lx-opt:hover:not([disabled]) { border-color:var(--border-strong); background:var(--surface-raised); }
.lx-opt:focus-visible { outline:2px solid var(--accent-bright); outline-offset:2px; }
.lx-opt-key {
  flex:0 0 auto; width:24px; height:24px; border-radius:var(--r-sm);
  display:grid; place-items:center;
  font-family:var(--font-mono); font-size:var(--fs-xs); font-weight:600;
  background:rgba(255,255,255,0.05); color:var(--text-muted);
}
.lx-opt.is-right { border-color:var(--accent); background:var(--accent-dim); color:var(--accent-bright); }
.lx-opt.is-right .lx-opt-key { background:var(--accent); color:#04140a; }
.lx-opt.is-wrong { border-color:var(--negative); background:rgba(255,95,122,0.10); color:var(--negative); }
.lx-opt.is-wrong .lx-opt-key { background:var(--negative); color:#1a0505; }
.lx-opt[disabled] { cursor:default; }

.lx-explain {
  margin-top:var(--s4); padding:var(--s3) var(--s4);
  border-left:2px solid var(--accent); border-radius:0 var(--r-sm) var(--r-sm) 0;
  background:var(--surface-inner);
  font-size:var(--fs-md); color:var(--text-secondary); line-height:var(--lh-base);
}
.lx-explain.is-wrong { border-left-color:var(--negative); }
.lx-quiz-foot { display:flex; justify-content:flex-end; margin-top:var(--s5); }

.lx-result { text-align:center; padding:var(--s5) 0; }
.lx-result-score {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-display); font-weight:700; color:var(--accent-bright); line-height:1;
}
.lx-result-rank { font-size:var(--fs-xl); font-weight:700; margin:var(--s4) 0 var(--s2); }
.lx-result-note { color:var(--text-secondary); max-width:46ch; margin:0 auto var(--s5); }
.lx-result-acts { display:flex; flex-wrap:wrap; gap:var(--s3); justify-content:center; }

/* ── 11b. LESSON-TO-LESSON NAV ─────────────────────────────────────────── */
/* Appended to .lx-shell by lesson.js. Three columns so the position readout
   stays centred no matter how long the two lesson titles are. */
.lx-nav {
  display:grid; grid-template-columns:1fr auto 1fr; align-items:stretch;
  gap:var(--s3); margin-top:var(--s16);
  padding-top:var(--s8); border-top:1px solid var(--border);
}
.lx-nav-link {
  display:flex; flex-direction:column; justify-content:center; gap:var(--s1);
  min-height:64px; padding:var(--s3) var(--s5);
  border:1px solid var(--border); border-radius:var(--r-lg);
  background:var(--surface-raised); color:var(--text); text-decoration:none;
  transition:border-color var(--d2) var(--ease), background var(--d2) var(--ease), transform var(--d1) var(--ease);
}
.lx-nav-link:hover { border-color:var(--accent); background:var(--surface-inner); }
.lx-nav-link:active { transform:translateY(1px); }
.lx-nav-link--next { grid-column:3; text-align:right; align-items:flex-end; }
.lx-nav-dir {
  font-size:var(--fs-xs); font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--text-muted);
}
.lx-nav-link--next .lx-nav-dir { color:var(--accent); }
.lx-nav-title { font-size:var(--fs-md); font-weight:600; line-height:var(--lh-tight); }
.lx-nav-count {
  display:flex; align-items:center; align-self:center; gap:var(--s1);
  padding:0 var(--s3);
  font-size:var(--fs-sm); color:var(--text-muted); white-space:nowrap;
}

/* ── 12. MOTION ────────────────────────────────────────────────────────── */
.lx-reveal { opacity:0; transform:translateY(18px); }
.lx-reveal.is-in {
  opacity:1; transform:none;
  transition:opacity .6s var(--ease), transform .6s var(--ease);
}
@keyframes lx-shake {
  0%,100%{transform:translateX(0)} 20%{transform:translateX(-7px)}
  40%{transform:translateX(6px)} 60%{transform:translateX(-4px)} 80%{transform:translateX(2px)}
}
.lx-shake { animation:lx-shake .42s cubic-bezier(.36,.07,.19,.97); }

@media (prefers-reduced-motion: reduce) {
  *,*::before,*::after {
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
  /* end states must remain — only the travel to them is removed */
  .lx-reveal { opacity:1; transform:none; }
}

/* ── 12b. COMPARISON BARS (two quantities, same track scale) ───────────── */
.lx-cmp { display:grid; gap:var(--s4); }
.lx-cmp-row { display:grid; grid-template-columns:136px 1fr; gap:var(--s3); align-items:center; }
.lx-cmp-k { font-size:var(--fs-sm); color:var(--text-secondary); }
.lx-cmp-k small { display:block; color:var(--text-muted); font-size:var(--fs-xs); }
.lx-cmp-track {
  position:relative; height:26px; border-radius:var(--r-sm);
  background:rgba(255,255,255,0.05); overflow:hidden;
}
.lx-cmp-fill {
  position:absolute; inset:0 auto 0 0; width:0; border-radius:var(--r-sm);
  background:linear-gradient(90deg, rgba(25,224,127,0.34), var(--accent));
  transition:width .45s var(--ease), background var(--d3) var(--ease);
}
.lx-cmp-fill.is-warn { background:linear-gradient(90deg, rgba(245,158,11,0.30), var(--warning)); }
.lx-cmp-fill.is-neg  { background:linear-gradient(90deg, rgba(255,95,122,0.30), var(--negative)); }
.lx-cmp-n {
  position:absolute; right:var(--s3); top:50%; transform:translateY(-50%);
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-md); font-weight:600; color:var(--text);
}

/* ── 12c. TWO-SYSTEM COMPARE ───────────────────────────────────────────── */
/* both sides get identical structure — neither may look "better" by styling */
.lx-grid2 { display:grid; gap:var(--s4); grid-template-columns:1fr 1fr; }
.lx-side-head {
  display:flex; align-items:center; gap:var(--s2);
  padding-bottom:var(--s2); margin-bottom:var(--s3);
  border-bottom:1px solid var(--hairline);
}

/* ── 12d. GAUGE ROW (a named thing scored on a bar) ────────────────────── */
.lx-gauge { display:grid; gap:var(--s2); padding:var(--s3) 0; border-bottom:1px solid var(--hairline); }
.lx-gauge:last-child { border-bottom:0; }
.lx-gauge-top { display:flex; align-items:baseline; justify-content:space-between; gap:var(--s3); }
.lx-gauge-name { font-size:var(--fs-md); color:var(--text); }
.lx-gauge-verdict {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-sm); color:var(--text-muted); text-align:right;
}
.lx-gauge-verdict.is-good { color:var(--accent-bright); }
.lx-gauge-verdict.is-warn { color:var(--warning); }
.lx-gauge-verdict.is-bad  { color:var(--negative); }

/* ── 12e. STEPPER (walk a sequence, one state at a time) ───────────────── */
.lx-stepnav { display:flex; gap:var(--s2); flex-wrap:wrap; margin-bottom:var(--s5); }
.lx-stepdot {
  min-height:44px; padding:0 var(--s4);
  border-radius:var(--r-full); border:1px solid var(--border);
  background:var(--surface-inner); color:var(--text-muted);
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:var(--fs-sm); font-weight:600; cursor:pointer;
  transition:color var(--d2) var(--ease), border-color var(--d2) var(--ease), background var(--d2) var(--ease);
}
.lx-stepdot:hover { color:var(--text); border-color:var(--border-strong); }
.lx-stepdot[aria-current="true"] {
  color:var(--accent-bright); border-color:var(--accent); background:var(--accent-dim);
}
.lx-stepdot.is-seen { color:var(--text-secondary); }

/* ── 12f. LEDGER / PATH ROWS (ordered hops with a live state) ───────────── */
.lx-hop { display:flex; align-items:center; gap:var(--s3); padding:var(--s3) 0; border-bottom:1px solid var(--hairline); }
.lx-hop:last-child { border-bottom:0; }
.lx-hop-dot {
  flex:0 0 auto; width:10px; height:10px; border-radius:50%;
  background:var(--text-muted); transition:background var(--d3) var(--ease), box-shadow var(--d3) var(--ease);
}
.lx-hop.is-on .lx-hop-dot { background:var(--accent); box-shadow:0 0 0 4px rgba(25,224,127,0.16); }
.lx-hop.is-warn .lx-hop-dot { background:var(--warning); box-shadow:0 0 0 4px rgba(255,200,87,0.16); }
.lx-hop.is-bad .lx-hop-dot { background:var(--negative); box-shadow:0 0 0 4px rgba(255,95,122,0.18); }
.lx-hop-txt { color:var(--text-muted); font-size:var(--fs-md); transition:color var(--d3) var(--ease); min-width:0; }
.lx-hop.is-on .lx-hop-txt, .lx-hop.is-warn .lx-hop-txt, .lx-hop.is-bad .lx-hop-txt { color:var(--text); }
.lx-hop-tag { margin-left:auto; flex:0 0 auto; }

/* ── 13. RESPONSIVE (down to 360px) ────────────────────────────────────── */
@media (max-width:720px) {
  .lx-shell { padding:var(--s6) var(--s4) var(--s12); }
  .lx-beat { margin-top:var(--s12); }
  .lx-h2 { font-size:var(--fs-xl); }
  .lx-sub,.lx-prose { font-size:var(--fs-md); }
  .lx-stats { gap:var(--s4) var(--s6); }
  .lx-flips { grid-template-columns:1fr; }
  .lx-grid2 { grid-template-columns:1fr; }
}
@media (max-width:520px) {
  .lx-cmp-row { grid-template-columns:1fr; gap:var(--s1); }
  /* Next first: at this width it's the action people actually reach for.
     Flex, not grid — the explicit order has to override DOM order, which
     puts "previous" first. */
  .lx-nav { display:flex; flex-direction:column; }
  .lx-nav-link--next { order:1; text-align:left; align-items:flex-start; }
  .lx-nav-count { order:2; justify-content:center; }
  .lx-nav-link:not(.lx-nav-link--next) { order:3; }
}
@media (max-width:400px) {
  .lx-shell { padding-left:var(--s3); padding-right:var(--s3); }
  .lx-stat-value { font-size:var(--fs-lg); }
  .lx-result-score { font-size:var(--fs-3xl); }
}

/* ── 14. A11Y UTILITIES ────────────────────────────────────────────────── */
.lx-sr {
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
:where(a,button,input,[tabindex]):focus-visible {
  outline:2px solid var(--accent-bright); outline-offset:3px; border-radius:var(--r-sm);
}

/* ── 15. BETA / UNTRANSLATED NOTICE ─────────────────────────────────────── */
/* Shown by shared/lesson.js when a learner has chosen a language this lesson
   has not been translated into yet, so they understand why the page in front
   of them is English rather than assuming the language switch failed.
   Injected at runtime — no lesson file carries this markup. */
.lx-i18n-note {
  display:flex; gap:var(--s3); align-items:flex-start;
  margin:0 0 var(--s6);
  padding:var(--s3) var(--s4);
  background:var(--surface-inner);
  border:1px solid var(--hairline);
  border-left:3px solid var(--warning);
  border-radius:var(--r-md);
  color:var(--text-secondary);
  font-size:var(--fs-sm); line-height:var(--lh-snug);
}
.lx-i18n-note-tag {
  flex:0 0 auto;
  font-size:var(--fs-xs); font-weight:700;
  letter-spacing:var(--caps-tracking); text-transform:uppercase;
  color:var(--warning);
  padding-top:1px;
}
.lx-i18n-note-text { flex:1 1 auto; }
/* RTL locales flip the accent edge with the text direction. */
.lx-i18n-note[dir="rtl"] {
  border-left:1px solid var(--hairline);
  border-right:3px solid var(--warning);
}

/* ═══════════════════════════════════════════════════════════════════════════
   §16 · THE LESSON OVERVIEW  (30 Sep 2026)

   A lesson's first page. Replaces the 27 Sep "Before you start" preface card,
   which sat above a lesson that was already on screen: now the lesson opens
   on this overview alone and its content appears when the reader presses
   Continue. Built by renderOverview() in shared/lesson.js from the lesson's
   OWN beats, so all 167 lessons and every locale get one without a line in
   any lesson file. The look is AC Learning's "Start here" card
   (css/learn.css .ll-feat) one level down: orientation on the left, the
   numbered "What you'll learn" list on the right, one column below 900px.
   ═══════════════════════════════════════════════════════════════════════════ */

/* THE GATE. Everything in the shell except the overview, the back-link and
   the beta notice is out of sight — display:none, so out of the
   accessibility tree too — until Continue removes .is-overview. */
.lx-shell.is-overview > :not(.lx-overview):not(.lx-ov-keep):not(.lx-i18n-note) { display: none !important; }
.lx-overview[hidden] { display: none !important; }

.lx-overview {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s6);
  margin: var(--s6) 0 var(--s10);
  padding: var(--s6);
  background: var(--ds-glass-pane, var(--glass-pane)), var(--surface);
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--border));
  border-radius: var(--r-lg);
  box-shadow: var(--e2), var(--glass-bevel);
}
@media (min-width: 900px) {
  /* Equal columns (1 Oct 2026): each step now carries a 1–2 sentence
     description, and at 1.3fr:1 the list ran twice as tall as the summary. */
  .lx-overview { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s6) var(--s8); padding: var(--s8); }
  .lx-ov-side { border-left: 1px solid var(--hairline); padding-left: var(--s6); }
  .lx-ov-foot { grid-column: 1 / -1; }
}
.lx-ov-main { min-width: 0; }
.lx-ov-badge {
  display: inline-block; padding: 4px 12px; border-radius: var(--r-full);
  background: var(--accent); color: var(--bg-elevated);
  font-family: var(--font-sans); font-size: 10px; font-weight: 700;
  letter-spacing: var(--caps-tracking); text-transform: uppercase;
}
.lx-ov-ctx {
  margin: var(--s4) 0 2px;
  font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: 600;
  letter-spacing: var(--caps-tracking); text-transform: uppercase;
  color: var(--text-muted);
}
.lx-ov-title {
  margin: var(--s2) 0 var(--s3);
  font-family: var(--font-sans);
  font-size: clamp(26px, 3.4vw, 38px); font-weight: 800; line-height: 1.08;
  letter-spacing: -0.02em; color: var(--text); text-wrap: balance;
}
.lx-ov-sub {
  margin: 0 0 var(--s5); max-width: 54ch;
  font-size: var(--fs-md); line-height: var(--lh-base); color: var(--text-secondary);
}
.lx-ov-meta { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.lx-ov-m {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-sans); font-size: var(--fs-xs); color: var(--text-secondary);
}
.lx-ov-m svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--accent); }
.lx-ov-k {
  margin: 0 0 var(--s4);
  font-family: var(--font-sans); font-size: 10px; font-weight: 700;
  letter-spacing: var(--caps-tracking); text-transform: uppercase;
  color: var(--accent);
}
.lx-ov-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s4); }
.lx-ov-list li { display: flex; align-items: flex-start; gap: var(--s3); }
.lx-ov-n {
  flex: 0 0 auto; width: 22px; height: 22px; display: grid; place-items: center;
  border-radius: var(--r-full); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-muted);
}
.lx-ov-li { display: grid; gap: 2px; min-width: 0; }
.lx-ov-lt { font-family: var(--font-sans); font-size: var(--fs-base); font-weight: 600; color: var(--text); line-height: var(--lh-snug); }
.lx-ov-ld {
  font-family: var(--font-sans); font-size: var(--fs-sm); line-height: var(--lh-snug);
  color: var(--text-muted);
  /* Never clamped (1 Oct 2026): each line is a written 1–2 sentence
     description of the step, and a cut-off one read as a broken page. */
}
.lx-ov-foot {
  display: flex; justify-content: flex-end;
  padding-top: var(--s5); border-top: 1px solid var(--hairline);
}
.lx-ov-go { min-width: 160px; color: var(--bg-elevated); }
.lx-ov-go::after { content: ' →'; }
[dir="rtl"] .lx-ov-go::after { content: ' ←'; }
@media (max-width: 520px) {
  .lx-overview { padding: var(--s5); }
  .lx-ov-go { width: 100%; }
}
/* The lesson heading takes focus on Continue; it is a landing point, not a
   control, so it gets no ring when focus arrives by script. */
.lx-beat h1[tabindex="-1"]:focus:not(:focus-visible) { outline: none; }
