/* ============================================================
   PGCE Programme · BioCE CMU: Uniqcret-blue
   Deep-blue canvas, azure accent, glass surfaces (Canva brand).
   Dark is the default; <html data-scheme="light"> (set by the BioCE
   shell's light/dark toggle and the pre-paint script
   assets/js/scheme-prepaint.js) swaps the tokens for the light navy
   palette below (T-753).
   This stylesheet uses one raster image, the lesson preview poster
   (assets/img/preview-cover.png); everything else is SVG + CSS.
   ============================================================ */

/* Theme tokens. Every colour below the token blocks goes through these, so a
   programme can re-theme the shared sheet with one :root[data-theme] block
   (see "Programme themes" at the end). --accent-rgb / --bg-rgb are the same
   colours as --accent / --bg written as "R G B" so translucent tints can use
   rgb(var(--accent-rgb) / alpha). Keep each pair in step. */
:root {
  --bg: #071426;
  --bg-rgb: 7 20 38;       /* = --bg */
  --bg-2: #0a1c33;
  --bg-glow-1: #155da8;    /* page-top glow, centre */
  --bg-glow-2: #0c2f5b;    /* page-top glow, outer ring */
  --ink: #eef4fb;          /* headings */
  --body-c: #c4d2e4;       /* body text, >9:1 on bg */
  --muted: #8ea2bd;        /* secondary text, >5:1 on bg */
  --accent: #35b8f0;
  --accent-rgb: 53 184 240; /* = --accent */
  --accent-hover: #41e0cc; /* primary button hover */
  --accent-deep: #04263f;
  --accent-soft: rgb(var(--accent-rgb) / 0.14);
  --glass: rgba(255, 255, 255, 0.05);
  --line: rgba(255, 255, 255, 0.09);
  --line-soft: rgba(255, 255, 255, 0.06);
  --radius: 18px;
  --font-display: "Sora", system-ui, sans-serif;
  --font-text: "Inter", system-ui, sans-serif;
  /* Clearance at the top for anchor jumps: the sticky PGCE section nav. */
  --nav-h: 72px;
  /* The PGCE programme section nav below the shell (sticky, in normal flow). */
  --subnav-h: 56px;
  /* Shell + section nav above the hero, so the hero fills the first screen. */
  --chrome-h: 120px;
  /* Scheme tokens (T-753): on the dark page each one is exactly the literal
     its rule used before; html[data-scheme="light"] swaps them. */
  --tint-rgb: 255 255 255;  /* translucent lines/fills laid over the page */
  --halo-rgb: 0 0 0;        /* text-shadow lifting overlay text off the page */
  --selection-ink: #fff;
  --banner-ink: #eaf7ff;    /* live-sessions banner text */
  --note-ink: #9fb8d6;      /* schedule footnote (sits on the page, not a slide) */
  --hud-bg: linear-gradient(160deg, rgba(13, 17, 24, 0.92), rgba(10, 12, 16, 0.78));
  --lock-ring: rgba(10, 12, 16, 0.9);
  --shadow-frame: 0 30px 80px rgba(0, 0, 0, 0.5);
  --shadow-panel: 0 18px 50px rgba(0,0,0,.45);
  --shadow-device: 0 54px 80px -28px rgba(0, 0, 0, 0.72), 0 16px 30px -12px rgba(0, 0, 0, 0.7);
  --shadow-hud: 0 18px 40px -28px rgba(0, 0, 0, 0.9);
  /* Fixed in both schemes (no light value): the play glyph on the phone
     poster, which stays near-black (#04060a) on the light page too. */
  --poster-ink: #35b8f0;
  color-scheme: dark;
}

/* Light scheme (T-753): the shell toggle (and the pre-paint script, from the
   saved 'bioce-scheme') sets <html data-scheme="light">; no attribute = dark.
   Only tokens change. --accent is darkened from the brief's #1273b0 so text
   clears WCAG 2.1 4.5:1 on every light surface it sits on: ink, body and
   muted text and the accent on --bg, --bg-2, the page-top --bg-glow-1 and
   glass; the accent on the icon tint (accent-soft over glass); --accent-deep
   text on --accent and --accent-hover. Tightest pair: accent on accent-soft
   over glass over --bg, 4.52:1. The schedule slides and the phone mock keep
   their own dark surfaces in both schemes. */
html[data-scheme="light"] {
  --bg: #ffffff;
  --bg-rgb: 255 255 255;    /* = --bg */
  --bg-2: #eef4fb;
  --bg-glow-1: #dbeafe;
  --bg-glow-2: #eef4fb;
  --ink: #071426;
  --body-c: #2b3d55;
  --muted: #4f647f;
  --accent: #1068a0;
  --accent-rgb: 16 104 160; /* = --accent */
  --accent-hover: #0d5a8a;
  --accent-deep: #e6f2fa;
  --glass: rgba(7, 20, 38, 0.04);
  --line: rgba(7, 20, 38, 0.12);
  --line-soft: rgba(7, 20, 38, 0.08);
  --tint-rgb: 7 20 38;
  --halo-rgb: 255 255 255;
  --selection-ink: #071426;
  --banner-ink: #071426;
  --note-ink: #4f647f;
  --hud-bg: linear-gradient(160deg, rgba(255, 255, 255, 0.94), rgba(238, 244, 251, 0.86));
  --lock-ring: rgba(255, 255, 255, 0.9);
  --shadow-frame: 0 30px 80px rgba(7, 20, 38, 0.18);
  --shadow-panel: 0 18px 50px rgba(7, 20, 38, 0.22);
  --shadow-device: 0 54px 80px -28px rgba(7, 20, 38, 0.42), 0 16px 30px -12px rgba(7, 20, 38, 0.36);
  --shadow-hud: 0 18px 40px -28px rgba(7, 20, 38, 0.4);
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; overflow-x: clip; }

body {
  font-family: var(--font-text);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--body-c);
  background: radial-gradient(125% 65% at 50% -6%, var(--bg-glow-1) 0%, var(--bg-glow-2) 30%, var(--bg) 64%) var(--bg);
  overflow-x: clip; /* horizontal-scroll track + orbs may overflow */
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
svg { display: block; }
[hidden] { display: none !important; }

::selection { background: rgb(var(--accent-rgb) / 0.32); color: var(--selection-ink); }

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

/* Native anchor jumps (reduced motion / JS or CDN blocked) must clear the
   sticky section nav, Lenis applies its own -76px offset on the smooth path. */
