/* =============================================================
   SHARED.CSS — GSL Foundations Revision App
   Theme tokens · Typography · Footer · Motion · TTS · Drills
   Locked infrastructure. RE-SKIN (go RESKIN, 2026-05-23): warm
   editorial design language ported from reskin-preview-home.html.
   Fonts: Fraunces (display + italic accents) · Manrope (body) ·
   JetBrains Mono (labels). Loaded centrally below so every page
   that links this file inherits them — no per-page font <link>.

   THREE THEMES (slug → look). The slug keys are kept stable so the
   collision-safe per-page boot scripts (data-theme="pitch") need no
   edits; only the palettes change. Default is the warm CREAM look:
     · pitch  → Cream     (light · DEFAULT — the preview look)
     · bone   → Espresso  (warm dark · for low-light study)
     · dusk   → Dusk      (warm twilight · between the two)
   To rename the slugs later, find/replace pitch|bone|dusk app-wide
   (CSS + each page's boot script + shared.js THEMES array).
   Accent: terracotta #b8632a · gilt gold #c8a45c.
   ============================================================= */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;0,9..144,700;1,9..144,400;1,9..144,500;1,9..144,600&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');

/* ---------- FONT FAMILIES (theme-independent) ---------- */
:root {
  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body:    'Manrope', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'JetBrains Mono', 'IBM Plex Mono', 'Menlo', monospace;
  /* Bottom offset for the right-edge floating rail (theme-switcher + jump
     button). One shared var keeps them stacked without overlap, lifts them
     clear of the centred TTS bar on mobile, and respects notched devices.
     (go UX-2 — fixes floating-button overlap + mobile collision.) */
  --rail-bottom: calc(16px + env(safe-area-inset-bottom));
}

/* ---------- THEME TOKENS ---------- */
/* Default: PITCH slug → CREAM (warm light) — verbatim from the preview */
:root, :root[data-theme="pitch"] {
  --bg:         #f3ede1;
  --bg-elev:    #fbf6ec;
  --bg-sunk:    #ece3d1;
  --ink:        #1b1612;
  --ink-2:      #3d3228;
  --ink-muted:  #7a6a58;
  --hairline:   rgba(27,22,18,0.10);
  --hairline-2: rgba(27,22,18,0.18);
  --accent:     #b8632a;
  --hl:         rgba(245, 201, 80, 0.55);   /* user highlighter — warm marker yellow on cream */
  --accent-2:   #8a5a2b;
  --gold:       #c8a45c;
  --name:       #8a5a2b;   /* story names — legible on cream (gold #c8a45c fails contrast here) */
  --cta:        #1b1612;
  --cta-ink:    #f3ede1;
  --danger:     #c2402a;
  --success:    #5b7a1d;
  --grain-opacity: 0.04;
  --radial-1: rgba(200,164,92,0.28);
  --radial-2: rgba(184,99,42,0.14);
  --tts-hl:   color-mix(in srgb, var(--gold) 22%, transparent); /* sentence-being-read highlight */
}

/* BONE slug → ESPRESSO (warm dark) — deep roasted brown for low light */
:root[data-theme="bone"] {
  --bg:         #1c1510;
  --bg-elev:    #272019;
  --bg-sunk:    #120c08;
  --ink:        #f1e7d6;
  --ink-2:      #d7c9b1;
  --ink-muted:  #b4a489;   /* go UX-2: lifted from #9a8b75 — captions/labels now clear in the dark */
  --hairline:   rgba(241,231,214,0.15);  /* go UX-2: was 0.09 — card edges & dividers were invisible */
  --hairline-2: rgba(241,231,214,0.26);  /* go UX-2: was 0.17 */
  --accent:     #db8b4e;
  --hl:         rgba(232, 172, 92, 0.40);   /* user highlighter — amber wash, readable on dark */
  --accent-2:   #eca96c;
  --gold:       #d9b46a;
  --name:       #e6bd80;   /* story names — brighter than gold so they pop on espresso */
  --cta:        #db8b4e;
  --cta-ink:    #1c1510;
  --danger:     #e8745a;
  --success:    #9dbf59;
  --grain-opacity: 0.04;   /* go UX-2: was 0.06 — lighter texture keeps dark surfaces clean */
  --radial-1: rgba(217,180,106,0.16);
  --radial-2: rgba(219,139,78,0.12);
  --tts-hl:   color-mix(in srgb, var(--gold) 30%, transparent); /* go UX-2: stronger on dark so the read line is obvious */
}

/* DUSK slug → DUSK (warm twilight) — a lifted mid-tone between cream and espresso */
:root[data-theme="dusk"] {
  --bg:         #2e2620;
  --bg-elev:    #3a302a;
  --bg-sunk:    #221b16;
  --ink:        #f1e7d8;
  --ink-2:      #d6c8b4;
  --ink-muted:  #bba98e;   /* go UX-2: lifted from #a3937d */
  --hairline:   rgba(241,231,216,0.15);  /* go UX-2: was 0.10 */
  --hairline-2: rgba(241,231,216,0.27);  /* go UX-2: was 0.18 */
  --accent:     #d4844a;
  --hl:         rgba(226, 168, 100, 0.42);  /* user highlighter — amber wash for twilight */
  --accent-2:   #e6a86c;
  --gold:       #d6af68;
  --name:       #e4b673;   /* story names — pop on dusk */
  --cta:        #d4844a;
  --cta-ink:    #2e2620;
  --danger:     #e87d62;
  --success:    #a6c264;
  --grain-opacity: 0.035;  /* go UX-2: was 0.05 */
  --radial-1: rgba(214,175,104,0.18);
  --radial-2: rgba(212,132,74,0.12);
  --tts-hl:   color-mix(in srgb, var(--gold) 30%, transparent); /* go UX-2 */
}

/* ---------- RESET ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }   /* go JUMP-X: removed scroll-behavior:smooth — it re-animated every JS scroll step and fought the reading-follow + jump (the shake). Discrete UI jumps pass behavior:'smooth' explicitly. */
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  min-height: 100dvh;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  transition: background 500ms cubic-bezier(0.22,1,0.36,1),
              color    500ms cubic-bezier(0.22,1,0.36,1);
  padding-bottom: env(safe-area-inset-bottom);
}
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
img, svg { display: block; max-width: 100%; }

/* ---------- TYPOGRAPHY ---------- */
h1, h2, h3, .display-text {
  font-family: var(--font-display);
  font-weight: 600;
  font-optical-sizing: auto;
  letter-spacing: -0.018em;
  line-height: 1.1;
}
h1 { font-size: clamp(2.1rem, 5.5vw, 3.8rem); line-height: 1.04; }
h2 { font-size: clamp(1.55rem, 3.5vw, 2.4rem); }
h3 { font-size: clamp(1.2rem, 2.5vw, 1.65rem); }
/* Editorial italic accent — the preview's signature move. Scoped to
   display headings only so the .gold colour utility stays plain elsewhere. */
h1 em, h2 em, h3 em,
h1 .gold, h2 .gold, h3 .gold {
  font-style: italic;
  font-weight: 500;
}

.body-text { font-family: var(--font-body); font-size: 16px; line-height: 1.65; }
.caption { font-family: var(--font-mono); font-size: 12px; color: var(--ink-muted); letter-spacing: 0.04em; text-transform: uppercase; }
.gold { color: var(--gold); }

/* ---------- ATMOSPHERE: radials + grain ---------- */
.bg-fx {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(ellipse 80% 50% at 15% 10%, var(--radial-1), transparent 60%),
    radial-gradient(ellipse 60% 60% at 90% 85%, var(--radial-2), transparent 60%);
  transition: background 500ms ease;
}
.grain {
  position: fixed; inset: 0; pointer-events: none; z-index: 1;
  opacity: var(--grain-opacity);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  mix-blend-mode: multiply;
}

/* ---------- SCROLL PROGRESS BAR ---------- */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
  height: 3px;
  background: transparent;
}
.scroll-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width 60ms linear;
}

