/* SerVC AML Training – design system
   Layout: one focused 600px learning column (path / lesson / exam), a full-width workspace for admin.
   Look: SerVC gold on cool slate ink; Duolingo-style chunky, pressable controls; Cayman content in sea blue.
   Light Orca-inspired restyle (Oct 2026, orcainc.com – docs/motion/orca-style-notes.md): Poppins display headlines in
   a soft near-black (--ink-head), pill buttons, 20px cards with a soft translucent edge (--edge) instead of shadows,
   sentence-case accent eyebrows, a little more air on home / path. The gold brand accent stays.
   Theme: <html data-theme="light|dark"> is always set before first paint (inline script in each page, kept in sync by
   theme.js – stored choice, otherwise the device setting), so the dark token set below exists exactly once.
   Contrast (QA 5 Oct 2026): every text token ≥ 4.5:1 on --bg, --raised and --sunken in both themes; the on-colour on
   --gold / --ok / --bad / --sea ≥ 4.5:1; --focus and --field (input edges) ≥ 3:1. Re-check when changing a colour. */
:root {
  --auth-step: #30281B;
  --bg: #F4F5F7;
  --raised: #FFFFFF;
  --sunken: #E9ECF0;
  --line: #E0E3E9;
  --line-strong: #C7CDD6;
  --field: #7E8693;        /* edge of text inputs – 3:1 against the surface they sit on */
  --focus: #8A5F14;        /* focus ring – gold ink in light, gold in dark */
  --seg: #FFFFFF;          /* the active segment of a segmented control (tabs, admin nav) */
  --ink: #12161C;
  --ink-head: #2B3038;     /* display headlines: a soft near-black (Orca uses #303030) – 13.3:1 on --raised, 11.2:1 on --sunken */
  --ink-2: #545D6B;
  --ink-3: #606874;
  --edge: rgba(18, 22, 28, .08);   /* soft translucent card edge (Orca-style) – decorative, the surface colour carries the shape */
  --halo: rgba(18, 22, 28, .05);   /* a 4px soft ring for a hovered card, instead of a drop shadow */

  --gold: #D9A445;
  --gold-press: #A87526;
  --gold-ink: #8A5F14;
  --gold-wash: #FBF0DA;
  --on-gold: #1D1505;

  --ok: #188357;
  --ok-press: #0F5E3D;
  --ok-ink: #12704A;
  --ok-wash: #E2F5EB;
  --bad: #D03A37;
  --bad-press: #9E2B29;
  --bad-ink: #AE2F2D;
  --bad-wash: #FCE8E7;
  --sea: #1C7DA4;
  --sea-press: #135C79;
  --sea-ink: #15688A;
  --sea-wash: #E0F0F7;
  --on-color: #FFFFFF;
  --flame: #C2541B;        /* streak icon */

  /* the signature pad is paper in both themes (black ink, saved as a transparent PNG onto a white certificate) */
  --paper: #FFFFFF;
  --paper-ink: #606874;
  --paper-rule: #C7CDD6;

  --locked: #DCE0E6;
  --locked-press: #C2C8D1;
  --locked-ink: #6E7581;
  --scrim: rgba(18, 22, 28, .45);
  --shadow: 0 1px 2px rgba(18, 22, 28, .06), 0 8px 24px rgba(18, 22, 28, .08);
  --shadow-seg: 0 1px 2px rgba(0, 0, 0, .08), 0 2px 8px rgba(0, 0, 0, .06);

  /* Poppins (600 / 700 only) for display headlines. Its Google Fonts build has no tabular figures, so numbers that count
     up or must align (score ring, stat pills, tables) stay in the body face with tabular-nums. */
  --font-display: "Poppins", "Segoe UI", system-ui, sans-serif;
  --font-body: "Instrument Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;

  /* type scale for UI text (headings keep their own display sizes) */
  --fs-label: 12px;    /* mono labels, eyebrows, table heads, pills */
  --fs-xs: 13.5px;
  --fs-sm: 14.5px;
  --fs-md: 15.5px;
  --fs-ui: 16px;       /* buttons, options; also the iOS no-zoom minimum for fields */
  --fs-base: 17px;

  --r-xs: 6px;
  --r-sm: 10px;
  --r-ctl: 12px;       /* small controls and tiles */
  --r-md: 16px;
  --r-lg: 20px;        /* cards and panels (Orca: 20–24px) */
  --r-xl: 26px;
  --r-pill: 999px;
  --press: 4px;
  --tap: 44px;         /* minimum touch target on coarse pointers */

  /* Motion. Things that enter, leave or answer a press use a strong ease-out and stay well under 300ms – lesson cards
     are seen ~150 times per course, so they must feel instant. Things that change shape on screen (outline opening,
     chevron) use ease-in-out. Exits are faster than entrances. The critically damped spring (Apple, damping 1.0) is
     kept for the rare "fill" moments: score and progress rings. Never ease-in, never `transition: all`. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --spring: cubic-bezier(0.23, 1, 0.32, 1);   /* fallback = --ease-out; replaced by a linear() spring curve below where supported */
  --dur-down: 40ms;    /* the press itself */
  --dur-color: 150ms;  /* colour / border changes */
  --dur-press: 160ms;  /* release after a press */
  --dur-fast: 200ms;   /* menus, feedback, small things */
  --dur-card: 260ms;   /* lesson / exam card, toast, dialog, outline, progress */
  --dur-nudge: 280ms;  /* the wrong-answer head-shake */
  --dur-exit: 150ms;   /* everything leaves faster than it came */
  --dur-ring-sm: 700ms;   /* home progress ring (spring) */
  --dur-ring: 1100ms;     /* exam score ring (spring) */
  --dur-spin: 600ms;      /* one spinner turn – brisk spinners make waiting feel shorter */
  --slide: 12px;       /* how far a lesson card travels in (short – it is seen constantly) */
  --lift: 8px;         /* feedback / toast rise */
  --stagger-lift: 6px; /* items following their card in */
  --pop-y: -6px;       /* menus and dialogs grow out of their trigger */
  --pop-s: .96;
  --nudge: 6px;        /* the "wrong answer" head-shake */
  --card-blur: 2px;    /* bridges the old and new lesson card; 0 under reduced motion */
  /* Rare moments (motion pass 3): celebrations grow from 90 % (never from 0), reveals step 60 ms apart */
  --dur-moment: 420ms;    /* trophy / milestone / certificate entrances – rare tier only */
  --dur-sheen: 900ms;     /* one-time highlight sweep on a freshly earned certificate */
  --spinner-delay: 400ms; /* a page spinner shows only when loading takes longer than this */
  --stagger: 60ms;        /* rare reveals (result, lesson complete); lesson cards keep their 35 ms steps */
  --moment-s: .9;         /* scale a celebration element grows from; 1 under reduced motion */
  color-scheme: light;
}
:root[data-theme="dark"] {
  --auth-step: #30281B;
  --bg: #0E1115; --raised: #161A20; --sunken: #0A0C0F; --line: #242A32; --line-strong: #36404B;
  --field: #606A77; --focus: #E2B055; --seg: #2A313B;
  --ink: #EEF0F3; --ink-head: #EEF0F3; --ink-2: #A4ACB8; --ink-3: #7E8794;
  --edge: rgba(255, 255, 255, .07); --halo: rgba(255, 255, 255, .05);
  --gold: #E2B055; --gold-press: #94691F; --gold-ink: #EBC071; --gold-wash: #2A2213; --on-gold: #1D1505;
  --ok: #36C47F; --ok-press: #1F8353; --ok-ink: #5CD69A; --ok-wash: #11261B;
  --bad: #EE6461; --bad-press: #A13D3B; --bad-ink: #F58B88; --bad-wash: #2C1615;
  --sea: #48ADD4; --sea-press: #24718F; --sea-ink: #76C6E5; --sea-wash: #0F222B; --on-color: #0B0D10;
  --flame: #F08A4B;
  --paper: #ECE9E2; --paper-ink: #5A616C; --paper-rule: #B5BBC4;
  --locked: #252B33; --locked-press: #191D23; --locked-ink: #7E8794;
  --scrim: rgba(0, 0, 0, .6); --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 30px rgba(0, 0, 0, .35);
  --shadow-seg: 0 1px 2px rgba(0, 0, 0, .5), inset 0 0 0 1px var(--line-strong);
  color-scheme: dark;
}

@supports (transition-timing-function: linear(0, 1)) {
  :root { --spring: linear(0, 0.0012 0.5%, 0.0105 1.7%, 0.0351 3.2%, 0.0789 5%, 0.142 7.2%, 0.2215 9.6%, 0.3122 12.3%, 0.4082 15.2%, 0.5037 18.3%, 0.5942 21.7%, 0.6761 25.3%, 0.7474 29%, 0.8074 33%, 0.8562 37.1%, 0.8949 41.5%, 0.9247 46%, 0.9471 50.7%, 0.9635 55.5%, 0.9753 60.5%, 0.9836 65.7%, 0.9893 71.1%, 0.9931 76.5%, 0.9956 82.2%, 0.9973 88%, 0.9983 93.9%, 1); }
}
/* lets the ring fills animate (a registered number interpolates; a plain custom property would jump) */
@property --p { syntax: '<number>'; inherits: false; initial-value: 0; }
/* --n: an integer that can animate – drives the counting numbers (XP, score, ring %) with the same curve as the rings */
@property --n { syntax: '<integer>'; inherits: false; initial-value: 0; }

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; interpolate-size: allow-keywords; scrollbar-gutter: stable; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh; min-height: 100dvh;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
/* a dialog is open: the page behind it does not scroll */
html:has(.modal-scrim:not(.out)) { overflow: hidden; }
/* lesson / exam: no pull-to-refresh or rubber-band reload that would lose the answers given so far */
html:has(.player) { overscroll-behavior-y: none; }
/* Theme switch (theme.js): one cross-fade of the whole page instead of the body fading while panels and bars snap.
   Opacity only, so it stays under reduced motion (a brightness change is eased, not removed). */