[id] { scroll-margin-top: calc(var(--nav-h) + 8px); }

/* ---------- Thai script fallback ---------- */
:lang(th), [lang="th"] { font-family: "Noto Sans Thai", var(--font-text); }

/* ---------- Global scroll-progress bar ---------- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  z-index: 110;            /* above the sticky section nav (z-index 100); the
                              BioCE shell (z-index 1000) covers it only while the
                              shell is on screen, i.e. near 0% progress */
  width: 100%;
  height: 3px;
  background: var(--line-soft);
  pointer-events: none;
}
.scroll-progress-bar {
  display: block;
  height: 100%;
  background: var(--accent);
  transform-origin: left center;
  transform: scaleX(0);
  will-change: transform;
}

/* ---------- Skip link ----------
   Fixed at the top-left, exactly where the opaque BioCE shell bar sits
   (shell.css: .bx-shell z-index 1000), so it must paint above the shell or
   the focused link is invisible to keyboard users (WCAG 2.4.7). */
.skip-link {
  position: fixed;
  top: 0.6rem; left: 0.6rem;
  z-index: 1100;
  padding: 0.7rem 1.2rem;
  background: var(--accent);
  color: var(--accent-deep);
  font-weight: 600;
  border-radius: 999px;
  transform: translateY(-300%);
}
.skip-link:focus { transform: none; }

/* ---------- Atmosphere: SVG grain (not raster) ---------- */
.grain {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
}

/* ---------- Layout primitives ---------- */
.container { width: min(1180px, 92vw); margin-inline: auto; }

.section {
  padding: clamp(5.5rem, 11vw, 9rem) 0;
  border-top: 1px solid var(--line-soft); /* thin editorial dividers */
}

.section-head { max-width: 720px; margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }
.section-head h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.9rem, 4.2vw, 3.1rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
}
.section-head .lede { margin-top: 1rem; color: var(--muted); font-size: 1.05rem; }

.eyebrow {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.1rem;
}

.tint { color: var(--accent); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-text);
  font-size: 0.95rem;
  font-weight: 600;
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  transition: transform 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}
.btn:hover { transform: translateY(-2px); border-color: rgb(var(--tint-rgb) / 0.2); }

.btn-primary { background: var(--accent); border-color: transparent; color: var(--accent-deep); }
.btn-primary:hover { background: var(--accent-hover); }

.btn-ghost { background: var(--glass); }

.btn-cta { padding: 0.7rem 1.25rem; background: var(--glass); } /* ≥44px tap target */
.btn-cta:hover { border-color: var(--accent); color: var(--accent); }

/* T-778: a status pill in button shape (applications closed), like the
   Courses hub's grey door. Not a link: no hover lift, default cursor. Body
   text on a translucent page-colour fill clears 4.5:1 in both schemes even
   over the brightest hero glow (test_theme_palette.py pins it). */
.btn-closed {
  background: rgb(var(--bg-rgb) / 0.6);
  border: 1px dashed rgb(var(--tint-rgb) / 0.28);
  color: var(--body-c);
  cursor: default;
}
.btn-closed:hover { transform: none; border-color: rgb(var(--tint-rgb) / 0.28); }

/* ---------- PGCE programme section nav ----------
   The BioCE shell is the one site header (brand, site nav, ไทย/EN, sign-in)
   and scrolls away with the page. This bar sits BELOW it in normal flow,
   carries only the programme's own pages, and sticks to the top once the
   shell has scrolled off, so it never covers or duplicates the shell. */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgb(var(--bg-rgb) / 0.82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.nav-inner {
  min-height: var(--subnav-h);
  width: min(1180px, 92vw);
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1rem;
}
.nav-logo {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--ink);
  white-space: nowrap;
}
.nav-links { display: flex; gap: 1.8rem; }
.nav-links a {
  font-size: 0.92rem;
  color: var(--body-c);
  transition: color 0.25s ease;
  /* expand the tap target to ≥44px without shifting the layout */
  padding: 0.75rem 0.5rem;
  margin: -0.75rem -0.5rem;
}
.nav-links a:hover { color: var(--accent); }

/* Right-hand cluster: the fallback language toggle (hidden once the shell's
   own ไทย/EN control is live). Sign-in lives only in the shell. */
.nav-actions { display: flex; align-items: center; gap: 0.9rem; }

/* ---------- Fallback language control (ไทย | EN, T-780) ----------
   Two segments; the segment of the language the page shows is filled
   (aria-checked="true": accent ground, page-ground text), the other is quiet
   body text. Same contract as the shell's switch. */
.lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--glass);
}
.lang-btn {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--body-c);
  font-family: var(--font-text);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1;
  /* ≥36px tall segments; the 3px group padding takes the chip to 44px */
  min-height: 36px;
  padding: 0 0.75rem;
  border-radius: 999px;
  transition: color 0.2s ease, background-color 0.2s ease;
}
.lang-btn[lang="th"] { font-family: "Noto Sans Thai", var(--font-text); }
.lang-btn:hover { color: var(--ink); }
.lang-btn[aria-checked="true"],
.lang-btn[aria-checked="true"]:hover {
  background: var(--accent);
  color: var(--bg);
  cursor: default;
}
.lang-btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 1px; }
@media (forced-colors: active) {
  .lang-btn[aria-checked="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: calc(100vh - var(--chrome-h));  /* fallback for browsers without svh support */
  min-height: calc(100svh - var(--chrome-h));
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-bg {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 72% 8%, rgb(var(--accent-rgb) / 0.07), transparent 55%);
}
.orb {
  position: absolute;
  border-radius: 50%;
  will-change: transform; /* parallax-scrubbed */
}
.orb-a {
  width: 58vmax; height: 58vmax;
  top: -22%; left: -18%;
  background: radial-gradient(circle at 38% 38%, rgb(var(--accent-rgb) / 0.16), transparent 62%);
}
.orb-b {
  width: 44vmax; height: 44vmax;
  top: 24%; right: -20%;
  background: radial-gradient(circle at 45% 45%, rgba(255, 255, 255, 0.05), transparent 60%);
}
.orb-c {
  width: 36vmax; height: 36vmax;
  bottom: -26%; left: 28%;
  background: radial-gradient(circle at 50% 40%, rgb(var(--accent-rgb) / 0.10), transparent 65%);
}
.hero-inner { position: relative; z-index: 2; padding-block: 2rem; }
.hero-kicker {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3.1rem, 10vw, 7.5rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 1.4rem 0 1.6rem;
}
/* mask wrappers give the words a clean clipped reveal; padding keeps descenders */
.word-mask {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.word { display: inline-block; will-change: transform; }
.hero-tagline {
  max-width: 640px;
  margin: -0.4rem 0 1.2rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.3rem, 3vw, 2rem);
  line-height: 1.18;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.hero-sub {
  max-width: 620px;
  font-size: clamp(1.02rem, 1.6vw, 1.2rem);
  color: var(--body-c);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 2.2rem; }
/* T-778: the cohort notice under the hero CTAs (twin spans, see index.html). */
.hero-closed-note {
  max-width: 620px;
  margin-top: 1.4rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 12px;
  background: rgb(var(--bg-rgb) / 0.6);
  color: var(--body-c);
  font-size: 0.95rem;
}
/* scheme-prepaint.js flags html[data-pgce-cohort="ended"] from the second after
   the last learning second, so the closed twin paints before main.js removes
   its hidden flag. The closed rule needs !important because [hidden] has it. */
html[data-pgce-cohort="ended"] [data-pgce-closed-note] [data-note-state="open"] { display: none; }
html[data-pgce-cohort="ended"] [data-pgce-closed-note] [data-note-state="closed"] { display: inline !important; }
.scroll-cue {
  position: absolute;
  bottom: 2.2rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--muted);
}
.scroll-cue span {
  width: 1px; height: 44px;
  background: linear-gradient(var(--accent), transparent);
  transform-origin: top;
  animation: cue 2.2s ease-in-out infinite;
}
@keyframes cue {
  0%, 100% { transform: scaleY(0.25); opacity: 0.4; }
  50% { transform: scaleY(1); opacity: 1; }
}

/* ---------- Live-sessions banner (hero) ----------
   Moved here from an inline <style> block in index.html (T-717) so every
   colour follows the theme tokens; the rules and their behaviour are unchanged. */
.live-banner{display:flex;align-items:center;gap:14px;flex-wrap:wrap;justify-content:center;
  width:100%;max-width:700px;margin:0 0 28px;padding:18px 24px;border-radius:18px;
  color:var(--banner-ink);font-weight:600;font-size:clamp(15px,2.2vw,17px);line-height:1.4;
  background:linear-gradient(100deg,rgb(var(--accent-rgb) / .22),rgb(var(--accent-rgb) / .07));
  border:1px solid rgb(var(--accent-rgb) / .5);box-shadow:0 0 0 0 rgb(var(--accent-rgb) / .5);
  animation:lbPulse 2.4s ease-in-out infinite;transition:transform .15s ease, box-shadow .15s ease;}
.live-banner:hover{transform:translateY(-2px) scale(1.012);box-shadow:0 12px 34px rgb(var(--accent-rgb) / .28);}
.live-banner .lb-live{display:inline-flex;align-items:center;gap:7px;background:#ff4d4f;color:#fff;
  padding:5px 12px;border-radius:999px;font-size:12.5px;font-weight:700;letter-spacing:.07em;white-space:nowrap;}
.live-banner .lb-dot{width:8px;height:8px;border-radius:50%;background:#fff;animation:lbBlink 1.1s steps(2) infinite;}
.live-banner .lb-text{flex:1 1 260px;}
.live-banner .lb-cta{background:var(--accent);color:var(--accent-deep);padding:11px 22px;border-radius:999px;
  font-size:15px;font-weight:700;white-space:nowrap;}
@keyframes lbPulse{0%,100%{box-shadow:0 0 0 0 rgb(var(--accent-rgb) / .5);}50%{box-shadow:0 0 0 9px rgb(var(--accent-rgb) / 0);}}
@keyframes lbBlink{50%{opacity:.2;}}
@media (prefers-reduced-motion: reduce){.live-banner,.live-banner .lb-dot{animation:none;}}

/* ---------- Pillars ---------- */
.pillar-stack { display: grid; gap: 3rem; margin-top: 1rem; }
.pillar {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 5.6vw, 4.2rem);
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--ink);
  will-change: transform; /* crossfaded while pinned */
}
/* .pillars--pinned is added by JS on desktop only (motion allowed) */
.pillars--pinned { height: 100vh; height: 100svh; padding: 0; display: flex; align-items: center; }
.pillars--pinned .pillars-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.pillars--pinned .pillar-stack { display: grid; place-items: center; width: min(1000px, 92vw); }
.pillars--pinned .pillar { grid-area: 1 / 1; }

/* ---------- How it works ---------- */
.how-viewport { position: relative; }
.how-track { display: grid; gap: 1.25rem; will-change: transform; }
.step-card {
  position: relative;
  padding: 2rem;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.step-num {
  display: block;
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.4rem;
}
.step-card h3, .feature-card h3 {
  font-family: var(--font-display);
  font-size: 1.12rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.55rem;
}
.step-card p, .feature-card p { color: var(--muted); font-size: 0.95rem; }

/* .how--horizontal is added by JS on desktop only */
.how--horizontal { height: 100vh; height: 100svh; padding: 0; overflow: hidden; display: flex; }
.how--horizontal .container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100%;
}
.how--horizontal .section-head { margin-bottom: 3rem; }
.how--horizontal .how-track {
  display: flex;
  width: max-content;
  gap: 1.5rem;
  padding-right: 8vw;
}
.how--horizontal .step-card {
  flex: none;
  width: min(400px, 72vw);
  min-height: 290px;
}

/* ---------- Icons ---------- */
.icon {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid rgb(var(--accent-rgb) / 0.25);
  border-radius: 12px;
  margin-bottom: 1.2rem;
}
.icon svg { width: 22px; height: 22px; }

/* ---------- Course schedule (homepage) ----------
   The June 2026 homepage schedule (restored by T-709). Every rule is scoped
   under #schedule so the card classes (.slide, .section-title, .note ...)
   never collide with the rest of the page. Values are June's own. */
#schedule .slides{max-width:1100px;margin:0 auto;display:flex;flex-direction:column;gap:26px;}
#schedule .slide{position:relative;border-radius:22px;overflow:hidden;padding:34px 38px 40px;
  border:1px solid rgba(120,180,240,.25);
  background:
    radial-gradient(120% 130% at 78% 38%, rgba(72,160,220,.42) 0%, rgba(20,80,140,.30) 38%, rgba(9,40,80,.20) 70%, rgba(6,26,55,.10) 100%),
    linear-gradient(135deg,#0a2c57 0%,#0d3e74 45%,#11528f 70%,#0a3360 100%);
  box-shadow:var(--shadow-panel);
  /* navy in both schemes, so its scrollbars (.table-wrap) and controls stay dark */
  color-scheme:dark;}