/* ---------- ANNOUNCE BANNER (neutral, optional) ----------
   Replaces the old campaign vote-banner. A generic dismissible
   strip for app-wide notices (e.g. "Exam in 31 days"). Empty by
   default — populate per page only if needed. */
.announce-banner {
  position: fixed; top: 3px; left: 0; right: 0; z-index: 999;
  background: var(--accent);
  color: var(--cta-ink);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
  padding: 6px 40px 6px 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  transition: transform 300ms ease, opacity 300ms ease;
}
.announce-banner.hidden { transform: translateY(-120%); opacity: 0; pointer-events: none; }
.announce-banner-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.announce-banner-close {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(0,0,0,0.15);
  font-size: 14px; line-height: 1; cursor: pointer;
}
.announce-banner-close:hover { background: rgba(0,0,0,0.3); }

/* ---------- FOOTER SIGNATURE ---------- */
.footer-signature {
  position: relative;
  background: var(--bg-sunk);
  border-top: 1px solid var(--hairline);
  padding: 40px 20px 32px;
  text-align: center;
  font-family: var(--font-mono);
  margin-top: 80px;
}
.footer-primary {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.5vw, 1.45rem);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 6px;
}
.footer-secondary {
  font-size: 12px;
  color: var(--ink-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 16px;
}
.footer-links {
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 13px;
}
/* go LOCK-IN — post-election initiative dedication (Constitution §13).
   Sits above .footer-links / the iCann credit. Quiet, dignified, italic;
   a dedication line, never a campaign banner. */
.footer-initiative {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  opacity: 0.85;
  margin-bottom: 14px;
}
.footer-links a { color: var(--ink-muted); }
.footer-links a:hover { color: var(--accent); }

/* ---------- CONTACT & FEEDBACK CHANNEL (go UX-4) ----------
   Redesigned per owner review: the channel is now a FLOATING MESSAGE BUTTON
   (.contact-fab, in the shared .floating-action rail) that opens a bottom-sheet
   popup (.cc-*) with a WhatsApp action and a button to the Google form. Built
   and injected by shared.js, so it reaches the FROZEN cp-ch1.html and every
   page. The old footer pills are retired; the footer adinkra is hidden below. */

/* The floating message button — distinct from the page-nav (.floatnav-toggle)
   by its accent ring, marking it as the "talk to us" control. Reuses .fab-btn
   for size/hover/active, so it themes + animates like the rest of the rail. */
.contact-fab { border: 1.5px solid var(--accent); color: var(--accent); }
.contact-fab svg { width: 22px; height: 22px; }

/* The popup — a bottom sheet over a dimmed backdrop, mirroring the owner's
   reference. position:fixed is correct here (real app, not the visualizer). */
.cc-overlay {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity 220ms ease;
}
.cc-overlay.open { opacity: 1; pointer-events: auto; }
.cc-overlay[hidden] { display: none; }
.cc-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.45); }
.cc-sheet {
  position: relative;
  width: 100%; max-width: 520px;
  background: var(--bg-elev);
  border: 1px solid var(--hairline);
  border-bottom: none;
  border-radius: 22px 22px 0 0;
  padding: 14px 22px calc(26px + env(safe-area-inset-bottom));
  box-shadow: 0 -18px 50px rgba(0,0,0,0.28);
  transform: translateY(100%);
  transition: transform 320ms cubic-bezier(0.22,1,0.36,1);
}
.cc-overlay.open .cc-sheet { transform: translateY(0); }
.cc-grab {
  width: 42px; height: 4px; border-radius: 999px;
  background: var(--hairline-2);
  margin: 2px auto 14px;
}
.cc-close {
  position: absolute; top: 14px; right: 16px;
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bg-sunk); color: var(--ink-muted);
  border: 1px solid var(--hairline);
  transition: color 160ms ease, border-color 160ms ease;
}
.cc-close:hover { color: var(--accent); border-color: var(--accent); }
.cc-title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 5vw, 1.7rem);
  font-weight: 600; color: var(--ink);
  margin: 0 0 8px;
}
.cc-intro {
  font-family: var(--font-body);
  font-size: 14px; line-height: 1.6; color: var(--ink-muted);
  margin: 0 0 18px; max-width: 42ch;
}
.cc-btn {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; padding: 15px 16px;
  border-radius: 14px;
  font-family: var(--font-body); font-size: 15px; font-weight: 600;
  text-decoration: none; cursor: pointer;
  border: 1px solid transparent;
  transition: transform 160ms ease, background 160ms ease,
              color 160ms ease, border-color 160ms ease;
}
.cc-btn + .cc-btn { margin-top: 11px; }
.cc-btn:active { transform: scale(0.985); }
/* Primary: WhatsApp brand green (instantly recognisable, self-contained). */
.cc-wa { background: #25d366; color: #06351b; }
.cc-wa:hover { background: #1fbd5b; }
.cc-wa svg { color: #06351b; }
/* Secondary: the Google form — calm accent-tinted surface. */
.cc-form {
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elev));
  color: var(--accent);
  border-color: var(--accent);
}
.cc-form:hover { background: color-mix(in srgb, var(--accent) 16%, var(--bg-elev)); }
/* Close: the app's dark CTA, mirroring the reference "Done". */
.cc-done {
  margin-top: 16px;
  background: var(--cta); color: var(--cta-ink);
}
.cc-done:hover { background: color-mix(in srgb, var(--cta) 88%, var(--accent)); }
@media (prefers-reduced-motion: reduce) {
  .cc-overlay, .cc-sheet, .cc-btn { transition: none; }
}

/* go UX-4 — adinkra footer glyph hidden for now (owner directive). Kept in the
   stylesheet (display:none) rather than deleted, so it is a one-line revert and
   the frozen chapters' hardcoded .footer-adinkra simply stops rendering. */
.footer-adinkra {
  display: none;
}
.footer-adinkra--legacy {
  margin-top: 20px;
  opacity: 0.15;
  font-size: 36px;
  line-height: 1;
}

/* ---------- HEADER INITIATIVE RIBBON (go FIX-TTS, Constitution §13) ----------
   The post-election dedication, repeated at the TOP of every page as a film's
   opening card — visible on load, no scrolling. Injected by shared.js as the
   first child of <body>, so it reaches the FROZEN chapters too.
   · NORMAL FLOW (position: relative), so it SCROLLS AWAY with the page — it is
     NOT sticky; only .main-nav frosts/sticks (§13).
   · ~29px tall; the fixed nav's text starts ~39px down (top:3px + 36px pad), so
     the two never collide on any breakpoint.
   · One line, clamped small, letter-spacing eased on the narrowest phones, so
     the long line sits comfortably full-width on mobile without wrapping (a wrap
     would grow it into the nav).
   · Quiet and dignified — a dedication, never a banner. Mirrors .footer-initiative. */
.header-initiative {
  position: relative;
  z-index: 1;                                /* below the fixed nav (998) + progress bar (1000) */
  width: 100%;
  text-align: center;
  white-space: nowrap;                       /* keep to ONE line (it fits even at 320px) */
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(10.5px, 3.2vw, 12.5px);
  letter-spacing: 0.04em;
  line-height: 1.2;
  color: var(--ink-muted);
  opacity: 0.9;
  padding: 7px 14px 6px;                     /* top pad clears the 3px scroll-progress bar */
  background: color-mix(in srgb, var(--accent) 5%, var(--bg-sunk));
  border-bottom: 1px solid var(--hairline);
}
@media (max-width: 360px) {
  .header-initiative { letter-spacing: 0.02em; }   /* extra safety on the very narrowest screens */
}

/* ---------- NAVIGATION ---------- */
.main-nav {
  position: fixed; top: 3px; right: 0; left: 0;
  z-index: 998;
  padding: 36px 16px 10px;
  display: flex; align-items: center; justify-content: space-between;
  /* go UX-2: removed the `linear-gradient(to bottom, var(--bg) …)` top scrim
     (the "white shade" at the top of every page). The bar now rests fully
     transparent and only frosts once you scroll, matching Phase_5D. */
  background: transparent;
  pointer-events: none;
  transition: background 240ms ease, backdrop-filter 240ms ease, border-color 240ms ease;
  border-bottom: 1px solid transparent;
}
/* go UX-2: frosted bar appears only after scrolling, so headings/links stay
   legible over content without a permanent shaded band at rest. JS toggles
   `.scrolled` past ~8px. */
.main-nav.scrolled {
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  border-bottom: 1px solid var(--hairline);
}
.main-nav > * { pointer-events: auto; }
.nav-brand {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--accent);
  text-decoration: none;
  position: relative;
  z-index: 999;
}
.nav-brand em { font-style: italic; color: var(--accent); }
.nav-links { display: flex; gap: 20px; align-items: center; }
.nav-links a {
  font-family: var(--font-mono);
  font-size: 12px; letter-spacing: 0.04em;
  color: var(--ink-2); text-decoration: none;
  position: relative; padding: 4px 2px;
  transition: color 180ms ease;
}
/* a slim accent underline that grows in on hover/active — cleaner than a colour flip */
.nav-links a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1.5px;
  background: var(--accent); border-radius: 2px;
  transform: scaleX(0); transform-origin: left; transition: transform 200ms ease;
}
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--accent); }
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after { transform: scaleX(1); }
.nav-cta {
  /* go NAV-X — softer than a solid terracotta slab: an accent OUTLINE pill at
     rest that fills in on hover. Reads as a button, not a warning sign.
     inline-flex + matched padding keeps the label properly centred in the pill. */
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 55%, transparent);
  padding: 8px 16px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  letter-spacing: 0.01em; text-decoration: none !important; white-space: nowrap;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