::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--dur-fast); animation-timing-function: var(--ease-out); }
:root:active-view-transition body { transition: none; }
a { color: var(--gold-ink); text-underline-offset: 3px; }
button { font: inherit; cursor: pointer; color: inherit; }
/* Response: no tap delay, no grey flash, no accidental text selection on controls that are pressed repeatedly */
a, button, summary, label, .option, .chip { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.btn, .option, .chip, .next-card, .tabs button, .lesson-row, summary { -webkit-user-select: none; user-select: none; }
input, select, textarea { font: inherit; color: inherit; }
img { max-width: 100%; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
h1[tabindex="-1"]:focus, h2[tabindex="-1"]:focus { outline: none; }
a:not([class]):focus-visible { border-radius: var(--r-xs); }
.hidden, [hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
svg.i { width: 1.15em; height: 1.15em; flex: 0 0 auto; vertical-align: -0.18em; }

/* Poppins is wide with tall ascenders: tracking tightens as the size grows (Apple: size-specific tracking), leading
   stays a touch looser than a condensed face would need. 700 for page titles, 600 for everything below. */
h1, h2, h3 { font-family: var(--font-display); color: var(--ink-head); text-wrap: balance; }
h1 { font-size: clamp(27px, 6vw, 36px); line-height: 1.14; font-weight: 700; letter-spacing: -0.022em; margin: 6px 0 10px; }
h2 { font-size: 22px; line-height: 1.25; font-weight: 600; letter-spacing: -0.012em; margin: 30px 0 12px; }
h3 { font-size: 18px; line-height: 1.32; font-weight: 600; letter-spacing: -0.006em; margin: 0 0 4px; }
p { margin: 0 0 12px; }
.muted { color: var(--ink-2); }
.faint { color: var(--ink-3); }
.small { font-size: var(--fs-sm); }
.center { text-align: center; }
.mono { font-family: var(--font-mono); font-size: .9em; letter-spacing: 0; }
/* Eyebrow (Orca-style): a small sentence-case label in the accent ink above a heading – not shouty mono caps.
   Gold ink 5.6:1 on --raised, 4.75:1 on --sunken; Cayman parts switch to sea ink (6.2:1 / 5.2:1). */
.eyebrow { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 600; line-height: 1.35; letter-spacing: 0; color: var(--gold-ink); }
.section.cayman .eyebrow { color: var(--sea-ink); }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row > * { min-width: 0; }
.stack { display: flex; flex-direction: column; gap: 12px; }
.grow { flex: 1; min-width: 0; }
.tnum { font-variant-numeric: tabular-nums; }

/* ---------- top bar ---------- */
.topbar {
  --gutter: max(16px, calc((100% - 1240px) / 2));
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 10px;
  /* the bar itself runs under the status bar / notch, its content stays clear of it */
  padding: calc(10px + env(safe-area-inset-top, 0px)) max(var(--gutter), env(safe-area-inset-right, 0px)) 10px max(var(--gutter), env(safe-area-inset-left, 0px));
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line);
}
/* Scroll edge effect: the divider only appears once content actually slides under the translucent bar */
@supports (animation-timeline: scroll()) {
  .topbar { border-bottom-color: transparent; animation: topbar-edge linear both; animation-timeline: scroll(root block); animation-range: 0 48px; }
  @keyframes topbar-edge { to { border-bottom-color: var(--line); box-shadow: 0 10px 24px -18px rgba(18, 22, 28, .35); } }
}
.topbar .spacer { flex: 1; }
.logo { display: inline-flex; align-items: center; text-decoration: none; line-height: 0; flex: 0 0 auto; }
.logo img { height: 38px; width: auto; display: block; }
.logo .logo-dark { display: none; }
:root[data-theme="dark"] .logo .logo-light { display: none; }
:root[data-theme="dark"] .logo .logo-dark { display: block; }
.stat-pill {
  display: inline-flex; align-items: center; gap: 6px; height: 36px;
  font-weight: 700; font-size: var(--fs-md); padding: 0 12px; border-radius: var(--r-pill);
  background: var(--raised); border: 1px solid var(--line); font-variant-numeric: tabular-nums;
}
.stat-pill.xp svg { color: var(--gold); }
.stat-pill.streak svg { color: var(--flame); }
.icon-btn {
  width: 38px; height: 38px; border-radius: var(--r-pill); border: 1px solid var(--line); background: var(--raised);
  display: inline-grid; place-items: center; color: var(--ink-2); padding: 0;
}
@media (hover: hover) and (pointer: fine) { .icon-btn:hover { color: var(--ink); border-color: var(--line-strong); } }
/* Every pressable thing answers the press: small controls scale to .97 instantly and release in 160ms */
.icon-btn, .close-x, .avatar, .btn-ghost, .tabs button {
  transition: transform var(--dur-press) var(--ease-out), background-color var(--dur-color) var(--ease-out),
    color var(--dur-color) var(--ease-out), border-color var(--dur-color) var(--ease-out);
}
.icon-btn:active, .close-x:active, .avatar:active, .btn-ghost:active, .tabs button:active { transform: scale(.97); transition-duration: var(--dur-down); }
.avatar {
  width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0;
  background: var(--ink); color: var(--bg); font-weight: 700; font-size: var(--fs-sm); letter-spacing: .02em;
  display: grid; place-items: center;
}
@media (max-width: 460px) {
  .logo img { height: 30px; }
  .stat-pill { padding: 0 9px; font-size: var(--fs-sm); height: 34px; }
  .topbar { gap: 6px; }
}
/* small phones: logo, streak, XP, theme and avatar must still fit one row without squeezing the 44px controls */
@media (max-width: 400px) {
  .logo img { height: 26px; }
  .stat-pill { padding: 0 7px; gap: 4px; }
  .topbar { gap: 4px; }
}
.topbar > :not(.spacer) { flex-shrink: 0; }
.stat-pill { white-space: nowrap; }

/* ---------- page column ---------- */
.wrap {
  max-width: 640px; margin: 0 auto;
  padding: 28px max(16px, env(safe-area-inset-right, 0px)) calc(120px + env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
}
.wrap.wide { max-width: 1240px; }

/* ---------- buttons (chunky, pressable) ---------- */
.btn {
  --b-bg: var(--raised); --b-fg: var(--ink); --b-edge: var(--line-strong); --b-press: var(--line-strong);
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 50px; padding: 12px 26px; border-radius: var(--r-pill);   /* pill (Orca) – the press edge below follows the curve */
  font-family: var(--font-body); font-weight: 700; font-size: var(--fs-ui); letter-spacing: .01em; line-height: 1.2;
  background: var(--b-bg); color: var(--b-fg); border: 2px solid var(--b-edge);
  box-shadow: 0 var(--press) 0 var(--b-press);
  text-decoration: none; text-align: center;
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press) var(--ease-out),
    background-color var(--dur-color) var(--ease-out), filter var(--dur-color) var(--ease-out);
  margin-bottom: var(--press);
}
@media (hover: hover) and (pointer: fine) { .btn:hover:not(:disabled) { filter: brightness(1.04); } }
.btn:active:not(:disabled) { transform: translateY(var(--press)); box-shadow: 0 0 0 var(--b-press); transition-duration: var(--dur-down), var(--dur-down), var(--dur-color), var(--dur-color); }
.btn-primary { --b-bg: var(--gold); --b-fg: var(--on-gold); --b-edge: var(--gold); --b-press: var(--gold-press); }
.btn-danger { --b-bg: var(--bad); --b-fg: var(--on-color); --b-edge: var(--bad); --b-press: var(--bad-press); }
.btn-secondary { --b-bg: var(--raised); --b-fg: var(--ink); --b-edge: var(--line-strong); --b-press: var(--line-strong); }
/* locked look for a button that is unavailable – but not for one that is busy (K1) */
.btn:disabled:not([aria-busy="true"]) { --b-bg: var(--locked); --b-fg: var(--locked-ink); --b-edge: var(--locked); --b-press: var(--locked-press); cursor: not-allowed; }
.btn-ghost {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 0; box-shadow: none; color: var(--ink-2);
  padding: 8px 12px; border-radius: var(--r-pill); font-weight: 600; text-decoration: none; font-size: var(--fs-md);
}
@media (hover: hover) and (pointer: fine) { .btn-ghost:hover:not(:disabled) { color: var(--ink); background: var(--sunken); } }
.btn-ghost:disabled:not([aria-busy="true"]) { opacity: .55; cursor: not-allowed; }
.btn.btn-ghost { min-height: 0; margin-bottom: 0; border: 0; box-shadow: none; --b-bg: transparent; }
.btn.btn-ghost:active:not(:disabled) { transform: scale(.97); }
/* K2: red ghost button for removals inside tables (Remove, Withdraw) */
.btn-ghost.danger { color: var(--bad-ink); }
@media (hover: hover) and (pointer: fine) { .btn-ghost.danger:hover:not(:disabled) { color: var(--bad-ink); background: var(--bad-wash); } }
.btn-sm { min-height: 38px; padding: 7px 18px; font-size: var(--fs-sm); --press: 3px; }
.btn-block { width: 100%; }
a.btn-ghost.back { margin-left: -12px; }   /* the icon lines up with the column edge */
/* K1: busy = waiting on the server. Keeps its own colours, cannot be pressed again, shows an inline spinner. */
.btn[aria-busy="true"], .btn-ghost[aria-busy="true"] { pointer-events: none; cursor: progress; }
.btn[aria-busy="true"]::after, .btn-ghost[aria-busy="true"]::after {
  content: ""; flex: 0 0 auto; width: 1em; height: 1em; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: spin var(--dur-spin) linear infinite;
}
/* K3: in a dialog's action row (admin: .modal-actions), Delete comes first and sits apart on the left, away from Save */
.modal :is(.modal-actions, .row) > .btn-danger:first-child { margin-right: auto; }

/* ---------- forms ---------- */
.field { display: block; margin-bottom: 16px; }
.field > span { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); margin-bottom: 6px; }
.input, .field input, .field select, .field textarea {
  width: 100%; min-height: 50px; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--raised); color: var(--ink); border: 2px solid var(--field);
  transition: border-color var(--dur-color) var(--ease-out), box-shadow var(--dur-color) var(--ease-out);
}
.field input:disabled { background: var(--sunken); color: var(--ink-2); border-color: var(--line-strong); }
.field input:focus, .field select:focus, .field textarea:focus, .input:focus, textarea.code:focus {
  border-color: var(--focus); outline: none; box-shadow: 0 0 0 4px var(--gold-wash);
}
.field textarea { min-height: 120px; resize: vertical; }
.field > .hint { margin: 6px 0 0; font-size: var(--fs-xs); font-weight: 500; color: var(--ink-3); }
.field textarea:disabled { background: var(--sunken); color: var(--ink-3); border-color: var(--line-strong); cursor: not-allowed; }
select.input { min-height: 42px; padding: 8px 12px; border-radius: var(--r-ctl); width: auto; }
input.input[type="search"] { min-height: 42px; padding: 8px 12px; border-radius: var(--r-ctl); }
/* compact number fields (admin exam rules: questions, pass mark, count per question type) */
input.input[type="number"] { min-height: 42px; padding: 8px 12px; border-radius: var(--r-ctl); }
textarea.code { font-family: var(--font-mono); font-size: var(--fs-xs); min-height: 320px; line-height: 1.5; width: 100%; padding: 12px; border-radius: var(--r-md); border: 2px solid var(--field); background: var(--sunken); color: var(--ink); }
.error-msg { color: var(--bad-ink); font-size: var(--fs-sm); font-weight: 600; margin: 4px 0 12px; min-height: 1.2em; }
.check-row { display: flex; gap: 12px; align-items: flex-start; cursor: pointer; }
.check-row input { width: 22px; height: 22px; accent-color: var(--gold); flex: 0 0 auto; margin-top: 2px; }

/* ---------- surfaces ---------- */
.panel { background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg); padding: 20px; }
.panel + .panel { margin-top: 14px; }
.panel.flat { background: var(--sunken); border-color: transparent; }

/* segmented control: pill track and pill segments – concentric by construction */
.tabs { display: flex; background: var(--sunken); border-radius: var(--r-pill); padding: 4px; margin-bottom: 20px; }
.tabs button { flex: 1; border: 0; background: transparent; color: var(--ink-2); padding: 10px; border-radius: var(--r-pill); font-weight: 700; }
.tabs button:is(.active, [aria-selected="true"]) { background: var(--seg); color: var(--ink); box-shadow: var(--shadow-seg); }
@media (hover: hover) and (pointer: fine) { .tabs button:not(.active):not([aria-selected="true"]):hover { color: var(--ink); } }

