/* ============================================================================
   NCEA Level 3 Study Hub — Design System
   ----------------------------------------------------------------------------
   Palette: Phthalo green. All colours live as CSS custom properties so the
   whole theme can be retuned from one place.

   Structure of this file:
     1. Design tokens (colours, type, spacing, radius, shadow)  -> :root
     2. Dark mode overrides                                      -> [data-theme]
     3. Per-subject accent overrides                             -> [data-subject]
     4. Base / reset
     5. Layout (sidebar + topbar + content)
     6. Components (cards, buttons, tables, callouts, quiz, etc.)
     7. Utilities & responsive
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. DESIGN TOKENS
   --------------------------------------------------------------------------- */
:root {
  /* --- Phthalo green scale (the core identity of the site) --- */
  --phthalo-950: #08180F;
  --phthalo-900: #0C2418;
  --phthalo-800: #123524;   /* deep base (requested primary) */
  --phthalo-700: #17482F;
  --phthalo-600: #1B5E3F;   /* accent (requested) */
  --phthalo-500: #2D8A5F;   /* bright accent (requested) */
  --phthalo-400: #4FA97C;
  --phthalo-300: #7CC49E;
  --phthalo-200: #B4DEC8;
  --mint-100:   #E8F3ED;    /* soft mint background (requested) */
  --mint-50:    #F3F9F5;

  /* --- Semantic colours (light mode defaults) --- */
  --bg:            #F6F9F7;
  --bg-tint:       var(--mint-50);
  --surface:       #FFFFFF;
  --surface-2:     #FBFDFB;
  --text:          #12211A;
  --text-strong:   #0C2418;
  --muted:         #56685E;
  --faint:         #8A9A90;
  --border:        #E1EAE4;
  --border-strong: #CBDACF;

  --accent:        var(--phthalo-600);
  --accent-strong: var(--phthalo-800);
  --accent-bright: var(--phthalo-500);
  --accent-soft:   var(--mint-100);
  --on-accent:     #FFFFFF;

  /* --- Branded surfaces (sidebar, hero, toast, brand mark) ---
     These are the deep-green panels that carry the site's identity. They are
     deliberately SEPARATE from --accent so a theme can restyle them without
     touching every accent in the content area. Defaults are the phthalo values
     the site has always used, so light/dark are unchanged. */
  --brand-deep:   var(--phthalo-800);
  --brand-mid:    var(--phthalo-600);
  --brand-bright: var(--phthalo-500);
  --brand-line:   var(--phthalo-300);
  --brand-on-dim: var(--phthalo-200);

  /* Feedback colours (kept in-family where possible) */
  --good:    #1B7A4E;
  --good-bg: #E4F3EA;
  --warn:    #9A6B12;
  --warn-bg: #FBF1DC;
  --bad:     #B23A48;
  --bad-bg:  #FBE7E9;
  --info:    #1F6E6A;
  --info-bg: #E1F1F0;

  /* --- Typography --- */
  /* Headings only. Newsreader is drawn for screens, has a full weight range
     and reads as authoritative rather than quirky, which suits dense
     reference pages. Body text, figures and numbers stay on Inter. */
  --font-display: "Newsreader", "Iowan Old Style", Georgia, serif;
  /* Big figures stay on the body face. They are data, and Inter's tabular
     numerals line up in columns where a serif's proportional ones do not. */
  --font-figure: var(--font-body);
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  --fs-xs:  0.78rem;
  --fs-sm:  0.875rem;
  --fs-base:1rem;
  --fs-md:  1.125rem;
  --fs-lg:  1.35rem;
  --fs-xl:  1.75rem;
  --fs-2xl: 2.4rem;
  --fs-3xl: 3.1rem;

  --lh-tight: 1.2;
  --lh-snug:  1.4;
  --lh-body:  1.68;

  /* --- Spacing scale --- */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;

  /* --- Radius --- */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-pill: 999px;

  /* --- Shadow (soft, low, never heavy) --- */
  --shadow-xs: 0 1px 2px rgba(12, 36, 24, 0.05);
  --shadow-sm: 0 1px 3px rgba(12, 36, 24, 0.06), 0 1px 2px rgba(12, 36, 24, 0.04);
  --shadow-md: 0 4px 14px rgba(12, 36, 24, 0.08), 0 2px 4px rgba(12, 36, 24, 0.04);
  --shadow-lg: 0 12px 34px rgba(12, 36, 24, 0.12);

  /* --- Layout metrics --- */
  --sidebar-w: 264px;
  --topbar-h: 62px;
  --content-max: 940px;

  --transition: 160ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---------------------------------------------------------------------------
   2. DARK MODE
   --------------------------------------------------------------------------- */
[data-theme="dark"] {
  --bg:            #0B1611;
  --bg-tint:       #0E1D15;
  --surface:       #12211A;
  --surface-2:     #16281F;
  --text:          #E7F2EB;
  --text-strong:   #F4FAF6;
  --muted:         #9FB4A8;
  --faint:         #6F857A;
  --border:        #223A2D;
  --border-strong: #2E4A3A;

  --accent:        var(--phthalo-400);
  --accent-strong: var(--phthalo-300);
  --accent-bright: var(--phthalo-400);
  --accent-soft:   #16301F;
  --on-accent:     #08180F;

  --good:    #6FD59B; --good-bg: #12301F;
  --warn:    #E5C275; --warn-bg: #2E2510;
  --bad:     #F1929C; --bad-bg:  #331419;
  --info:    #74CFC9; --info-bg: #10302E;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.45);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 14px 40px rgba(0, 0, 0, 0.6);
}

/* ---------------------------------------------------------------------------
   2b. EXTRA COLOUR SCHEMES
   Each one redefines the SAME semantic variables as light/dark — nothing else
   in the stylesheet needs to know these exist. Registered in js/themes.js.
   Dark-family schemes must also be added to the :is() selector lists in
   section 3 and to the .sidebar rules, or subject pages keep the light accents.
   --------------------------------------------------------------------------- */

/* --- MIDNIGHT — deep indigo. A genuinely different mood from the green dark
       mode, and the lowest-glare option for studying at night. --- */
[data-theme="midnight"] {
  --bg:            #0C1020;
  --bg-tint:       #111730;
  --surface:       #151C38;
  --surface-2:     #1A2242;
  --text:          #E4E8F7;
  --text-strong:   #F2F5FF;
  --muted:         #A3AACB;
  --faint:         #6F769A;
  --border:        #262E52;
  --border-strong: #333D68;

  --accent:        #7C8CFF;
  --accent-strong: #A5B0FF;
  --accent-bright: #7C8CFF;
  --accent-soft:   #1C2450;
  --on-accent:     #0A0E1C;

  --good: #6FD5A8; --good-bg: #12302A;
  --warn: #E7C77A; --warn-bg: #2E2712;
  --bad:  #F3939F; --bad-bg:  #331722;
  --info: #78CEE6; --info-bg: #102A36;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.45);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 14px 40px rgba(0, 0, 0, 0.65);

  --brand-deep:   #10152C;
  --brand-mid:    #232C63;
  --brand-bright: #7C8CFF;
  --brand-line:   #A5B0FF;
  --brand-on-dim: #B9C0E8;
}


/* --- SANDSTONE — warm clay and sand. A light theme that isn't white: much
       lower glare for long reading, and the terracotta accent stops it reading
       as "the green one with the lights off". Palette built from the standard
       sand family (#F4EFE3 / #DFCEAC / #C9AE74) with a clay accent for contrast. --- */
[data-theme="sandstone"] {
  --bg:            #F4EFE4;
  --bg-tint:       #FAF6EE;
  --surface:       #FFFCF6;
  --surface-2:     #FBF6EC;
  --text:          #2E2419;
  --text-strong:   #1C150C;
  --muted:         #6E6151;
  --faint:         #9A8B76;
  --border:        #E4D9C4;
  --border-strong: #CFBE9F;

  --accent:        #A8623A;
  --accent-strong: #7C4526;
  --accent-bright: #C2734A;
  --accent-soft:   #F2E3D5;
  --on-accent:     #FFFCF6;

  --good: #4E7A3F; --good-bg: #E9EFDD;
  --warn: #97600F; --warn-bg: #F8ECD5;
  --bad:  #A8443C; --bad-bg:  #F7E3DF;
  --info: #3F6E74; --info-bg: #E2EDEE;

  --brand-deep:   #3A2A1E;
  --brand-mid:    #6E4327;
  --brand-bright: #C2734A;
  --brand-line:   #E0B48D;
  --brand-on-dim: #E7D8C6;

  --shadow-xs: 0 1px 2px rgba(76, 58, 34, 0.06);
  --shadow-sm: 0 1px 3px rgba(76, 58, 34, 0.08), 0 1px 2px rgba(76, 58, 34, 0.05);
  --shadow-md: 0 4px 14px rgba(76, 58, 34, 0.10), 0 2px 4px rgba(76, 58, 34, 0.05);
  --shadow-lg: 0 12px 34px rgba(76, 58, 34, 0.15);
}
[data-theme="sandstone"] .sidebar { background: #33251A; border-right: 1px solid #4A3626; }

/* --- OCEAN — deep blue. Cooler and less saturated than Midnight's indigo, with
       a cyan-leaning accent that stays legible on the dark ground. --- */
[data-theme="ocean"] {
  --bg:            #0A1826;
  --bg-tint:       #0E1F30;
  --surface:       #12283C;
  --surface-2:     #163047;
  --text:          #DCEAF5;
  --text-strong:   #F0F7FC;
  --muted:         #9CB4C8;
  --faint:         #6C8399;
  --border:        #1F3D57;
  --border-strong: #2B5170;

  --accent:        #4FA3D1;
  --accent-strong: #7FC2E4;
  --accent-bright: #4FA3D1;
  --accent-soft:   #14304A;
  --on-accent:     #06131F;

  --good: #5FCBA8; --good-bg: #0E2E2C;
  --warn: #E2BE72; --warn-bg: #2C2614;
  --bad:  #EE8C97; --bad-bg:  #31171F;
  --info: #6FC6DE; --info-bg: #0E2B34;

  --brand-deep:   #071522;
  --brand-mid:    #14415F;
  --brand-bright: #4FA3D1;
  --brand-line:   #7FC2E4;
  --brand-on-dim: #A9C6DA;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.45);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 14px 40px rgba(0, 0, 0, 0.65);
}
[data-theme="ocean"] .sidebar { background: #061320; border-right: 1px solid var(--border); }

/* ---------------------------------------------------------------------------
   3. PER-SUBJECT ACCENTS
   Each subject nudges the accent hue within the phthalo-green family so
   subjects are distinguishable at a glance without breaking cohesion.
   Applied via [data-subject] on <body>, set by the router.
   --------------------------------------------------------------------------- */
[data-subject="chemistry"]           { --accent:#1B5E3F; --accent-bright:#2D8A5F; --accent-soft:#E7F3EC; }
[data-subject="physics"]             { --accent:#106B5E; --accent-bright:#1E9686; --accent-soft:#E1F2EF; }
[data-subject="calculus"]            { --accent:#256B4E; --accent-bright:#38946B; --accent-soft:#E6F2EB; }
[data-subject="statistics"]          { --accent:#3F7440; --accent-bright:#5C9A57; --accent-soft:#EAF3E6; }
[data-subject="biology"]             { --accent:#3B8A57; --accent-bright:#55AE76; --accent-soft:#E9F5ED; }
[data-subject="english"]             { --accent:#4C6B3A; --accent-bright:#6E9152; --accent-soft:#EEF3E6; }

:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="chemistry"]           { --accent:#4FA97C; --accent-soft:#12301F; }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="physics"]             { --accent:#3FB6A5; --accent-soft:#0E2E2A; }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="calculus"]            { --accent:#5CB98A; --accent-soft:#123020; }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="statistics"]          { --accent:#7FB86F; --accent-soft:#172E14; }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="biology"]             { --accent:#6BC98C; --accent-soft:#123322; }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) [data-subject="english"]             { --accent:#94B872; --accent-soft:#1E2A14; }

/* ---------------------------------------------------------------------------
   4. BASE / RESET
   --------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; }
/* Smooth-scroll only for in-page anchor jumps (added by JS), so it never
   interferes with normal page scrolling. */
html.smooth-anchors { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background var(--transition), color var(--transition);
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--lh-tight);
  color: var(--text-strong);
  letter-spacing: -0.01em;
}
h1 { font-size: var(--fs-2xl); font-weight: 600; }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); font-family: var(--font-body); font-weight: 700; }

p { line-height: var(--lh-body); }

a { color: var(--accent); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 2px; }

code, kbd, samp { font-family: var(--font-mono); font-size: 0.9em; }

img, svg { max-width: 100%; }

::selection { background: var(--accent-bright); color: #fff; }

:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Scrollbars (subtle, on-theme) */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; border: 3px solid var(--bg); }

/* ---------------------------------------------------------------------------
   5. LAYOUT
   --------------------------------------------------------------------------- */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
  transition: grid-template-columns 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Desktop: the menu button collapses the sidebar to give the content room. */
.app.sidebar-collapsed { grid-template-columns: 0 1fr; }
.app.sidebar-collapsed .sidebar {
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
}
.sidebar { transition: transform 220ms cubic-bezier(0.4,0,0.2,1), opacity 180ms ease; }

/* ---- Sidebar ---- */
.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  background: var(--brand-deep);
  color: #DCEAE1;
  display: flex;
  flex-direction: column;
  padding: var(--sp-5) var(--sp-4);
  border-right: 1px solid rgba(255,255,255,0.06);
}
[data-theme="dark"] .sidebar    { background: #0A1712; border-right: 1px solid var(--border); }
[data-theme="midnight"] .sidebar { background: #080B18; border-right: 1px solid var(--border); }

.brand {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-2) var(--sp-5);
  text-decoration: none;
}
.brand:hover { text-decoration: none; }
/* The mark is an SVG rather than a letter: three climbing bars (credits
   accumulating) under an arc (the goal being tracked toward). It stays legible
   at favicon size, where a serif "N" turned to mush. */
.brand-mark {
  width: 38px; height: 38px; flex: none;
  display: block; border-radius: var(--r-md); overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15), var(--shadow-sm);
  transition: transform var(--transition);
}
.brand-mark svg { display: block; width: 100%; height: 100%; }
.brand:hover .brand-mark { transform: translateY(-1px) scale(1.03); }
@media (prefers-reduced-motion: reduce) { .brand-mark, .brand:hover .brand-mark { transition:none; transform:none; } }
.brand-text { line-height: 1.15; }
.brand-text strong { display:block; color:#fff; font-family: var(--font-display); font-size: 1.02rem; font-weight:600; }
.brand-text span { display:block; color: var(--brand-on-dim); font-size: var(--fs-xs); letter-spacing: 0.02em; }

.nav-label {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--brand-line); font-weight: 600;
  padding: var(--sp-4) var(--sp-2) var(--sp-2);
}

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px var(--sp-3);
  border-radius: var(--r-md);
  color: #CFE0D6;
  font-size: var(--fs-sm); font-weight: 500;
  text-decoration: none;
  transition: background var(--transition), color var(--transition);
  position: relative;
}
.nav-item:hover { background: rgba(255,255,255,0.07); color: #fff; text-decoration: none; }
.nav-item.active { background: rgba(255,255,255,0.12); color: #fff; }
.nav-item.active::before {
  content:""; position:absolute; left:-var(--sp-4); left:0; top:50%; transform:translateY(-50%);
  width:3px; height:60%; border-radius:0 3px 3px 0; background: var(--brand-line);
  margin-left: calc(-1 * var(--sp-4));
}
.nav-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; box-shadow: 0 0 0 2px rgba(0,0,0,0.15); }
.nav-item .nav-meta { margin-left:auto; font-size: var(--fs-xs); color: var(--brand-on-dim); opacity:.8; }

.sidebar-footer { margin-top: auto; padding-top: var(--sp-5); }
.sidebar-progress { padding: var(--sp-3); background: rgba(255,255,255,0.05); border-radius: var(--r-md); }
.sidebar-progress .sp-label { display:flex; justify-content:space-between; font-size: var(--fs-xs); color: var(--brand-on-dim); margin-bottom: 6px; }
.sidebar-progress .sp-label b { color:#fff; font-weight:600; }

/* ---- Main column ---- */
.main { display: flex; flex-direction: column; min-width: 0; }

.topbar {
  position: sticky; top: 0; z-index: 40;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 0 var(--sp-6);
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--border);
}
.menu-toggle { display: grid; }   /* works on desktop (collapse) and mobile (drawer) */

.search-wrap { position: relative; flex: 1; max-width: 520px; }
.search-input {
  width: 100%; height: 40px;
  padding: 0 var(--sp-4) 0 42px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--bg-tint);
  color: var(--text); font-size: var(--fs-sm);
  transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
}
.search-input::placeholder { color: var(--faint); }
.search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); background: var(--surface); }
.search-icon { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: var(--faint); pointer-events: none; }
.search-kbd { position:absolute; right:12px; top:50%; transform:translateY(-50%); font-size:0.7rem; color:var(--faint); border:1px solid var(--border-strong); border-radius:5px; padding:1px 6px; background:var(--surface); }

.search-results {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  max-height: 60vh; overflow-y: auto; padding: var(--sp-2);
  display: none; z-index: 60;
}
.search-results.open { display: block; }
.search-hit { display:block; padding: 10px var(--sp-3); border-radius: var(--r-md); text-decoration:none; color:var(--text); }
.search-hit:hover, .search-hit.sel { background: var(--accent-soft); text-decoration:none; }
.search-hit .sh-title { font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.search-hit .sh-sub { font-size: var(--fs-xs); color: var(--muted); }
.search-hit mark { background: var(--accent-bright); color:#fff; border-radius:3px; padding:0 2px; }
.search-empty { padding: var(--sp-4); color: var(--muted); font-size: var(--fs-sm); text-align:center; }

.topbar-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }
.icon-btn {
  width: 40px; height: 40px; flex:none;
  display: grid; place-items: center;
  border: 1px solid var(--border-strong); border-radius: var(--r-md);
  background: var(--surface); color: var(--muted); cursor: pointer;
  transition: all var(--transition);
}
.icon-btn:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

/* ---- Content ---- */
.content { padding: var(--sp-6) var(--sp-6) var(--sp-8); }
.content-inner { max-width: var(--content-max); margin: 0 auto; animation: fade-up 0.28s ease both; }
@keyframes fade-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Breadcrumb */
.crumbs { display:flex; align-items:center; gap:8px; font-size: var(--fs-sm); color: var(--muted); margin-bottom: var(--sp-4); flex-wrap:wrap; }
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--accent); }
.crumbs .sep { color: var(--faint); }

/* Page header */
.page-head { margin-bottom: var(--sp-6); }
.page-head .eyebrow { display:inline-flex; align-items:center; gap:8px; font-size: var(--fs-xs); font-weight:600; letter-spacing:0.08em; text-transform:uppercase; color: var(--accent); margin-bottom: var(--sp-3); }
.page-head h1 { margin-bottom: var(--sp-3); }
.page-head .lede { font-size: var(--fs-md); color: var(--muted); max-width: 60ch; }

/* ---------------------------------------------------------------------------
   6. COMPONENTS
   --------------------------------------------------------------------------- */

/* ---- Buttons ---- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px; border-radius: var(--r-md);
  font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 600;
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  transition: all var(--transition);
}
.btn:hover { text-decoration: none; }
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-strong); color: var(--on-accent); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn-ghost { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn-sm { padding: 6px 12px; font-size: var(--fs-xs); }

/* ---- Badges / pills ---- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.5;
  background: var(--accent-soft); color: var(--accent-strong);
}
.badge-ext { background: var(--accent); color: var(--on-accent); }
.badge-int { background: var(--accent-soft); color: var(--accent-strong); border:1px solid var(--border-strong); }
.badge-credits { background: transparent; border:1px solid var(--border-strong); color: var(--muted); }
.badge-flag { background: var(--warn-bg); color: var(--warn); }
.badge-done { background: var(--good-bg); color: var(--good); }

/* ---- Cards ---- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-xs);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.card-link { display:block; text-decoration:none; color:inherit; }
.card-link:hover { text-decoration:none; transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }

.grid { display: grid; gap: var(--sp-4); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-auto { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

/* Subject tile (home + subject list) */
.subject-tile { position: relative; overflow: hidden; }
.subject-tile .st-top { display:flex; align-items:flex-start; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.subject-tile .st-icon {
  width: 46px; height: 46px; flex:none; border-radius: var(--r-md);
  display: grid; place-items: center; font-size: 1.4rem;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.subject-tile h3 { font-size: var(--fs-lg); margin-bottom: 2px; }
.subject-tile .st-level { font-size: var(--fs-xs); color: var(--muted); }
.subject-tile .st-blurb { font-size: var(--fs-sm); color: var(--muted); margin-bottom: var(--sp-4); }
.subject-tile .st-foot { display:flex; align-items:center; justify-content:space-between; gap: var(--sp-3); }
.subject-tile .st-accent-bar { position:absolute; top:0; left:0; right:0; height:4px; background: linear-gradient(90deg, var(--accent), var(--accent-bright)); }

/* Progress bar */
.progress { height: 8px; border-radius: var(--r-pill); background: var(--border); overflow: hidden; }
.progress > span { display:block; height:100%; border-radius: var(--r-pill); background: linear-gradient(90deg, var(--accent), var(--accent-bright)); transition: width 500ms cubic-bezier(0.4,0,0.2,1); }
.progress-mini { height: 6px; }
.progress-row { display:flex; align-items:center; gap: var(--sp-3); }
.progress-row .progress { flex:1; }
.progress-row .pr-num { font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; white-space:nowrap; }

/* ---- Standard rows (subject overview) ---- */
.std-list { display:flex; flex-direction:column; gap: var(--sp-3); }
.std-row {
  display:grid; grid-template-columns: auto 1fr auto; gap: var(--sp-4); align-items:center;
  padding: var(--sp-4) var(--sp-5); background: var(--surface);
  border:1px solid var(--border); border-radius: var(--r-lg);
  text-decoration:none; color:inherit; box-shadow: var(--shadow-xs);
  transition: all var(--transition);
}
.std-row:hover { text-decoration:none; border-color: var(--border-strong); transform: translateX(3px); box-shadow: var(--shadow-sm); }
.std-code { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight:600; color: var(--accent); background: var(--accent-soft); padding: 6px 9px; border-radius: var(--r-sm); white-space:nowrap; }
.std-main .std-title { font-weight:600; color: var(--text-strong); font-size: var(--fs-md); }
.std-main .std-blurb { font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }
.std-tags { display:flex; align-items:center; gap: var(--sp-2); flex-wrap:wrap; justify-content:flex-end; }

/* ---- Callouts ---- */
.callout {
  display:flex; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-radius: var(--r-md);
  border:1px solid var(--border); border-left-width: 4px;
  background: var(--surface-2); margin: var(--sp-4) 0;
}
.callout .co-icon { flex:none; font-size:1.1rem; line-height:1.5; }
.callout .co-body { min-width:0; }
.callout h4 { margin-bottom: 4px; font-size: var(--fs-base); }
.callout p { font-size: var(--fs-sm); color: var(--text); }
.callout p + p { margin-top: var(--sp-2); }
.callout-note { border-left-color: var(--info); background: var(--info-bg); }
.callout-note .co-icon { color: var(--info); }
.callout-tip  { border-left-color: var(--good); background: var(--good-bg); }
.callout-tip .co-icon { color: var(--good); }
.callout-warn { border-left-color: var(--warn); background: var(--warn-bg); }
.callout-warn .co-icon { color: var(--warn); }
.callout-mistake { border-left-color: var(--bad); background: var(--bad-bg); }
.callout-mistake .co-icon { color: var(--bad); }

/* ---- Content typography blocks ---- */
.prose { font-size: var(--fs-base); color: var(--text); }
.prose > * + * { margin-top: var(--sp-4); }
.prose p { line-height: var(--lh-body); }
.prose ul, .prose ol { padding-left: 1.4em; }
.prose li { margin: 4px 0; line-height: var(--lh-snug); }
.prose strong { color: var(--text-strong); font-weight: 650; }
.prose h3 { margin-top: var(--sp-6); }
.section { margin: var(--sp-7) 0; }
.section > h2 { display:flex; align-items:center; gap: var(--sp-3); margin-bottom: var(--sp-4); padding-bottom: var(--sp-3); border-bottom: 1px solid var(--border); }
.section-num { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--accent); font-weight:600; }

/* ---- Key points ---- */
.keypoints { background: var(--accent-soft); border:1px solid color-mix(in srgb, var(--accent) 18%, transparent); border-radius: var(--r-lg); padding: var(--sp-5); }
.keypoints h4 { color: var(--accent-strong); margin-bottom: var(--sp-3); display:flex; align-items:center; gap:8px; }
.keypoints ul { list-style:none; padding:0; display:flex; flex-direction:column; gap: var(--sp-2); }
.keypoints li { position:relative; padding-left: 1.7em; font-size: var(--fs-sm); line-height: var(--lh-snug); }
.keypoints li::before { content:"→"; position:absolute; left:0; color: var(--accent); font-weight:700; }

/* ---- Tables ---- */
.table-wrap { overflow-x: auto; border:1px solid var(--border); border-radius: var(--r-lg); margin: var(--sp-4) 0; box-shadow: var(--shadow-xs); }
table.data { width:100%; border-collapse: collapse; font-size: var(--fs-sm); background: var(--surface); }
table.data caption { text-align:left; padding: var(--sp-3) var(--sp-4); font-weight:600; color: var(--text-strong); font-family: var(--font-display); background: var(--surface-2); border-bottom:1px solid var(--border); }
table.data th { text-align:left; padding: 11px var(--sp-4); background: var(--accent-soft); color: var(--accent-strong); font-weight:600; font-size: var(--fs-xs); text-transform:uppercase; letter-spacing:0.03em; border-bottom:1px solid var(--border-strong); white-space:nowrap; }
table.data td { padding: 10px var(--sp-4); border-bottom:1px solid var(--border); vertical-align: top; }
table.data tr:last-child td { border-bottom:none; }
table.data tbody tr:hover { background: var(--bg-tint); }
table.data td.mono, table.data th.mono { font-family: var(--font-mono); }

/* ---- Formula display ---- */
.formula {
  font-family: var(--font-mono); font-size: 1.02rem;
  background: var(--surface-2); border:1px solid var(--border);
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
  overflow-x:auto; color: var(--text-strong); line-height: 1.9;
}
.formula-list { display:flex; flex-direction:column; gap: var(--sp-3); margin: var(--sp-4) 0; }
.formula-item { display:grid; grid-template-columns: 1fr; gap: 6px; padding: var(--sp-4); background: var(--surface); border:1px solid var(--border); border-radius: var(--r-md); border-left:3px solid var(--accent); }
.formula-item .fi-name { font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.formula-item .fi-eq { font-family: var(--font-mono); font-size: 1.05rem; color: var(--accent-strong); padding: 4px 0; overflow-x:auto; }
.formula-item .fi-note { font-size: var(--fs-xs); color: var(--muted); }
sup, sub { line-height: 0; }

/* ---- KaTeX -------------------------------------------------------------
   All maths/chemistry is typeset by KaTeX (see js/math.js). Before it
   renders, the readable source text is shown as a graceful fallback. */
.math { font-family: var(--font-mono); }
.math.is-rendered { font-family: inherit; }
.katex { font-size: 1.05em; }
.formula-item .katex { font-size: 1.12em; }
.katex-display { margin: 0.4em 0; }
/* long equations scroll rather than overflowing the card */
.fi-eq { overflow-x: auto; overflow-y: hidden; padding-bottom: 2px; }
.fi-eq .katex-display > .katex { text-align: left; }
.math-fallback { color: var(--text); font-family: var(--font-mono); }
@media (max-width: 640px) { .katex { font-size: 1em; } .formula-item .katex { font-size: 1.02em; } }
@media print { .katex { color: #000; } }

/* ---- Worked example ---- */
.example { border:1px solid var(--border); border-radius: var(--r-lg); margin: var(--sp-4) 0; overflow:hidden; background: var(--surface); }
.example > summary { cursor:pointer; padding: var(--sp-4) var(--sp-5); font-weight:600; color: var(--text-strong); display:flex; align-items:center; gap: var(--sp-3); list-style:none; background: var(--surface-2); transition: background var(--transition); }
.example > summary:hover { background: var(--accent-soft); }
.example > summary::-webkit-details-marker { display:none; }
.example > summary .ex-tag { font-size: var(--fs-xs); font-weight:600; color: var(--on-accent); background: var(--accent); padding: 3px 9px; border-radius: var(--r-pill); }
.example > summary .ex-chev { margin-left:auto; color: var(--muted); transition: transform var(--transition); }
.example[open] > summary .ex-chev { transform: rotate(90deg); }
.example .ex-body { padding: var(--sp-5); border-top:1px solid var(--border); }
.example .ex-problem { font-size: var(--fs-base); margin-bottom: var(--sp-4); padding: var(--sp-3) var(--sp-4); background: var(--bg-tint); border-radius: var(--r-md); border-left:3px solid var(--accent-bright); }
.ex-steps { counter-reset: step; display:flex; flex-direction:column; gap: var(--sp-3); }
.ex-step { display:flex; gap: var(--sp-3); }
.ex-step::before { counter-increment: step; content: counter(step); flex:none; width:24px; height:24px; border-radius:50%; background: var(--accent-soft); color: var(--accent-strong); font-size: var(--fs-xs); font-weight:700; display:grid; place-items:center; margin-top:2px; }
.ex-step .step-body { font-size: var(--fs-sm); line-height: var(--lh-snug); }
.ex-answer { margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4); background: var(--good-bg); color: var(--good); border-radius: var(--r-md); font-weight:600; font-size: var(--fs-sm); border:1px solid color-mix(in srgb, var(--good) 25%, transparent); }
.ex-answer strong { color: var(--good); }

/* ---- Reveal cards (naming/structure practice) ---- */
.reveal { border:1px solid var(--border); border-radius: var(--r-md); background: var(--surface); overflow:hidden; }
.reveal > summary { cursor:pointer; padding: var(--sp-3) var(--sp-4); list-style:none; display:flex; align-items:center; gap: var(--sp-3); font-size: var(--fs-sm); }
.reveal > summary::-webkit-details-marker { display:none; }
.reveal > summary .rv-q { font-weight:500; }
.reveal > summary .rv-hint { margin-left:auto; font-size: var(--fs-xs); color: var(--accent); font-weight:600; }
.reveal[open] > summary .rv-hint { color: var(--muted); }
.reveal .rv-a { padding: var(--sp-3) var(--sp-4); border-top:1px dashed var(--border); background: var(--surface-2); font-size: var(--fs-sm); }
.reveal-list { display:flex; flex-direction:column; gap: var(--sp-2); margin: var(--sp-4) 0; }

/* ---- Links list (past papers) ---- */
.linklist { display:flex; flex-direction:column; gap: var(--sp-2); margin: var(--sp-3) 0; }
.linkrow { display:flex; align-items:center; gap: var(--sp-3); padding: 11px var(--sp-4); border:1px solid var(--border); border-radius: var(--r-md); background: var(--surface); text-decoration:none; color:inherit; transition: all var(--transition); }
.linkrow:hover { text-decoration:none; border-color: var(--accent); background: var(--accent-soft); transform: translateX(2px); }
.linkrow .lr-icon { color: var(--accent); flex:none; }
.linkrow .lr-main { min-width:0; flex:1; }
.linkrow .lr-label { display:block; font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.linkrow .lr-note { display:block; font-size: var(--fs-xs); color: var(--muted); margin-top:2px; }
.linkrow .lr-ext { flex:none; color: var(--faint); }
.linkrow .lr-verify { flex:none; font-size:0.66rem; padding:2px 7px; border-radius: var(--r-pill); font-weight:600; }
.lr-verify.v-ok { background: var(--good-bg); color: var(--good); }
.lr-verify.v-check { background: var(--warn-bg); color: var(--warn); }

/* ---- Quiz ---- */
.quiz { background: var(--surface); border:1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-sm); }
.quiz-head { display:flex; align-items:center; justify-content:space-between; margin-bottom: var(--sp-4); gap: var(--sp-3); flex-wrap:wrap; }
.quiz-progress-text { font-size: var(--fs-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.quiz-q { font-size: var(--fs-md); font-weight:600; color: var(--text-strong); margin-bottom: var(--sp-4); line-height: var(--lh-snug); }
.quiz-q .qq-num { color: var(--accent); font-family: var(--font-mono); font-size: var(--fs-sm); margin-right:8px; }
.quiz-choices { display:flex; flex-direction:column; gap: var(--sp-3); }
.quiz-choice { display:flex; align-items:center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); border:1.5px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface); cursor:pointer; text-align:left; font-size: var(--fs-sm); color: var(--text); transition: all var(--transition); font-family: var(--font-body); }
.quiz-choice:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
.quiz-choice .qc-key { flex:none; width:26px; height:26px; border-radius:50%; border:1.5px solid var(--border-strong); display:grid; place-items:center; font-weight:700; font-size: var(--fs-xs); color: var(--muted); transition: all var(--transition); }
.quiz-choice.correct { border-color: var(--good); background: var(--good-bg); color: var(--good); }
.quiz-choice.correct .qc-key { border-color: var(--good); background: var(--good); color:#fff; }
.quiz-choice.wrong { border-color: var(--bad); background: var(--bad-bg); color: var(--bad); }
.quiz-choice.wrong .qc-key { border-color: var(--bad); background: var(--bad); color:#fff; }
.quiz-choice:disabled { cursor:default; }
.quiz-explain { margin-top: var(--sp-4); padding: var(--sp-4); border-radius: var(--r-md); background: var(--info-bg); border-left:3px solid var(--info); font-size: var(--fs-sm); display:none; }
.quiz-explain.show { display:block; animation: fade-up 0.25s ease both; }
.quiz-explain b { color: var(--info); }
.quiz-foot { display:flex; align-items:center; justify-content:space-between; margin-top: var(--sp-5); gap: var(--sp-3); }
.quiz-result { text-align:center; padding: var(--sp-5); }
.quiz-result .qr-score { font-family: var(--font-figure); font-size: var(--fs-3xl); color: var(--accent); font-weight:700; font-variant-numeric: tabular-nums; }
.quiz-result .qr-msg { color: var(--muted); margin: var(--sp-2) 0 var(--sp-5); }

/* Short answer input */
.sa-input { width:100%; padding: 10px var(--sp-4); border:1.5px solid var(--border-strong); border-radius: var(--r-md); font-size: var(--fs-sm); font-family: var(--font-body); background: var(--surface); color: var(--text); }
.sa-input:focus { outline:none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.quiz-opts { display:flex; gap: var(--sp-3); flex-wrap:wrap; align-items:center; margin-bottom: var(--sp-4); }
.quiz-opts label { display:inline-flex; align-items:center; gap:6px; font-size: var(--fs-sm); color: var(--muted); cursor:pointer; }

/* ---- Videos ---- */
.video-list { display:flex; flex-direction:column; gap: var(--sp-2); margin: var(--sp-3) 0; }
.video-row { display:flex; align-items:center; gap: var(--sp-3); padding: 11px var(--sp-4); border:1px solid var(--border); border-radius: var(--r-md); background: var(--surface); text-decoration:none; color:inherit; transition: all var(--transition); }
.video-row:hover { text-decoration:none; border-color: var(--accent); background: var(--accent-soft); transform: translateX(2px); }
.vr-play { flex:none; width:32px; height:32px; border-radius: var(--r-sm); display:grid; place-items:center; background:#E8402E; color:#fff; }
.vr-main { flex:1; min-width:0; }
.vr-label { display:block; font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.vr-note { display:block; font-size: var(--fs-xs); color: var(--muted); margin-top:2px; }

/* ---- Flashcards ---- */
.flashcards { background: var(--surface); border:1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-sm); }
.fc-head { display:flex; align-items:center; justify-content:space-between; gap: var(--sp-3); flex-wrap:wrap; margin-bottom: var(--sp-4); }
.fc-progress { font-size: var(--fs-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-scene { perspective: 1600px; }
.fc-card {
  position: relative; width: 100%; min-height: 240px;
  transform-style: preserve-3d; transition: transform 0.5s cubic-bezier(0.4,0,0.2,1);
  cursor: pointer;
}
.fc-card.flipped { transform: rotateY(180deg); }
.fc-face {
  position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border-radius: var(--r-lg); border:1.5px solid var(--border-strong);
  padding: var(--sp-6); display:flex; flex-direction:column; justify-content:center;
  overflow-y: auto;
}
.fc-front { background: linear-gradient(160deg, var(--accent-soft), var(--surface)); }
.fc-back { background: var(--surface-2); transform: rotateY(180deg); border-color: var(--accent); }
.fc-tag { position:absolute; top: var(--sp-3); left: var(--sp-4); font-size:0.66rem; font-weight:600; letter-spacing:0.05em; text-transform:uppercase; color: var(--accent); }
.fc-flip-hint { position:absolute; bottom: var(--sp-3); right: var(--sp-4); font-size: var(--fs-xs); color: var(--faint); }
.fc-q { font-family: var(--font-display); font-size: var(--fs-lg); color: var(--text-strong); text-align:center; line-height: var(--lh-snug); }
.fc-a { font-weight:700; font-size: var(--fs-md); color: var(--accent-strong); margin-bottom: var(--sp-3); }
.fc-explain { font-size: var(--fs-sm); color: var(--text); line-height: var(--lh-body); }
.fc-explain .fc-explain-label { display:block; font-size: var(--fs-xs); text-transform:uppercase; letter-spacing:0.05em; color: var(--muted); margin-bottom: 4px; font-weight:600; }
.fc-controls { display:flex; align-items:center; justify-content:space-between; gap: var(--sp-3); margin-top: var(--sp-4); }
.fc-nav { display:flex; gap: var(--sp-2); }
.fc-count-badge { font-size: var(--fs-xs); color: var(--muted); }
.fc-done { text-align:center; padding: var(--sp-6) var(--sp-4); }
.fc-box-pill { font-size: var(--fs-xs); font-weight:600; padding:3px 9px; border-radius: var(--r-pill);
  background: var(--accent-soft); color: var(--accent-strong); border:1px solid var(--border-strong); }
.fc-grade { display:flex; gap: var(--sp-3); width:100%; justify-content:center; }
.fc-wrong:hover { border-color: var(--bad) !important; color: var(--bad) !important; }
.fc-boxes { display:grid; grid-template-columns:repeat(4,1fr); gap: var(--sp-3); margin: var(--sp-5) 0 0; }
.fc-box { background: var(--surface-2); border:1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-3); }
.fcb-n { display:block; font-family: var(--font-figure); font-size: var(--fs-xl); color: var(--accent); font-weight:700; font-variant-numeric: tabular-nums; }
.fcb-l { display:block; font-size: 0.68rem; color: var(--muted); text-transform:uppercase; letter-spacing:.04em; }
/* "Explain this answer" expander on the card back */
.fc-explain-toggle { margin-top: var(--sp-3); border-top:1px dashed var(--border); padding-top: var(--sp-3); }
.fc-explain-toggle > summary {
  cursor:pointer; list-style:none; font-size: var(--fs-sm); font-weight:600;
  color: var(--topic-accent, var(--accent)); display:inline-flex; align-items:center; gap:6px;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--topic-accent, var(--accent)) 10%, transparent);
}
.fc-explain-toggle > summary::-webkit-details-marker { display:none; }
.fc-explain-toggle > summary:hover { background: color-mix(in srgb, var(--topic-accent, var(--accent)) 18%, transparent); }
.fc-explain-toggle[open] > summary { margin-bottom: var(--sp-2); }
.fc-explain-body { font-size: var(--fs-sm); color: var(--text); line-height: var(--lh-body); text-align:left; }
.fc-done .fcd-num { font-family: var(--font-figure); font-size: var(--fs-2xl); color: var(--accent); font-weight:700; font-variant-numeric: tabular-nums; }

/* ---- Countdown / dashboard widgets ---- */
.dash-grid { display:grid; grid-template-columns: 1.4fr 1fr; gap: var(--sp-5); margin-bottom: var(--sp-6); }
.hero {
  background: linear-gradient(155deg, var(--brand-deep), var(--brand-mid));
  color:#fff; border-radius: var(--r-xl); padding: var(--sp-6);
  position:relative; overflow:hidden;
}
.hero::after { content:""; position:absolute; right:-40px; bottom:-60px; width:220px; height:220px; border-radius:50%; background: radial-gradient(circle, rgba(255,255,255,0.12), transparent 70%); }
.hero h1 { color:#fff; font-size: var(--fs-2xl); margin-bottom: var(--sp-2); }
.hero .hero-sub { color: var(--brand-on-dim); font-size: var(--fs-md); max-width: 46ch; }
.hero-stats { display:flex; gap: var(--sp-6); margin-top: var(--sp-5); }
.hero-stat .hs-num { font-family: var(--font-figure); font-size: var(--fs-2xl); font-weight:700; font-variant-numeric: tabular-nums; line-height:1; }
.hero-stat .hs-label { font-size: var(--fs-xs); color: var(--brand-on-dim); text-transform:uppercase; letter-spacing:0.06em; margin-top:4px; }

.countdown-card { display:flex; flex-direction:column; }
.countdown-card h3 { display:flex; align-items:center; gap:8px; margin-bottom: var(--sp-2); }
.cd-next { text-align:center; padding: var(--sp-4) 0; }
.cd-next .cd-days { font-family: var(--font-figure); font-size: var(--fs-3xl); font-weight:700; font-variant-numeric: tabular-nums; color: var(--accent); line-height:1; }
.cd-next .cd-label { font-size: var(--fs-sm); color: var(--muted); margin-top: var(--sp-2); }
.cd-next .cd-exam { font-weight:600; color: var(--text-strong); margin-top: var(--sp-1); }
.cd-list { display:flex; flex-direction:column; gap: 6px; margin-top: var(--sp-3); max-height: 220px; overflow-y:auto; }
.cd-item { display:flex; align-items:center; gap: var(--sp-3); padding: 8px 10px; border-radius: var(--r-sm); font-size: var(--fs-sm); }
.cd-item:hover { background: var(--bg-tint); }
.cd-item .cd-dot { width:8px; height:8px; border-radius:50%; flex:none; }
.cd-item .cd-name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cd-item .cd-date { font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.cd-item .cd-in { font-size: var(--fs-xs); font-weight:600; color: var(--accent); white-space:nowrap; }

/* Streak */
.streak-card { display:flex; align-items:center; gap: var(--sp-4); }
.streak-flame { font-size: 2.4rem; line-height:1; filter: saturate(1.1); }
.streak-num { font-family: var(--font-figure); font-size: var(--fs-2xl); font-weight:700; font-variant-numeric: tabular-nums; color: var(--accent); }
.streak-sub { font-size: var(--fs-sm); color: var(--muted); }

/* Stat tiles */
.stat-row { display:grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap: var(--sp-4); }
.stat-tile { background: var(--surface); border:1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-4) var(--sp-5); }
.stat-tile .stt-num { font-family: var(--font-figure); font-size: var(--fs-xl); font-weight:700; font-variant-numeric: tabular-nums; color: var(--text-strong); }
.stat-tile .stt-label { font-size: var(--fs-xs); color: var(--muted); text-transform:uppercase; letter-spacing:0.04em; margin-top:2px; }

/* ---- Topic toolbar (review/flag) ---- */
.topic-toolbar { display:flex; align-items:center; gap: var(--sp-3); flex-wrap:wrap; padding: var(--sp-4); background: var(--surface); border:1px solid var(--border); border-radius: var(--r-lg); margin-bottom: var(--sp-6); box-shadow: var(--shadow-xs); }
.toggle-btn { display:inline-flex; align-items:center; gap:8px; padding: 8px 14px; border-radius: var(--r-md); border:1.5px solid var(--border-strong); background: var(--surface); color: var(--text); font-size: var(--fs-sm); font-weight:600; cursor:pointer; transition: all var(--transition); font-family: var(--font-body); }
.toggle-btn:hover { border-color: var(--accent); color: var(--accent); }
.toggle-btn.on-review { background: var(--good-bg); border-color: var(--good); color: var(--good); }
.toggle-btn.on-flag { background: var(--warn-bg); border-color: var(--warn); color: var(--warn); }
.topic-toolbar .tt-spacer { flex:1; }
.topic-toolbar .tt-jump { font-size: var(--fs-sm); }

/* On-page table of contents */
/* Sticky so the section list stays with you as you read.
   NOTE: do NOT add a second `.toc { position: … }` rule below this one — an
   earlier `position: relative` here silently cancelled the stickiness.
   max-height + overflow keep a long list usable on a short window. */
.toc {
  position: sticky;
  top: calc(var(--topbar-h) + var(--sp-5));
  max-height: calc(100vh - var(--topbar-h) - var(--sp-6));
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  padding-right: 2px;
}
.toc::-webkit-scrollbar { width: 6px; }
.toc::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; }
.toc-title { font-size: var(--fs-xs); text-transform:uppercase; letter-spacing:0.08em; color: var(--muted); font-weight:600; margin-bottom: var(--sp-3); position:sticky; top:0; background:var(--bg); padding-bottom: var(--sp-2); }
/* The rail the links sit against — the active marker slides along it. */
.toc a {
  display:block; padding: 5px var(--sp-3); font-size: var(--fs-sm);
  color: var(--muted); border-left:2px solid var(--border); margin-left:1px;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  transition: color .22s cubic-bezier(.4,0,.2,1),
              background-color .22s cubic-bezier(.4,0,.2,1),
              border-left-color .22s cubic-bezier(.4,0,.2,1),
              padding-left .22s cubic-bezier(.4,0,.2,1);
}
.toc a:hover { color: var(--text); background: var(--bg-tint); text-decoration:none; }
.toc a.active {
  color: var(--accent); border-left-color: var(--accent);
  background: var(--accent-soft); text-decoration:none;
  padding-left: calc(var(--sp-3) + 4px);   /* slight nudge in, so it reads as selected */
  font-weight: 600;
}
@media (prefers-reduced-motion: reduce) {
  .toc a { transition: none; }
}

.topic-layout { display:grid; grid-template-columns: 1fr 200px; gap: var(--sp-6); align-items:start; }
.topic-layout .topic-body { min-width:0; }

/* Empty / placeholder state */
.placeholder { text-align:center; padding: var(--sp-8) var(--sp-5); border:2px dashed var(--border-strong); border-radius: var(--r-xl); background: var(--surface-2); }
.placeholder .ph-icon { font-size: 2.4rem; margin-bottom: var(--sp-3); }
.placeholder h3 { margin-bottom: var(--sp-2); }
.placeholder p { color: var(--muted); font-size: var(--fs-sm); max-width: 44ch; margin: 0 auto; }

/* Reaction map (organic pathways) */
.rxn-map { overflow-x:auto; padding: var(--sp-4); background: var(--surface-2); border:1px solid var(--border); border-radius: var(--r-lg); margin: var(--sp-4) 0; }
.rxn-node { display:inline-block; padding: 8px 14px; border-radius: var(--r-md); background: var(--surface); border:1.5px solid var(--accent); color: var(--accent-strong); font-weight:600; font-size: var(--fs-sm); text-align:center; box-shadow: var(--shadow-xs); }
.rxn-reagent { font-size: var(--fs-xs); color: var(--muted); font-style:italic; }

/* ---- Key Definitions panel (prominent, scannable) ---- */
.defs {
  border: 2px solid var(--topic-accent, var(--accent));
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: var(--sp-5); margin: var(--sp-5) 0;
  box-shadow: var(--shadow-sm);
}
.defs h4 {
  color: var(--topic-accent, var(--accent-strong));
  font-size: var(--fs-lg); font-family: var(--font-display);
  margin-bottom: var(--sp-2);
}
.defs-intro { font-size: var(--fs-sm); color: var(--muted); margin-bottom: var(--sp-4); }
.defs-list { display: grid; gap: 0; }
.def-item {
  display: grid; grid-template-columns: minmax(150px, 240px) 1fr;
  gap: var(--sp-4); padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border);
}
.def-item:last-child { border-bottom: none; }
.def-item dt {
  font-weight: 700; font-size: var(--fs-sm); color: var(--text-strong);
  padding-left: var(--sp-3);
  border-left: 3px solid var(--topic-accent, var(--accent));
  line-height: var(--lh-snug);
}
.def-item dd { margin: 0; font-size: var(--fs-sm); color: var(--text); line-height: var(--lh-snug); }
.def-note { display: block; font-size: var(--fs-xs); color: var(--muted); margin-top: 3px; font-style: italic; }
@media (max-width: 640px) {
  .def-item { grid-template-columns: 1fr; gap: var(--sp-1); }
  .def-item dd { padding-left: var(--sp-3); }
}

/* ---- Biology per-topic colour coding ----------------------------------
   Biology only (Chey asked for this to be subject-specific). Each topic gets
   a distinct hue, but all are muted/desaturated so they read as accents
   inside the phthalo-green system rather than clashing with it.
   `--topic-accent` is set on <body> by the router from the topic's `accent`. */
.topic-accent-bar {
  height: 5px; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--topic-accent), transparent 85%);
  margin-bottom: var(--sp-4);
}
[data-topic-accent] .page-head h1 { border-left: 5px solid var(--topic-accent); padding-left: var(--sp-4); margin-left: -1px; }
[data-topic-accent] .page-head .eyebrow { color: var(--topic-accent); }
[data-topic-accent] .section > h2 { border-bottom-color: color-mix(in srgb, var(--topic-accent) 40%, var(--border)); }
[data-topic-accent] .section-num { color: var(--topic-accent); }
[data-topic-accent] .page-head .chip {
  border-color: color-mix(in srgb, var(--topic-accent) 45%, transparent);
  background: color-mix(in srgb, var(--topic-accent) 10%, transparent);
  color: var(--topic-accent);
}
/* flashcard + quiz pick up the topic colour too */
[data-topic-accent] .fc-card.flipped .fc-back,
[data-topic-accent] .fc-front { border-color: color-mix(in srgb, var(--topic-accent) 55%, transparent); }
[data-topic-accent] .fc-tag, [data-topic-accent] .fc-a { color: var(--topic-accent); }
[data-topic-accent] .keypoints {
  border-color: color-mix(in srgb, var(--topic-accent) 30%, transparent);
  background: color-mix(in srgb, var(--topic-accent) 7%, var(--surface));
}
[data-topic-accent] .keypoints h4 { color: var(--topic-accent); }
[data-topic-accent] .keypoints li::before { color: var(--topic-accent); }
[data-topic-accent] table.data th { background: color-mix(in srgb, var(--topic-accent) 12%, var(--surface)); color: var(--topic-accent); }

/* ---- Real-world / motivation panel (subject overview) ---- */
.realworld {
  border-radius: var(--r-lg); padding: var(--sp-5); margin: var(--sp-5) 0 var(--sp-6);
  background: linear-gradient(150deg, color-mix(in srgb, var(--accent) 14%, var(--surface)), var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
}
.realworld h3 { color: var(--accent-strong); margin-bottom: var(--sp-3); font-size: var(--fs-lg); }
.realworld p { font-size: var(--fs-base); line-height: var(--lh-body); color: var(--text); }
.realworld .video-row { margin-top: var(--sp-4); }

/* ---- "How this connects" cross-link panel ---- */
.connects {
  border: 1.5px solid color-mix(in srgb, var(--accent) 35%, transparent);
  background: linear-gradient(150deg, var(--accent-soft), var(--surface));
  border-radius: var(--r-lg); padding: var(--sp-5); margin: var(--sp-5) 0;
}
.connects h4 { color: var(--accent-strong); margin-bottom: var(--sp-2); font-size: var(--fs-md); }
.connects .cx-intro { font-size: var(--fs-sm); color: var(--text); margin-bottom: var(--sp-4); }
.cx-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.cx-item {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: 11px var(--sp-4); border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--border);
  text-decoration: none; color: inherit; transition: all var(--transition);
}
.cx-item:hover { text-decoration: none; border-color: var(--accent); transform: translateX(3px); box-shadow: var(--shadow-sm); }
.cx-arrow { color: var(--accent); font-weight: 700; flex: none; line-height: 1.5; }
.cx-body { min-width: 0; }
.cx-label { display: block; font-weight: 650; font-size: var(--fs-sm); color: var(--accent-strong); }
.cx-why { display: block; font-size: var(--fs-sm); color: var(--muted); line-height: var(--lh-snug); margin-top: 2px; }

/* Chip row */
.chips { display:flex; flex-wrap:wrap; gap: var(--sp-2); }
.chip { padding: 4px 11px; border-radius: var(--r-pill); background: var(--surface-2); border:1px solid var(--border); font-size: var(--fs-xs); color: var(--muted); }

/* Divider */
.hr { height:1px; background: var(--border); border:none; margin: var(--sp-6) 0; }

/* Toast */
.toast { position: fixed; bottom: 24px; left:50%; transform: translateX(-50%) translateY(80px); background: var(--brand-deep); color:#fff; padding: 12px 20px; border-radius: var(--r-pill); font-size: var(--fs-sm); box-shadow: var(--shadow-lg); z-index: 200; opacity:0; transition: all 300ms cubic-bezier(0.4,0,0.2,1); pointer-events:none; }
.toast.show { transform: translateX(-50%) translateY(0); opacity:1; }

/* ---------------------------------------------------------------------------
   7. UTILITIES & RESPONSIVE
   --------------------------------------------------------------------------- */
.muted { color: var(--muted); }
.small { font-size: var(--fs-sm); }
.xs { font-size: var(--fs-xs); }
.center { text-align:center; }
.mono { font-family: var(--font-mono); }
.mt-0 { margin-top:0; } .mt-3 { margin-top: var(--sp-4); } .mt-5 { margin-top: var(--sp-6); }
.mb-3 { margin-bottom: var(--sp-4); } .mb-5 { margin-bottom: var(--sp-6); }
.flex { display:flex; } .items-center { align-items:center; } .gap-3 { gap: var(--sp-3); }
.wrap { flex-wrap:wrap; }
.hidden { display:none !important; }
.nowrap { white-space:nowrap; }

/* Backdrop for mobile sidebar */
.backdrop { position: fixed; inset:0; background: rgba(8,24,15,0.5); z-index: 45; opacity:0; pointer-events:none; transition: opacity var(--transition); }
.backdrop.show { opacity:1; pointer-events:auto; }

/* --- Tablet --- */
@media (max-width: 1100px) {
  :root { --sidebar-w: 232px; }
  .dash-grid { grid-template-columns: 1fr; }
  .topic-layout { grid-template-columns: 1fr; }
  .toc { display:none; }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}

/* --- Mobile --- */
@media (max-width: 780px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; top:0; left:0; bottom:0; width: 280px; z-index: 50;
    transform: translateX(-100%); transition: transform var(--transition);
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .menu-toggle { display:grid; }
  .topbar { padding: 0 var(--sp-4); }
  .search-kbd { display:none; }
  .content { padding: var(--sp-5) var(--sp-4) var(--sp-7); }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .hero-stats { gap: var(--sp-4); flex-wrap:wrap; }
  .std-row { grid-template-columns: 1fr; gap: var(--sp-3); }
  .std-tags { justify-content:flex-start; }
  h1 { font-size: var(--fs-xl); }
  .hero h1, .page-head h1 { font-size: var(--fs-xl); }
}

/* --- Reduced motion --- */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto; }
}


/* ---------------------------------------------------------------------------
   PROGRESS / CREDIT TRACKER
   --------------------------------------------------------------------------- */
.prog-top { display:grid; grid-template-columns: 1.15fr 1fr; gap: var(--sp-5); align-items:start; }
.prog-donut h3, .prog-goal h3 { margin-bottom: var(--sp-4); }
.dn-wrap { display:flex; gap: var(--sp-5); align-items:center; flex-wrap:wrap; }
.donut { flex:none; }
.donut .dn-top { font-family: var(--font-figure); font-size: 30px; font-weight:700; font-variant-numeric: tabular-nums; fill: var(--text-strong); }
.donut .dn-sub { font-size: 12px; fill: var(--muted); font-family: var(--font-body); }
.dn-legend { display:flex; flex-direction:column; gap:7px; min-width:180px; flex:1; }
.dn-key { display:flex; align-items:center; gap:8px; font-size: var(--fs-sm); }
.dn-dot { width:11px; height:11px; border-radius:3px; flex:none; }
.dn-label { color: var(--muted); flex:1; }
.dn-val { font-weight:700; color: var(--text-strong); font-variant-numeric: tabular-nums; }
.goal-picker { display:flex; gap: var(--sp-3); flex-wrap:wrap; }
.goal-picker .sa-input { flex:1; min-width:150px; }
.goal-figure { margin-top: var(--sp-5); }
.gf-num { font-family: var(--font-figure); font-size: var(--fs-2xl); font-weight:700; font-variant-numeric: tabular-nums; color: var(--accent); line-height:1; }
.gf-of { font-size:0.45em; color: var(--muted); }
.subj-bar { margin-bottom: var(--sp-4); }
.subj-bar:last-child { margin-bottom:0; }
.sb-head { display:flex; justify-content:space-between; align-items:center; gap: var(--sp-3); margin-bottom:6px; font-size: var(--fs-sm); }
.sb-head .cd-dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:6px; }
tr.tbl-subj td { background: var(--bg-tint); font-size: var(--fs-sm); }
tr.tbl-subj .cd-dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:6px; }
#credit-table select.sa-input, #credit-table input.sa-input { font-size: var(--fs-xs); }
@media (max-width: 900px) { .prog-top { grid-template-columns: 1fr; } }


/* ---------------------------------------------------------------------------
   COMMAND WORDS + EXAM TIMER
   --------------------------------------------------------------------------- */
.cw-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(320px,1fr)); gap: var(--sp-4); }
.cw-card { background: var(--surface); border:1px solid var(--border); border-left:4px solid var(--accent);
  border-radius: var(--r-lg); padding: var(--sp-5); box-shadow: var(--shadow-xs); }