.nav-cta::after { display: none; }   /* no underline on the pill */
.nav-cta:hover {
  background: var(--accent); color: var(--cta-ink);
  border-color: var(--accent); opacity: 1;
}
.nav-hamburger {
  display: none; width: 36px; height: 36px;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  position: relative;
  z-index: 999;
}
.nav-hamburger span {
  display: block; width: 20px; height: 2px; background: var(--ink); border-radius: 2px;
  transition: transform 300ms, opacity 200ms;
}
/* Hamburger → X transform when open */
.nav-hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-hamburger.open span:nth-child(2) { opacity: 0; }
.nav-hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
@media (max-width: 768px) {
  .nav-links { display: none; }
  .nav-hamburger { display: flex; }
  .nav-links.open {
    display: flex; flex-direction: column;
    align-items: center;
    justify-content: center;
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    padding: 80px 24px 40px;
    gap: 22px;
    z-index: 1400;
    /* solid base FIRST (guaranteed opaque, so reading content can't show
       through), with the gold glow layered on top */
    background-color: var(--bg);
    background-image: radial-gradient(ellipse 70% 50% at 50% 18%, var(--radial-1), transparent 60%);
  }
  :root[data-theme="bone"] .nav-links.open {
    background:
      radial-gradient(ellipse 70% 50% at 50% 18%, var(--radial-1), transparent 60%),
      var(--bg);
  }
  :root[data-theme="dusk"] .nav-links.open {
    background-color: var(--bg);
    background-image: radial-gradient(ellipse 70% 50% at 50% 18%, var(--radial-1), transparent 60%);
  }
  body.nav-open { overflow: hidden; }
  .nav-links.open a { font-size: 20px; letter-spacing: 0.02em; }
  .nav-links.open .nav-cta { font-size: 16px; padding: 10px 24px; }
}

/* ---------- THEME SWITCHER (pill) ---------- */
.theme-switcher {
  position: fixed; bottom: var(--rail-bottom); right: 16px; z-index: 958;
  display: flex; gap: 5px;
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  padding: 5px;
  transition: bottom 240ms cubic-bezier(0.22,1,0.36,1);
}
.theme-btn {
  width: 30px; height: 30px; border-radius: 50%;
  border: 2px solid var(--hairline); display: flex; align-items: center; justify-content: center;
  font-size: 12px; transition: all 200ms; cursor: pointer;
}
.theme-btn:hover { border-color: var(--accent); }
.theme-btn.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.theme-btn[data-theme-val="pitch"] { background: linear-gradient(135deg, #fbf6ec, #e2d3b6); } /* Cream */
.theme-btn[data-theme-val="bone"]  { background: #1c1510; }                                    /* Espresso */
.theme-btn[data-theme-val="dusk"]  { background: #2e2620; }                                    /* Dusk */

/* ---------- REVEAL ANIMATIONS ---------- */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 500ms ease-out, transform 500ms ease-out;
}
.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
/* Stagger children */
.reveal-stagger > .reveal:nth-child(1) { transition-delay: 0ms; }
.reveal-stagger > .reveal:nth-child(2) { transition-delay: 80ms; }
.reveal-stagger > .reveal:nth-child(3) { transition-delay: 160ms; }
.reveal-stagger > .reveal:nth-child(4) { transition-delay: 240ms; }
.reveal-stagger > .reveal:nth-child(5) { transition-delay: 320ms; }
.reveal-stagger > .reveal:nth-child(6) { transition-delay: 400ms; }
.reveal-stagger > .reveal:nth-child(7) { transition-delay: 480ms; }
.reveal-stagger > .reveal:nth-child(8) { transition-delay: 560ms; }

/* prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .parallax-bg { transform: none !important; }
  .scroll-progress-fill { transition: none; }
}

/* ---------- PARALLAX ---------- */
.parallax-section {
  position: relative; overflow: hidden;
}
.parallax-bg {
  position: absolute; inset: -20% 0; z-index: 0;
  background-size: cover; background-position: center;
  will-change: transform;
}
.parallax-content {
  position: relative; z-index: 2;
}

/* ---------- TTS FLOATING CONTROLLER ---------- */
.tts-sentence { cursor: default; }
body[data-tts-available="true"] .tts-sentence { cursor: pointer; }
.tts-sentence.active {
  background: var(--tts-hl); /* go UX-2: per-theme token — visible on cream AND espresso/dusk */
  border-radius: 3px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
@keyframes tts-tap-flash {
  0% { background: color-mix(in srgb, var(--gold) 40%, transparent); }
  100% { background: transparent; }
}
.tts-sentence.tap-flash { animation: tts-tap-flash 220ms ease; }

/* ====================== go UX-3 ======================
   Sentence-level units. .tts-frag = one sentence (inline span); .tts-unit = a
   whole readable box read as one (e.g. .real-life-box). Both get the same
   per-theme read-highlight and tap behaviour the old .tts-sentence had, so the
   exact sentence being read is highlighted and any single sentence is tappable. */
.tts-frag, .tts-unit { cursor: default; }
body[data-tts-available="true"] .tts-frag,
body[data-tts-available="true"] .tts-unit { cursor: pointer; }
.tts-frag.active, .tts-unit.active {
  background: var(--tts-hl);
  border-radius: 3px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.tts-frag.tap-flash, .tts-unit.tap-flash { animation: tts-tap-flash 220ms ease; }

/* "Jump to where it's reading" — a compact arrow that lives in the TTS bar
   (hidden until you scroll away from the read line), with its label floating
   ABOVE it as a small pop-up bubble, outside the pill, so it never squashes the
   other controls. Accent-tinted = the live "bring me back" control. */
.tts-jump {
  position: relative;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
  width: 0; padding: 0; margin: 0; overflow: visible;   /* visible so the tip escapes */
  opacity: 0; transform: scale(0.6);
  transition: width 200ms ease, opacity 200ms ease, transform 200ms ease;
  pointer-events: none; flex: 0 0 auto;
}
.tts-jump .tts-jump-ico { font-size: 16px; line-height: 1; }
.tts-jump.show { width: 38px; opacity: 1; transform: scale(1); pointer-events: auto; }
.tts-jump:hover { background: var(--accent); color: var(--cta-ink); }
/* the floating label bubble, centred above the arrow */
.tts-jump .tts-jump-tip {
  position: absolute; bottom: calc(100% + 11px); left: 50%;
  transform: translateX(-50%) translateY(5px);
  white-space: nowrap;
  background: var(--accent); color: var(--cta-ink);
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.02em;
  padding: 6px 11px; border-radius: 9px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.28);
  opacity: 0; pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease;
}
.tts-jump .tts-jump-tip::after {   /* little downward caret */
  content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--accent);
}
.tts-jump.show .tts-jump-tip { opacity: 1; transform: translateX(-50%) translateY(0); }

/* "Read case & rule notes aloud" toggle, appended into the gear panel. */
.tts-sources-toggle {
  display: flex; align-items: center; gap: 9px;
  width: 100%; margin-top: 6px; padding: 9px 4px 2px;
  border-top: 1px solid var(--hairline);
  font-size: 12.5px; color: var(--ink-muted); text-align: left;
}
.tts-sources-toggle .tsr-box {
  width: 16px; height: 16px; border-radius: 4px;
  border: 1.5px solid var(--hairline-2); flex: 0 0 auto;
  position: relative; transition: all 150ms;
}
.tts-sources-toggle.on { color: var(--ink); }
.tts-sources-toggle.on .tsr-box { background: var(--accent); border-color: var(--accent); }
.tts-sources-toggle.on .tsr-box::after {
  content: "\2713"; color: var(--cta-ink);
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}

/* go PLAIN-VOICE / SOUND-X — extra gear toggles share the sources-toggle
   look; only the first carries the divider so they stack flush beneath it. */
.tts-sources-toggle + .tts-sources-toggle {
  border-top: 0; margin-top: 0; padding-top: 5px;
}

/* Back button injected at the left of the top nav (go UX-3). */
.nav-back {
  display: inline-flex; align-items: center; gap: 5px;
  margin-right: 4px; padding: 5px 11px 5px 9px;
  border-radius: 999px;
  border: 1px solid var(--hairline-2);
  color: var(--ink-muted); font-size: 13px; font-family: var(--font-mono);
  background: transparent; transition: all 160ms; text-decoration: none !important;
}
.nav-back:hover { color: var(--accent); border-color: var(--accent); }
.nav-back .nb-arrow { font-size: 15px; line-height: 1; }

/* Theme-aware callout defaults (go UX-3) — used by chapters built from CV2 on,
   so the Encode-it and Real-life boxes stand out and re-tint with the theme.
   (CV1's frozen inline styles are unaffected; they unify at go F-STORY-POLISH.) */
.encode-note {
  background: color-mix(in srgb, var(--accent) 9%, var(--bg-elev));
  border-left: 3px solid var(--accent);
  border-radius: 8px; padding: 14px 16px; margin: 18px 0;
  line-height: 1.6;
}
.encode-note b { color: var(--accent); }

.tts-wrap {
  position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
  z-index: 950;
  display: flex; flex-direction: column; align-items: center;
  max-width: 380px; width: 90%;
  opacity: 0; pointer-events: none;
  transition: opacity 300ms, transform 300ms;
}
body[data-tts-available="true"] .tts-wrap { opacity: 1; transform: translateX(-50%) translateY(0); }
/* The wrapper stays click-through (so it can't block the bottom-right controls
   on narrow screens where it goes full-width); only the actual bar and gear
   panel are interactive. */
body[data-tts-available="true"] .tts-bar,
body[data-tts-available="true"] .tts-options { pointer-events: auto; }

.tts-bar {
  display: flex; align-items: center; gap: 4px;
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  padding: 4px 6px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.3);
  width: 100%;
  justify-content: center;
}
.tts-btn {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; transition: all 150ms;
}
.tts-btn:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); }
.tts-btn:active { transform: scale(0.94); }
.tts-btn.primary { width: 44px; height: 44px; background: var(--bg-sunk); }
.tts-btn.primary:hover { background: var(--accent); color: var(--cta-ink); }
.tts-btn.primary.playing { background: var(--accent); color: var(--cta-ink); }