/* ---------- auth ---------- */
.auth { min-height: 100vh; min-height: 100dvh; display: grid; grid-template-columns: 1.05fr 1fr; }
.auth-art {
  position: relative; overflow: hidden; padding: 48px clamp(24px, 5vw, 64px);
  display: flex; flex-direction: column; justify-content: space-between; gap: 32px;
  background: #0E1115; color: #EEF0F3;   /* always the dark brand panel, in both themes */
}
.auth-art .logo img { height: 46px; }
.auth-art h1 { color: #F6F3EC; font-size: clamp(32px, 4.2vw, 50px); line-height: 1.1; letter-spacing: -0.028em; max-width: 13ch; }
.auth-art h1 em { font-style: normal; color: #E2B055; }
.auth-art p { color: #A4ACB8; max-width: 44ch; }
.auth-art .ledger { display: grid; gap: 10px; max-width: 420px; }
.auth-art .ledger div { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: calc(var(--r-sm) + 4px); background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.07); font-size: var(--fs-md); color: #D5D9E0; }
.auth-art .ledger b { display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--r-pill); background: var(--auth-step); font-family: var(--font-mono); font-size: var(--fs-label); color: #E2B055; min-width: 28px; }
.auth-art::after {
  content: ""; position: absolute; right: -120px; bottom: -120px; width: 420px; height: 420px; border-radius: 50%;
  border: 60px solid rgba(226, 176, 85, .08); pointer-events: none;
}
.auth-form { display: flex; flex-direction: column; justify-content: center; padding: 40px clamp(16px, 5vw, 64px); }
.auth-form .inner { width: 100%; max-width: 420px; margin: 0 auto; }
.auth-form h2 { margin-top: 0; }
.auth-intro { margin-top: -4px; margin-bottom: 20px; }
@media (min-width: 861px) {
  .auth-form .inner { max-width: 460px; padding: 32px; border: 1px solid var(--edge); border-radius: var(--r-lg); background: var(--raised); }
  .auth-art .ledger div { background: transparent; border: 0; padding: 8px 0; }
}
/* First impression (seen about once per device): the brand panel's text and ledger rise in, 60 ms apart.
   Never the form side – people start typing at once. */
.auth-art .stack > *, .auth-art .ledger > div { animation: rise-in var(--dur-card) var(--ease-out) backwards; }
.auth-art .stack > :nth-child(2) { animation-delay: var(--stagger); }
.auth-art .stack > :nth-child(3) { animation-delay: calc(var(--stagger) * 2); }
.auth-art .ledger > div:nth-child(1) { animation-delay: calc(var(--stagger) * 3); }
.auth-art .ledger > div:nth-child(2) { animation-delay: calc(var(--stagger) * 4); }
.auth-art .ledger > div:nth-child(3) { animation-delay: calc(var(--stagger) * 5); }
@media (max-width: 860px) {
  .auth { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .auth-art { padding: calc(28px + env(safe-area-inset-top, 0px)) 16px 32px; }
  .auth-art .ledger, .auth-art::after { display: none; }
  .auth-art h1 { font-size: 32px; }
  .auth-form { justify-content: flex-start; padding: 24px 16px calc(48px + env(safe-area-inset-bottom, 0px)); }
}
/* Phones: a compact brand strip, so the sign-in form and its button fit on the first screen */
@media (max-width: 560px) {
  .auth-art { gap: 12px; padding: calc(14px + env(safe-area-inset-top, 0px)) 16px 18px; }
  .auth-art .logo img { height: 30px; }
  .auth-art > .stack { gap: 4px !important; }   /* out-ranks the inline gap of the login markup */
  .auth-art h1 { font-size: 24px; max-width: none; margin: 0; }
  .auth-art p { display: none; }
  .auth-form { padding-top: 18px; }
  .auth-form h2 { font-size: 21px; margin-bottom: 6px; }
  .auth-form .inner > p.muted { font-size: var(--fs-sm); margin-bottom: 14px !important; }
  .auth-form .tabs { margin-bottom: 14px; }
  .auth-form .field { margin-bottom: 12px; }
}

/* ---------- guided learning ---------- */
.home-welcome { margin: 8px 0 26px; }
.home-welcome h1 { margin: 8px 0; font-size: clamp(30px, 6vw, 40px); }
.home-welcome p { margin: 0; }
.home-welcome > .eyebrow { color: var(--ink-2); }
.learning-focus { background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg); overflow: hidden; }
.focus-main { display: flex; align-items: center; gap: 28px; padding: 28px 28px 0; }
.focus-copy { flex: 1; min-width: 0; }
.focus-copy h2 { margin: 9px 0 12px; font-size: clamp(23px, 4vw, 28px); line-height: 1.2; overflow-wrap: anywhere; }
.focus-copy p { margin: 0; font-size: var(--fs-md); }
.focus-progress { display: grid; justify-items: center; gap: 8px; flex: 0 0 auto; }
.focus-progress .ring { width: 88px; height: 88px; }
.focus-progress .ring > span { width: 68px; height: 68px; font-size: 21px; }
.focus-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 24px 28px 0; }
.focus-detail { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 18px 28px 24px; color: var(--ink-2); font-size: var(--fs-xs); }
.focus-detail > span:first-of-type { flex: 1; min-width: 140px; overflow-wrap: anywhere; }
.focus-detail > svg { color: var(--gold-ink); }
.learning-journey { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); list-style: none; margin: 0; padding: 18px 24px; gap: 12px; background: var(--sunken); border-top: 1px solid var(--edge); }
.learning-journey li { display: flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: var(--fs-xs); font-weight: 600; min-width: 0; }
.journey-icon { width: 30px; height: 30px; display: grid; place-items: center; flex: 0 0 auto; border-radius: var(--r-pill); background: var(--raised); }
.learning-journey .current { color: var(--gold-ink); }
.learning-journey .current .journey-icon { background: var(--gold); color: var(--on-gold); }
.learning-journey .done { color: var(--ok-ink); }
.learning-journey .done .journey-icon { background: var(--ok-wash); color: var(--ok-ink); }
.section-label { display: flex; gap: 12px; align-items: baseline; justify-content: space-between; margin: 30px 0 12px; }
.section-label h2 { margin: 0; }
.home-wrap .team-card { margin-top: 20px; }
.path-head.panel { padding: 24px; }
.path-head .learning-journey { border-radius: var(--r-md); border: 0; padding: 14px; }
.lesson-context { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 16px; align-items: baseline; padding: 12px 0 16px; }
.lesson-context .eyebrow { flex: 1; min-width: 160px; }
.lesson-context .tnum { white-space: nowrap; }
.learning-focus.enter { animation: rise-in var(--dur-card) var(--ease-out) both; }
.focus-actions .btn-ghost svg { transition: transform var(--dur-fast) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .focus-actions .btn-ghost:hover svg { transform: translateX(var(--nudge)); }
}
@media (max-width: 560px) {
  .home-welcome { margin: 4px 0 20px; }
  .focus-main { padding: 22px 20px 0; gap: 16px; align-items: flex-start; }
  .focus-progress .ring { width: 60px; height: 60px; }
  .focus-progress .ring > span { width: 46px; height: 46px; font-size: var(--fs-sm); }
  .focus-progress > .small { font-size: var(--fs-xs); }
  .focus-actions { padding: 20px 20px 0; gap: 6px; }
  .focus-actions > a { width: 100%; justify-content: center; }
  .focus-detail { padding: 12px 20px 20px; }
  .learning-journey { padding: 16px 12px; gap: 6px; }
  .learning-journey li { flex-direction: column; gap: 6px; text-align: center; }
  .path-head.panel { padding: 20px 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .learning-focus.enter { animation: fade-in var(--dur-fast) var(--ease-out) both; }
  .focus-actions .btn-ghost svg { transition: none; }
}

/* ---------- home ---------- */
.ring { --p: 0; --c: var(--gold); width: 76px; height: 76px; border-radius: 50%; flex: 0 0 auto;
  background: conic-gradient(var(--c) calc(var(--p) * 1%), var(--sunken) 0); display: grid; place-items: center;
  animation: ring-fill var(--dur-ring-sm) var(--spring) both; }
/* --p-from = the value last seen in this session (home ring), so a revisit fills only what changed; unset = from 0 */
@keyframes ring-fill { from { --p: var(--p-from, 0); } }
.ring > span { width: 58px; height: 58px; border-radius: 50%; background: var(--raised); display: grid; place-items: center; font-weight: 700; font-size: var(--fs-md); font-variant-numeric: tabular-nums; }

/* Home atmosphere (app.js homeAtmosphere, icons.js homeArt) – Orca-style colour that lives behind and around the white
   cards, never on them: soft radial glows (gold left, sea blue right, a faint cool tint over the top), a faint grid that
   shows only in the side margins, and on wide screens a stack of glass tiles centred in the right margin. One absolutely
   positioned layer under the page (z-index -1 inside #app), aria-hidden, pointer-events none, painted once: gradients
   only, no filter blur, no looping motion – it fades in once per session and is still after that.
   Contrast (6 Oct 2026, every point of the column at widths 375–1920px, all glows stacked + the grid's edge): the text
   that sits on the page background here – h2 in --ink-head, the empty state in --ink-2 – keeps ≥ 9.3:1 / ≥ 4.68:1 in
   light and ≥ 13.4:1 / ≥ 6.7:1 in dark (worst at 760px, where the margins are narrowest). --ink-3 would drop to 3.96:1,
   so faint text never goes directly on this background – keep it inside the white cards. */
:root {
  --glow-gold: rgba(217, 164, 69, .26);
  --glow-sea: rgba(28, 125, 164, .15);
  --glow-cool: rgba(97, 106, 255, .08);   /* Orca's periwinkle, barely there */
  --grid-line: rgba(18, 22, 28, .05);
  --tile-gold-1: #FFF8EA; --tile-gold-2: #F2D7A0; --tile-gold-side: #DDB063; --mark-gold: #A87526;
  --tile-cool-1: #F8F9FF; --tile-cool-2: #DDE0F6; --tile-cool-side: #B8BDE4; --mark-cool: #6C73C9;
  --tile-sea-1: #F0F8FC; --tile-sea-2: #BEDFED; --tile-sea-side: #86BFD7; --mark-sea: #1C7DA4;
  --tile-rim: rgba(255, 255, 255, .9); --tile-sheen: rgba(255, 255, 255, .7); --tile-shadow: rgba(18, 22, 28, .13);
}
/* dark: glows dim and warm, no light blobs; tiles become deep tinted glass with a faint rim */
:root[data-theme="dark"] {
  --glow-gold: rgba(226, 176, 85, .085);
  --glow-sea: rgba(72, 173, 212, .085);
  --glow-cool: rgba(112, 120, 255, .06);
  --grid-line: rgba(255, 255, 255, .035);
  --tile-gold-1: #4A3B1E; --tile-gold-2: #2A2214; --tile-gold-side: #6A5126; --mark-gold: #E2B055;
  --tile-cool-1: #30345A; --tile-cool-2: #1B1E34; --tile-cool-side: #3B4174; --mark-cool: #9CA2F5;
  --tile-sea-1: #1E4556; --tile-sea-2: #0F232D; --tile-sea-side: #245B72; --mark-sea: #5BB8DC;
  --tile-rim: rgba(255, 255, 255, .16); --tile-sheen: rgba(255, 255, 255, .09); --tile-shadow: rgba(0, 0, 0, .5);
}
#app:has(> .atmos) { position: relative; isolation: isolate; min-height: 100vh; min-height: 100dvh; }
.atmos {
  position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  /* side centres: the column is 640px wide, so each margin's middle sits at 25% − 160px and 75% + 160px */
  background:
    radial-gradient(1100px 420px at 50% -160px, var(--glow-cool), transparent 70%),
    radial-gradient(560px 480px at calc(25% - 160px) 170px, var(--glow-gold), transparent 70%),
    radial-gradient(620px 520px at calc(75% + 160px) 250px, var(--glow-sea), transparent 70%);
}
.atmos-grid {
  position: absolute; inset: 0 0 auto; height: 680px;
  background-image: linear-gradient(var(--grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 44px 44px; background-position: calc(50% - 22px) 20px;
  /* two soft ellipses, one per margin (mask layers add up), each as wide as its margin + 60px and centred on it, so no
     line runs behind the column's text */
  -webkit-mask: radial-gradient(closest-side, #000 30%, transparent) left -30px top 0 / calc(50% - 260px) 640px no-repeat,
    radial-gradient(closest-side, #000 30%, transparent) right -30px top 0 / calc(50% - 260px) 640px no-repeat;
  mask: radial-gradient(closest-side, #000 30%, transparent) left -30px top 0 / calc(50% - 260px) 640px no-repeat,
    radial-gradient(closest-side, #000 30%, transparent) right -30px top 0 / calc(50% - 260px) 640px no-repeat;
}
/* the art: centred in the right margin, level with the greeting; only where the margin is wide enough to hold it */
.atmos-art { --art-w: min(260px, calc(50% - 384px)); position: absolute; top: 92px; left: calc(75% + 160px - var(--art-w) / 2); width: var(--art-w); display: none; }
.atmos-art svg { display: block; width: 100%; height: auto; overflow: visible; }
@media (min-width: 1220px) { .atmos-art { display: block; } }
.atmos-art .gold-1 { stop-color: var(--tile-gold-1); } .atmos-art .gold-2 { stop-color: var(--tile-gold-2); }
.atmos-art .cool-1 { stop-color: var(--tile-cool-1); } .atmos-art .cool-2 { stop-color: var(--tile-cool-2); }
.atmos-art .sea-1 { stop-color: var(--tile-sea-1); } .atmos-art .sea-2 { stop-color: var(--tile-sea-2); }
.atmos-art .sheen { stop-color: var(--tile-sheen); } .atmos-art .sheen-0 { stop-color: var(--tile-sheen); stop-opacity: 0; }
.atmos-art .shadow { stop-color: var(--tile-shadow); } .atmos-art .shadow-0 { stop-color: var(--tile-shadow); stop-opacity: 0; }
.atm-side.gold { fill: var(--tile-gold-side); } .atm-side.cool { fill: var(--tile-cool-side); } .atm-side.sea { fill: var(--tile-sea-side); }
.atm-rim { fill: none; stroke: var(--tile-rim); stroke-width: 1.5; }
.atm-mark { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; opacity: .85; }
.atm-mark.gold { color: var(--mark-gold); } .atm-mark.cool { color: var(--mark-cool); } .atm-mark.sea { color: var(--mark-sea); }
.atm-orb { stroke: var(--tile-rim); stroke-width: 1; }
.atm-orb.gold { fill: var(--tile-gold-2); } .atm-orb.cool { fill: var(--tile-cool-2); } .atm-orb.sea { fill: var(--tile-sea-2); }
/* phones and narrow windows: no margins to fill – one soft glow across the top only, behind the bar and the greeting */
@media (max-width: 759px) {
  .atmos {
    background:
      radial-gradient(130% 320px at 0% -60px, var(--glow-gold), transparent 70%),
      radial-gradient(110% 300px at 100% 0%, var(--glow-sea), transparent 70%);
  }
  .atmos-grid { display: none; }
}
/* first home view of the session: the layer fades in and the art rises 8px – once (seen.atmos), then it is still */
.atmos.enter { animation: fade-in var(--dur-moment) var(--ease-out) backwards; }
.atmos.enter .atmos-art { animation: rise-in var(--dur-moment) var(--ease-out) 60ms backwards; }

/* Count-up (util.js countUp): the digits are a CSS counter fed by --n, so they tick on the animation clock with the
   ring's own curve. The span's own (hidden) text is the final value, so the box has exactly its final width from the
   first frame – no jitter while counting, no gap after; the counter is drawn over it, right-aligned. The visible
   digits are aria-hidden; the real value sits in an sr-only span next to them. */
.count { position: relative; display: inline-block; visibility: hidden; font-variant-numeric: tabular-nums;
  counter-reset: count var(--n); animation: count-up var(--count-dur, var(--dur-ring-sm)) var(--count-ease, var(--ease-out)) both; }
.count::after { content: counter(count); visibility: visible; position: absolute; inset-block-start: 0; inset-inline-end: 0; }
@keyframes count-up { from { --n: var(--n-from, 0); } }
.ring .count { --count-dur: var(--dur-ring-sm); --count-ease: var(--spring); }
.score-ring .count { --count-dur: var(--dur-ring); --count-ease: var(--spring); }

.training-card {
  display: grid; gap: 10px; background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg);
  padding: 18px 20px; text-decoration: none; color: var(--ink);
  transition: border-color var(--dur-color) var(--ease-out), transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.training-card + .training-card { margin-top: 14px; }
@media (hover: hover) and (pointer: fine) { .training-card:not([aria-disabled="true"]):hover { border-color: var(--line-strong); box-shadow: 0 0 0 4px var(--halo); transform: translateY(-1px); } }
.training-card:not([aria-disabled="true"]):active { transform: scale(.98); transition-duration: var(--dur-color), var(--dur-down), var(--dur-down); }
/* paused client: the card stays readable but no longer behaves like a link */
.training-card[aria-disabled="true"] { cursor: not-allowed; background: var(--bg); border-style: dashed; border-color: var(--line-strong); }
.training-card[aria-disabled="true"] .go { color: var(--ink-3); }
.training-card h3 { font-size: 19px; margin: 2px 0 0; }
.training-card .go { display: inline-flex; align-items: center; gap: 6px; color: var(--gold-ink); font-weight: 700; font-size: var(--fs-md); }
.cert-row { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border-radius: var(--r-lg); background: var(--raised); border: 1px solid var(--edge); text-decoration: none; color: var(--ink); }
.cert-row + .cert-row { margin-top: 10px; }
@media (hover: hover) and (pointer: fine) { .cert-row:hover { border-color: var(--line-strong); } }
.cert-row .seal { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--gold-wash); color: var(--gold-ink); flex: 0 0 auto; }

.pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-label); font-weight: 700; line-height: 1;
  padding: 6px 10px; border-radius: var(--r-pill); background: var(--sunken); color: var(--ink-2); white-space: nowrap;
}
.pill.gold { background: var(--gold-wash); color: var(--gold-ink); }
.pill.green { background: var(--ok-wash); color: var(--ok-ink); }
.pill.red { background: var(--bad-wash); color: var(--bad-ink); }
.pill.sea { background: var(--sea-wash); color: var(--sea-ink); }
.progress { height: 14px; background: var(--sunken); border-radius: var(--r-pill); overflow: hidden; }
/* width (not scaleX) so the rounded ends of a short bar are not squashed */
.progress > div {
  height: 100%; border-radius: var(--r-pill); background: var(--gold); transition: width var(--dur-card) var(--ease-out);
  box-shadow: inset 0 -3px 0 rgba(0,0,0,.12), inset 0 3px 0 rgba(255,255,255,.28);
}
/* Path page: the bar fills only what changed since the last visit, with the rings' spring, just after the page lands */
.progress.delta > div { transition-duration: var(--dur-ring-sm); transition-timing-function: var(--spring); transition-delay: 120ms; }

/* ---------- countries ---------- */
.chips { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.chip {
  position: relative; display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 12px; align-items: center;
  text-align: left; padding: 16px; border-radius: var(--r-lg); background: var(--raised); color: var(--ink);
  border: 2px solid var(--line-strong); box-shadow: 0 var(--press) 0 var(--line-strong); margin-bottom: var(--press);
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press) var(--ease-out),
    border-color var(--dur-color) var(--ease-out), background-color var(--dur-color) var(--ease-out);
}
.chip:active { transform: translateY(var(--press)); box-shadow: 0 0 0 var(--line-strong); transition-duration: var(--dur-down), var(--dur-down), var(--dur-color), var(--dur-color); }
.chip .flag {
  grid-row: 1 / 3; min-width: 52px; height: 44px; padding: 0 8px; border-radius: var(--r-ctl); display: grid; place-items: center;
  background: var(--sunken); color: var(--ink-2); font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 600; letter-spacing: .04em;
}
.chip.on .flag { background: var(--gold); color: var(--on-gold); }
.chip.on.ky .flag { background: var(--sea); color: var(--on-color); }
.chip .name { font-weight: 700; font-size: var(--fs-base); line-height: 1.2; padding-right: 26px; }
.chip .code { font-size: var(--fs-xs); color: var(--ink-3); line-height: 1.3; }
.chip .tick { position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--field); display: grid; place-items: center; color: transparent; }
.chip.on { border-color: var(--gold); background: var(--gold-wash); box-shadow: 0 var(--press) 0 var(--gold-press); }
.chip.on .tick { background: var(--gold); border-color: var(--gold); color: var(--on-gold); }
.chip.on.ky { border-color: var(--sea); background: var(--sea-wash); box-shadow: 0 var(--press) 0 var(--sea-press); }
.chip.on.ky .tick { background: var(--sea); border-color: var(--sea); color: var(--on-color); }
.scenario { display: flex; gap: 12px; align-items: flex-start; margin-top: 16px; padding: 14px 16px; border-radius: var(--r-md); background: var(--sea-wash); color: var(--ink); font-size: var(--fs-md); }
.scenario svg { color: var(--sea-ink); margin-top: 3px; }
.scenario:empty { display: none; }
/* Selecting a country: the tick grows in instead of teleporting; the Cayman note fades up when it appears (hiding it
   stays instant – [hidden] removes it at once) */
.chip .tick svg { opacity: 0; scale: var(--moment-s); transition: opacity var(--dur-fast) var(--ease-out), scale var(--dur-fast) var(--ease-out); }
.chip.on .tick svg { opacity: 1; scale: 1; }
.scenario { transition: opacity var(--dur-fast) var(--ease-out), translate var(--dur-fast) var(--ease-out); }
@starting-style { .scenario { opacity: 0; translate: 0 var(--lift); } }
@media (max-width: 380px) { .chips { grid-template-columns: 1fr; } }

/* ---------- learning path: course outline ---------- */
.path-head { display: grid; gap: 14px; margin-bottom: 10px; }
.outline { display: grid; gap: 16px; margin-top: 24px; }
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }
.chev { flex: 0 0 auto; width: 30px; height: 30px; border-radius: var(--r-sm); display: grid; place-items: center; color: var(--ink-3); transition: transform var(--dur-fast) var(--ease-in-out); }
details[open] > summary .chev { transform: rotate(90deg); }
/* Units and sections open and close with the same curve (Chromium 131+; elsewhere they simply toggle) */
details::details-content { block-size: 0; overflow-y: clip; transition: block-size var(--dur-card) var(--ease-in-out), content-visibility var(--dur-card) allow-discrete; }
details[open]::details-content { block-size: auto; }
/* the outline clips its corners and collapsing content, so focus rings are drawn inside the element */
.section-head:focus-visible, .unit-head:focus-visible, .lesson-row:focus-visible, .outline summary:focus-visible { outline-offset: -3px; }

.section { background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg); overflow: hidden; }
.section-head { display: flex; align-items: center; gap: 14px; padding: 16px 18px; cursor: pointer; color: var(--ink); border-radius: var(--r-lg); }
@media (hover: hover) and (pointer: fine) { .section-head:hover { background: color-mix(in srgb, var(--sunken) 45%, transparent); } }
.section-head h2 { margin: 0 0 2px; font-size: 20px; }
.section-badge { flex: 0 0 auto; width: 46px; height: 46px; border-radius: calc(var(--r-sm) + 4px); display: grid; place-items: center; background: var(--gold); color: var(--on-gold); box-shadow: 0 3px 0 var(--gold-press); font-size: var(--fs-md); font-weight: 700; }
.section-badge svg { width: 24px; height: 24px; }
.section.cayman .section-badge { background: var(--sea); color: var(--on-color); box-shadow: 0 3px 0 var(--sea-press); }
.section-progress { flex: 0 0 auto; display: grid; justify-items: end; gap: 6px; font-weight: 700; font-size: var(--fs-sm); color: var(--ink-2); }
.mini-bar { display: block; width: 72px; height: 6px; border-radius: var(--r-pill); background: var(--sunken); overflow: hidden; }
.mini-bar > span { display: block; height: 100%; background: var(--gold); border-radius: var(--r-pill); }
.section.cayman .mini-bar > span { background: var(--sea); }
.units { display: grid; gap: 8px; padding: 0 12px 12px; }

.unit { border-radius: var(--r-md); background: var(--bg); border: 1px solid var(--line); }
.unit[open] { border-color: var(--line-strong); }
.unit-head { display: flex; align-items: center; gap: 12px; padding: 10px 12px; cursor: pointer; border-radius: var(--r-md); color: var(--ink); }
@media (hover: hover) and (pointer: fine) { .unit-head:hover { background: var(--sunken); } }
.unit-head b { display: block; font-family: var(--font-display); font-weight: 600; font-size: var(--fs-ui); line-height: 1.32; color: var(--ink-head); }
.unit-head .eyebrow { display: block; font-size: var(--fs-label); line-height: 1.4; }
.unit-icon { flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-ctl); display: grid; place-items: center; background: var(--raised); border: 1px solid var(--line); font-size: 20px; color: var(--gold-ink); }
.unit-icon svg { width: 21px; height: 21px; }
.section.cayman .unit-icon { color: var(--sea-ink); }
.unit.complete .unit-icon { color: var(--ok-ink); }
.unit-meta { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); font-weight: 700; color: var(--ink-3); }
.unit.complete .unit-meta { color: var(--ok-ink); }
.unit.locked .unit-head { opacity: .62; }
.lessons { list-style: none; margin: 0; padding: 0 10px 10px; display: grid; gap: 6px; }
.lesson-row {
  width: 100%; display: flex; align-items: center; gap: 12px; text-align: left; padding: 9px 12px; border-radius: var(--r-ctl);
  background: var(--raised); border: 1px solid var(--line); color: var(--ink); font-size: var(--fs-md); line-height: 1.35;
  transition: transform var(--dur-press) var(--ease-out), border-color var(--dur-color) var(--ease-out),
    background-color var(--dur-color) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .lesson-row:hover { border-color: var(--line-strong); } }