.cw-head { display:flex; align-items:center; justify-content:space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.cw-head h3 { font-size: var(--fs-md); }
.cw-demands { font-size: var(--fs-sm); color: var(--text); margin-bottom: var(--sp-3); }
.cw-example { font-size: var(--fs-sm); background: var(--bg-tint); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4); border-left:3px solid var(--accent-bright); margin-bottom: var(--sp-3); }
.cw-ex-label { display:block; font-size:0.66rem; text-transform:uppercase; letter-spacing:.06em;
  color: var(--muted); font-weight:700; margin-bottom:4px; }
.cw-note { font-size: var(--fs-xs); color: var(--muted); }

/* Floating exam timer */
.exam-timer { position: fixed; right: 20px; bottom: 20px; z-index: 150; width: 230px;
  background: var(--surface); border:1.5px solid var(--accent); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); padding: var(--sp-4); animation: fade-up .3s ease both; }
.et-head { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.et-dot { width:8px; height:8px; border-radius:50%; background: var(--good); flex:none;
  animation: et-pulse 2s ease-in-out infinite; }
@keyframes et-pulse { 0%,100%{opacity:1} 50%{opacity:.35} }
.et-label { font-size: var(--fs-xs); color: var(--muted); flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.et-close { background:none; border:none; color: var(--faint); cursor:pointer; font-size: var(--fs-sm); padding:2px 4px; }
.et-close:hover { color: var(--bad); }
.et-time { font-family: var(--font-mono); font-size: 2rem; font-weight:600; color: var(--text-strong);
  line-height:1; font-variant-numeric: tabular-nums; }
.et-bar { height:5px; background: var(--border); border-radius: var(--r-pill); overflow:hidden; margin: var(--sp-3) 0 6px; }
.et-bar > span { display:block; height:100%; width:0%; background: var(--accent); transition: width .3s linear; }
.et-foot { font-size: var(--fs-xs); color: var(--muted); }
.exam-timer.is-warning { border-color: var(--warn); }
.exam-timer.is-warning .et-time { color: var(--warn); }
.exam-timer.is-warning .et-bar > span { background: var(--warn); }
.exam-timer.is-warning .et-dot { background: var(--warn); }
.exam-timer.is-done { border-color: var(--bad); }
.exam-timer.is-done .et-time { color: var(--bad); }
.exam-timer.is-done .et-bar > span { background: var(--bad); }
.exam-timer.is-done .et-dot { background: var(--bad); animation:none; }
@media (max-width: 780px) { .exam-timer { right:12px; bottom:12px; width:180px; padding: var(--sp-3); }
  .et-time { font-size:1.5rem; } }

/* Focus-on-this (weak topics) on the dashboard */
.focus-list { display:flex; flex-direction:column; gap: var(--sp-2); }
.focus-item { display:flex; align-items:center; gap: var(--sp-3); padding: 10px var(--sp-4);
  border:1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  text-decoration:none; color:inherit; transition: all var(--transition); }
.focus-item:hover { text-decoration:none; border-color: var(--accent); transform: translateX(3px); }
.fi-score { font-family: var(--font-mono); font-weight:700; font-size: var(--fs-sm);
  padding:3px 9px; border-radius: var(--r-pill); flex:none; }
.fi-score.low { background: var(--bad-bg); color: var(--bad); }
.fi-score.mid { background: var(--warn-bg); color: var(--warn); }
.fi-main { flex:1; min-width:0; }
.fi-title { display:block; font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.fi-sub { display:block; font-size: var(--fs-xs); color: var(--muted); }

/* ---------------------------------------------------------------------------
   PRINTABLE DOUBLE-SIDED FLASHCARDS
   Fixed geometry so fronts and backs line up exactly when duplexed.
   A4 = 210 × 297 mm. With 10mm margins the printable area is 190 × 277 mm.
   A 2 × 4 grid gives cards of 95 × 69.25 mm — we round to 94 × 66 mm and
   centre the grid, leaving a little slack for printer drift.
   --------------------------------------------------------------------------- */
.pc-wrap { max-width: 1000px; }
.pc-sheet { margin: 0 auto var(--sp-6); }
.pc-sheet-label {
  font-size: var(--fs-xs); color: var(--muted); font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: var(--sp-2);
}
.pc-grid {
  display: grid;
  grid-template-columns: repeat(2, 94mm);
  grid-auto-rows: 66mm;
  gap: 0;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
}
.pc-card {
  border: 1px dashed var(--border-strong);
  padding: 6mm 7mm;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: var(--surface);
}
.pc-blank { background: transparent; }
.pc-meta {
  display: flex; justify-content: space-between;
  font-size: 7pt; color: var(--faint); letter-spacing: .04em;
  text-transform: uppercase; margin-bottom: 3mm; flex: none;
}
.pc-body { flex: 1; display: flex; flex-direction: column; justify-content: center; min-height: 0; overflow: hidden; }
.pc-q { font-family: var(--font-display); font-size: 11.5pt; line-height: 1.32; color: var(--text-strong); text-align: center; }
.pc-a { font-weight: 700; font-size: 10.5pt; line-height: 1.3; color: var(--text-strong); margin-bottom: 2mm; }
.pc-x { font-size: 8pt; line-height: 1.34; color: var(--muted); overflow: hidden; }

@media print {
  @page { size: A4 portrait; margin: 10mm; }
  .pc-wrap { max-width: none; }
  .pc-sheet { margin: 0; break-after: page; page-break-after: always; }
  .pc-sheet:last-child { break-after: auto; page-break-after: auto; }
  .pc-sheet-label { display: none; }             /* keep the printed sheet clean */
  .pc-grid { border: none; background: #fff; }
  .pc-card { border: 1px dashed #bbb; background: #fff; break-inside: avoid; }
  .pc-q, .pc-a { color: #000; }
  .pc-x { color: #333; }
  .pc-meta { color: #888; }
}

/* ---- Stacked credit bars (Progress page) ---- */
.stack-bar { display:flex; height:14px; border-radius: var(--r-pill); overflow:hidden; background: var(--border); }
.stack-seg { display:block; height:100%; transition: width 400ms cubic-bezier(0.4,0,0.2,1); }
.stack-seg:not(:last-child) { border-right:1px solid var(--surface); }
.stack-empty { display:block; width:100%; height:100%; background: var(--border); }
.stack-legend { display:flex; flex-wrap:wrap; gap: var(--sp-3) var(--sp-4); }
.sl-key { display:inline-flex; align-items:center; gap:6px; font-size: var(--fs-xs); color: var(--muted); }
.sl-dot { width:11px; height:11px; border-radius:3px; flex:none; }

/* ---- Loading spinner + search hint ---- */
.spinner {
  display:inline-block; width:13px; height:13px; vertical-align:-2px; margin-right:6px;
  border:2px solid var(--border-strong); border-top-color: var(--accent);
  border-radius:50%; animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.search-hint {
  border-top:1px solid var(--border); margin-top: var(--sp-2); padding: 8px var(--sp-3) 2px;
  font-size: 0.7rem; color: var(--faint); text-align:right; letter-spacing:.02em;
}

/* ---- Skeleton loading blocks (charts etc.) ---- */
.skeleton {
  background: linear-gradient(90deg, var(--border) 25%, var(--surface-2) 50%, var(--border) 75%);
  background-size: 200% 100%; animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--r-md);
}
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ---- Empty states ---- */
.empty-state {
  text-align:center; padding: var(--sp-7) var(--sp-5);
  border: 2px dashed var(--border-strong); border-radius: var(--r-xl);
  background: var(--surface-2);
}
.empty-state .es-icon { font-size: 2.2rem; margin-bottom: var(--sp-3); }
.empty-state h3 { margin-bottom: var(--sp-2); }
.empty-state p { color: var(--muted); font-size: var(--fs-sm); max-width: 48ch; margin: 0 auto var(--sp-4); }

/* ---- Motion polish: subtle, fast, and respectful of reduced-motion ---- */
.btn, .toggle-btn, .icon-btn, .nav-item, .card-link, .std-row,
.linkrow, .video-row, .cx-item, .focus-item {
  transition: transform 140ms cubic-bezier(0.4,0,0.2,1),
              box-shadow 140ms ease, background-color 140ms ease,
              border-color 140ms ease, color 140ms ease;
}
.btn:active, .toggle-btn:active, .icon-btn:active { transform: translateY(1px) scale(0.985); }
.card-link:active, .std-row:active { transform: scale(0.995); }
.stack-seg, .progress > span { transition: width 480ms cubic-bezier(0.4,0,0.2,1); }
.donut circle { transition: stroke-dasharray 600ms cubic-bezier(0.4,0,0.2,1); }

/* Visible, consistent focus ring for keyboard users */
:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 2px; border-radius: 4px; }
.nav-item:focus-visible { outline-offset: -2px; }
/* Skip link for keyboard users */
.skip-link {
  position:absolute; left:-9999px; top:0; z-index:300;
  background: var(--accent); color: var(--on-accent);
  padding: 10px 16px; border-radius: 0 0 var(--r-md) 0; font-weight:600; font-size: var(--fs-sm);
}
.skip-link:focus { left:0; text-decoration:none; }

@media (prefers-reduced-motion: reduce) {
  .spinner, .skeleton { animation: none; }
  .stack-seg, .progress > span, .donut circle, .app { transition: none; }
}

/* ---------------------------------------------------------------------------
   INTERNAL DEADLINE PLANNER
   --------------------------------------------------------------------------- */
.int-list { display:flex; flex-direction:column; gap: var(--sp-2); }

/* "What's coming" packs into columns once there is room. Seven stacked rows ran
   to 676px on a 720px viewport, so the card swallowed the whole screen and
   pushed everything below it out of sight. Two columns brings the same seven
   items down to about 250px. */
.due-list {
  display: grid; gap: var(--sp-2);
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
}
.due-item, .int-row {
  display:flex; align-items:center; gap: var(--sp-3);
  padding: 9px var(--sp-4); border:1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface);
  text-decoration:none; color:inherit;
  transition: border-color var(--transition), transform var(--transition);
}
.int-row { padding: 11px var(--sp-4); }
.due-item:hover { text-decoration:none; border-color: var(--accent); transform: translateY(-1px); }
.int-row:hover  { text-decoration:none; border-color: var(--accent); transform: translateX(3px); }
.due-main, .int-main { flex:1; min-width:0; }
.due-title, .int-title { display:block; font-weight:600; font-size: var(--fs-sm); color: var(--text-strong); }
.due-title { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.due-sub   { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.due-sub, .int-meta { display:block; font-size: var(--fs-xs); color: var(--muted); margin-top:2px; }
.int-dot { width:10px; height:10px; border-radius:50%; flex:none; }

.due-pill {
  flex:none; font-size: var(--fs-xs); font-weight:700; padding:3px 10px;
  border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent-strong);
  font-variant-numeric: tabular-nums; white-space:nowrap;
}
.due-pill.soon    { background: var(--warn-bg); color: var(--warn); }
.due-pill.today   { background: var(--bad-bg);  color: var(--bad); }
.due-pill.overdue { background: var(--bad); color:#fff; }

.int-status {
  flex:none; font-size:0.7rem; font-weight:600; padding:3px 10px;
  border-radius: var(--r-pill); border:1px solid transparent; white-space:nowrap;
}
.int-actions { display:flex; gap:6px; flex:none; }

/* form */
.int-form { margin-bottom: var(--sp-5); }
.field { display:block; margin-bottom: var(--sp-4); }
.field > span, .field > legend { display:block; font-size: var(--fs-sm); font-weight:600; color: var(--text-strong); margin-bottom:6px; }
.field .req { color: var(--bad); }
/* Inputs inside a .field previously relied on each page adding .sa-input, so a
   form that did not (the account page) rendered browser-default white boxes on
   a dark background. Style them here instead. */
.field > input, .field > select, .field > textarea {
  width: 100%; padding: 9px 11px; font: inherit; font-size: var(--fs-sm);
  color: var(--text); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.field > input::placeholder, .field > textarea::placeholder { color: var(--faint); }
.field > input:focus, .field > select:focus, .field > textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field > input:disabled, .field > select:disabled { opacity:.6; cursor:not-allowed; }
fieldset.field { border:1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-4); }
.seg { display:flex; gap: var(--sp-2); flex-wrap:wrap; margin-bottom: var(--sp-4); }
.seg-opt { position:relative; }
.seg-opt input { position:absolute; opacity:0; width:0; height:0; }
.seg-opt span {
  display:inline-block; padding:7px 14px; border-radius: var(--r-pill);
  border:1.5px solid var(--border-strong); font-size: var(--fs-sm); cursor:pointer;
  transition: all var(--transition);
}
.seg-opt input:checked + span { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-strong); font-weight:600; }
.seg-opt input:focus-visible + span { outline:2px solid var(--accent-bright); outline-offset:2px; }
.int-error {
  background: var(--bad-bg); color: var(--bad); border-left:3px solid var(--bad);
  padding: 10px var(--sp-4); border-radius: var(--r-sm); font-size: var(--fs-sm);
}

@media (max-width: 640px) {
  /* Give the title its own full-width line. Without this, .int-main (flex:1 1 0
     with min-width:0) gets crushed to ~18px by the fixed-width status pill,
     due pill and action buttons beside it, and the title wraps one word per
     line. The pills and buttons then flow onto a second row underneath. */
  .due-list { grid-template-columns: 1fr; }
  .due-item, .int-row { flex-wrap: wrap; row-gap: var(--sp-2); max-width: 100%; }
  /* min-width:100% was the bug here: it stopped the row shrinking, so a long
     nowrap title pushed the whole card past the viewport and gave the phone a
     horizontal scrollbar. flex-basis still gives the title its own line;
     min-width:0 is what lets the ellipsis actually do its job. */
  .due-main, .int-main { flex: 1 1 100%; min-width: 0; max-width: 100%; order: 1; }
  .due-item .cd-dot, .int-row .int-dot { order: 0; }
  .int-status, .due-pill, .int-row > .xs, .int-actions { order: 2; }
  .int-actions { margin-left: auto; }
}

/* ============================================================================
   Revision session (#/revise)
   ========================================================================== */
.hero-cta { margin-top: var(--sp-5); padding-top: var(--sp-5); border-top:1px solid rgba(255,255,255,0.14); }
.btn-hero {
  background:#fff; color: var(--brand-deep); font-weight:700; border:none;
  padding: 12px 22px; border-radius: var(--r-lg); display:inline-flex; align-items:center; gap:8px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.18); transition: transform .18s ease, box-shadow .18s ease;
}
.btn-hero:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.24); text-decoration:none; }
.hero-cta-sub { color: var(--brand-on-dim); margin-top: 10px; max-width: 48ch; }

.rv-setup .field + .field { margin-top: var(--sp-5); }
.rv-setup legend { font-weight:700; margin-bottom: var(--sp-3); }
.rv-scope { display:grid; grid-template-columns: repeat(auto-fill, minmax(190px,1fr)); gap: var(--sp-3); }
.rv-chip { position:relative; cursor:pointer; }
.rv-chip input { position:absolute; opacity:0; width:0; height:0; }
.rv-chip span {
  display:flex; flex-direction:column; gap:2px; padding: 12px 14px;
  border:1.5px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  transition: border-color .16s ease, background .16s ease, transform .16s ease;
}
.rv-chip span strong { font-size: var(--fs-sm); }
.rv-chip span em { font-style:normal; font-size: var(--fs-xs); color: var(--muted); }
.rv-chip:hover span { transform: translateY(-1px); border-color: var(--brand-line); }
.rv-chip input:checked + span { border-color: var(--accent); background: var(--accent-soft); }
.rv-chip input:focus-visible + span { outline:2px solid var(--accent); outline-offset:2px; }

.rv-loading { display:flex; align-items:center; gap:10px; justify-content:center; padding: 80px 0; color: var(--muted); }

/* --- the run --- */
.rv-bar { height:4px; background: var(--border); border-radius:99px; overflow:hidden; margin-bottom: var(--sp-4); }
.rv-bar-fill { height:100%; background: linear-gradient(90deg, var(--brand-bright), var(--accent)); transition: width .35s cubic-bezier(.4,0,.2,1); }
.rv-head { display:flex; align-items:center; justify-content:space-between; gap: var(--sp-3); flex-wrap:wrap; margin-bottom: var(--sp-5); }
.rv-topic { font-weight:600; font-size: var(--fs-sm); }
.rv-count { font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.rv-scene { margin-bottom: var(--sp-4); }
.rv-quiz { animation: fade-up .28s ease both; }

/* --- summary --- */
.rv-summary { text-align:center; animation: fade-up .3s ease both; }
.rv-ring {
  --pct: 0;
  width:132px; height:132px; margin: 0 auto var(--sp-4); border-radius:50%;
  display:grid; place-items:center;
  background: conic-gradient(var(--accent) calc(var(--pct) * 1%), var(--border) 0);
  position:relative;
}
.rv-ring::before { content:""; position:absolute; inset:10px; border-radius:50%; background: var(--surface); }
.rv-ring-num { position:relative; font-family: var(--font-figure); font-size: 2.1rem; font-weight:700; font-variant-numeric: tabular-nums; }
.rv-ring-num small { font-size: .5em; color: var(--muted); }
.rv-msg { color: var(--muted); max-width: 54ch; margin: 0 auto var(--sp-5); }
.rv-summary .stat-row, .rv-summary .focus-list { text-align:left; }

@media (max-width: 640px) {
  .rv-scope { grid-template-columns: 1fr 1fr; }
  .rv-head { gap: var(--sp-2); }
}

/* ============================================================================
   Internal due-date widget (topic pages)
   ========================================================================== */
.toggle-btn.on-due { border-color: var(--due-col); color: var(--due-col); background: color-mix(in srgb, var(--due-col) 12%, transparent); }
.due-panel {
  border:1px solid var(--border); border-radius: var(--r-lg); background: var(--surface);
  padding: var(--sp-5); margin-bottom: var(--sp-5); animation: fade-up .22s ease both;
}
.dp-head { display:flex; justify-content:space-between; gap: var(--sp-4); flex-wrap:wrap; align-items:flex-start;
  padding-bottom: var(--sp-4); margin-bottom: var(--sp-4); border-bottom:1px solid var(--border); }
.dp-grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(190px,1fr)); gap: var(--sp-4); margin-bottom: var(--sp-4); }
.dp-dates { display:grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.dp-dates.dp-exact { grid-template-columns: 1fr; }
.due-panel .field { margin:0; }
.int-manual { border:1px solid var(--border); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); }
.int-manual > summary { cursor:pointer; font-weight:600; font-size: var(--fs-sm); }
.int-manual[open] > summary { margin-bottom: var(--sp-2); }

/* ============================================================================
   Dashboard: unified "What's coming" + snapshot row
   ========================================================================== */
.due-chips { display:flex; gap: var(--sp-2); flex-wrap:wrap; margin-bottom: var(--sp-4); }
.due-chip {
  display:inline-flex; align-items:center; gap:6px;
  padding: 5px 12px; border-radius:99px; font-size: var(--fs-xs); font-weight:600;
  border:1px solid var(--border); background: var(--surface); color: var(--muted);
  cursor:pointer; transition: border-color .16s ease, background .16s ease, color .16s ease;
}
.due-chip:hover { border-color: var(--brand-line); color: var(--text); }
.due-chip.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.due-chip .dc-n {
  font-variant-numeric: tabular-nums; font-size: 0.9em; opacity:.75;
  padding: 0 5px; border-radius:99px; background: color-mix(in srgb, currentColor 14%, transparent);
}
.linklike { background:none; border:none; padding:0; color: var(--accent); cursor:pointer;
  font: inherit; text-decoration: underline; }

.snapshot { display:grid; grid-template-columns: minmax(180px, 260px) 1fr; gap: var(--sp-5); align-items:start; }
.snap-stats { display:flex; flex-direction:column; gap: var(--sp-3); }
.snap-stat {
  display:grid; grid-template-columns: 28px auto 1fr; align-items:baseline; gap: var(--sp-2);
  color:inherit; text-decoration:none; padding: 6px 8px; border-radius: var(--r-md);
  transition: background .16s ease;
}
a.snap-stat:hover { background: var(--bg-tint); text-decoration:none; }
.snap-icon { font-size: 1.05rem; line-height:1; }
.snap-num { font-family: var(--font-figure); font-size: 1.35rem; font-weight:700; font-variant-numeric: tabular-nums; }
.snap-label { font-size: var(--fs-xs); color: var(--muted); }
.snap-focus { min-width:0; }

@media (max-width: 780px) {
  .snapshot { grid-template-columns: 1fr; gap: var(--sp-4); }
  .snap-stats { flex-direction:row; justify-content:space-between; }
  .snap-stat { grid-template-columns: auto; text-align:center; justify-items:center; }
}

/* ---- Section tabs (grouped nav pages) ---- */
.section-tabs {
  display:flex; gap: var(--sp-2); flex-wrap:wrap;
  border-bottom:1px solid var(--border); margin-bottom: var(--sp-5); padding-bottom: 0;
}
.section-tab {
  padding: 9px 16px; font-size: var(--fs-sm); font-weight:600;
  color: var(--muted); text-decoration:none; border-radius: var(--r-md) var(--r-md) 0 0;
  border:1px solid transparent; border-bottom:none; margin-bottom:-1px;
  transition: color .16s ease, background .16s ease, border-color .16s ease;
}
.section-tab:hover { color: var(--text); background: var(--bg-tint); text-decoration:none; }
.section-tab.on {
  color: var(--accent); background: var(--surface);
  border-color: var(--border); border-bottom: 1px solid var(--surface);
}
@media (max-width: 480px) {
  .section-tab { flex:1 1 auto; text-align:center; padding: 9px 10px; font-size: var(--fs-xs); }
}

/* "I don't know" affordance */
.dunno-note { font-size: var(--fs-xs); color: var(--warn); margin-bottom: var(--sp-2); font-weight:600; }
.fc-dunno { color: var(--muted); }
.fc-dunno:hover { color: var(--warn); border-color: var(--warn); }
#q-dunno, #rv-qdunno { margin-left:auto; margin-right: var(--sp-3); color: var(--muted); }
#q-dunno:hover, #rv-qdunno:hover { color: var(--warn); border-color: var(--warn); }
.auto-badge { font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  padding:2px 6px; border-radius:99px; background: var(--warn-bg); color: var(--warn); margin-left:6px; }
.fc-nearly { color: var(--warn); }
.fc-nearly:hover { border-color: var(--warn); background: var(--warn-bg); }
.fc-grade { display:flex; gap: var(--sp-2); flex-wrap:wrap; justify-content:center; }
@media (max-width: 560px) { .fc-grade .btn { flex:1 1 45%; } }
.sp-link { display:block; color:inherit; text-decoration:none; border-radius: var(--r-sm); }
.sp-link:hover { text-decoration:none; opacity:.85; }

/* ============================================================================
   Calendar (#/calendar)
   ----------------------------------------------------------------------------
   Colour language matches the rest of the site: the dot is the SUBJECT accent,
   the entry style is the KIND (internal filled · derived outlined · external
   solid phthalo). Nothing new is invented.
   ========================================================================== */
.cal-toolbar { display:flex; justify-content:space-between; align-items:center;
  gap: var(--sp-4); flex-wrap:wrap; margin-bottom: var(--sp-5); }
.cal-legend { display:flex; gap: var(--sp-4); flex-wrap:wrap; font-size: var(--fs-xs); color: var(--muted); }
.cl-key { display:inline-flex; align-items:center; gap:6px; }
.cl-swatch { width:14px; height:10px; border-radius:3px; display:inline-block; }
.cl-swatch.k-internal { background: var(--accent); }
.cl-swatch.k-derived  { background: transparent; border:1.5px dashed var(--accent); }
.cl-swatch.k-external { background: var(--brand-deep); border:1px solid var(--brand-bright); }
:is([data-theme="dark"],[data-theme="midnight"],[data-theme="ocean"]) .cl-swatch.k-external { background: var(--accent); }
.cl-swatch.cl-today   { background: var(--warn); }

.cal-months { display:grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--sp-6); }
.cal-month { min-width:0; }
/* A month with nothing in it recedes, but must stay readable — .55 over a dark
   grid was close to invisible. */
.cal-quiet { opacity:.72; }
.cal-quiet .cal-mtitle { opacity:.85; }
.cal-mtitle { margin-bottom: var(--sp-3); font-size: var(--fs-lg); }

.cal-grid { display:grid; grid-template-columns: repeat(7, 1fr); gap:2px;
  background: var(--border); border:1px solid var(--border);
  border-radius: var(--r-md); overflow:hidden; }
.cal-dow { background: var(--bg-tint); padding:5px 2px; text-align:center;
  font-size: 0.66rem; text-transform:uppercase; letter-spacing:.05em;
  color: var(--muted); font-weight:600; }
.cal-cell { background: var(--surface); min-height:62px; padding:3px 3px 4px;
  display:flex; flex-direction:column; gap:2px; }
.cal-pad { background: var(--surface-2); }
.cal-cell.is-past { background: var(--surface-2); }
.cal-cell.is-past .cal-daynum { opacity:.45; }
.cal-daynum { font-size:0.68rem; color: var(--muted); font-variant-numeric: tabular-nums;
  line-height:1; padding:2px; }
.cal-cell.is-today { outline:2px solid var(--warn); outline-offset:-2px; }
.cal-cell.is-today .cal-daynum { color: var(--warn); font-weight:700; }

.cal-ev { display:flex; align-items:center; gap:3px; min-width:0;
  font-size:0.6rem; line-height:1.25; padding:2px 3px; border-radius:3px;
  text-decoration:none; color: var(--text); border:1px solid transparent;
  transition: transform .12s ease, filter .12s ease; }
.cal-ev:hover { text-decoration:none; transform: translateY(-1px); filter: brightness(1.08); }
.cal-dot { width:6px; height:6px; border-radius:50%; background: var(--sub); flex:0 0 auto; }
.cal-ev-txt { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* kind styling — subject colour still carries through via --sub */
.cal-ev.k-internal { background: color-mix(in srgb, var(--sub) 16%, transparent);
  border-color: color-mix(in srgb, var(--sub) 40%, transparent); }
.cal-ev.k-derived  { background: transparent;
  border: 1px dashed color-mix(in srgb, var(--sub) 55%, transparent); }
.cal-ev.k-external { background: color-mix(in srgb, var(--sub) 34%, transparent);
  border-color: var(--sub); font-weight:600; }
.cal-ev.is-span { border-radius:3px; }
/* Continuation days of a multi-day assessment: a plain tinted bar. Repeating
   the dot on every day of a four-day report just makes the week look busy. */
.cal-ev.is-mid  { opacity:.55; }
.cal-ev.is-mid .cal-dot { display:none; }
/* Handed in or graded — still worth seeing, but it shouldn't compete with the
   work you still have to do. Kept in sync with the planner status live. */
.cal-ev.is-done { opacity:.5; }
.cal-ev.is-done .cal-ev-txt { text-decoration: line-through; }
.cal-ev.is-done:hover { opacity:1; }

/* Per-month list. Hidden on desktop (the grid labels do the job) and shown on
   phones, where a 49px cell can only fit a dot. */
.cal-list { display:none; list-style:none; margin: var(--sp-3) 0 0; padding:0; }
.cal-list li + li { margin-top:4px; }
.cal-li { display:flex; gap: var(--sp-3); align-items:baseline; padding:8px 10px;
  border-radius: var(--r-sm); text-decoration:none; color: var(--text);
  background: color-mix(in srgb, var(--sub) 10%, transparent);
  border-left:3px solid var(--sub); }
.cal-li.k-derived { border-left-style: dashed; }
.cal-li.k-external { background: color-mix(in srgb, var(--sub) 20%, transparent); }
.cal-li.is-done { opacity:.55; }
.cal-li.is-done b { text-decoration: line-through; }
.cli-day { font-variant-numeric: tabular-nums; font-weight:700; font-size: var(--fs-sm);
  min-width:2.6em; color: var(--sub); flex:0 0 auto; }
.cli-body { min-width:0; display:flex; flex-direction:column; gap:1px; }
.cli-body b { font-size: var(--fs-sm); font-weight:600; line-height:1.3; }
.cli-meta { font-size: var(--fs-xs); color: var(--muted); }

@media (max-width: 640px) {
  .cal-months { grid-template-columns: 1fr; }
  .cal-cell { min-height:44px; }
  .cal-ev-txt { display:none; }          /* the list below carries the labels */
  .cal-ev { justify-content:center; padding:3px; }
  .cal-ev.is-mid .cal-dot { display:block; }  /* a bar with no dot reads as empty */
  .cal-list { display:block; }
}
@media (prefers-reduced-motion: reduce) { .cal-ev { transition:none; } }

/* ============================================================================
   Theme picker (topbar)
   ========================================================================== */
.theme-picker { position: relative; }
.theme-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  min-width: 250px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg);
  animation: fade-up 140ms ease;
}
.theme-menu[hidden] { display: none; }
.theme-opt {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; padding: 8px 10px; text-align: left;
  background: none; border: 0; border-radius: var(--r-sm);
  color: var(--text); cursor: pointer; font: inherit;
}
.theme-opt:hover { background: var(--bg-tint); }
.theme-opt.on    { background: var(--accent-soft); }
.theme-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Two-tone chip: page background on the left, accent on the right. */
.tw {
  width: 26px; height: 26px; flex: 0 0 auto; border-radius: 7px;
  border: 1px solid var(--border-strong);
  background: linear-gradient(135deg, var(--a) 0 50%, var(--b) 50% 100%);
}
.to-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.to-text strong { font-size: var(--fs-sm); font-weight: 600; }
.to-text em { font-style: normal; font-size: var(--fs-xs); color: var(--muted); }
.to-tick { margin-left: auto; color: var(--accent); font-weight: 700; }

@media (max-width: 640px) {
  .theme-menu { min-width: 210px; }
  .to-text em { display: none; }
}
@media (prefers-reduced-motion: reduce) { .theme-menu { animation: none; } }

/* ============================================================================
   Standards library (Progress page) — browse and add NCEA standards from
   subjects this site doesn't teach.
   ========================================================================== */
.field-inline { display:flex; flex-direction:column; gap:3px; }
.field-inline select, .field-inline input {
  padding: 7px 10px; border:1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text); font: inherit; font-size: var(--fs-sm);
}
.field-inline select:focus, .field-inline input:focus {
  outline:2px solid var(--accent); outline-offset:-1px; border-color: var(--accent);
}