.tts-options {
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 14px;
  padding: 12px;
  margin-bottom: 8px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.3);
  width: 100%;
  opacity: 0; pointer-events: none;
  transform: translateY(8px) scale(0.96);
  transition: all 200ms ease;
}
.tts-options.open { opacity: 1; pointer-events: auto; transform: translateY(0) scale(1); }

.tts-opt-row { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; }
.tts-opt-row + .tts-opt-row { border-top: 1px solid var(--hairline); }
.tts-opt-label { font-size: 12px; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.05em; }

.tts-speed-group, .tts-voice-group { display: flex; gap: 4px; }
.tts-speed-pill, .tts-voice-pill {
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--hairline-2);
  font-size: 12px; font-family: var(--font-mono);
  transition: all 150ms;
}
.tts-speed-pill:hover, .tts-voice-pill:hover { color: var(--accent); border-color: var(--accent); }
.tts-speed-pill.active, .tts-voice-pill.active {
  background: var(--accent); color: var(--cta-ink); border-color: var(--accent);
}

@media (max-width: 520px) {
  .tts-wrap { left: 12px; right: 12px; transform: none; max-width: none; }
  body[data-tts-available="true"] .tts-wrap { transform: none; }
  /* go UX-2: on phones the TTS bar spans the full width at the bottom, so the
     right-edge rail (theme + jump button) is lifted clear of it. On desktop
     the bar is a centred pill that never reaches the right edge, so no lift
     is needed there. */
  body[data-tts-available="true"] { --rail-bottom: calc(84px + env(safe-area-inset-bottom)); }
}

/* ---------- WHATSAPP FAB ---------- */
.whatsapp-fab {
  position: fixed; bottom: 16px; left: 16px; z-index: 900;
  width: 48px; height: 48px; border-radius: 50%;
  background: #25d366; color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px;
  box-shadow: 0 2px 12px rgba(37,211,102,0.3);
  transition: transform 200ms, box-shadow 200ms;
  text-decoration: none !important;
}
.whatsapp-fab:hover { transform: scale(1.08); box-shadow: 0 4px 20px rgba(37,211,102,0.4); }

/* ---------- FLOATING ACTION SLOT (Constitution §14.2 — empty hook) ----------
   Reserved bottom-right, sitting above the TTS controller and below any
   scroll-to-top button. Populated post-launch by the iCann 360 chatbot
   embed, a WhatsApp click-to-chat button, or a feedback link. At SCAFFOLD
   time this is intentionally empty — the slot exists; what fills it is a
   later decision. Hidden until it has children. */
.floating-action {
  position: fixed; right: 16px;
  /* Sits ABOVE the theme-switcher with a comfortable gap, and ABOVE the TTS
     bar (z 950) so its taps are never swallowed by the bar's full-width
     wrapper on narrow screens. */
  bottom: calc(var(--rail-bottom) + 58px);
  z-index: 960;
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  pointer-events: none;
  transition: bottom 240ms cubic-bezier(0.22,1,0.36,1);
}
.floating-action:empty { display: none; }
.floating-action > * { pointer-events: auto; }
/* go UX-2: redesigned to the Phase_5D `.util-btn` language — a calm,
   surface-coloured round button that lifts and warms to accent on hover,
   instead of a heavy solid-accent disc that fought the page. */
.floating-action .fab-btn {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--bg-elev); color: var(--ink);
  border: 1px solid var(--hairline-2);
  display: grid; place-items: center;
  font-size: 20px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.14);
  transition: transform 260ms cubic-bezier(0.22,1,0.36,1),
              background 220ms ease, color 220ms ease, box-shadow 220ms ease;
}
.floating-action .fab-btn:hover {
  transform: translateY(-2px) rotate(-6deg);
  background: var(--accent); color: var(--cta-ink);
  box-shadow: 0 10px 26px rgba(0,0,0,0.22);
}
.floating-action .fab-btn:active { transform: translateY(0) scale(0.96); }
@media (max-width: 520px) {
  /* fuller thumb target on phones */
  .floating-action .fab-btn { width: 52px; height: 52px; }
}