.lesson-row:active:not(.locked) { transform: scale(.98); transition-duration: var(--dur-down), var(--dur-color), var(--dur-color); }
.lesson-row .dot { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--sunken); color: var(--ink-3); }
.lesson-row .dot svg { width: 17px; height: 17px; }
.lesson-row .act { flex: 0 0 auto; font-size: var(--fs-xs); font-weight: 700; color: var(--ink-3); }
.lesson-row.done .dot { background: var(--ok); color: var(--on-color); }
.lesson-row.done .act { color: var(--ok-ink); }
.lesson-row.next { border: 2px solid var(--gold); background: var(--gold-wash); }
.lesson-row.next .dot { background: var(--gold); color: var(--on-gold); box-shadow: 0 3px 0 var(--gold-press); }
.lesson-row.next .act { color: var(--gold-ink); }
.section.cayman .lesson-row.next { border-color: var(--sea); background: var(--sea-wash); }
.section.cayman .lesson-row.next .dot { background: var(--sea); color: var(--on-color); box-shadow: 0 3px 0 var(--sea-press); }
.section.cayman .lesson-row.next .act { color: var(--sea-ink); }
.lesson-row.locked { color: var(--ink-3); cursor: not-allowed; background: transparent; }
/* Back on the path after a first completion: the finished lesson's tick lands, the newly unlocked lesson warms to gold,
   a completed unit's check lands, the Up next card rises in – once (app.js removes the classes), then the page is still */