.lib-list { display:flex; flex-direction:column; gap:6px; }
.lib-sub { border:1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); }
.lib-sub > summary {
  display:flex; align-items:center; gap: var(--sp-3);
  padding: 10px 12px; cursor:pointer; list-style:none;
}
.lib-sub > summary::-webkit-details-marker { display:none; }
.lib-sub > summary::before {
  content:'▸'; color: var(--muted); flex:0 0 auto; transition: transform var(--transition);
}
.lib-sub[open] > summary::before { transform: rotate(90deg); }
.lib-sub > summary:hover { background: var(--bg-tint); }
.ls-icon { font-size:1.1rem; flex:0 0 auto; }
.ls-name { display:flex; flex-direction:column; min-width:0; line-height:1.25; }
.ls-name strong { font-size: var(--fs-sm); }
.ls-name em { font-style:normal; font-size: var(--fs-xs); color: var(--muted); }
.lib-sub > summary .badge { margin-left:auto; }
.lib-sub > summary .btn { margin-left: auto; }
.lib-sub > summary .badge + .btn { margin-left: var(--sp-2); }
.lib-table { width:100%; border-top:1px solid var(--border); }
.lib-table td { padding: 7px 12px; font-size: var(--fs-sm); vertical-align: middle; }
.lib-table tr + tr td { border-top:1px solid var(--border); }