#schedule .slide-head{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;flex-wrap:wrap;margin-bottom:22px;}
#schedule .head-left{display:flex;align-items:center;gap:20px;flex-wrap:wrap;flex:1 1 420px;}
#schedule .section-pill{display:inline-block;white-space:nowrap;padding:12px 28px;border-radius:16px;
  font-weight:800;font-size:clamp(18px,2.4vw,24px);color:#c8f1ff;text-shadow:0 0 14px rgba(120,220,255,.85);
  background:linear-gradient(180deg,rgba(150,205,245,.5),rgba(40,95,160,.55));border:1px solid rgba(255,255,255,.55);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65),inset 0 -2px 6px rgba(0,0,0,.25),0 6px 16px rgba(0,0,0,.3);}
#schedule .section-title{font-size:clamp(20px,2.8vw,28px);font-weight:800;color:#fff;line-height:1.25;text-shadow:0 2px 10px rgba(0,0,0,.4);}
#schedule .sched-pill{flex:0 0 auto;text-align:center;padding:14px 26px;border-radius:18px;color:#fff;font-weight:700;
  font-size:clamp(14px,1.7vw,17px);line-height:1.35;
  background:linear-gradient(180deg,rgba(255,255,255,.22),rgba(255,255,255,.06));border:1px solid rgba(255,255,255,.45);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 6px 16px rgba(0,0,0,.3);}
#schedule .sched-pill .lbl{display:block;font-weight:600;opacity:.92;}
#schedule .sched-pill .dates{display:block;font-weight:800;margin-top:2px;}
#schedule .pill-group{display:flex;gap:12px;flex-wrap:wrap;flex:0 0 auto;}
#schedule .sched-pill.live{background:linear-gradient(180deg,rgb(var(--accent-rgb) / .34),rgb(var(--accent-rgb) / .10));
  border-color:rgba(120,220,255,.7);box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 0 18px rgb(var(--accent-rgb) / .35),0 6px 16px rgba(0,0,0,.3);}
#schedule .sched-pill.live .lbl{color:#cdeeff;}
#schedule .table-wrap{overflow-x:auto;border-radius:14px;border:1px solid rgba(255,255,255,.12);}
#schedule table.sched{width:100%;border-collapse:collapse;font-size:clamp(13.5px,1.5vw,15.5px);min-width:520px;}
#schedule table.sched thead th{text-align:left;color:#cdeeff;font-weight:700;padding:11px 14px;font-size:12.5px;
  text-transform:uppercase;letter-spacing:.05em;background:rgba(120,180,240,.16);border-bottom:2px solid rgba(150,205,245,.45);}
#schedule table.sched td{padding:9px 14px;border-bottom:1px solid rgba(255,255,255,.09);vertical-align:top;color:#eaf4ff;}
#schedule table.sched tbody tr:last-child td{border-bottom:none;}
#schedule table.sched tbody tr:hover td{background:rgba(255,255,255,.045);}
#schedule table.sched .grp td{font-weight:800;color:#cdeeff;background:rgba(120,180,240,.12);
  text-shadow:0 0 10px rgba(120,220,255,.4);letter-spacing:.01em;}
#schedule table.sched .c-date{white-space:nowrap;color:#bcd5ee;width:160px;}
#schedule table.sched .c-hrs{white-space:nowrap;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;color:#9fe0ff;width:80px;}
#schedule th.c-date,#schedule th.c-hrs{text-align:left;}
#schedule th.c-hrs{text-align:right;}
#schedule .sec-total{margin-top:14px;text-align:right;font-weight:700;color:#bfe6ff;font-size:14px;}
#schedule .sec-total b{color:#9fe0ff;}
#schedule .note{max-width:1100px;margin:24px auto 0;color:var(--note-ink);font-size:13px;text-align:center;line-height:1.6;}
#schedule .schedule-cta{text-align:center;margin-top:24px;}
@media (max-width:640px){
  #schedule .slide{padding:24px 18px 30px;}
  #schedule .sched-pill{width:100%;}
}

/* ---------- Lesson preview / player ---------- */
.cinema {
  max-width: 960px;
  margin-inline: auto;
  padding: clamp(0.6rem, 1.4vw, 1rem);
  background: linear-gradient(160deg, rgb(var(--tint-rgb) / 0.08), rgb(var(--tint-rgb) / 0.02));
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 8px);
  box-shadow: var(--shadow-frame), 0 0 120px rgb(var(--accent-rgb) / 0.06);
}
.player {
  position: relative;
  aspect-ratio: 16 / 9; /* reserves space: no layout shift when the iframe lands */
  border-radius: var(--radius);
  overflow: hidden;
  /* June 2026 "How to sign in" poster (restored by T-709) */
  background: #07090d url("../img/preview-cover.png") center / cover no-repeat;
}
/* once the iframe is playing it sits above this; drop the poster so a paused
   frame never shows the cover bleeding through translucent areas */
.player.is-playing { background-image: none; }
.player-stage iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.player-lock {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  background: radial-gradient(80% 80% at 50% 40%, rgb(var(--accent-rgb) / 0.05), transparent 70%);
}
.lock-icon {
  width: 52px; height: 52px;
  color: var(--accent);
  animation: lock-float 3.6s ease-in-out infinite;
}
@keyframes lock-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}
.lock-text {
  position: relative;
  overflow: hidden;
  padding: 0.2rem 0.5rem;
  font-size: 1rem;
  letter-spacing: 0.04em;
  color: var(--body-c);
}
.lock-text::after { /* shimmer sweep: transform only */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, 0.16) 50%, transparent 70%);
  transform: translateX(-110%);
  animation: shimmer 3s ease-in-out infinite;
}
@keyframes shimmer {
  60%, 100% { transform: translateX(110%); }
}
.player-play {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 4;
  width: 88px; height: 88px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgb(var(--accent-rgb) / 0.4);
  background: rgb(var(--accent-rgb) / 0.12);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--accent);
  cursor: pointer;
  transition: transform 0.25s ease, background-color 0.25s ease;
}
.player-play:hover { transform: translate(-50%, -50%) scale(1.07); background: rgb(var(--accent-rgb) / 0.2); }
.player-play svg { width: 32px; height: 32px; }
.watermark {
  position: absolute;
  z-index: 5;
  left: 6%; top: 8%;
  opacity: 0.28;
  pointer-events: none;       /* never blocks playback controls */
  user-select: none;
  -webkit-user-select: none;
  max-width: 92%;             /* belt-and-braces: wraps instead of clipping */
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.65);
}
.player-caption {
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
  margin-top: 1.3rem;
}