.lesson-row.just-done .dot, .unit.just-complete .unit-meta svg { animation: moment-in var(--dur-card) var(--ease-out) 150ms backwards; }
.lesson-row.just-unlocked { transition-duration: var(--dur-press), var(--dur-card), var(--dur-card); transition-delay: 0ms, 250ms, 250ms; }
/* as specific as `.section.cayman .lesson-row.next`, so the sea-blue Cayman row warms up too */
@starting-style { .section .lesson-row.next.just-unlocked { border-color: var(--line); background-color: var(--raised); } }
.lesson-row.just-unlocked .dot { animation: moment-in var(--dur-card) var(--ease-out) 250ms backwards; }
.next-card.just-unlocked { animation: rise-in var(--dur-card) var(--ease-out) 200ms backwards; }
/* a tap on a locked lesson: the row shakes its head (with the toast); --nudge is 0 under reduced motion */
.lesson-row.nudge { animation: nudge var(--dur-nudge) var(--ease-out); }

.next-card {
  width: 100%; display: flex; align-items: center; gap: 14px; text-align: left; margin-top: 20px; padding: 14px 16px;
  border-radius: var(--r-lg); border: 2px solid var(--gold); background: var(--gold-wash); color: var(--ink);
  box-shadow: 0 var(--press) 0 var(--gold-press); margin-bottom: var(--press);
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press) var(--ease-out);
}
.next-card:active { transform: translateY(var(--press)); box-shadow: 0 0 0 var(--gold-press); transition-duration: var(--dur-down); }
.next-card .dot { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--gold); color: var(--on-gold); }
.next-card b { display: block; font-family: var(--font-display); font-weight: 600; font-size: var(--fs-base); line-height: 1.3; letter-spacing: -0.006em; color: var(--ink-head); }
.next-card .eyebrow { display: block; color: var(--gold-ink); }
.next-card .go { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; color: var(--gold-ink); }
@media (max-width: 460px) { .next-card .go span, .next-card .go { font-size: 0; } .next-card .go svg { width: 22px; height: 22px; } }

.exam-card { display: flex; align-items: center; gap: 14px; padding: 16px 18px; border-radius: var(--r-lg); border: 1px dashed var(--line-strong); background: var(--raised); }
.exam-card h2 { margin: 0 0 2px; font-size: 20px; }
.exam-card.locked .section-badge { background: var(--locked); color: var(--locked-ink); box-shadow: 0 3px 0 var(--locked-press); }
.exam-card.ready { border: 2px solid var(--gold); background: var(--gold-wash); }
.exam-card.passed { border-style: solid; border-color: var(--ok); background: var(--ok-wash); }
.exam-card.passed .section-badge { background: var(--ok); color: var(--on-color); box-shadow: 0 3px 0 var(--ok-press); }
.exam-card .btn { margin-bottom: 3px; }
@media (max-width: 460px) {
  .section-head, .exam-card { padding: 14px; gap: 10px; }
  .section-badge { width: 40px; height: 40px; }
  .mini-bar { width: 52px; }
  .exam-card { flex-wrap: wrap; }
  .exam-card .btn { width: 100%; }
}