.badge-warn { background: var(--warn-bg); color: var(--warn); border:1px solid var(--warn); }
.badge-good { background: var(--good-bg); color: var(--good); border:1px solid var(--good); }
.row-tools { display:inline-flex; gap: var(--sp-3); align-items:center; margin-top:4px; flex-wrap:wrap; }

@media (max-width: 640px) {
  .lib-sub > summary { flex-wrap: wrap; }
  .lib-sub > summary .btn { margin-left: 0; }
  .lib-table td:nth-child(2) { max-width: 40vw; }
}

/* UE goal breakdown. Three thin bars rather than a table: the goal card sits
   beside the donut, so it must not run away down the page. Detail moved into a
   collapsed <details>. */
.ue-breakdown { text-align:left; border-top:1px solid var(--border); padding-top: var(--sp-3); margin-top: var(--sp-3); }
.ue-rows { display:flex; flex-direction:column; gap:5px; }
.ue-row  { display:flex; align-items:center; gap: var(--sp-2); font-size: var(--fs-xs); }
.ue-g    { flex:0 0 4.2em; color: var(--muted); }
.ue-n    { flex:0 0 3.4em; text-align:right; color: var(--muted); font-variant-numeric: tabular-nums; }
.ue-bar  { flex:1; height:6px; border-radius: var(--r-pill); background: var(--bg-tint);
           border:1px solid var(--border); overflow:hidden; }