/* ---------- Features ---------- */
.features-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 1.25rem;
}
.feature-card {
  padding: 1.8rem;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

/* ---------- Numbers ---------- */
.numbers-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.25rem;
}
.stat { padding: 1.6rem 0 1.6rem 1.4rem; border-left: 1px solid var(--line); }
.stat-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.6rem, 5.5vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.stat-label { margin-top: 0.5rem; color: var(--muted); font-size: 0.92rem; }

/* ---------- Curriculum timeline ---------- */
.timeline { position: relative; max-width: 760px; }
.timeline-rail {
  position: absolute;
  left: 10px; top: 6px; bottom: 6px;
  width: 2px;
  background: var(--line);
  border-radius: 2px;
}
.timeline-progress {
  position: absolute;
  inset: 0;
  background: linear-gradient(var(--accent), rgb(var(--accent-rgb) / 0.35));
  transform-origin: top; /* draws downward with scaleY scrub */
  border-radius: 2px;
}
.timeline-list { display: grid; gap: 3.2rem; }
.tl-node { position: relative; padding-left: 3.4rem; }
.tl-dot {
  position: absolute;
  left: 1px; top: 0.35rem;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid var(--line);
  background: var(--bg-2);
  transition: border-color 0.4s ease, box-shadow 0.4s ease, background-color 0.4s ease;
}
.tl-node.is-lit .tl-dot {
  border-color: var(--accent);
  background: rgb(var(--accent-rgb) / 0.22);
  box-shadow: 0 0 0 5px var(--accent-soft);
}
.tl-tag {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.4s ease;
}
.tl-node.is-lit .tl-tag { color: var(--accent); }
.tl-body h3 {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0.4rem 0 0.5rem;
}
.tl-body p { color: var(--muted); max-width: 56ch; }
.lesson-types { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }
.lesson-types li {
  font-size: 0.8rem;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--glass);
  color: var(--body-c);
}

/* ---------- Access ---------- */
.access-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 1.5rem;
}
.access-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 2.4rem;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.access-panel h3 {
  font-family: var(--font-display);
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.7rem;
}
.access-panel > p { color: var(--muted); }
.access-panel .btn { margin-top: 1.6rem; }
.micro { font-size: 0.83rem; color: var(--muted); margin-top: 1rem; }

/* ---------- What's New ---------- */
.whatsnew { position: relative; }
.whatsnew-grid {
  display: grid;
  /* give the device column more room now that the phone is larger */
  grid-template-columns: 1fr 1.05fr;
  align-items: center;
  gap: clamp(2.5rem, 6vw, 5rem);
}
.whatsnew-grid .section-head { margin-bottom: 0; max-width: 30ch; }
.whatsnew-grid .section-head h2 { margin-bottom: 0.9rem; }
.whatsnew-grid .section-head .lede { color: var(--body-c); }
.whatsnew-visual {
  display: flex;
  justify-content: center;
  align-items: center;
  /* a settled perspective so the slight scroll-tilt reads as 3-D, not skew */
  perspective: 1600px;
  perspective-origin: 50% 42%;
}

/* ---- Smartphone mockup (pure CSS/SVG, no raster) ----
   Figma device-mockup quality: titanium rim, glass screen, dynamic island,
   layered ambient + contact shadows, a faint screen gloss, and a teal glow. */