/* ---------- FLOATING QUICK-NAV (jump-anywhere menu) ----------
   Lives in the .floating-action slot (§14.2). The round toggle reuses
   .fab-btn; the menu opens upward so it never collides with the centred
   TTS bar. All warm theme tokens — works in every theme automatically. */
.floatnav-wrap { position: relative; display: flex; flex-direction: column; align-items: flex-end; }
/* go UX-2: accent ring marks this as the page's "jump anywhere" control,
   mirroring the Phase_5D `.areas-btn`. Hover state inherits from .fab-btn. */
.floatnav-toggle { border: 1.5px solid var(--accent); color: var(--accent); }
.floatnav-toggle svg { width: 22px; height: 22px; }
.floatnav-menu {
  position: absolute; bottom: calc(100% + 10px); right: 0;
  width: 264px; max-width: calc(100vw - 32px);
  max-height: min(62vh, 460px); overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px;
  background: color-mix(in srgb, var(--bg-elev) 94%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border: 1px solid var(--hairline-2);
  border-radius: 16px;
  box-shadow: 0 14px 40px rgba(0,0,0,0.22);
  opacity: 0; pointer-events: none;
  transform: translateY(8px) scale(0.97);
  transform-origin: bottom right;
  transition: opacity 180ms ease, transform 200ms cubic-bezier(0.22,1,0.36,1);
}
.floatnav-wrap.open .floatnav-menu { opacity: 1; pointer-events: auto; transform: translateY(0) scale(1); }
.floatnav-head {
  font-family: var(--font-mono);
  font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--ink-muted); padding: 8px 10px 4px;
}
.floatnav-item {
  display: block; width: 100%; text-align: left;
  padding: 9px 10px; border-radius: 9px;
  font-size: 13.5px; line-height: 1.3; color: var(--ink);
  text-decoration: none; transition: background 150ms ease, color 150ms ease;
}
.floatnav-item.sub { padding-left: 22px; font-size: 12.5px; color: var(--ink-2); }
.floatnav-item:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.floatnav-item.top { color: var(--accent); font-weight: 600; }
.floatnav-sep { height: 1px; background: var(--hairline); margin: 6px 4px; }

/* ---------- COMMON CARD ---------- */
.card {
  background: var(--bg-elev);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  padding: 24px;
  transition: transform 250ms ease, box-shadow 250ms ease, border-color 250ms ease;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 16px 36px rgba(27,22,18,0.09);
  border-color: var(--hairline-2);
}

/* ---------- CHAPTER NAVIGATION ---------- */
.chapter-nav {
  display: flex; justify-content: space-between; align-items: center;
  padding: 20px 0;
  border-top: 1px solid var(--hairline);
  margin-top: 40px;
  font-size: 14px;
}
.chapter-nav a {
  color: var(--ink-muted);
  text-decoration: none;
  display: flex; align-items: center; gap: 6px;
  transition: color 200ms;
}
.chapter-nav a:hover { color: var(--accent); }

/* ---------- COLLAPSIBLE SECTIONS ---------- */
.collapsible-header {
  display: flex; justify-content: space-between; align-items: center;
  cursor: pointer; padding: 12px 0;
  border-bottom: 1px solid var(--hairline);
}
.collapsible-header::after {
  content: '▸'; font-size: 14px; transition: transform 300ms;
}
.collapsible-header.open::after { transform: rotate(90deg); }
.collapsible-body {
  max-height: 0; overflow: hidden;
  transition: max-height 400ms ease;
}
.collapsible-body.open { max-height: 4000px; }

/* ---------- FLASHCARD ---------- */
.flashcard {
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 14px;
  padding: 24px;
  min-height: 180px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  cursor: pointer;
  transition: transform 300ms;
  perspective: 1000px;
}
.flashcard:active { transform: scale(0.97); }
.flashcard-answer { display: none; color: var(--gold); margin-top: 12px; }
.flashcard.flipped .flashcard-answer { display: block; }
.flashcard.flipped .flashcard-question { opacity: 0.5; font-size: 13px; }

/* ---------- CONFIDENCE RATING ---------- */
.confidence-row {
  display: flex; gap: 6px; justify-content: center; margin-top: 16px;
}
.confidence-btn {
  width: 40px; height: 40px; border-radius: 50%;
  border: 2px solid var(--hairline-2);
  font-size: 16px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  transition: all 200ms;
}
.confidence-btn:hover { border-color: var(--accent); color: var(--accent); }
.confidence-btn.selected { background: var(--accent); color: var(--cta-ink); border-color: var(--accent); }

/* ---------- EXAM TIMER ---------- */
.exam-timer {
  background: var(--bg-elev);
  border: 1px solid var(--hairline-2);
  border-radius: 14px;
  padding: 20px;
  text-align: center;
}
.timer-display {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 6vw, 3.2rem);
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.02em;
}
.timer-label { font-family: var(--font-mono); font-size: 12px; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }
.timer-controls { display: flex; gap: 8px; justify-content: center; margin-top: 16px; }
.timer-btn {
  padding: 8px 20px; border-radius: 8px;
  border: 1px solid var(--hairline-2);
  font-size: 13px; font-weight: 600;
  transition: all 200ms;
}
.timer-btn:hover { border-color: var(--accent); color: var(--accent); }
.timer-btn.primary { background: var(--accent); color: var(--cta-ink); border-color: var(--accent); }

/* ---------- BOOKMARK UI ---------- */
.bookmark-icon {
  cursor: pointer; font-size: 18px; color: var(--ink-muted);
  transition: color 200ms, transform 200ms;
}
.bookmark-icon:hover { color: var(--gold); transform: scale(1.15); }
.bookmark-icon.active { color: var(--gold); }

/* ---------- DAILY QUESTION ---------- */
.daily-question {
  background: linear-gradient(135deg, var(--bg-elev), color-mix(in srgb, var(--accent) 5%, var(--bg-elev)));
  border: 1px solid var(--hairline-2);
  border-radius: 14px;
  padding: 24px;
}
.daily-badge {
  display: inline-block;
  background: var(--accent); color: var(--cta-ink);
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 3px 10px; border-radius: 999px;
  margin-bottom: 12px;
}

/* ---------- BREADCRUMB PILL ---------- */
.breadcrumb-pill {
  position: fixed; top: 52px; left: 50%; transform: translateX(-50%);
  z-index: 997;
  background: color-mix(in srgb, var(--bg-elev) 80%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 4px 14px;
  font-size: 11px; color: var(--ink-muted);
  letter-spacing: 0.04em;
  white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity 300ms;
}
.breadcrumb-pill.visible { opacity: 1; pointer-events: auto; }

/* ---------- PHONETIC NAME SPANS ---------- */
.name { color: var(--name); font-style: italic; font-weight: 700; } /* go UX-2: bold (was 500) — names now anchor the eye in the prose */

/* ---------- MODE TABS ---------- */
.mode-tabs {
  display: flex; gap: 4px; overflow-x: auto;
  padding: 4px; background: var(--bg-sunk);
  border-radius: 10px; margin-bottom: 24px;
  -webkit-overflow-scrolling: touch;
}
.mode-tab {
  padding: 8px 16px; border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 500; letter-spacing: 0.02em;
  white-space: nowrap;
  color: var(--ink-muted);
  transition: all 200ms;
}
.mode-tab:hover { color: var(--ink); }
.mode-tab.active {
  background: var(--bg-elev);
  color: var(--ink);
  box-shadow: 0 1px 4px rgba(27,22,18,0.10);
}

/* ---------- STATUTE BLOCKS ---------- */
.statute-block {
  background: var(--bg-sunk);
  border-left: 3px solid var(--gold);
  padding: 16px 20px;
  margin: 16px 0;
  border-radius: 0 8px 8px 0;
  font-size: 14px;
  line-height: 1.7;
}
.statute-ref {
  font-size: 11px; color: var(--gold);
  text-transform: uppercase; letter-spacing: 0.06em;
  margin-bottom: 6px; display: block;
}

/* ---------- CASE CARDS ---------- */
.case-card {
  background: var(--bg-elev);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 16px; margin: 12px 0;
}
.case-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--accent);
}
.case-citation { font-size: 12px; color: var(--ink-muted); margin-top: 2px; }
.case-body { font-size: 14px; margin-top: 10px; line-height: 1.65; }