.ue-bar > i { display:block; height:100%; background: var(--accent); border-radius: var(--r-pill); }
.ue-more > summary { cursor:pointer; color: var(--accent); margin-top: var(--sp-3); font-size: var(--fs-xs); }
 }

/* Cards whose height changes on a filter click must not let the browser's
   scroll-anchoring nudge the page. We restore scroll ourselves. */
#whats-coming, .cal-months { overflow-anchor: none; }

/* ============================================================================
   Per-standard remove control.
   ----------------------------------------------------------------------------
   The X sits OUTSIDE the standard's row, in the gutter to its right, vertically
   centred, and is invisible until that row is hovered. Keeping it out of the
   row means it can never be hit while reaching for a grade or status control.

   .table-wrap clips (overflow-x: auto), so the credit table gets its own
   wrapper that does not, plus a right gutter for the button to live in.
   ========================================================================== */
/* ITEM 1 + 2 + 5 ------------------------------------------------------------
   The assessments table used to sit in .table-wrap, which draws the frame and
   clips to it with overflow:auto. Overriding that to overflow:visible (so the
   X could escape) meant the table's SQUARE corners poked out past the wrapper's
   ROUNDED border, which is the glitched-corner effect. And padding-right:46px
   pushed the wrapper's right border 46px past the table, so the box no longer
   lined up with the cards above it, and that border read as a divider penning
   the X icons in.

   Fixed by moving the frame off the wrapper and onto the table itself. A table
   cannot round its own corners while border-collapse is `collapse`, so this one
   uses `separate` with zero spacing and rounds the four corner cells. The
   wrapper is now a bare positioning context: no border, no padding, edges flush
   with every other box on the page, and the X floats free in the page margin
   outside the frame entirely. */