.phone-mock {
  position: relative;
  /* BIGGER device so the 9:16 clip is large and clearly watchable.
     Was clamp(222px, 27vw, 286px); bumped up substantially. */
  width: clamp(280px, 34vw, 392px);
  aspect-ratio: 9 / 19.5;          /* modern handset proportion */
  margin-inline: auto;
  transform-style: preserve-3d;
  /* will-change is added by JS only while a tween is live, then removed */
}
/* Soft teal aura + a wide ambient glow pool behind the device (decorative) */
.phone-glow {
  position: absolute;
  inset: -34% -56% -20%;
  z-index: 0;
  border-radius: 50%;
  background:
    radial-gradient(closest-side at 50% 38%, rgb(var(--accent-rgb) / 0.22), rgb(var(--accent-rgb) / 0) 70%),
    radial-gradient(closest-side at 50% 64%, rgb(var(--accent-rgb) / 0.10), rgb(var(--accent-rgb) / 0) 72%);
  filter: blur(10px);
  pointer-events: none;
}
/* Outer titanium band: gives the chassis a thin, brushed metallic edge */
.phone-frame {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  border-radius: 13.4% / 6.2%;     /* proportional rounding tracks the screen */
  padding: 3.4%;                   /* bezel thickness, proportional */
  background:
    linear-gradient(145deg, #5b626d 0%, #20242c 18%, #2b3038 50%, #181b22 82%, #4b515b 100%);
  box-shadow:
    /* ambient drop shadow (large, soft, low) + contact shadow (tight, dark,
       directly under the device); softer on the light page (--shadow-device) */
    var(--shadow-device),
    /* polished metal rim highlights */
    0 0 0 1px rgba(255, 255, 255, 0.10) inset,
    0 1px 1px rgba(255, 255, 255, 0.22) inset,
    0 -1px 1px rgba(0, 0, 0, 0.5) inset;
}
/* Inner black bezel ring that frames the glass (sits between rim and screen) */
.phone-frame::before {
  content: "";
  position: absolute;
  inset: 2.2%;
  z-index: 1;
  border-radius: 11.6% / 5.4%;
  background: #04060a;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.9) inset;
}
/* Dynamic-island pill: floats over the screen, true to-scale */
.phone-island {
  position: absolute;
  top: 2.6%; left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  width: 34%;
  aspect-ratio: 5 / 1.5;
  border-radius: 999px;
  background: #04060a;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.9) inset,
    0 0 0 1px rgba(255, 255, 255, 0.04);
}
/* faux front camera dot inside the island */
.phone-island::after {
  content: "";
  position: absolute;
  top: 50%; right: 16%;
  width: 26%;
  aspect-ratio: 1;
  transform: translateY(-50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, #0d3a5e 0%, #04101f 70%);
  box-shadow: 0 0 0 1px rgb(var(--accent-rgb) / 0.18);
}
/* Side buttons (decorative): titanium, soft top highlight */
.phone-button {
  position: absolute;
  z-index: 0;
  width: 2.5px;
  border-radius: 3px;
  background: linear-gradient(180deg, #5b626d, #2b3038 40%, #181b22);
  box-shadow: 1px 0 1px rgba(0, 0, 0, 0.5);
}
.phone-button-vol-up  { left: -3.5px; top: 21%; height: 7%; }
.phone-button-vol-dn  { left: -3.5px; top: 30.5%; height: 7%; }
.phone-button-power   { right: -3.5px; top: 25%; height: 12%; box-shadow: -1px 0 1px rgba(0, 0, 0, 0.5); }
/* The glass display: clips the video to the rounded screen */
.phone-screen {
  position: absolute;
  inset: 3.4%;                     /* sits inside the bezel padding */
  z-index: 2;
  border-radius: 9.6% / 4.4%;
  overflow: hidden;
  background: #04060a;
  isolation: isolate;              /* keep the gloss blend local to the screen */
}
/* Faint diagonal glass gloss + top vignette on the screen (above video, below UI) */
.phone-screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: inherit;
  background:
    linear-gradient(125deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 22%),
    radial-gradient(140% 60% at 50% -10%, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0) 60%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
  mix-blend-mode: screen;
}
/* Video shell: holds the runtime-injected iframe. COVER-FILL technique:
   a YouTube Short (9:16) is rendered inside YouTube's 16:9 PLAYER, which
   pillarboxes the clip. To make the 9:16 clip fill the 9:16 screen edge-to-edge,
   we oversize the iframe so its 16:9 player is taller AND wider than the screen,
   then clip the bars with overflow:hidden on .phone-screen.
   Math: to show only the centred 9:16 video strip at screen width W, the player
   must be P_w = W·(16/9)² ≈ 3.16·W wide; that makes it exactly screen-height tall.
   We express it as: iframe height = screen height, aspect-ratio 16/9 → width
   = height·16/9 ≈ 3.16× visible width. A small overscan crops residual 1px chrome.
   The screen is 9:19.5 (taller than 9:16), so we scale by HEIGHT (the larger
   overflow) to guarantee no top/bottom gap, accepting extra left/right crop. */
.phone-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: #04060a;
}
.phone-video iframe,
.phone-video .phone-video-frame {
  position: absolute;
  top: 50%; left: 50%;
  /* COVER BY HEIGHT. The iframe holds YouTube's 16:9 player; the 9:16 clip sits
     as a centred vertical strip of width = player_height·(9/16). With:
        iframe height  = 106% of screen height H  (H = W·19.5/9, 6% overscan)
        aspect-ratio   = 16/9  → iframe width = 1.06·H·16/9
     the visible centred strip = iframe_width·(81/256) ≈ 1.29·W > screen width W,
     so the clip overflows the screen on all four sides → NO bars, NO chrome.
     overflow:hidden on .phone-screen / .phone-video crops the surplus. */
  height: 106%;
  aspect-ratio: 16 / 9;
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: auto;
}
/* Poster overlay shown before the API initialises / while paused (fallback).
   A real <button> so the no-GSAP / reduced-motion click-to-play stays
   keyboard-accessible; in the primary path it fades out once ready. */
.phone-poster {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  cursor: pointer;
  background:
    radial-gradient(120% 80% at 50% 38%, rgb(var(--accent-rgb) / 0.16), rgba(4, 6, 10, 0.92) 70%),
    #04060a;
  transition: opacity 0.55s ease;
}
.phone-mock.is-ready .phone-poster { opacity: 0; pointer-events: none; }
.phone-poster-play {
  width: 30%; max-width: 64px;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgb(var(--accent-rgb) / 0.5);
  background: rgb(var(--accent-rgb) / 0.16);
  color: var(--poster-ink);  /* fixed: the poster is near-black in both schemes */
  box-shadow: 0 0 24px rgb(var(--accent-rgb) / 0.25);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.phone-poster-play svg { width: 42%; height: 42%; }
/* Small round speaker toggle: the persistent mute/unmute control. Sits over
   the lower-left of the screen once the video is playing; toggles sound on/off. */
.phone-sound {
  position: absolute;
  z-index: 5;
  left: 7%; bottom: 5%;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  color: #fff;
  background: rgba(4, 6, 10, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  cursor: pointer;
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.35s ease, transform 0.35s ease, background 0.2s ease;
}
.phone-mock.is-playing .phone-sound { opacity: 1; transform: scale(1); }
.phone-sound:hover { background: rgb(var(--accent-rgb) / 0.22); }
.phone-sound svg { width: 19px; height: 19px; display: block; }
.phone-sound .icon-on { display: none; }
.phone-sound[aria-pressed="true"] .icon-on { display: block; }
.phone-sound[aria-pressed="true"] .icon-off { display: none; }

/* PROMINENT "Tap for sound" pill: the obvious unmute affordance over the
   muted, playing video. JS adds .is-muted-hint while playing+muted and removes
   it the instant sound comes on. It overlays the whole screen so a tap anywhere
   on the phone unmutes; the pill itself is the visible call-to-action. */
.phone-sound-hint {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  margin: 0;
  width: 100%;
  cursor: pointer;
  background: linear-gradient(180deg, rgba(4, 6, 10, 0) 40%, rgba(4, 6, 10, 0.5) 100%);
  color: #fff;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease, visibility 0.4s ease;
}
/* Visible only while the video is playing AND still muted */
.phone-mock.is-playing.is-muted .phone-sound-hint { opacity: 1; visibility: visible; }
.phone-sound-hint .hint-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1.1rem;
  border-radius: 999px;
  background: rgb(var(--accent-rgb) / 0.92);
  color: var(--accent-deep);
  font-family: var(--font-text);
  font-weight: 700;
  font-size: clamp(0.86rem, 1.6vw, 1rem);
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
  animation: hint-pulse 2.2s ease-in-out infinite;
}
.phone-sound-hint .hint-pill svg { width: 20px; height: 20px; flex: none; }
@keyframes hint-pulse {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-3px) scale(1.035); }
}

/* ---------- Flexible Learning ---------- */
.flexible-body {
  max-width: 60ch;
  font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  line-height: 1.9;
  color: var(--body-c);
}

/* ---------- What You'll Learn ---------- */
.learn-card { display: flex; flex-direction: column; }
.learn-card h3 { margin-bottom: 0; }
/* numbered icon variant: reuses the 44x44 teal icon box */
.icon-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  color: var(--accent);
}