/* ---------- IRAC TRIGGER ---------- */
.irac-trigger {
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elev));
  border: 1px dashed var(--accent);
  border-radius: 10px;
  padding: 16px 20px;
  margin: 16px 0;
}
.irac-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  color: var(--accent); letter-spacing: 0.08em; margin-bottom: 6px;
}

/* ---------- MNEMONIC ANCHOR ---------- */
.mnemonic-box {
  background: color-mix(in srgb, var(--gold) 6%, var(--bg-elev));
  border: 1px solid color-mix(in srgb, var(--gold) 20%, transparent);
  border-radius: 10px;
  padding: 16px 20px;
  margin: 16px 0;
}
.mnemonic-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  color: var(--gold); letter-spacing: 0.08em; margin-bottom: 6px;
}

/* ---------- REAL LIFE ANCHOR ---------- */
.real-life-box {
  background: color-mix(in srgb, var(--success) 6%, var(--bg-elev));
  border: 1px solid color-mix(in srgb, var(--success) 20%, transparent);
  border-radius: 10px;
  padding: 16px 20px;
  margin: 16px 0;
}
.real-life-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  color: var(--success); letter-spacing: 0.08em; margin-bottom: 6px;
}

/* ---------- COLOURED LISTS (go UX-2) ----------
   Opt-in semantic lists chapters can use without any JS. Markers are drawn
   with ::before so they colour independently of the text and never break TTS
   (the glyphs aren't in the DOM text, so the reader won't say "tick"). Use:
     <ul class="list-do">   ✓ green   — requirements / what to do
     <ul class="list-dont"> ✗ red     — pitfalls / what to avoid
     <ul class="list-key">  ◆ gold    — key points to remember
     <ol class="list-steps"> 1·2·3    — ordered procedure, accent badges     */
ul.list-do, ul.list-dont, ul.list-key {
  list-style: none; padding-left: 2px; margin: 14px 0;
}
ul.list-do li, ul.list-dont li, ul.list-key li {
  position: relative; padding-left: 30px; margin-bottom: 9px; line-height: 1.6;
}
ul.list-do li::before, ul.list-dont li::before, ul.list-key li::before {
  position: absolute; left: 0; top: 0.05em;
  font-family: var(--font-mono); font-weight: 700; font-size: 0.95em;
  width: 22px; text-align: center;
}
ul.list-do li::before   { content: '✓'; color: var(--success); }
ul.list-dont li::before  { content: '✗'; color: var(--danger);  }
ul.list-key li::before   { content: '◆'; color: var(--gold); font-size: 0.8em; top: 0.18em; }

ol.list-steps {
  list-style: none; counter-reset: cp-step; padding-left: 2px; margin: 14px 0;
}
ol.list-steps li {
  counter-increment: cp-step; position: relative;
  padding-left: 40px; margin-bottom: 12px; line-height: 1.6; min-height: 28px;
}
ol.list-steps li::before {
  content: counter(cp-step);
  position: absolute; left: 0; top: 0;
  width: 26px; height: 26px; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-elev));
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
}

/* ---------- READING-CONTENT LISTS (go LIST-X) ----------
   Plain <ul>/<ol> in the body and the in-chapter rule spine (.spine-list) get
   one clear, well-separated row per item with a gentle alternating tint, so
   they're easy to scan and to keep your place in while the voice reads. The
   DESIGNED list classes (.list-do/.list-dont/.list-key/.list-steps) and the
   dedicated printable (.print-spine) keep their own look — they carry a class,
   so :not([class]) skips them. Nav/UI lists live OUTSIDE .container, untouched.
   Theme-aware via the same tokens the rest of the app uses. */