.credit-wrap {
  overflow: visible;
  border: 0;
  box-shadow: none;
  border-radius: 0;
  padding-right: 0;
}
#credit-table {
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
}
/* `separate` drops the collapsed cell borders, so put the horizontal rules back */
#credit-table td { border-bottom: 1px solid var(--border); }
#credit-table tr:last-child td { border-bottom: 0; }
#credit-table th { border-bottom: 1px solid var(--border-strong); }
/* round the four outer corner cells so the frame closes cleanly */
#credit-table thead tr:first-child th:first-child { border-top-left-radius:  calc(var(--r-lg) - 1px); }
#credit-table thead tr:first-child th:last-child  { border-top-right-radius: calc(var(--r-lg) - 1px); }
#credit-table tbody tr:last-child  td:first-child { border-bottom-left-radius:  calc(var(--r-lg) - 1px); }
#credit-table tbody tr:last-child  td:last-child  { border-bottom-right-radius: calc(var(--r-lg) - 1px); }

#credit-table tr { position: relative; }
.cr-last { position: relative; }

/* The hover BRIDGE.
   ----------------------------------------------------------------------------
   The button sits outside the table, so travelling to it means crossing the
   gap between the table's edge and the button. This transparent strip spans the
   full height of the row and the whole gutter, and is always interactive.
   Because it is a DESCENDANT of the row, tr:hover stays true the whole way
   across, so the button cannot vanish mid-journey. */