/* ---------- What You'll Learn · RPG level-up ----------
   BASELINE (this block, no `.learn--rpg`): the HUD + FX layers + lock glyphs +
   "NEW SKILL!" badges are all hidden, every skill card is the normal lit glass
   card at full opacity. This is what renders with JS disabled, with GSAP blocked,
   AND under prefers-reduced-motion, so the section is always a readable list of
   all 12 areas. The dramatic RPG visuals appear only once learn-rpg.js (motion
   allowed) adds `.learn--rpg` to the section.  The `.learn-stage` is a transparent
   wrapper in the baseline; it only becomes a pinned full-height stage when JS
   adds `.learn--rpg`. */
.learn .learn-hud,
.learn .learn-flash,
.learn .skill-lock,
.learn .skill-ring,
.learn .skill-new { display: none; }

/* === Active RPG mode (class added by JS, motion-allowed branch only) === */
.learn--rpg .learn-hud { display: flex; }
.learn--rpg .skill-lock { display: grid; }
.learn--rpg .skill-ring { display: block; }
.learn--rpg .skill-new { display: block; }

/* Pinned stage: JS pins this while the level climbs; it holds the HUD + grid
   centred in the viewport so the skills pop in front of a settled frame. The
   flash overlay is positioned against it. */
.learn--rpg .learn-stage {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}

/* HUD: Lv badge + glowing EXP bar. Sits at the top of the pinned stage. */
.learn-hud {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 2vw, 1.4rem);
  margin-bottom: clamp(1.6rem, 4vw, 2.6rem);
  padding: 0.85rem 1rem;
  background: var(--hud-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: var(--shadow-hud);
}
.hud-badge {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(58px, 14vw, 78px);
  aspect-ratio: 1;
  border-radius: 14px;
  background: radial-gradient(120% 120% at 50% 18%, var(--accent-soft), rgb(var(--accent-rgb) / 0.04));
  border: 1px solid rgb(var(--accent-rgb) / 0.4);
  box-shadow: 0 0 0 1px rgb(var(--accent-rgb) / 0.08), 0 0 22px -6px rgb(var(--accent-rgb) / 0.45);
  line-height: 1;
  transform-origin: 50% 55%;
  will-change: transform;
}
.hud-lv-label {
  font-family: var(--font-display);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.12em;
}
.hud-lv-num {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 4.4vw, 2.2rem);
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* MAX LEVEL flair: badge pulses accent once Lv 100 hit */
.learn-hud.is-max .hud-badge {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgb(var(--accent-rgb) / 0.25), 0 0 34px -2px rgb(var(--accent-rgb) / 0.8);
}
.learn-hud.is-max .hud-lv-label { letter-spacing: 0.18em; }

.hud-bar { flex: 1 1 auto; min-width: 0; }
.hud-bar-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}
.hud-bar-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(0.78rem, 2.2vw, 0.95rem);
  letter-spacing: 0.04em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hud-bar-exp {
  flex: none;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.hud-bar-track {
  position: relative;
  height: 14px;
  border-radius: 999px;
  background: rgb(var(--tint-rgb) / 0.06);
  border: 1px solid var(--line);
  overflow: hidden;
}
.hud-bar-fill {
  position: absolute;
  inset: 0;
  transform: scaleX(0);
  transform-origin: left center;
  border-radius: inherit;
  background: linear-gradient(90deg, rgb(var(--accent-rgb) / 0.55), var(--accent));
  box-shadow: 0 0 16px -2px rgb(var(--accent-rgb) / 0.75);
  will-change: transform;
}
/* travelling sheen on the EXP fill (cosmetic; halts under the reduced-motion
   global kill-switch below) */
.hud-bar-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  transform: translateX(-100%);
  animation: hud-sheen 2.2s ease-in-out infinite;
}
@keyframes hud-sheen { to { transform: translateX(100%); } }

/* ── Skill cards in RPG mode ──
   LOCKED is genuinely HIDDEN, not just dimmed: the card starts invisible,
   shrunk and blurred behind a lock plate so the grid reads as empty slots and
   each unlock is an obvious POP, not a brightening. JS sets the entry tween
   (autoAlpha/scale/blur) so we keep the CSS default at the *visible* end state
   for fail-open. The locked look below is applied by JS via gsap.set on enter. */
.learn--rpg .learn-card {
  position: relative;
  overflow: visible;        /* let the ring flare and NEW badge spill out */
  transition: border-color 0.45s ease, box-shadow 0.45s ease;
}
/* Locked slot plate: the empty socket a skill drops into. Shown only while
   the card has NOT unlocked; JS handles the card's own opacity/transform. */
.learn--rpg .learn-card:not(.unlocked) {
  border-style: dashed;
  border-color: rgb(var(--tint-rgb) / 0.14);
  background: rgb(var(--tint-rgb) / 0.018);
}
.learn--rpg .learn-card:not(.unlocked) .icon { /* drain the teal from the icon box */
  color: var(--muted);
  background: rgb(var(--tint-rgb) / 0.04);
  border-color: var(--line);
}
.learn--rpg .learn-card:not(.unlocked) .icon-num { opacity: 0; }
.learn--rpg .learn-card:not(.unlocked) h3 { color: var(--muted); }