/* ---------- lesson player ---------- */
.player { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; background: var(--bg); }
.player-top {
  --gutter: max(16px, calc((100% - 648px) / 2));
  position: sticky; top: 0; z-index: 9; display: flex; align-items: center; gap: 14px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) max(var(--gutter), env(safe-area-inset-right, 0px)) 14px max(var(--gutter), env(safe-area-inset-left, 0px));
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px);
}
.player-top .progress { flex: 1; height: 16px; }
.close-x { width: 40px; height: 40px; display: grid; place-items: center; background: transparent; border: 0; color: var(--ink-3); border-radius: var(--r-ctl); padding: 0; }
@media (hover: hover) and (pointer: fine) { .close-x:hover { color: var(--ink); background: var(--sunken); } }
.close-x svg { width: 24px; height: 24px; }
/* K4: the footer's real height (--foot-h, measured by app.js) keeps the last option clear of it */
.player-body {
  flex: 1; max-width: 680px; width: 100%; margin: 0 auto;
  padding: 8px max(16px, env(safe-area-inset-right, 0px)) calc(var(--foot-h, 180px) + 24px + env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
}
.player-foot {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
  padding: 18px max(16px, env(safe-area-inset-right, 0px)) calc(18px + env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
  background: color-mix(in srgb, var(--bg) 84%, transparent); border-top: 1px solid var(--line);
  backdrop-filter: saturate(1.4) blur(16px); -webkit-backdrop-filter: saturate(1.4) blur(16px);
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.player-foot .inner { max-width: 680px; margin: 0 auto; display: flex; gap: 14px; align-items: center; }
.player-foot .btn { min-width: 160px; }
.player-foot .btn-secondary { min-width: 0; }
.player-foot.ok { background: var(--ok-wash); border-top-color: transparent; }   /* colour sits on a solid layer */
.player-foot.bad { background: var(--bad-wash); border-top-color: transparent; }
.player-foot.ok .feedback, .player-foot.bad .feedback { animation: rise-in var(--dur-fast) var(--ease-out) backwards; }
.player-foot.ok .btn-primary { --b-bg: var(--ok); --b-fg: var(--on-color); --b-edge: var(--ok); --b-press: var(--ok-press); }
.player-foot.bad .btn-primary { --b-bg: var(--bad); --b-fg: var(--on-color); --b-edge: var(--bad); --b-press: var(--bad-press); }
/* a long explanation scrolls inside the footer instead of pushing it over the question */
.feedback { flex: 1; min-width: 0; display: flex; gap: 12px; align-items: flex-start; max-height: 40vh; max-height: 40dvh; overflow-y: auto; overscroll-behavior: contain; }
.feedback .badge { width: 44px; height: 44px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center; background: var(--raised); }
.player-foot.ok .badge { color: var(--ok); }
.player-foot.bad .badge { color: var(--bad); }
.feedback b { display: block; font-family: var(--font-display); font-size: 20px; letter-spacing: -0.01em; }
.player-foot.ok .feedback b { color: var(--ok-ink); }
.player-foot.bad .feedback b { color: var(--bad-ink); }
.feedback p { margin: 2px 0 0; font-size: var(--fs-md); color: var(--ink); }
/* Phones: feedback on its own row, then Back (a square icon button) and the primary action side by side */
@media (max-width: 560px) {
  .player-foot { padding-top: 12px; padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .player-foot .inner { flex-wrap: wrap; gap: 10px; }
  .player-foot .feedback { flex: 1 0 100%; order: -1; gap: 10px; }
  .player-foot .feedback:empty { display: none; }
  .player-foot .feedback .badge { width: 36px; height: 36px; }
  .player-foot .feedback b { font-size: 18px; }
  .player-foot .inner > .grow { flex: 0 1 auto; }
  .player-foot .inner > .grow:empty { display: none; }
  .player-foot .btn { min-width: 0; }
  .player-foot .btn-primary, .player-foot .btn-secondary:not(.btn-back) { flex: 1 1 auto; }
  .player-foot .btn-back { flex: 0 0 auto; width: 54px; padding: 0; }
  .player-foot .btn-back .lbl { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
  .player-foot .btn-back svg { width: 22px; height: 22px; }
}

.lcard { animation: card-in var(--dur-card) var(--ease-out) backwards; }
/* Spatial consistency: Continue brings the next card in from the right, Back brings the previous one from the left */
.lcard.from-back { --from: calc(var(--slide) * -1); }
/* a 2px blur bridges the old and new card so the swap reads as one movement, not two objects crossing */
@keyframes card-in { from { opacity: 0; transform: translateX(var(--from, var(--slide))); filter: blur(var(--card-blur)); } }
/* Stagger: a card's options / items / steps follow it in, 35ms apart (decorative – they are clickable throughout) */
.lcard :is(.options, .item-list, .steps) > *, .summary-points > li { animation: rise-in var(--dur-card) var(--ease-out) backwards; --lift: var(--stagger-lift); }
.lcard :is(.options, .item-list, .steps) > :nth-child(1), .summary-points > li:nth-child(1) { animation-delay: 40ms; }
.lcard :is(.options, .item-list, .steps) > :nth-child(2), .summary-points > li:nth-child(2) { animation-delay: 75ms; }
.lcard :is(.options, .item-list, .steps) > :nth-child(3), .summary-points > li:nth-child(3) { animation-delay: 110ms; }
.lcard :is(.options, .item-list, .steps) > :nth-child(4), .summary-points > li:nth-child(4) { animation-delay: 145ms; }
.lcard :is(.options, .item-list, .steps) > :nth-child(5), .summary-points > li:nth-child(5) { animation-delay: 180ms; }
.lcard :is(.options, .item-list, .steps) > :nth-child(n+6), .summary-points > li:nth-child(n+6) { animation-delay: 215ms; }
/* individual `translate` (not `transform`), so a press (.option:active, .next-card:active) still shows mid-stagger */
@keyframes rise-in { from { opacity: 0; translate: 0 var(--lift); } }
@keyframes fade-in { from { opacity: 0; } }
/* a rare celebration element lands: grows from --moment-s and fades in (individual `scale`, so it never fights a
   transform set elsewhere); under reduced motion --moment-s = 1 and it only fades */
@keyframes moment-in { from { opacity: 0; scale: var(--moment-s); } }
.lcard h2 { font-size: clamp(24px, 5vw, 30px); margin: 6px 0 16px; line-height: 1.22; letter-spacing: -0.016em; }
.lcard .body { font-size: 18px; }
.lcard .body p { margin: 0 0 14px; }
.lcard .body ul { margin: 0 0 14px; padding-left: 0; list-style: none; display: grid; gap: 8px; }
.lcard .body li { position: relative; padding-left: 26px; }
.lcard .body li::before { content: ""; position: absolute; left: 4px; top: .62em; width: 9px; height: 9px; border-radius: 3px; background: var(--gold); transform: rotate(45deg); }
.lcard .body b { font-weight: 700; background: linear-gradient(transparent 62%, var(--gold-wash) 62%); }
.lcard.intro { padding-top: 12px; }
.lcard.intro .hero { width: 84px; height: 84px; border-radius: var(--r-xl); display: grid; place-items: center; background: var(--gold-wash); color: var(--gold-ink); margin-bottom: 8px; }
.lcard.intro .hero svg { width: 44px; height: 44px; }
.lcard.intro h2 { font-size: clamp(27px, 6vw, 34px); font-weight: 700; line-height: 1.16; letter-spacing: -0.022em; }
.card-kind { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2); }

.item-list { display: grid; gap: 10px; }
.item { display: flex; gap: 14px; align-items: flex-start; background: var(--raised); border: 1px solid var(--line); border-radius: var(--r-md); padding: 14px 16px; }
.item .ic { flex: 0 0 44px; height: 44px; border-radius: var(--r-ctl); background: var(--sunken); display: grid; place-items: center; font-size: 20px; font-weight: 700; color: var(--gold-ink); font-family: var(--font-mono); }
.item > div:last-child { min-width: 0; }
.item b { display: block; font-size: var(--fs-ui); }
.item span { color: var(--ink-2); font-size: var(--fs-md); }

.steps { display: flex; flex-direction: column; }
.step { display: flex; gap: 16px; }
.step .rail { display: flex; flex-direction: column; align-items: center; }
.step .dot { width: 36px; height: 36px; border-radius: 50%; background: var(--gold); color: var(--on-gold); display: grid; place-items: center; font-weight: 800; flex: 0 0 auto; font-family: var(--font-mono); box-shadow: 0 3px 0 var(--gold-press); }
.step .bar { width: 3px; flex: 1; background: var(--line); margin: 6px 0; border-radius: 2px; }
.step:last-child .bar { display: none; }
.step .content { padding-bottom: 20px; min-width: 0; }
.step .content small { color: var(--gold-ink); font-weight: 600; font-size: var(--fs-xs); }
.step .content h3 { margin: 2px 0 4px; }
.step .content > div { color: var(--ink-2); }

.callout { display: grid; gap: 4px; border-radius: var(--r-md); padding: 16px 18px; background: var(--gold-wash); border: 1px solid color-mix(in srgb, var(--gold) 35%, transparent); }
.callout.warn { background: var(--bad-wash); border-color: color-mix(in srgb, var(--bad) 30%, transparent); }
.callout.info { background: var(--sea-wash); border-color: color-mix(in srgb, var(--sea) 30%, transparent); }
.callout.tip { background: var(--ok-wash); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.callout b.title { display: block; font-family: var(--font-display); font-weight: 600; font-size: 18px; line-height: 1.32; color: var(--ink-head); }
.callout .body { font-size: var(--fs-base); }
.callout .body p:last-child { margin-bottom: 0; }

.q-head { display: inline-flex; align-items: center; gap: 6px; color: var(--gold-ink); font-weight: 600; font-size: var(--fs-xs); }
.q-head.sea { color: var(--sea-ink); }
.options { display: grid; gap: 12px; margin-top: 18px; }
.option {
  display: flex; gap: 14px; align-items: center; text-align: left; width: 100%;
  padding: 14px 16px; border-radius: var(--r-md); background: var(--raised); color: var(--ink);
  border: 2px solid var(--line-strong); box-shadow: 0 var(--press) 0 var(--line-strong); margin-bottom: var(--press);
  font-size: var(--fs-ui); line-height: 1.4;
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press) var(--ease-out),
    border-color var(--dur-color) var(--ease-out), background-color var(--dur-color) var(--ease-out);
}
.option .key { flex: 0 0 34px; height: 34px; border-radius: var(--r-sm); border: 2px solid var(--line-strong); display: grid; place-items: center; font-weight: 700; font-size: var(--fs-sm); color: var(--ink-3); font-family: var(--font-mono); }
/* a revealed lesson check stays focusable (aria-disabled) but no longer reacts like a live control */
.option:is(:disabled, [aria-disabled="true"]) { cursor: default; }
@media (hover: hover) and (pointer: fine) { .option:hover:not(:disabled):not([aria-disabled="true"]):not(.selected) { background: var(--sunken); } }
.option:active:not(:disabled):not([aria-disabled="true"]) { transform: translateY(var(--press)); box-shadow: 0 0 0 var(--line-strong); transition-duration: var(--dur-down), var(--dur-down), var(--dur-color), var(--dur-color); }
/* Answer feedback, fired on the same frame as the footer and the haptic: a head-shake for wrong, a settle for right */
.option.nudge { animation: nudge var(--dur-nudge) var(--ease-out); }
.option.pop { animation: pop var(--dur-fast) var(--ease-out); }
.lcard .options > .option:is(.nudge, .pop) { animation-delay: 0ms; }   /* answer feedback never waits for the stagger */
@keyframes nudge { 20% { transform: translateX(calc(var(--nudge) * -1)); } 45% { transform: translateX(var(--nudge)); } 70% { transform: translateX(calc(var(--nudge) * -.5)); } 90% { transform: translateX(calc(var(--nudge) * .25)); } }
@keyframes pop { from { transform: scale(.97); } }
.option.selected { border-color: var(--gold); background: var(--gold-wash); box-shadow: 0 var(--press) 0 var(--gold-press); }
.option.selected .key { border-color: var(--gold); background: var(--gold); color: var(--on-gold); }
.option.right { border-color: var(--ok); background: var(--ok-wash); box-shadow: 0 var(--press) 0 var(--ok-press); }
.option.right .key { border-color: var(--ok); background: var(--ok); color: var(--on-color); }
.option.wrong { border-color: var(--bad); background: var(--bad-wash); box-shadow: 0 var(--press) 0 var(--bad-press); }
.option.wrong .key { border-color: var(--bad); background: var(--bad); color: var(--on-color); }
.tf { grid-template-columns: 1fr 1fr; }
.tf .option { justify-content: center; font-weight: 700; font-size: 18px; min-height: 64px; }

.summary-points { list-style: none; padding: 0; margin: 18px 0; display: grid; gap: 2px; text-align: left; }
.summary-points li { padding: 12px 0 12px 38px; position: relative; border-bottom: 1px solid var(--line); }
.summary-points li:last-child { border-bottom: 0; }
.summary-points li::before { content: ""; position: absolute; left: 0; top: 12px; width: 26px; height: 26px; border-radius: 50%; background: var(--ok) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.2 4.2L19 7'/%3E%3C/svg%3E") center / 15px no-repeat; }
.trophy { width: 96px; height: 96px; margin: 24px auto 6px; border-radius: var(--r-xl); display: grid; place-items: center; background: var(--gold-wash); color: var(--gold-ink); }
.trophy svg { width: 52px; height: 52px; }
.trophy.ok { background: var(--ok-wash); color: var(--ok-ink); }
/* Lesson complete (app.js finish): the trophy lands, the next step rises in, the rewards follow once the save is done.
   Only a first completion gets .moment; a re-read is a calm "Review complete". The stats row keeps its height
   reserved (.reserve) so the pills arriving after the save never push the Up next panel down. */
.trophy.moment { animation: moment-in var(--dur-moment) var(--spring) 60ms backwards; }
.milestone { margin-top: 4px; animation: moment-in var(--dur-card) var(--ease-out) calc(60ms + var(--stagger) * 2) backwards; }
.moment-stats.reserve { min-height: 36px; }
.moment-stats > * { animation: rise-in var(--dur-card) var(--ease-out) backwards; }
.moment-stats > :nth-child(2) { animation-delay: var(--stagger); }
.moment-next { animation: rise-in var(--dur-card) var(--ease-out) calc(var(--stagger) * 3) backwards; }

/* ---------- exam / result ---------- */
.exam-facts { display: grid; gap: 0; padding: 4px 20px; }
.exam-facts > div { display: flex; gap: 14px; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--line); }
.exam-facts > div:last-child { border-bottom: 0; }
.exam-facts svg { color: var(--gold-ink); width: 22px; height: 22px; }
.score-ring { --p: 0; --c: var(--gold); width: 180px; height: 180px; margin: 16px auto 6px; border-radius: 50%; display: grid; place-items: center;
  background: conic-gradient(var(--c) calc(var(--p) * 1%), var(--sunken) 0); animation: ring-fill var(--dur-ring) var(--spring) both; }
.score-ring .inner { width: 146px; height: 146px; border-radius: 50%; background: var(--bg); display: grid; place-items: center; text-align: center; }
/* the score counts up (.count): body face for its tabular figures – Poppins' digits are proportional */
.score-ring b { font-family: var(--font-body); font-weight: 700; font-size: 48px; line-height: 1; letter-spacing: -0.02em; display: block; font-variant-numeric: tabular-nums; }
/* Fresh result (just submitted): heading, text, actions and topics follow the ring in, 60 ms apart – decorative, the
   page is usable at once. Revisits get no .play. */
.reveal.play > * { animation: rise-in var(--dur-card) var(--ease-out) backwards; }
.reveal.play > :nth-child(1) { animation-delay: 120ms; }
.reveal.play > :nth-child(2) { animation-delay: calc(120ms + var(--stagger)); }
.reveal.play > :nth-child(3) { animation-delay: calc(120ms + var(--stagger) * 2); }
.reveal.play > :nth-child(n+4) { animation-delay: calc(120ms + var(--stagger) * 3); }
/* the answer review below follows as one block – never visible before the heading above it */
.reveal.play ~ * { animation: rise-in var(--dur-card) var(--ease-out) calc(120ms + var(--stagger) * 4) backwards; }
.review-item { border-radius: var(--r-md); padding: 14px 16px 14px 18px; background: var(--raised); border: 1px solid var(--line); position: relative; overflow: hidden; }
.review-item::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px; background: var(--line); }
.review-item + .review-item { margin-top: 10px; }
.review-item.ok::before { background: var(--ok); }
.review-item.bad::before { background: var(--bad); }
.review-item b { display: block; margin: 4px 0; }
.review-item .ans { font-size: var(--fs-md); margin-top: 6px; }

/* ---------- signature ---------- */
.sig-box { background: var(--paper); border-radius: var(--r-lg); position: relative; touch-action: none; border: 2px solid var(--field); }
.sig-box canvas { display: block; width: 100%; height: 210px; border-radius: var(--r-lg); cursor: crosshair; }
.sig-box .hint { position: absolute; left: 20px; bottom: 46px; right: 20px; border-top: 2px dashed var(--paper-rule); pointer-events: none; }
.sig-box .hint span { position: absolute; left: 0; top: 6px; color: var(--paper-ink); font-size: var(--fs-xs);
  transition: opacity var(--dur-fast) var(--ease-out); }
/* once there is ink the guide text steps aside (the dashed line stays); Clear brings it back */
.sig-box.inked .hint span { opacity: 0; }
.ack-list { padding-left: 0; list-style: none; display: grid; gap: 4px; margin: 6px 0 16px; }
.ack-list li { padding: 8px 0 8px 34px; position: relative; }
.ack-list li::before { content: ""; position: absolute; left: 0; top: 9px; width: 22px; height: 22px; border-radius: var(--r-xs); background: var(--gold-wash); border: 2px solid var(--gold); }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; font-size: var(--fs-md); }
.kv dt { color: var(--ink-3); }
.kv dd { margin: 0; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }

/* ---------- certificate preview ---------- */
/* the certificate's own proportions (3508 × 2480, certificate.js) are reserved, so the preview arriving never pushes
   the page; the image fades in once decoded */
.cert-frame { position: relative; aspect-ratio: 3508 / 2480; border-radius: var(--r-md); overflow: hidden; box-shadow: var(--shadow); border: 1px solid var(--line); background: #FFFFFF; }
.cert-frame img { display: block; width: 100%; opacity: 0; transition: opacity var(--dur-card) var(--ease-out); }
.cert-frame.loaded img { opacity: 1; }
/* first view after signing (about once a year per learner): the certificate lands – rise + grow with the rings' spring –
   then one gold sheen crosses it (white would be invisible on the white paper) */
.cert-frame.fresh:not(.loaded) { opacity: 0; }
.cert-frame.fresh.loaded { animation: cert-land var(--dur-ring-sm) var(--spring) backwards; }
@keyframes cert-land { from { opacity: 0; translate: 0 calc(var(--lift) * 2); scale: var(--moment-s); } }
.cert-frame.fresh.loaded::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 35%, color-mix(in srgb, var(--gold) 28%, transparent) 50%, transparent 65%);
  translate: -100% 0; animation: sheen var(--dur-sheen) var(--ease-in-out) var(--dur-ring-sm) both;
}
@keyframes sheen { to { translate: 100% 0; } }

/* ---------- toast / misc ---------- */
.toast {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%);
  background: var(--ink); color: var(--bg); padding: 12px 18px; border-radius: calc(var(--r-sm) + 4px); font-weight: 600;
  box-shadow: var(--shadow); z-index: 100; max-width: calc(100% - 32px);
  transition: opacity var(--dur-card) var(--ease-out), transform var(--dur-card) var(--ease-out);
}
@starting-style { .toast { opacity: 0; transform: translate(-50%, var(--lift)); } }
.toast.err { background: var(--bad); color: var(--on-color); }
.toast.out { opacity: 0; transform: translate(-50%, var(--lift)); transition-duration: var(--dur-exit); }
/* In the lesson player and exam the footer owns the bottom edge: toasts hang under the top bar and come from above */
body:has(.player-foot) .toast { bottom: auto; top: calc(78px + env(safe-area-inset-top, 0px)); --lift: -8px; }
.loading { display: grid; place-items: center; min-height: 50vh; min-height: 50dvh; color: var(--ink-2); }
.spinner { width: 38px; height: 38px; border: 4px solid var(--sunken); border-top-color: var(--gold); border-radius: 50%; animation: spin var(--dur-spin) linear infinite; }
/* A page spinner shows only when loading takes longer than --spinner-delay: fast loads show nothing instead of a flash.
   (Button spinners – aria-busy – stay immediate: they answer a press.) */