.cr-xzone {
  position: absolute; top: 0; bottom: 0; right: -44px; width: 44px;
  display: flex; align-items: center; justify-content: center;
}

/* ITEM 2: floating, slightly skewed, no frame around it. */
.x-btn {
  display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; padding:0;
  border:0; background:none; border-radius: var(--r-sm);
  color: var(--faint);
  cursor:pointer; opacity:0; pointer-events:none;
  transition: opacity .14s ease, color .14s ease, background .14s ease,
              transform .18s cubic-bezier(.34,1.56,.64,1);
}
#credit-table tr:hover .x-btn,
#credit-table tr:focus-within .x-btn { opacity:.7; pointer-events:auto; }
#credit-table tr:hover .x-btn:hover {
  opacity:1; color: var(--bad); background: var(--bad-bg);
  transform: rotate(90deg) scale(1.12);
}
.x-btn:active { transform: rotate(90deg) scale(.9); }
.x-btn:focus-visible { opacity:1; pointer-events:auto; outline:2px solid var(--accent); outline-offset:2px; }

/* Touch has no hover, and no room for a gutter, so show it inline instead. */
@media (hover: none), (max-width: 720px) {
  .credit-wrap { overflow-x: auto; padding-right: 0; }
  .cr-xzone { position: static; width: auto; display: inline-flex; margin-left: var(--sp-2); }
  .x-btn { opacity:.55; pointer-events:auto; }
}