/* CSS-drawn padlock, centred over the icon box while locked */
.skill-lock {
  position: absolute;
  top: 1.8rem; left: 1.8rem;
  width: 44px; height: 44px;
  place-items: center;
  pointer-events: none;
  z-index: 2;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.skill-lock::before { /* shackle */
  content: "";
  width: 13px; height: 11px;
  border: 2.4px solid var(--muted);
  border-bottom: none;
  border-radius: 7px 7px 0 0;
  margin-bottom: -1px;
}
.skill-lock::after {  /* body */
  content: "";
  width: 19px; height: 14px;
  border-radius: 3px;
  background: var(--muted);
  box-shadow: 0 0 0 2px var(--lock-ring);
}
.learn-card.unlocked .skill-lock { opacity: 0; transform: scale(0.4); }

/* Burst RING: a flare ring that expands once on unlock. JS toggles .is-burst;
   transform/opacity only (scale + fade). Sits centred on the icon box. */
.skill-ring {
  position: absolute;
  top: calc(1.8rem + 22px); left: calc(1.8rem + 22px);
  width: 44px; height: 44px;
  margin: -22px 0 0 -22px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transform: scale(0.3);
  will-change: transform, opacity;
}
.skill-ring.is-burst { animation: skill-ring-burst 0.72s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes skill-ring-burst {
  0%   { opacity: 0.9; transform: scale(0.3); border-width: 3px; }
  70%  { opacity: 0.35; }
  100% { opacity: 0; transform: scale(3.4); border-width: 0.5px; }
}

/* "NEW SKILL!" badge: pops over the top-right corner on unlock, then settles
   into a quiet "unlocked" tag. JS toggles .is-pop for the one-shot entrance. */
.skill-new {
  position: absolute;
  top: -10px; right: 12px;
  z-index: 5;
  padding: 0.28rem 0.6rem;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-deep);
  background: var(--accent);
  border-radius: 999px;
  box-shadow: 0 6px 18px -6px rgb(var(--accent-rgb) / 0.8);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px) scale(0.6);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.learn-card.unlocked .skill-new { opacity: 1; transform: translateY(0) scale(1); }
.skill-new.is-pop { animation: skill-new-pop 0.7s cubic-bezier(0.16, 1.3, 0.3, 1); }
@keyframes skill-new-pop {
  0%   { opacity: 0; transform: translateY(10px) scale(0.4); }
  55%  { opacity: 1; transform: translateY(-4px) scale(1.18); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* UNLOCKED skill: lit, accent border, soft glow. Entry transform is JS-driven. */
.learn--rpg .learn-card.unlocked {
  border-style: solid;
  border-color: rgb(var(--accent-rgb) / 0.5);
  background: var(--glass);
  box-shadow: 0 0 0 1px rgb(var(--accent-rgb) / 0.12), 0 22px 50px -28px rgb(var(--accent-rgb) / 0.6);
}
.learn--rpg .learn-card.unlocked .icon {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: rgb(var(--accent-rgb) / 0.35);
}
.learn--rpg .learn-card.unlocked .icon-num { opacity: 1; }
.learn--rpg .learn-card.unlocked h3 { color: var(--ink); }

/* Big "LEVEL UP!" flash: centred over the pinned stage, fires on each unlock. */
.learn-flash {
  position: absolute;
  inset: 0;
  z-index: 25;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.3rem;
  pointer-events: none;
  opacity: 0;
}
.learn-flash.is-flash { animation: learn-flash-burst 0.95s ease-out; }
@keyframes learn-flash-burst {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}
.flash-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 9vw, 5rem);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--accent);
  text-shadow: 0 0 40px rgb(var(--accent-rgb) / 0.6), 0 8px 30px rgb(var(--halo-rgb) / 0.7);
}
.learn-flash.is-flash .flash-title { animation: flash-title-pop 0.95s cubic-bezier(0.16, 1.1, 0.3, 1); }
@keyframes flash-title-pop {
  0%   { transform: scale(0.5); }
  45%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}
.flash-sub {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(0.85rem, 2.6vw, 1.05rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 4px 18px rgb(var(--halo-rgb) / 0.8);
}

/* ---------- Footer ---------- */
.footer { border-top: 1px solid var(--line-soft); padding: 3rem 0 3.5rem; }
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2rem;
}
.footer-brand { font-family: var(--font-display); font-weight: 600; color: var(--ink); }
.footer-note { font-size: 0.85rem; color: var(--muted); margin-top: 0.35rem; }
.footer-meta { font-size: 0.85rem; color: var(--muted); display: grid; gap: 0.3rem; }
.footer-meta a {
  color: var(--body-c);
  transition: color 0.25s ease;
  /* underline via text-decoration so the expanded tap target keeps it on the text */
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
  display: inline-block;
  padding: 0.6rem 0;
  margin: -0.6rem 0;
}
.footer-meta a:hover { color: var(--accent); }

/* ---------- Responsive ---------- */
/* breakpoint matches the JS matchMedia split at 768px */
@media (max-width: 767.98px) {
  /* Programme pages stay reachable on phones: a swipeable row under the title. */
  .nav-inner { padding-top: 0.6rem; }
  .nav-links {
    order: 3;
    width: 100%;
    gap: 1.4rem;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-links a { white-space: nowrap; padding: 0.7rem 0; margin: 0; }
  .nav-actions { gap: 0.55rem; }
  .lang-toggle { padding: 0.15rem 0.4rem; }
  .whatsnew-grid { grid-template-columns: 1fr; gap: clamp(1.8rem, 7vw, 2.6rem); }
  .whatsnew-grid .section-head { max-width: none; text-align: center; margin-inline: auto; }
  .whatsnew-visual { order: -1; } /* visual sits above the heading when stacked */
  /* Bigger on mobile too: fills more of the width so the clip is watchable,
     still capped so it never overflows the gutter. */
  .phone-mock { width: clamp(240px, 74vw, 320px); }

  /* RPG HUD on mobile: keep the badge + bar side-by-side (compact). */
  .learn-hud { gap: 0.75rem; padding: 0.7rem 0.8rem; }
  /* On a short mobile viewport the pinned stage scrolls internally if the 12
     slots can't all fit; min-height stays at the visual viewport. */
  .learn--rpg .learn-stage { min-height: 100svh; }
  .learn--rpg .learn-grid { gap: 0.8rem; }
}

/* ---------- Reduced motion: kill all CSS animation/transition ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .scroll-cue { display: none; }
}

/* ---------- Programme themes ----------
   A programme page opts in with <html data-theme="NAME">; only tokens change,
   so every rule above re-colours itself. PGCE (no data-theme) keeps the
   defaults in the first :root block. The BioCE shell header keeps its own
   --bx-* tokens (estate blue) on every theme. data-theme (which programme)
   and data-scheme (light or dark, T-753) are separate attributes.
   The light block (html[data-scheme="light"]) does not cover wine: no page
   under app/web sets data-theme="wine", and this block (0,2,0) would
   outrank the light tokens (0,1,1) if one ever did.

   wine: the PGCS programme (T-717). Contrast (WCAG 2.1, checked by
   PGCS website/deploy/check_contrast.py): ink, body and muted text and the
   accent all clear 4.5:1 on --bg and --bg-2; button text on --accent clears
   4.5:1. --bg-glow-1 is only the faint page-top glow behind the hero. */
:root[data-theme="wine"] {
  --bg: #1a0610;
  --bg-rgb: 26 6 16;       /* = --bg */
  --bg-2: #2a0b18;
  --bg-glow-1: #8f1f3a;
  --bg-glow-2: #4a0d20;
  --ink: #fbeff2;
  --body-c: #ecd3da;
  --muted: #c39aa6;
  --accent: #e8637a;
  --accent-rgb: 232 99 122; /* = --accent */
  --accent-hover: #f08397;
  --accent-deep: #3a0816;
}