.loading .spinner { animation: fade-in var(--dur-fast) var(--ease-out) var(--spinner-delay) backwards, spin var(--dur-spin) linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* K6: anchored under the avatar that opened it (app.js sets --menu-top / --menu-right from its position) */
.menu {
  position: fixed; top: var(--menu-top, calc(64px + env(safe-area-inset-top, 0px))); right: var(--menu-right, 16px);
  background: var(--raised); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 6px; min-width: 230px; max-width: calc(100vw - 32px); box-shadow: var(--shadow); z-index: 30;
  transform-origin: top right;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
@starting-style { .menu { opacity: 0; transform: translateY(var(--pop-y)) scale(var(--pop-s)); } }
.menu.out { opacity: 0; transform: translateY(var(--pop-y)) scale(var(--pop-s)); transition-duration: var(--dur-exit); }
.out { pointer-events: none; }
.menu .who { padding: 10px 12px 8px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.menu .who b { display: block; font-size: var(--fs-md); }
.menu .who span { font-size: var(--fs-xs); color: var(--ink-3); overflow-wrap: anywhere; }
.menu a, .menu button { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 10px 12px; border-radius: var(--r-sm); color: var(--ink); background: transparent; border: 0; text-decoration: none; font-size: var(--fs-md); }
.menu a:focus-visible, .menu button:focus-visible { outline-offset: -3px; }
.menu a svg, .menu button svg { color: var(--ink-3); }
@media (hover: hover) and (pointer: fine) { .menu a:hover, .menu button:hover { background: var(--sunken); } }
.menu a:active, .menu button:active { background: var(--sunken); }
canvas.confetti { position: fixed; inset: 0; pointer-events: none; z-index: 200; }
.empty { text-align: center; padding: 34px 20px; border: 2px dashed var(--line-strong); border-radius: var(--r-lg); color: var(--ink-2); }

/* ---------- my team ---------- */
/* Home: paused-client notice above the greeting, "My team" card above the trainings */
.callout.notice { margin: 6px 0 14px; }
.callout.notice b.title { display: flex; align-items: center; gap: 8px; font-size: var(--fs-base); color: var(--bad-ink); }
.callout.notice .body { font-size: var(--fs-md); }
.team-card { margin-bottom: 18px; }
.team-card + h2 { margin-top: 10px; }
/* Access removed: a calm dead end */
.access-gate { text-align: center; padding-top: 40px; }
.access-gate .trophy { background: var(--sunken); color: var(--ink-2); }
.access-gate h1 { margin-bottom: 6px; }
.access-gate .btn { margin-top: 18px; }
/* Seats + invite */
.team .seats { display: grid; gap: 10px; }
.team .seats b { font-family: var(--font-display); font-weight: 600; font-size: 22px; letter-spacing: -0.012em; color: var(--ink-head); font-variant-numeric: tabular-nums; }
.team .invite { margin-top: 14px; }
.team .invite .field { margin-bottom: 8px; }
.team .invite textarea { min-height: 88px; font-family: var(--font-mono); font-size: var(--fs-sm); }
.team .invite > p.small { display: flex; align-items: center; gap: 6px; margin: 0 0 14px; }
.team .share { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.copy-row { flex-wrap: nowrap; }
.copy-row .input { flex: 1; min-height: 42px; padding: 8px 12px; border-radius: var(--r-ctl); font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-2); background: var(--sunken); }
.copy-row .btn { flex: 0 0 auto; margin-bottom: 0; }
/* Copy link answers in place: "Copied" with a tick for a moment (team.js); the width is fixed so the swap never jumps */
.copy-btn { min-width: 8.5em; }
.copy-btn.copied { --b-bg: var(--ok-wash); --b-fg: var(--ok-ink); --b-edge: var(--ok); --b-press: var(--ok-press); }
.team-table td { vertical-align: middle; }
.team-table .t-email .mono { font-size: var(--fs-xs); overflow-wrap: anywhere; }
.team-table .t-act .row { flex-wrap: nowrap; justify-content: flex-end; gap: 8px; }
.team-table .t-act .btn { margin-bottom: 0; white-space: nowrap; }
.team-table .t-act .faint { white-space: nowrap; }
.team-table tr.contact td { background: color-mix(in srgb, var(--gold-wash) 45%, transparent); }

/* ---------- admin ---------- */
.admin-nav { display: flex; gap: 2px; flex-wrap: wrap; padding: 4px; border-radius: var(--r-pill); background: var(--sunken); }
.admin-nav a { padding: 7px 14px; border-radius: var(--r-pill); color: var(--ink-2); text-decoration: none; font-weight: 600; font-size: var(--fs-sm); transition: background-color var(--dur-color) var(--ease-out), color var(--dur-color) var(--ease-out); }
.admin-nav a:focus-visible { outline-offset: -3px; }
@media (hover: hover) and (pointer: fine) { .admin-nav a:hover { color: var(--ink); } }
.admin-nav a:is(.active, [aria-current="page"]) { background: var(--seg); color: var(--ink); box-shadow: var(--shadow-seg); }
@media (max-width: 900px) { .topbar.admin { flex-wrap: wrap; } .topbar.admin .admin-nav { order: 9; width: 100%; overflow-x: auto; flex-wrap: nowrap; } }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin: 18px 0 22px; }
.kpi { background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg); padding: 16px 18px; display: grid; gap: 2px; }
.kpi b { font-family: var(--font-display); font-size: 32px; font-weight: 600; line-height: 1.15; letter-spacing: -0.02em; color: var(--ink-head); }   /* static numbers – Poppins has no tabular figures, none needed here */
.kpi span { color: var(--ink-2); font-size: var(--fs-sm); }
.kpi.alert b { color: var(--bad-ink); }
.table-wrap { overflow-x: auto; border: 1px solid var(--edge); border-radius: var(--r-lg); background: var(--raised); }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
th, td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
th { background: var(--sunken); color: var(--ink-2); font-weight: 600; font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .05em; white-space: nowrap; }
@media (hover: hover) and (pointer: fine) { tbody tr:hover td { background: color-mix(in srgb, var(--sunken) 55%, transparent); } }

/* admin "Exam answers" (admin-answers.js): Answers (ghost) sits before Certificate in the table cells; on wide tables
   its icon lines up with the column text (the ghost padding hangs into the cell padding) */
td.ans-actions { white-space: nowrap; }
td.ans-actions > .btn + .btn { margin-left: 6px; }
.ans-btn { padding-inline: 12px; }
@media (min-width: 641px) { td.ans-actions > .ans-btn:first-child { margin-left: -12px; } }
.ans-inline { gap: 2px 8px; }
.ans-inline + .ans-inline { margin-top: 2px; }
/* the dialog: header facts in two pairs per line once the dialog is wide enough, then summary + filter, then the list */
.ans-body { container-type: inline-size; }
.ans-head { padding: 16px 18px; }
.ans-head .kv { gap: 8px 16px; }
.ans-head .kv dd .small { font-weight: 400; }   /* fund names under the client */
@container (min-width: 680px) {
  .ans-head .kv { grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr); }
  .ans-head .kv dt:nth-of-type(even) { padding-left: 12px; }   /* a little air between the two pairs */
}
/* phone: each label above its value, so long emails and fund names get the full width */
@container (max-width: 440px) {
  .ans-head .kv { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .ans-head .kv dt { font-size: var(--fs-sm); }
  .ans-head .kv dd + dt { margin-top: 10px; }
}
.ans-summary { margin: 18px 0 12px; gap: 10px 16px; }
.ans-summary .ans-count { flex: 1 1 14em; font-weight: 600; }   /* drops the filter to its own line before it squeezes */
/* All / Incorrect only: a small segmented control (same look as .tabs and .admin-nav), aria-pressed = the active one */
.ans-filters { flex-wrap: nowrap; gap: 2px; padding: 4px; border-radius: var(--r-pill); background: var(--sunken); }
.ans-filters .ans-filter { min-height: 32px; padding: 6px 14px; color: var(--ink-2);
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-color) var(--ease-out),
    background-color var(--dur-color) var(--ease-out), color var(--dur-color) var(--ease-out); }