.container ul:not([class]),
.container ol:not([class]),
.container ol.spine-list {
  list-style: none;
  margin: 16px 0;
  padding-left: 0;
  counter-reset: lx;
}
.container ul:not([class]) > li,
.container ol:not([class]) > li,
.container ol.spine-list > li {
  position: relative;
  margin: 7px 0;
  padding: 11px 14px 11px 16px;
  border-radius: 10px;
  border-left: 3px solid color-mix(in srgb, var(--accent) 50%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  line-height: 1.62;
  break-inside: avoid;
}
.container ul:not([class]) > li:nth-child(even),
.container ol:not([class]) > li:nth-child(even),
.container ol.spine-list > li:nth-child(even) {
  background: color-mix(in srgb, var(--accent) 11%, transparent);
}
/* numbered rows show their number in a small accent badge at the left */
.container ol:not([class]) > li,
.container ol.spine-list > li {
  counter-increment: lx;
  padding-left: 46px;
}
.container ol:not([class]) > li::before,
.container ol.spine-list > li::before {
  content: counter(lx);
  position: absolute; left: 10px; top: 10px;
  min-width: 24px; height: 24px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  color: var(--accent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 42%, var(--hairline));
  border-radius: 7px;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
/* bullet rows get a small accent dot instead */
.container ul:not([class]) > li { padding-left: 30px; }
.container ul:not([class]) > li::before {
  content: ''; position: absolute; left: 15px; top: 1.05em;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
}
/* a citation tucked inside a rule row sits on its own line beneath it */
.container .spine-list .sp-cite,
.container ol:not([class]) .sp-cite,
.container ul:not([class]) .sp-cite {
  display: block; margin-top: 6px;
  font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-muted);
}


/* ---------- USER HIGHLIGHTER (go HL-X) ----------
   Two ways to highlight like a pen on a book/PDF: (1) tap the pen button to
   enter highlight mode, then tap any line; (2) select text and pick a colour.
   Five colours; highlights save per page (localStorage) and restore on reload.
   Text inside a highlight is forced DARK on the light marker so it stays
   readable in every theme (light, espresso, dusk). */
mark.user-hl {
  border-radius: 2px; padding: 0 1px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  cursor: pointer; transition: filter 140ms ease;
  background-color: #ffe07a;
}
/* contrast: dark ink across the whole highlight, regardless of theme/spans */
mark.user-hl, mark.user-hl * { color: #2a1d08 !important; }
mark.user-hl[data-c="y"] { background-color: #ffe07a; }
mark.user-hl[data-c="g"] { background-color: #b6e3a0; }
mark.user-hl[data-c="p"] { background-color: #f6b8cf; }
mark.user-hl[data-c="b"] { background-color: #aed4f5; }
mark.user-hl[data-c="o"] { background-color: #f9c79a; }
mark.user-hl:hover { filter: brightness(0.96); }

/* selection toolbar (swatches + remove) */
.hl-toolbar {
  position: absolute; z-index: 1200; display: none; align-items: center; gap: 6px; padding: 6px 8px;
  background: var(--bg-elev); border: 1px solid var(--hairline-2);
  border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.28);
}
.hl-toolbar.show { display: inline-flex; }
.hl-tb-swatches { display: inline-flex; gap: 6px; }
.hl-btn {
  font-family: var(--font-mono); font-size: 12px; white-space: nowrap;
  background: transparent; color: var(--ink); border: none; border-radius: 8px;
  padding: 6px 10px; cursor: pointer; transition: background 140ms ease, color 140ms ease;
}
.hl-btn.hl-del:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 13%, transparent); }

/* colour swatch (shared by toolbar + pen palette) */
.hl-sw {
  width: 24px; height: 24px; border-radius: 50%; cursor: pointer; padding: 0;
  border: 2px solid rgba(0,0,0,0.18);
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
  transition: transform 130ms ease, box-shadow 130ms ease;
}
.hl-sw:hover { transform: scale(1.12); }
.hl-sw.on { box-shadow: 0 0 0 2px var(--bg-elev), 0 0 0 4px var(--accent); }

/* the pen button (lives in the floating-action column, above the nav button) */
.hl-fab-wrap { position: relative; display: flex; align-items: center; gap: 8px; }
.hl-fab { border: 1.5px solid var(--hairline-2); position: relative; }
.hl-fab::after {           /* current-colour dot */
  content: ''; position: absolute; right: 4px; bottom: 4px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--cur, #ffe07a); border: 1.5px solid var(--bg-elev);
}
.hl-fab.on {
  background: var(--accent); color: var(--cta-ink);
  border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
/* palette sits to the LEFT of the pen, hidden until highlight mode is on */
.hl-palette {
  display: flex; gap: 7px; align-items: center; padding: 7px 9px;
  background: var(--bg-elev); border: 1px solid var(--hairline-2);
  border-radius: 999px; box-shadow: 0 8px 24px rgba(0,0,0,0.26);
  opacity: 0; transform: translateX(8px) scale(0.95); pointer-events: none;
  transition: opacity 180ms ease, transform 200ms cubic-bezier(0.22,1,0.36,1);
}
.hl-palette.show { opacity: 1; transform: translateX(0) scale(1); pointer-events: auto; }

/* in highlight mode, text invites a tap (word) or a drag (phrase) */
body.hl-mode .tts-sentence,
body.hl-mode .container li,
body.hl-mode .encode-note,
body.hl-mode .real-life-box { cursor: text; }
body.hl-mode .tts-sentence:hover,
body.hl-mode .container li:hover {
  background: color-mix(in srgb, var(--hl, #ffe07a) 10%, transparent);
  border-radius: 4px;
}

/* one-time coaching toast when the pen is first switched on */
.hl-coach {
  position: fixed; left: 50%; bottom: calc(var(--rail-bottom) + 130px);
  transform: translate(-50%, 8px); z-index: 1450;
  max-width: min(86vw, 360px); text-align: center;
  background: var(--bg-elev); color: var(--ink);
  border: 1px solid var(--hairline-2); border-radius: 12px;
  padding: 12px 16px; font-size: 13.5px; line-height: 1.4;
  box-shadow: 0 12px 34px rgba(0,0,0,0.3);
  opacity: 0; pointer-events: none;
  transition: opacity 280ms ease, transform 280ms cubic-bezier(0.22,1,0.36,1);
}
.hl-coach.show { opacity: 1; transform: translate(-50%, 0); }

@media print {
  .hl-toolbar, .hl-fab-wrap, .hl-coach { display: none !important; }
  mark.user-hl { background: #fff2a8 !important; }
}

/* ---------- MOBILE TAP COACH-MARK (go UX-2) ----------
   One-time hint shown to touch users on a readable page: teaches that any
   line is tappable to hear it, and points to the round jump button. Sits
   above the rail/TTS bar; dismisses on tap, scroll, or after a few seconds.
   Persisted via lapp.coach-tap-seen so it never nags twice. */
.coach-mark {
  position: fixed; left: 50%; z-index: 960;
  bottom: calc(var(--rail-bottom) + 70px);
  transform: translateX(-50%) translateY(10px);
  width: min(320px, calc(100vw - 28px));
  background: color-mix(in srgb, var(--bg-elev) 96%, transparent);
  backdrop-filter: blur(12px) saturate(150%);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
  border: 1px solid var(--hairline-2);
  border-radius: 16px;
  box-shadow: 0 16px 44px rgba(0,0,0,0.26);
  padding: 14px 16px;
  opacity: 0; pointer-events: none;
  transition: opacity 260ms ease, transform 300ms cubic-bezier(0.22,1,0.36,1);
}
.coach-mark.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.coach-mark .cm-title {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
  margin-bottom: 6px;
}
.coach-mark .cm-body { font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.coach-mark .cm-body b { color: var(--ink); font-weight: 700; }
.coach-mark .cm-dismiss {
  margin-top: 12px; width: 100%;
  padding: 9px 12px; border-radius: 10px;
  background: var(--accent); color: var(--cta-ink);
  font-size: 13px; font-weight: 700;
}


/* ---------- UTILITY ---------- */
.container { max-width: 900px; margin: 0 auto; padding: 0 20px; position: relative; z-index: 2; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }
.mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 24px; } .mt-4 { margin-top: 32px; }
.mb-1 { margin-bottom: 8px; } .mb-2 { margin-bottom: 16px; } .mb-3 { margin-bottom: 24px; }
.text-center { text-align: center; }
.text-gold { color: var(--gold); }
.text-muted { color: var(--ink-muted); }

/* =============================================================
   SCAFFOLD ADDITIONS (go SCAFFOLD-CONTENT)
   Net-new SHARED components used by the course-picker home, the
   subject dashboard, the working Drill page, and the empty mode
   skeletons. Built once at the foundation phase, then frozen with
   the rest of shared.css. All use existing theme tokens above.
   ============================================================= */

/* ---------- PAGE HERO ---------- */
.page-hero {
  position: relative; z-index: 2;
  padding: 96px 0 28px;
  text-align: left;
}
.page-hero .kicker {
  font-family: var(--font-mono);
  font-size: 11.5px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 12px; font-weight: 500;
}
.page-hero h1 { margin-bottom: 10px; }
.page-hero .lede { color: var(--ink-2); max-width: 60ch; font-size: 15px; }

/* ---------- SECTION HEADING ---------- */
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin: 36px 0 16px;
  border-bottom: 1px solid var(--hairline); padding-bottom: 8px;
}
.section-head h2 { font-size: clamp(1.2rem, 3vw, 1.7rem); }
.section-head .count { font-family: var(--font-mono); font-size: 12px; color: var(--ink-muted); white-space: nowrap; letter-spacing: 0.02em; }

/* ---------- COURSE / SUBJECT GRID (home picker) ---------- */
.course-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.course-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg-elev); border: 1px solid var(--hairline);
  border-radius: 18px; padding: 24px; min-height: 168px;
  transition: transform 250ms ease, box-shadow 250ms ease, border-color 250ms ease;
  text-decoration: none; color: inherit;
}
.course-card.live:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 40px rgba(27,22,18,0.10);
  border-color: var(--hairline-2);
}
.course-card.soon { opacity: 0.62; cursor: not-allowed; }
.course-card .course-icon { font-family: var(--font-display); font-size: 28px; margin-bottom: 12px; line-height: 1; color: var(--accent); }
.course-card h3 { font-size: 1.45rem; margin-bottom: 8px; }
.course-card p { font-size: 14px; color: var(--ink-2); line-height: 1.6; }
.course-card .course-foot {
  margin-top: auto; padding-top: 16px; border-top: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 12px; color: var(--accent); font-weight: 500; letter-spacing: 0.03em;
}
.course-card .status-tag {
  position: absolute; top: 16px; right: 16px;
  font-family: var(--font-mono);
  font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.1em;
  padding: 4px 10px; border-radius: 999px;
}
.status-tag.live { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.status-tag.soon { background: var(--bg-sunk); color: var(--ink-muted); }

/* ---------- CHAPTER GRID (subject dashboard) ---------- */
.chapter-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.chapter-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg-elev); border: 1px solid var(--hairline);
  border-radius: 14px; padding: 16px 18px; min-height: 112px;
  transition: transform 250ms ease, box-shadow 250ms ease, border-color 250ms ease;
  text-decoration: none; color: inherit;
}
.chapter-card.built:hover {
  transform: translateY(-3px); box-shadow: 0 14px 32px rgba(27,22,18,0.09);
  border-color: var(--hairline-2);
}
.chapter-card.locked { opacity: 0.5; cursor: default; }
.chapter-card .ch-no {
  font-family: var(--font-mono); font-size: 11px;
  color: var(--ink-muted); letter-spacing: 0.08em;
}
.chapter-card .ch-title { font-family: var(--font-display); font-size: 1.1rem; font-weight: 600; margin: 5px 0 8px; line-height: 1.25; }
.chapter-card .ch-meta { margin-top: auto; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.chapter-card .ch-state {
  position: absolute; top: 14px; right: 14px; font-size: 14px;
}

/* ---------- BADGES / TAGS ---------- */
.freq-badge {
  display: inline-flex; align-items: center; gap: 4px;
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-elev));
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500; letter-spacing: 0.03em;
  padding: 3px 9px; border-radius: 999px;
}
.tentpole-star { color: var(--gold); font-size: 13px; }
.draft-tag {
  display: inline-flex; align-items: center;
  background: var(--bg-sunk); color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.08em;
  padding: 3px 8px; border-radius: 6px;
}

/* ---------- STAT PILLS (drill HUD) ---------- */
.stat-row { display: flex; gap: 10px; flex-wrap: wrap; }
.stat-pill {
  display: flex; flex-direction: column; align-items: center;
  background: var(--bg-elev); border: 1px solid var(--hairline);
  border-radius: 12px; padding: 12px 18px; min-width: 84px;
}
.stat-pill .stat-num {
  font-family: var(--font-display); font-size: 24px; font-weight: 600; color: var(--accent); line-height: 1;
}
.stat-pill .stat-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-muted); margin-top: 6px;
}