.removed-list { display:flex; gap: var(--sp-2); flex-wrap:wrap; }

@media (prefers-reduced-motion: reduce) {
  .x-btn, .x-btn:hover, .x-btn:active { transition:none; transform:none; }
}

/* Calendar month navigation. One month at a time, with prev/next. */
.cal-nav {
  display:flex; align-items:center; gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.cal-nav-title { font-family: var(--font-display); font-size: var(--fs-lg); font-weight:600; min-width: 11ch; }
.cal-nav .btn { min-width: 34px; font-size: var(--fs-md); line-height:1; }
.cal-nav .btn[disabled] { opacity:.35; cursor:not-allowed; }
.cal-months.one-month { grid-template-columns: 1fr; max-width: 760px; }
.one-month .cal-cell { min-height: 78px; }
@media (max-width: 640px) { .one-month .cal-cell { min-height: 46px; } }

/* ============================================================================
   Account page
   ========================================================================== */
.course-facts { display:grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap: var(--sp-4); margin-top: var(--sp-4); }
.course-facts > div { display:flex; flex-direction:column; gap:2px; padding: var(--sp-3) var(--sp-4);
  background: var(--bg-tint); border:1px solid var(--border); border-radius: var(--r-sm); }
.cf-label { font-size: var(--fs-xs); color: var(--muted); text-transform:uppercase; letter-spacing:.05em; }
.cf-val { font-weight:600; font-size: var(--fs-sm); }

.pw-checks { list-style:none; padding:0; margin: var(--sp-3) 0 0; display:flex; gap: var(--sp-4); flex-wrap:wrap; }
.pw-checks li { font-size: var(--fs-xs); color: var(--muted); display:flex; align-items:center; gap:5px; }
.pw-checks li::before { content:'○'; font-size:.9em; }
.pw-checks li[data-ok="true"] { color: var(--good); }
.pw-checks li[data-ok="true"]::before { content:'●'; }

#acct-signin { opacity:.85; }
#acct-signin input { background: var(--bg-tint); }

.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

/* ITEM 3 + 4: the editable controls inside the assessments table.
   ----------------------------------------------------------------------------
   The status and grade selects were sized by the browser default, so the
   longest option ("Sitting in Nov externals", "Dropped (not assessed)") ran
   under the dropdown arrow. They now reserve room for their widest option plus
   clear space for the arrow. The credits input went the other way: it was a
   fixed 62px holding at most two digits, so it carried obvious dead space. */
#credit-table .cr-status,
#credit-table .cr-grade {
  padding: 6px 30px 6px 10px;          /* right padding clears the arrow */
  background-position: right 9px center;
  text-overflow: ellipsis;
}
#credit-table .cr-status { min-width: 15.5rem; }
#credit-table .cr-grade  { min-width: 8.5rem; }
#credit-table .cr-credits {
  width: 3.4rem;                        /* two digits plus the spinner */
  padding: 6px 6px 6px 9px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* Give each column only the room it needs so the title column keeps the rest. */
#credit-table th:nth-child(3), #credit-table td:nth-child(3) { width: 1%; white-space: nowrap; }
#credit-table th:nth-child(4), #credit-table td:nth-child(4) { width: 1%; }
#credit-table th:nth-child(5), #credit-table td:nth-child(5) { width: 1%; }

@media (max-width: 900px) {
  #credit-table .cr-status { min-width: 12rem; }
  #credit-table .cr-grade  { min-width: 7rem; }
}

/* Removed subjects sit at the bottom of the add list, visually set apart so it
   reads as "things you took away" rather than more catalogue. */
.lib-sub.is-removed { border-color: var(--border-strong); background: var(--bg-tint); }
.lib-sub.is-removed > summary .ls-name em { color: var(--warn); }

/* ---- favourite goal star ------------------------------------------------- */
/* Hollow until starred, solid gold after, with a one-shot sparkle on the click
   that sets it. The sparkle is four pips thrown out on the diagonals; they are
   decorative <i> elements so nothing about them reaches the accessibility tree. */
.goal-picker { align-items: center; }
.goal-star {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  margin-left: auto;                      /* pins it to the right of the row */
  border: 0; background: none; border-radius: var(--r-sm);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform .18s cubic-bezier(.34,1.56,.64,1), background .14s ease;
}
.goal-star svg { width: 19px; height: 19px; overflow: visible; }
.goal-star svg path {
  fill: none;
  stroke: var(--faint);
  stroke-width: 1.6; stroke-linejoin: round;
  transition: fill .22s ease, stroke .22s ease, filter .22s ease;
}
.goal-star:hover { background: var(--bg-tint); transform: scale(1.08); }
.goal-star:hover svg path { stroke: #d8a12a; }
.goal-star:active { transform: scale(.9); }
.goal-star:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.goal-star.is-fav svg path {
  fill: #f0b429;
  stroke: #d8a12a;
  filter: drop-shadow(0 0 4px rgba(240,180,41,.55));
}
.goal-star.is-fav:hover svg path { fill: #f7c948; }

/* the shine sweep across the star as it fills */
.goal-star.is-bursting svg path { animation: gs-pop .45s cubic-bezier(.34,1.56,.64,1); }
@keyframes gs-pop {
  0%   { transform: scale(.5) rotate(-40deg); }
  55%  { transform: scale(1.35) rotate(8deg); filter: drop-shadow(0 0 10px rgba(247,201,72,.95)); }
  100% { transform: scale(1) rotate(0); }
}
.goal-star svg { transform-box: fill-box; transform-origin: center; }

.gs-spark {
  position: absolute; top: 50%; left: 50%;
  width: 4px; height: 4px; margin: -2px 0 0 -2px;
  border-radius: 50%; background: #f7c948;
  opacity: 0; pointer-events: none;
}
.goal-star.is-bursting .gs-spark { animation: gs-spark .52s ease-out forwards; }
.goal-star.is-bursting .gs-spark:nth-child(2) { animation-delay: .04s; --sx:  14px; --sy: -13px; }
.goal-star.is-bursting .gs-spark:nth-child(3) { animation-delay: .02s; --sx: -14px; --sy: -12px; }
.goal-star.is-bursting .gs-spark:nth-child(4) { animation-delay: .07s; --sx:  13px; --sy:  13px; }
.goal-star.is-bursting .gs-spark:nth-child(5) { animation-delay: .05s; --sx: -13px; --sy:  14px; }
@keyframes gs-spark {
  0%   { opacity: 0; transform: translate(0,0) scale(.4); }
  30%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--sx,10px), var(--sy,-10px)) scale(.9); }
}

@media (prefers-reduced-motion: reduce) {
  .goal-star, .goal-star svg path { transition: none; }
  .goal-star.is-bursting svg path, .goal-star.is-bursting .gs-spark { animation: none; }
  .gs-spark { display: none; }
}

/* ---- calendar: holiday and study-leave bands ----------------------------- */
/* Background context, drawn under the events. Deliberately low-contrast: these
   are periods, not deadlines, and must never compete with an exam chip. */
.cal-cell.in-band { position: relative; }
.cal-cell.band-holiday    { background: color-mix(in srgb, var(--good) 9%, transparent); }
.cal-cell.band-studyleave { background: color-mix(in srgb, var(--accent) 11%, transparent); }
.cal-cell.band-studyleave { background-image: repeating-linear-gradient(
    -45deg, transparent 0 6px, color-mix(in srgb, var(--accent) 8%, transparent) 6px 12px); }
.cal-band-label {
  font-size: 0.55rem; line-height: 1.1; font-weight: 700;
  letter-spacing: .02em; text-transform: uppercase;
  color: var(--muted); opacity: .85;
  margin: 0 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-cell.band-holiday    .cal-band-label { color: var(--good); }
.cal-cell.band-studyleave .cal-band-label { color: var(--accent); }
.cl-swatch.cl-holiday    { background: color-mix(in srgb, var(--good) 35%, transparent); }
.cl-swatch.cl-studyleave { background: color-mix(in srgb, var(--accent) 40%, transparent); }

/* ---- skeleton loading ---------------------------------------------------- */
/* Shown only when a route takes more than ~140ms to resolve (see router.js).
   The shimmer is a single moving highlight rather than a pulsing opacity: it
   reads as "working" instead of "broken". */
.sk-wrap { animation: sk-fade .18s ease; }
@keyframes sk-fade { from { opacity: 0 } to { opacity: 1 } }
.sk {
  border-radius: var(--r-sm);
  background: var(--border);
  background-image: linear-gradient(90deg,
    transparent 0%, color-mix(in srgb, var(--surface) 70%, transparent) 50%, transparent 100%);
  background-size: 220px 100%;
  background-repeat: no-repeat;
  animation: sk-shimmer 1.25s ease-in-out infinite;
  margin-bottom: var(--sp-3);
}
@keyframes sk-shimmer {
  from { background-position: -220px 0 }
  to   { background-position: calc(100% + 220px) 0 }
}
.sk-body { margin-top: var(--sp-5); }
.sk-block { margin-bottom: var(--sp-5); }
.sk-row  { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-4); }
.sk-row2 { display: grid; grid-template-columns: 1.6fr 1fr; gap: var(--sp-4); margin-top: var(--sp-4); }
.sk-tile { height: 96px; margin: 0; }
.sk-card { height: 320px; margin: 0; }
.sk-cal  { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.sk-cell { height: 58px; margin: 0; border-radius: var(--r-xs, 4px); }

@media (max-width: 640px) {
  .sk-row  { grid-template-columns: repeat(2, 1fr); }
  .sk-row2 { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; }
  .sk-wrap { animation: none; }
}