.ans-filters .ans-filter[aria-pressed="true"] { background: var(--seg); color: var(--ink); box-shadow: var(--shadow-seg); }
@media (hover: hover) and (pointer: fine) {
  .ans-filters .ans-filter:hover:not(:disabled) { background: transparent; color: var(--ink); }
  .ans-filters .ans-filter[aria-pressed="true"]:hover { background: var(--seg); }
}
.ans-note { margin: 0 0 12px; }
.ans-list { list-style: none; padding: 0; margin: 0; }
.ans-meta { gap: 6px 10px; }
.ans-item[data-state="ok"] .ans-state { color: var(--ok-ink); }
.ans-item:not([data-state="ok"]) .ans-state { color: var(--bad-ink); }
.ans-label { color: var(--ink-2); font-weight: 600; }
.ans-right { color: var(--ok-ink); font-weight: 600; }
.ans-right .ans-label { color: inherit; }
.review-item .ans-expl { margin-top: 8px; }
.ans-empty { padding: 14px 2px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-2 > * { min-width: 0; }
@media (max-width: 800px) { .grid-2 { grid-template-columns: 1fr; } }
.q-edit { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.q-edit .full { grid-column: 1 / -1; }
@media (max-width: 640px) { .q-edit { grid-template-columns: 1fr; } }
.wrap.wide details > summary { cursor: pointer; font-weight: 600; color: var(--ink-2); padding: 6px 0; }
.modal-scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 50; display: grid; place-items: center;
  padding: max(16px, env(safe-area-inset-top, 0px)) max(16px, env(safe-area-inset-right, 0px)) max(16px, env(safe-area-inset-bottom, 0px)) max(16px, env(safe-area-inset-left, 0px));
  transition: opacity var(--dur-fast) var(--ease-out); }
/* dialogs are not anchored to a trigger, so they grow from the centre */
.modal { width: min(940px, 100%); max-height: 90vh; max-height: 90dvh; overflow: auto; overscroll-behavior: contain;
  background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-lg); padding: 22px; box-shadow: var(--shadow);
  --pop-y: 10px; transition: opacity var(--dur-card) var(--ease-out), transform var(--dur-card) var(--ease-out); }
.modal.confirm { width: min(440px, 100%); }
@starting-style {
  .modal-scrim { opacity: 0; }
  .modal { opacity: 0; transform: translateY(var(--pop-y)) scale(var(--pop-s)); }
}
.modal-scrim.out { opacity: 0; transition-duration: var(--dur-exit); }
.modal-scrim.out .modal { opacity: 0; transform: translateY(var(--pop-y)) scale(var(--pop-s)); transition-duration: var(--dur-exit); }

/* ---------- phone tables: rows become cards ----------
   .team-table (learner "My team") and K9 .stack-table (admin: assignments, client users) share the card layout;
   cells with data-label get their column name in front. */
@media (max-width: 640px) {
  .table-wrap:is(.team-table, .stack-table) { border: 0; background: transparent; overflow: visible; border-radius: 0; }
  :is(.team-table, .stack-table) thead { display: none; }
  :is(.team-table, .stack-table) :is(table, tbody, tr, td) { display: block; }
  :is(.team-table, .stack-table) tr { background: var(--raised); border: 1px solid var(--edge); border-radius: var(--r-md); padding: 12px 14px; }
  :is(.team-table, .stack-table) tr + tr { margin-top: 10px; }
  :is(.team-table, .stack-table) td { padding: 0; border: 0; min-width: 0; background: transparent; }
  :is(.team-table, .stack-table) tbody tr:hover td { background: transparent; }
  :is(.team-table, .stack-table) td[data-label]::before { content: attr(data-label) ": "; color: var(--ink-3); }
  :is(.team-table, .stack-table) td .btn { margin-bottom: 0; }
  .stack-table td + td { margin-top: 4px; }
  .stack-table td:empty { display: none; }
  .stack-table td:first-child { font-weight: 600; }
  .stack-table td:last-child:has(.btn, .btn-ghost) { margin-top: 8px; }

  .team-table tr { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: center; }
  .team-table tr.contact { border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
  .team-table tr.contact td { background: transparent; }
  .team-table .t-email { grid-column: 1; grid-row: 1; font-weight: 600; }
  .team-table .t-status { grid-column: 2; grid-row: 1; justify-self: end; }
  .team-table .t-name { grid-column: 1 / -1; grid-row: 2; }
  .team-table .t-score, .team-table .t-signed { font-size: var(--fs-sm); color: var(--ink-2); }
  .team-table .t-score { grid-column: 1; grid-row: 3; }
  .team-table .t-signed { grid-column: 2; grid-row: 3; justify-self: end; }
  .team-table .t-act { grid-column: 1 / -1; grid-row: 4; margin-top: 6px; }
  .team-table .t-act .row { justify-content: flex-start; flex-wrap: wrap; }
}
@media (max-width: 560px) {
  .copy-row { flex-wrap: wrap; }
  .copy-row .btn { width: 100%; }
}

/* ---------- touch screens ---------- */
/* Every control reaches a 44px target; fields use 16px text so iOS does not zoom the page on focus */
@media (pointer: coarse) {
  .icon-btn, .avatar, .close-x { width: var(--tap); height: var(--tap); }
  .btn-sm, .btn-ghost, .btn.btn-ghost { min-height: var(--tap); }
  .tabs button, .menu a, .menu button { min-height: var(--tap); }
  .admin-nav a { display: inline-flex; align-items: center; min-height: var(--tap); }
  input, select, textarea, .input, .copy-row .input, .team .invite textarea, textarea.code { font-size: var(--fs-ui); }
}

/* Reduced motion: nothing slides, grows, shakes, blurs or sweeps – cards, feedback, menus and dialogs only cross-fade. */
@media (prefers-reduced-motion: reduce) {
  :root { --spring: var(--ease-out); --slide: 0px; --lift: 0px; --stagger-lift: 0px; --pop-y: 0px; --pop-s: 1; --nudge: 0px; --card-blur: 0px; --moment-s: 1; }
  .modal { --pop-y: 0px; }
  .lcard { animation-name: fade-in; }
  .ring, .score-ring, .option.pop, .count { animation: none; }   /* rings and numbers show their final value at once */
  .spinner, .btn[aria-busy="true"]::after, .btn-ghost[aria-busy="true"]::after { animation-duration: 2.4s; }
  .loading .spinner { animation-duration: var(--dur-fast), 2.4s; }   /* still delayed, still slow */
  .cert-frame::after { display: none; }
  details::details-content, .chev, .progress > div, .training-card { transition: none; }
  .atmos.enter, .atmos.enter .atmos-art { animation: none; }   /* the home atmosphere is simply there */
}
/* Reduced transparency: the floating bars become solid */
@media (prefers-reduced-transparency: reduce) {
  .topbar, .player-top, .player-foot { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .player-foot.ok { background: var(--ok-wash); }
  .player-foot.bad { background: var(--bad-wash); }
  /* home atmosphere: half-strength glows, no grid */
  .atmos { opacity: .5; }
  .atmos-grid { display: none; }
}
/* Increased contrast: firmer lines and secondary text */
@media (prefers-contrast: more) {
  :root, :root[data-theme="dark"] { --line: var(--line-strong); --line-strong: var(--field); --ink-3: var(--ink-2); --edge: var(--line); }
  .topbar, .player-top, .player-foot { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .player-foot.ok { background: var(--ok-wash); }
  .player-foot.bad { background: var(--bad-wash); }
  .atmos { display: none; }                  /* no decoration behind text */
}

/* ---------- print ---------- */
@media print {
  body { background: #FFFFFF; }
  .topbar, .no-print, .atmos { display: none !important; }
  .wrap { max-width: none; padding: 0; }
}