/* ---------- PROGRESS RING (daily target) ---------- */
.progress-ring { transform: rotate(-90deg); }
.progress-ring .ring-track { stroke: var(--hairline-2); fill: none; }
.progress-ring .ring-fill { stroke: var(--accent); fill: none; stroke-linecap: round; transition: stroke-dashoffset 500ms ease; }
.ring-wrap { position: relative; width: 96px; height: 96px; }
.ring-wrap .ring-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
}
.ring-wrap .ring-center .ring-num { font-family: var(--font-display); font-size: 18px; color: var(--ink); }
.ring-wrap .ring-center .ring-sub { font-size: 9px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); }

/* ---------- GRADE BUTTONS (Good / Almost / Miss) ---------- */
.grade-row { display: flex; gap: 8px; justify-content: center; margin-top: 16px; }
.grade-btn {
  flex: 1; max-width: 130px; padding: 12px 8px; border-radius: 10px;
  border: 1px solid var(--hairline-2); font-size: 13px; font-weight: 700;
  transition: all 180ms;
}
.grade-btn.good:hover, .grade-btn.good.flash { background: color-mix(in srgb, var(--success) 22%, transparent); border-color: var(--success); color: var(--success); }
.grade-btn.almost:hover, .grade-btn.almost.flash { background: color-mix(in srgb, var(--gold) 22%, transparent); border-color: var(--gold); color: var(--gold); }
.grade-btn.miss:hover, .grade-btn.miss.flash { background: color-mix(in srgb, var(--danger) 22%, transparent); border-color: var(--danger); color: var(--danger); }

/* ---------- EMPTY STATE (skeleton mode pages) ---------- */
.empty-state {
  text-align: center; padding: 56px 24px;
  border: 1px dashed var(--hairline-2); border-radius: 16px;
  background: color-mix(in srgb, var(--accent) 3%, var(--bg-elev));
}
.empty-state .empty-icon { font-size: 40px; margin-bottom: 14px; opacity: 0.8; }
.empty-state h3 { font-size: 1.1rem; margin-bottom: 8px; }
.empty-state p { color: var(--ink-muted); font-size: 14px; max-width: 46ch; margin: 0 auto 4px; }
.empty-state .hint { font-size: 12px; color: var(--accent); margin-top: 12px; font-weight: 700; }

/* ---------- SUB-TABS (Authority: Cases / Sections) ---------- */
.subtab-row { display: flex; gap: 8px; margin: 8px 0 20px; }
.subtab {
  padding: 8px 18px; border-radius: 999px; border: 1px solid var(--hairline-2);
  font-size: 13px; font-weight: 600; color: var(--ink-muted); transition: all 180ms;
}
.subtab:hover { color: var(--ink); }
.subtab.active { background: var(--accent); color: var(--cta-ink); border-color: var(--accent); }

/* ---------- BUTTONS ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 22px; border-radius: 10px; font-size: 14px; font-weight: 700;
  border: 1px solid var(--hairline-2); transition: all 180ms;
}
.btn.primary { background: var(--accent); color: var(--cta-ink); border-color: var(--accent); }
.btn.primary:hover { opacity: 0.9; transform: translateY(-1px); }
.btn.ghost:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- FAQ (help.html) ---------- */
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-q {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  cursor: pointer; padding: 16px 0; font-weight: 600; font-size: 15px;
}
.faq-q::after { content: '+'; font-size: 20px; color: var(--accent); transition: transform 300ms; }
.faq-q.open::after { transform: rotate(45deg); }
.faq-a { max-height: 0; overflow: hidden; transition: max-height 350ms ease; color: var(--ink-2); font-size: 14px; line-height: 1.65; }
.faq-a.open { max-height: 600px; padding-bottom: 16px; }
.faq-a p { margin-bottom: 10px; }

/* ============================================================================
   FLOATING RAIL COLLAPSE (go UX-5)
   A single master knob (.rail-toggle) at the bottom-right corner shows/hides the
   floating controls so they never cover the reading text. Tap to fan them out,
   tap again to tuck them away — like collapsing a dashboard panel. The knob owns
   the corner; the theme switcher and the action cluster are lifted one slot so
   they stack above it, and they fade/slide away when collapsed.
   ============================================================================ */

/* Make room for the knob: lift the existing two containers up by one slot. */
.theme-switcher  { bottom: calc(var(--rail-bottom) + 58px); }
.floating-action { bottom: calc(var(--rail-bottom) + 110px); }

/* The knob — always visible; the one control that reveals/hides the rest.
   Reuses the warm round-button language of the rail. */
.rail-toggle {
  position: fixed; bottom: var(--rail-bottom); right: 16px; z-index: 961;
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--bg-elev); color: var(--ink);
  border: 1px solid var(--hairline-2);
  display: grid; place-items: center;
  box-shadow: 0 6px 18px rgba(0,0,0,0.14);
  cursor: pointer;
  transition: transform 260ms cubic-bezier(0.22,1,0.36,1),
              background 220ms ease, color 220ms ease, box-shadow 220ms ease;
}
.rail-toggle:hover {
  transform: translateY(-2px);
  background: var(--accent); color: var(--cta-ink);
  box-shadow: 0 10px 26px rgba(0,0,0,0.22);
}
.rail-toggle:active { transform: translateY(0) scale(0.96); }
@media (max-width: 520px) { .rail-toggle { width: 52px; height: 52px; } }
.rail-toggle .rt-ico { display: grid; place-items: center; }
.rail-toggle .rt-ico svg { width: 22px; height: 22px; }
.rail-toggle .rt-hide { display: none; }
.rail-toggle.open .rt-show { display: none; }
.rail-toggle.open .rt-hide { display: grid; }

/* The smooth show/hide. The two containers animate bottom (their existing
   spring) plus opacity + a small downward tuck toward the knob. */
.theme-switcher,
.floating-action {
  transition: bottom 240ms cubic-bezier(0.22,1,0.36,1),
              opacity 220ms ease,
              transform 240ms cubic-bezier(0.22,1,0.36,1);
}
body.rail-collapsed .theme-switcher,
body.rail-collapsed .floating-action {
  opacity: 0;
  transform: translateY(14px) scale(0.92);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .rail-toggle,
  .theme-switcher,
  .floating-action { transition: none; }
}
