/* LevlPrep — "Clay" design system.
   Soft, tactile, calm: heavy Nunito, no outlines, generous radii, and
   layered soft shadows instead of hard offsets. Surfaces read as clay
   pieces resting on a pale mint ground; a tinted panel opens every page
   (mint for NREMT, lilac for ochem — see --ctint). Loaded on every page so
   the palette and the shared header live in one place.

   The token NAMES are unchanged from the previous "Guided Path" system so
   every page's local styles keep resolving: --bw is now 0 (outlines are
   gone), the --lift-* shadows are soft, and the hard --navy-press offsets
   only remain as hover/active tints.

   Layers, in order:
     1. Tokens (light + dark)
     2. Base reset / page shell / typography
     3. Primitives: buttons, cards, pills, tracks, tags
     4. Site shell layout (.xshell, .hero, .xsection, grids)
     5. Gamification components (level, XP, streak, path nodes, badges)
     6. Sticky site header (markup injected by nav.js)
     7. Auth modal, print
*/

/* ==========================================================================
   1. Tokens
   ========================================================================== */
:root{
  /* Core palette */
  --navy:#1F4A42;        /* deep teal — primary buttons, dark panels */
  --navy-press:#173B35;  /* darker teal — pressed / hover on navy */
  --navy2:#2A5F55;       /* secondary teal — hover states */
  --paper:#F3F6F4;       /* page background — pale mint ground */
  --white:#FFFFFF;       /* card surface */
  --surface2:#F7FAF8;    /* a quieter surface inside a card: answer rows, inputs */
  /* Deep teal. This used to be the mint #2C9C8B, which measured 3.37:1 on white
     — under the 4.5:1 AA needs for body text — and the accent carries real text
     all over this site: eyebrow labels, links, section heads, and white-on-fill
     buttons. #106D60 keeps the hue and clears AA at 6.2:1 on white, 5.4:1 on
     --tint-accent. --accent-bright is the old mint, kept for the places where
     the colour is decoration rather than text: bar fills, rules, dots. */
  --accent:#1C8C7B;      /* primary teal — safe for text and for fills */
  --accent-press:#156D60;
  --accent-bright:#35B39F;
  --amber:#E0A63C;       /* streaks, "in progress" */
  --amber-press:#B8842A;
  --coral:#F08A7C;       /* warm highlight, difficulty tags */
  --coral-press:#D06A5C;
  --lilac:#B9AEE8;       /* the ochem course tint's saturated partner */
  --accent-2:#F08A7C;    /* legacy alias for --coral */

  /* Course tint: the panel every page opens with, and the active tab. The
     chrome sets data-course on <body>; ochem swaps these for lilac. */
  --ctint:#DFF2ED;
  --cink:#0F5F53;

  /* Lines + tracks */
  --line:#E4ECE8;        /* hairlines and the inset ring on form controls */
  --line-soft:#EDF2EF;   /* 1px dividers between rows inside a card */
  --track:#E9F0ED;       /* unfilled portion of a progress bar */
  --hover-tint:#EEF4F1;

  /* Text */
  --ink:#1B2A26;
  --muted:#55706A;
  --on-accent:#FFFFFF;   /* text on a solid navy/bad fill — white in both themes */
  /* Text on a solid --accent fill, which is NOT the same thing: dark mode lifts
     the accent to a bright mint that white text cannot sit on (2.37:1). Kept
     separate so the navy buttons above aren't dragged along with it. */
  --on-accent-fill:#FFFFFF;
  /* Secondary text on the dark navy panels that appear in BOTH themes — the
     light theme's --muted is a dark grey and vanishes on them. */
  --muted-on-dark:#A8BDB6;

  /* Status */
  --good:#2F9E5B;
  --good-press:#237A45;
  --bad:#D1594A;
  --bad-press:#A84135;
  --warn:#C9973A;

  /* Text colours for a pill sitting on the matching pale tint below. The fill
     colours themselves are tuned for solid shapes and all measured under 3:1
     against their own tint (the coral tag was 2.48:1), so a tag that is mostly
     small bold text needs its own, darker value. */
  --coral-text:#A8452A;
  --amber-text:#8A5E10;
  --good-text:#1F6E3E;
  --bad-text:#A83B2C;
  --accent-text:#0F5F53;

  /* Pale tints — badge and answer-state backgrounds */
  --tint-accent:#DFF2ED;
  --tint-amber:#FBEFD6;
  --tint-coral:#FDE7E2;
  --tint-good:#E2F4E8;
  --tint-bad:#FCE4DF;
  --tint-warn:#FBEFD6;
  --tint-lilac:#ECE8FB;

  /* Type */
  --font-ui:'Nunito','Segoe UI',system-ui,sans-serif;
  --font-display:'Nunito','Segoe UI',system-ui,sans-serif;
  --font-serif:'Nunito','Segoe UI',system-ui,sans-serif; /* legacy alias — the serif is gone */
  --font-mono:'IBM Plex Mono',ui-monospace,Menlo,monospace;

  /* Shape */
  --radius-sm:12px;
  --radius:16px;
  --radius-lg:22px;
  --radius-pill:999px;
  --bw:0px;              /* outlines are gone; kept so page-local rules resolve */

  /* Soft layered shadows — the signature of this system. */
  --lift-sm:0 1px 2px rgba(20,40,35,0.04),0 6px 16px rgba(20,40,35,0.06);
  --lift:0 1px 2px rgba(20,40,35,0.05),0 12px 28px rgba(20,40,35,0.08);
  --lift-lg:0 2px 4px rgba(20,40,35,0.05),0 18px 40px rgba(20,40,35,0.10);
  --shadow-card:var(--lift);
  --shadow-pop:0 2px 4px rgba(20,40,35,0.06),0 24px 48px rgba(20,40,35,0.14);
  --btn-shadow:0 8px 20px rgba(31,74,66,0.28);
  --btn-shadow-accent:0 8px 20px rgba(28,140,123,0.30);

  --overlay-bg:rgba(243,246,244,0.92);
  --header-bg:rgba(243,246,244,0.82);
  --site-header-h:112px; /* fallback for both chrome rows; site-chrome.js
                            measures the real heights (see --chrome-row1-h) */
  --chrome-row1-h:60px;
}

/* Dark theme — toggled via [data-theme="dark"] on <html> by nav.js. */
:root[data-theme="dark"]{
  /* --navy is both the primary button fill and the dark-panel background. On a
     near-black page the light theme's #16332E is almost invisible, so dark
     lifts it to the mid teal — buttons stay legible and the dark panels read
     as a distinct surface rather than merging into the page. */
  --navy:#2A5F55;
  --navy-press:#1F4A42;
  --navy2:#33756A;
  --paper:#0F1917;
  --white:#17241F;
  --surface2:#1C2B26;
  --accent:#3FC2A9;
  --accent-press:#2E8D80;
  --accent-bright:#3FC2A9;
  --lilac:#9C8FE0;
  --ctint:rgba(63,194,169,0.14);
  --cink:#9FE6D6;
  --on-accent-fill:#0C1F1A;  /* 6.9:1 on the mint; white would be 2.37:1 */
  --muted-on-dark:#A8BDB6;
  --amber:#D9A54B;
  --amber-press:#A67A28;
  --coral:#E8776A;
  --coral-press:#C15A4E;
  --accent-2:#E8776A;

  --line:#243530;
  --line-soft:#213029;
  --track:#22322D;
  --hover-tint:#1E2E29;

  --ink:#E7F1EE;
  --muted:#8CA39B;

  --good:#4FBE79;
  --good-press:#237A45;
  --bad:#E4776A;
  --bad-press:#A84135;
  --warn:#D9A54B;

  --coral-text:#F0A093;
  --amber-text:#E5BC72;
  --good-text:#6FD094;
  --bad-text:#F0938A;
  --accent-text:#5FC7B3;

  --tint-accent:rgba(63,194,169,0.14);
  --tint-amber:rgba(229,184,90,0.16);
  --tint-coral:rgba(242,154,142,0.16);
  --tint-good:rgba(79,190,121,0.18);
  --tint-bad:rgba(228,119,106,0.18);
  --tint-warn:rgba(229,184,90,0.16);
  --tint-lilac:rgba(156,143,224,0.18);

  --lift-sm:0 1px 2px rgba(0,0,0,0.3),0 6px 16px rgba(0,0,0,0.3);
  --lift:0 1px 2px rgba(0,0,0,0.3),0 12px 28px rgba(0,0,0,0.35);
  --lift-lg:0 2px 4px rgba(0,0,0,0.3),0 18px 40px rgba(0,0,0,0.42);
  --shadow-pop:0 2px 4px rgba(0,0,0,0.3),0 24px 48px rgba(0,0,0,0.5);
  --btn-shadow:0 8px 20px rgba(0,0,0,0.35);
  --btn-shadow-accent:0 8px 20px rgba(63,194,169,0.22);

  --overlay-bg:rgba(15,25,23,0.92);
  --header-bg:rgba(15,25,23,0.82);
}

/* The ochem course's tint. Set on <body> by site-chrome.js from the course
   the page registered; the hub and NREMT keep the mint defaults above. */
body[data-course="ochem"]{--ctint:#ECE8FB;--cink:#4B3BA8;}
:root[data-theme="dark"] body[data-course="ochem"]{--ctint:rgba(156,143,224,0.18);--cink:#C9C0F2;}

/* ==========================================================================
   2. Base
   ========================================================================== */
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
/* Components in this system set explicit display values (inline-flex chips,
   flex cards), which otherwise beat the hidden attribute's UA rule — so the
   streak chip would still show at zero. */
[hidden]{display:none !important;}
body{
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-ui);
  font-weight:600;
  line-height:1.55;
  font-variant-numeric:tabular-nums;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;}
svg{display:block;}

h1,h2,h3,h4{font-family:var(--font-ui);letter-spacing:-0.02em;}
h1{font-size:clamp(28px,4.2vw,44px);font-weight:900;margin:6px 0 14px;line-height:1.08;}
h2{
  font-size:clamp(20px,2.6vw,26px);font-weight:900;color:var(--ink);
  margin:44px 0 16px;padding-top:0;border-top:0;line-height:1.2;text-wrap:balance;
}
/* Form controls lost their outline with --bw; a thin inset ring keeps them
   visible on a white card without bringing the outlines back. */
select,textarea,input:not([type="checkbox"]):not([type="radio"]):not([type="range"]){
  box-shadow:inset 0 0 0 1.5px var(--line);border:0;background:var(--surface2);
  border-radius:var(--radius-sm);font-family:var(--font-ui);color:var(--ink);
}
select:focus,textarea:focus,input:focus{box-shadow:inset 0 0 0 2px var(--accent);}
h3{font-size:17px;font-weight:900;margin:26px 0 10px;}
p{text-wrap:pretty;}
.lede{color:var(--muted);font-size:16.5px;font-weight:700;max-width:52ch;margin:0 0 26px;}
strong,b{font-weight:900;}

/* Every page is the width of the header. .wrap is the older shell name used
   by the NREMT tool pages; it now measures the same as .xshell. */
.wrap{max-width:1180px;margin:0 auto;padding:36px clamp(18px,3.5vw,48px) 90px;}

/* ==========================================================================
   3. Primitives
   ========================================================================== */

/* ---- The pressed button: the core primitive of this system. The hard
   offset shadow reads as the button's thickness; on :active the element
   drops by exactly that offset and the shadow collapses to zero. ---- */
.btn-press,.btn-dark,.start-btn,.auth-modal-submit{
  font:900 15px var(--font-ui);
  color:var(--on-accent);
  background:var(--navy);
  padding:14px 26px;
  border-radius:var(--radius);
  border:0;
  cursor:pointer;
  text-decoration:none;
  display:inline-block;
  text-align:center;
  box-shadow:var(--btn-shadow);
  transition:transform .12s cubic-bezier(.2,.8,.3,1.3), box-shadow .15s ease, filter .15s ease;
}
.btn-press:hover,.btn-dark:hover,.start-btn:hover,.auth-modal-submit:hover{
  filter:brightness(1.06);color:var(--on-accent);background:var(--navy);transform:translateY(-1px);
}
.btn-press:active,.btn-dark:active,.start-btn:active,.auth-modal-submit:active{
  transform:translateY(1px) scale(.98);box-shadow:0 3px 8px rgba(31,74,66,0.25);
}
.btn-press.alt,.btn-accent{background:var(--accent);color:var(--on-accent-fill);box-shadow:var(--btn-shadow-accent);}
.btn-press.alt:hover,.btn-accent:hover{background:var(--accent);color:var(--on-accent-fill);}
.btn-press.alt:active,.btn-accent:active{box-shadow:0 3px 8px rgba(28,140,123,0.25);}
.btn-press.coral{background:var(--coral);box-shadow:0 8px 20px rgba(240,138,124,0.32);}
.btn-press.coral:active{box-shadow:0 3px 8px rgba(240,138,124,0.25);}
.btn-press.sm{font-size:13.5px;padding:11px 20px;border-radius:13px;}
.btn-press.sm:active{transform:translateY(1px) scale(.98);}
.btn-press.wide{display:block;width:100%;}
.btn-press:disabled,.btn-dark:disabled,.start-btn:disabled{
  opacity:.45;cursor:not-allowed;transform:none;filter:none;
}

/* Outline variant — same thickness, paper fill. */
.btn-outline,.review-btn,.domain-btn{
  font:900 14px var(--font-ui);
  color:var(--ink);
  background:var(--white);
  border:var(--bw) solid var(--line);
  padding:12px 22px;
  border-radius:var(--radius);
  cursor:pointer;
  text-decoration:none;
  display:inline-block;
  text-align:center;
  box-shadow:var(--lift);
  transition:transform .12s cubic-bezier(.2,.8,.3,1.3), box-shadow .15s ease, background-color .15s ease;
}
.btn-outline:hover,.review-btn:hover,.domain-btn:hover{background:var(--hover-tint);color:var(--ink);transform:translateY(-1px);}
.btn-outline:active,.review-btn:active,.domain-btn:active{transform:translateY(1px) scale(.98);box-shadow:var(--lift-sm);}

/* Quiet text link with an accent underline. */
.link-underline,.link-quiet{
  font:800 14.5px var(--font-ui);color:var(--ink);background:none;border:0;
  border-bottom:var(--bw) solid var(--accent);padding:0 0 2px;cursor:pointer;
  text-decoration:none;display:inline-block;
}
.link-underline:hover,.link-quiet:hover{color:var(--accent);}

/* ---- Card: 2px outline + hard lift. Every panel on the site is one. ---- */
.card,.panel{
  background:var(--white);
  border:var(--bw) solid var(--line);
  border-radius:var(--radius-lg);
  padding:22px;
  box-shadow:var(--lift-lg);
}
.panel h2{font-size:16px;font-weight:900;margin:0 0 16px;letter-spacing:-0.01em;}
.card-tight{padding:18px 20px;border-radius:var(--radius);box-shadow:var(--lift);}

/* ---- Pills + tags ---- */
.chip-pill{
  font:800 13.5px var(--font-ui);color:var(--ink);background:var(--white);
  border:var(--bw) solid var(--line);border-radius:var(--radius-pill);
  padding:8px 16px;display:inline-block;
}
.tag{font:900 11.5px var(--font-ui);padding:6px 13px;border-radius:var(--radius-pill);display:inline-block;}
.tag.domain{color:var(--coral-text);background:var(--tint-coral);}
.tag.diff{color:var(--amber-text);background:var(--tint-amber);}
.tag.good{color:var(--good-text);background:var(--tint-good);}
.tag.accent{color:var(--accent-text);background:var(--tint-accent);}

/* ---- Progress track ---- */
.track{height:12px;border-radius:var(--radius-pill);background:var(--track);overflow:hidden;}
.track > i,.track > .fill{display:block;height:100%;border-radius:var(--radius-pill);background:var(--dc,var(--accent));transition:width .9s cubic-bezier(.2,.8,.2,1);}
.track.thin{height:8px;}
.track.thick{height:16px;}

/* ==========================================================================
   4. Site shell
   ========================================================================== */
.xshell{max-width:1180px;margin:0 auto;padding:0 clamp(18px,3.5vw,48px);}
.eyebrow{font:900 11px var(--font-ui);letter-spacing:.1em;text-transform:uppercase;color:var(--accent);margin-bottom:14px;}

/* The tinted panel every page opens with. Course-coloured (see --ctint), so
   a page says which course it belongs to before a word is read. */
.hero{
  margin-top:16px;padding:clamp(24px,4vw,44px);border-bottom:0;
  background:var(--ctint);border-radius:var(--radius-lg);
}
.hero h1{margin:0 0 16px;max-width:17ch;}
.hero .lede{margin:0 0 28px;max-width:48ch;}
.hero .lede:last-child,.hero > :last-child{margin-bottom:0;}
.hero .eyebrow{color:var(--cink);}
.hero-ctas{display:flex;align-items:center;gap:22px;flex-wrap:wrap;}

/* The compact opener — same tinted panel as .hero, at title scale. */
.page-head{
  margin-top:16px;padding:clamp(22px,3.5vw,34px) clamp(22px,3.5vw,36px);
  background:var(--ctint);border-radius:var(--radius-lg);
  animation:levl-rise .5s cubic-bezier(.2,.8,.2,1) both;
}
.page-head .eyebrow{color:var(--cink);}
.page-head h1{font-size:clamp(26px,3.2vw,34px);margin:0 0 6px;}
.page-head p{color:var(--muted);font-weight:700;font-size:14.5px;margin:0;max-width:60ch;}
.page-head p + p,.page-head .lede + *{margin-top:14px;}

.xsection{padding:clamp(28px,3.5vw,40px) 0;border-bottom:0;}
.xsection:last-child{border-bottom:0;}
.xsection-tight{padding-top:22px;}
.section-head{text-align:center;margin-bottom:8px;}
.section-head h2{margin:0 0 8px;font-size:clamp(23px,3vw,30px);}
.section-lede{color:var(--muted);font-size:15px;font-weight:700;max-width:50ch;margin:0 auto;}

.xgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:clamp(22px,3.5vw,38px);}
.xlabel{font:900 11px var(--font-ui);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding-top:4px;max-width:150px;}
.xcontent{grid-column:span 2;min-width:0;}
.xcontent.narrow{max-width:64ch;}

/* A labelled section (an .xlabel beside its .xcontent) reads as a titled card
   in this system, not as an editorial column with a gutter: the label becomes
   the card's heading and the content sits on a raised panel. Grids without a
   label — tool tiles, mnemonic cards — keep their multi-column layout. */
.xgrid:has(> .xlabel){display:block;}
.xgrid:has(> .xlabel) > .xlabel{
  font:900 16px var(--font-ui);letter-spacing:-0.01em;text-transform:none;
  color:var(--ink);max-width:none;padding-top:0;margin-bottom:14px;
}
.xgrid:has(> .xlabel) > .xlabel br{display:none;}
.xgrid:has(> .xlabel) > .xcontent{
  grid-column:auto;max-width:none;
  background:var(--white);border:var(--bw) solid var(--line);
  border-radius:var(--radius-lg);padding:22px 24px;box-shadow:var(--lift-lg);
}
/* A page is narrow or wide as a WHOLE — put `narrow` on the .xshell for a
   prose page (privacy, glossary, notes). Centring individual sections instead
   gave mixed pages two competing column widths and two left edges, so the eye
   had to re-anchor on every scroll. */
.xgrid:has(> .xlabel) > .xcontent.narrow{max-width:none;}
/* .xshell.narrow used to be 880px; every shell is one width now. */
.xshell.narrow{max-width:1180px;}

/* Tool tiles on the Tools page: the whole card is the link. */
.tool-card{
  display:block;background:var(--white);border:var(--bw) solid var(--line);
  border-radius:var(--radius-lg);padding:18px;box-shadow:var(--lift-lg);
  text-decoration:none;color:inherit;
  transition:transform .08s ease, box-shadow .08s ease, border-color .12s ease;
}
.tool-card:hover{transform:translateY(-3px);box-shadow:var(--lift-lg);}
.tool-card:active{transform:scale(.985);box-shadow:var(--lift-sm);}

/* Row inside a card: label left, value right, hairline divider. */
.xrow,.kv-row{
  display:flex;flex-wrap:wrap;gap:6px 20px;align-items:baseline;justify-content:space-between;
  padding:11px 0;border-bottom:1px solid var(--line-soft);font-size:14.5px;font-weight:700;
}
.xrow:last-child,.kv-row:last-child{border-bottom:0;}
.xnum{font:700 13px var(--font-mono);color:var(--accent);}
.xmeta,.kv-row .v{font:700 12.5px var(--font-mono);color:var(--muted);white-space:nowrap;}

.split{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:clamp(28px,4.5vw,52px);align-items:start;}
.split-divider{border-left:1px solid var(--line-soft);padding-left:clamp(20px,3vw,30px);}
.split-label{font:900 11px var(--font-ui);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;}

.step-row{display:flex;gap:18px;padding:16px 0;border-bottom:1px solid var(--line-soft);}
.step-row:last-child{border-bottom:0;}
.step-num{font:700 13px var(--font-mono);color:var(--accent);padding-top:6px;flex-shrink:0;}
.step-title{font-size:17px;font-weight:900;display:block;margin-bottom:2px;}
.step-sub{font-size:14px;font-weight:600;color:var(--muted);}

/* Trust strip — pills, not a ruled row. */
.trust-row{display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:center;}
.trust-pill{
  display:flex;align-items:center;gap:10px;background:var(--white);
  border:var(--bw) solid var(--line);border-radius:var(--radius-pill);
  padding:12px 20px;font-weight:900;font-size:13.5px;
}
.trust-item-title{font:900 14px var(--font-ui);color:var(--ink);}
.trust-item-sub{font-size:13px;font-weight:600;color:var(--muted);}
.trust-note,.disclaimer{
  font:600 12.5px var(--font-ui);color:var(--muted);margin:0 auto;
  max-width:65ch;text-align:center;padding-top:24px;
}

.screenshot-slot{
  min-height:220px;border:var(--bw) solid var(--line);border-radius:var(--radius-lg);
  background-image:repeating-linear-gradient(135deg,var(--hover-tint) 0 8px,var(--paper) 8px 16px);
  display:flex;align-items:flex-end;padding:14px;box-shadow:var(--lift);
}
.screenshot-slot span{font:700 11px var(--font-mono);color:var(--muted);background:var(--paper);padding:4px 8px;border-radius:6px;}

/* ==========================================================================
   5. Gamification components
   ========================================================================== */

/* Level ring — the circular "L4" chip used in the header and hero card. */
.level-ring{
  width:56px;height:56px;border-radius:50%;background:var(--tint-accent);
  border:3px solid var(--accent);display:flex;align-items:center;justify-content:center;
  font:900 16px var(--font-ui);color:var(--accent);flex-shrink:0;
}
.level-ring.sm{width:32px;height:32px;border-width:2px;font-size:11.5px;}

/* Streak chip — amber flame + count. */
.streak-chip{
  display:inline-flex;align-items:center;gap:8px;font-weight:900;font-size:17px;
  color:var(--amber);background:var(--tint-amber);padding:8px 14px;border-radius:var(--radius-pill);
}
.streak-chip svg{width:20px;height:20px;}
.streak-chip.sm{font-size:13.5px;gap:6px;padding:6px 11px;}
.streak-chip.sm svg{width:15px;height:15px;}

/* XP bar + label. */
.xp-track{height:16px;border-radius:var(--radius-pill);background:var(--track);overflow:hidden;margin-bottom:8px;}
.xp-fill{height:100%;border-radius:var(--radius-pill);background:var(--accent-bright);transition:width .9s cubic-bezier(.2,.8,.2,1);}
.xp-label{font:700 11.5px var(--font-mono);color:var(--muted);}

/* A domain row with an inline bar — used in the hero card and dashboard. */
.mini-domain-row{
  display:flex;justify-content:space-between;align-items:center;
  padding:9px 0;border-top:1px solid var(--line-soft);font-size:13px;font-weight:800;
}
.mini-domain-row .bar{flex:1;height:8px;border-radius:var(--radius-pill);background:var(--track);margin:0 12px;overflow:hidden;}
.mini-domain-row .bar i{display:block;height:100%;border-radius:var(--radius-pill);background:var(--dc,var(--accent));transition:width .9s cubic-bezier(.2,.8,.2,1);}
.mini-domain-row .pct{font:700 12px var(--font-mono);color:var(--muted);width:36px;text-align:right;}

/* Stat card — tinted icon tile over a big number. */
.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;}
.stat-card{
  background:var(--white);border:var(--bw) solid var(--line);border-radius:18px;
  padding:18px 20px;box-shadow:var(--lift);
}
.stat-card .icon{
  width:38px;height:38px;border-radius:11px;display:flex;align-items:center;
  justify-content:center;margin-bottom:12px;background:var(--tint-accent);
}
.stat-card .icon svg{width:20px;height:20px;}
.stat-card .v{font-weight:900;font-size:25px;line-height:1;}
.stat-card .l{font-size:12px;color:var(--muted);font-weight:800;margin-top:5px;}

/* Chunky answer option — letter circle + label, selectable, gradable. */
.qopt{
  display:flex;align-items:center;gap:14px;font-size:15.5px;font-weight:800;
  padding:15px 18px;border-radius:16px;border:0;
  margin-bottom:12px;box-shadow:none;cursor:pointer;background:var(--surface2);
  transition:transform .15s cubic-bezier(.2,.8,.3,1.3), box-shadow .2s ease, background-color .2s ease;
  width:100%;text-align:left;font-family:var(--font-ui);color:var(--ink);
}
.qopt:hover{transform:translateX(3px);background:var(--hover-tint);}
.qopt .letter{
  width:30px;height:30px;border-radius:50%;border:0;background:var(--white);box-shadow:var(--lift-sm);
  display:flex;align-items:center;justify-content:center;font:900 12px var(--font-ui);color:var(--ink);
  flex-shrink:0;transition:background-color .2s ease, color .2s ease, transform .3s cubic-bezier(.2,.8,.3,1.6);
}
.qopt.selected{background:var(--white);box-shadow:inset 0 0 0 2px var(--navy);}
.qopt.selected .letter{background:var(--navy);color:var(--on-accent);}
.qopt.correct{background:var(--tint-accent);box-shadow:inset 0 0 0 2px var(--accent-bright);}
.qopt.correct .letter{background:var(--accent);color:var(--on-accent-fill);transform:scale(1.12);}
.qopt.incorrect{background:var(--tint-bad);box-shadow:inset 0 0 0 2px var(--coral);animation:levl-shake .4s;}
.qopt.incorrect .letter{background:var(--bad);color:var(--on-accent);}
.qopt:disabled{cursor:default;}
.qopt:disabled:hover{transform:none;background:var(--surface2);}
.qopt:disabled.correct:hover{background:var(--tint-accent);}
.qopt:disabled.incorrect:hover{background:var(--tint-bad);}
@keyframes levl-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}

/* Badge grid — earned / locked achievement discs. */
.badge-grid{display:flex;flex-wrap:wrap;gap:14px;}
.badge{width:66px;text-align:center;}
.badge-circle{
  width:56px;height:56px;border-radius:50%;background:var(--tint-accent);
  border:3px solid var(--accent);display:flex;align-items:center;justify-content:center;
  font-size:22px;margin:0 auto 6px;
}
.badge-circle.locked{background:var(--track);border-color:var(--line);opacity:.5;}
.badge span{font-size:10.5px;font-weight:800;color:var(--muted);line-height:1.3;display:block;}

/* Streak calendar. */
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;}
.cal-day{
  aspect-ratio:1;border-radius:8px;background:var(--track);display:flex;
  align-items:center;justify-content:center;font:800 10px var(--font-mono);color:var(--muted);
}
.cal-day.done{background:var(--accent);color:var(--on-accent-fill);}
.cal-day.today{outline:2px solid var(--navy);outline-offset:1px;}

/* Skill path — zigzagging domain nodes joined by a dashed spine. */
.path{position:relative;max-width:520px;margin:0 auto;}
.path::before{
  content:"";position:absolute;left:50%;top:38px;bottom:38px;width:4px;
  background:repeating-linear-gradient(to bottom,var(--line) 0 10px,transparent 10px 20px);
  transform:translateX(-50%);z-index:0;
}
/* [ label ] [ circle ] [ label ] — the middle track is the circle's own width,
   so the spine at 50% runs straight through every node. */
.node{
  position:relative;display:grid;align-items:center;
  grid-template-columns:1fr 76px 1fr;gap:16px;margin-bottom:34px;z-index:1;
}
.node:last-child{margin-bottom:0;}
.node > *{grid-row:1;} /* keep circle and label on one row; auto-placement would push the left-side label to row 2 */
.node .node-circle{grid-column:2;}
.node.left .node-text{grid-column:1;justify-self:end;text-align:right;}
.node.right .node-text{grid-column:3;justify-self:start;}
.node.center .node-text{grid-column:3;justify-self:start;}
.node-circle{
  width:76px;height:76px;border-radius:50%;background:var(--white);
  border:4px solid var(--c,var(--accent));display:flex;align-items:center;justify-content:center;
  flex-shrink:0;box-shadow:var(--lift);cursor:pointer;
  transition:transform .18s cubic-bezier(.2,.8,.3,1.3), box-shadow .18s ease;text-decoration:none;
}
.node-circle:hover{transform:translateY(-3px);box-shadow:var(--lift-lg);}
.node-circle:active{transform:scale(.96);box-shadow:var(--lift-sm);}
.node-circle svg{width:30px;height:30px;}
.node-text{background:var(--white);border:0;border-radius:14px;padding:9px 14px;max-width:100%;box-shadow:var(--lift-sm);}
.node-text .n{font-weight:900;font-size:13.5px;line-height:1.25;}
.node-text .d{font-size:11.5px;color:var(--muted);font-weight:700;line-height:1.35;}

/* Side rail tip card. */
.tip-card{
  background:var(--white);border:var(--bw) solid var(--line);border-radius:18px;
  padding:20px 22px;box-shadow:var(--lift);
}
.tip-card .k{font:900 11px var(--font-ui);color:var(--accent);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;}
.tip-card .v{font-weight:900;font-size:15px;margin-bottom:4px;}
.tip-card .s{font-size:13px;color:var(--muted);font-weight:600;line-height:1.5;}

/* ==========================================================================
   6. Site chrome — two rows, injected by assets/site-chrome.js
      Row 1 (#site-header): global, identical on every course.
      Row 2 (.course-nav):  the current course's section tabs.
   ========================================================================== */
#site-header{
  position:sticky;top:0;z-index:30;
  background:var(--header-bg);
  border-bottom:0;
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
}
.site-header__inner{
  max-width:1180px;margin:0 auto;
  padding:11px clamp(18px,3.5vw,48px);
  display:flex;flex-wrap:wrap;align-items:center;
  gap:8px 14px;font-family:var(--font-ui);
}
.site-header__brand-row{display:inline-flex;align-items:center;gap:10px;min-width:0;}
.hub-back{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:50%;
  border:0;background:var(--white);box-shadow:var(--lift-sm);
  font-size:14px;font-weight:900;color:var(--muted);
  text-decoration:none;flex-shrink:0;line-height:1;
}
.hub-back:hover{border-color:var(--accent);color:var(--accent);}

.site-header__brand{
  display:inline-flex;align-items:center;gap:10px;
  font-weight:900;font-size:17px;color:var(--ink);text-decoration:none;
  letter-spacing:-0.01em;background:none;border:0;padding:0;cursor:pointer;
  flex-shrink:0;
}
.site-header__brand .brand-mark{
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:11px;
  background:var(--navy);color:var(--on-accent);
  font-size:17px;font-weight:900;line-height:1;
  box-shadow:0 6px 14px rgba(31,74,66,0.25);flex-shrink:0;
}
/* The course name sits beside the wordmark behind a hairline, so every page
   says which course you're in without the course competing with the site. */
.site-header__course{
  position:relative;padding-left:13px;
  font:800 14px var(--font-ui);color:var(--muted);text-decoration:none;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;
}
.site-header__course::before{
  content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:2px;height:17px;border-radius:2px;background:var(--line);
}
.site-header__course:hover{color:var(--ink);}

.nav-right{display:flex;align-items:center;gap:10px;flex-shrink:0;margin-left:auto;}

/* Header streak chip. Hidden at 0 so a new user doesn't see an empty flame. */
.nav-streak{
  display:inline-flex;align-items:center;gap:6px;font-weight:900;font-size:13.5px;
  color:var(--amber);background:var(--tint-amber);padding:6px 11px;border-radius:var(--radius-pill);
  text-decoration:none;white-space:nowrap;flex-shrink:0;
}
.nav-streak svg{width:15px;height:15px;flex-shrink:0;}

/* Header level badge — a ring, matching the mockup. */
.level-badge{
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;
  border:2.5px solid var(--accent);background:var(--tint-accent);color:var(--accent-text);
  font:900 11.5px var(--font-ui);text-decoration:none;flex-shrink:0;
}
.level-badge:hover{background:var(--accent);color:var(--on-accent-fill);}

.theme-toggle{
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;
  border:0;background:var(--white);color:var(--muted);box-shadow:var(--lift-sm);
  cursor:pointer;font-size:14px;line-height:1;flex-shrink:0;
}
.theme-toggle:hover{color:var(--accent);}

/* The mute switch for the correct-answer chime. Same 34px circle as the theme
   toggle, but carrying an SVG rather than a glyph, so the icon needs sizing and
   the muted state needs to read as off at a glance. */
.sound-toggle svg{width:17px;height:17px;display:block;}
.sound-toggle.is-muted{color:var(--muted);border-color:var(--line);}
.sound-toggle.is-muted:hover{color:var(--ink);}

.account-btn{
  display:inline-flex;align-items:center;height:34px;padding:0 15px;
  border-radius:var(--radius-pill);border:0;background:var(--white);box-shadow:var(--lift-sm);
  color:var(--ink);font-family:var(--font-ui);font-weight:800;font-size:12.5px;
  cursor:pointer;white-space:nowrap;flex-shrink:0;max-width:130px;overflow:hidden;text-overflow:ellipsis;
}
.account-btn:hover{color:var(--accent);}

/* Row 2 — section tabs for the course you're in. Underlined tabs rather than
   pills: they read as "where am I in this course", which is exactly what a
   second-tier bar is for, and they stay legible at seven-plus items where a
   pill row starts to look like a toolbar. */
/* Pill tabs on the course row. The active pill takes the course tint. */
.course-nav{
  position:sticky;top:var(--chrome-row1-h,60px);z-index:20;
  background:var(--header-bg);border-bottom:0;
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
}
.course-nav__inner{
  max-width:1180px;margin:0 auto;padding:2px clamp(12px,3vw,42px) 10px;
  display:flex;gap:4px;
  overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;
}
.course-nav__inner::-webkit-scrollbar{display:none;}
.course-nav__link{
  display:inline-block;padding:8px 15px;border-radius:var(--radius-pill);
  font:800 14px var(--font-ui);color:var(--muted);
  text-decoration:none;white-space:nowrap;
  transition:background-color .15s ease,color .15s ease;
}
.course-nav__link:hover{color:var(--ink);background:var(--hover-tint);}
.course-nav__link.active{color:var(--cink);background:var(--ctint);}

/* Phone: a bottom tab bar instead of the scrolling row. The first four tabs
   sit in it; the rest fold into "More", which opens a sheet. */
.bottom-nav,.bottom-sheet,.bottom-scrim{display:none;}
@media (max-width:640px){
  .bottom-sheet,.bottom-scrim{display:block;}
  .course-nav{display:none;}
  .bottom-nav{
    position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;
    background:var(--white);box-shadow:0 -8px 24px rgba(20,40,35,0.10);
    padding:8px 6px calc(8px + env(safe-area-inset-bottom));
  }
  .bottom-nav__item{
    flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
    font:900 10.5px var(--font-ui);color:var(--muted);text-decoration:none;
    background:none;border:0;padding:0;cursor:pointer;min-width:0;
  }
  .bottom-nav__item .i{display:flex;padding:4px 14px;border-radius:12px;transition:background-color .15s ease;}
  .bottom-nav__item .i svg{width:22px;height:22px;}
  .bottom-nav__item.active{color:var(--cink);} .bottom-nav__item.active .i{background:var(--ctint);}
  .bottom-nav__item span.t{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  body{padding-bottom:calc(74px + env(safe-area-inset-bottom));}
  .bottom-sheet{
    position:fixed;left:0;right:0;bottom:0;z-index:45;background:var(--white);
    border-radius:var(--radius-lg) var(--radius-lg) 0 0;box-shadow:var(--shadow-pop);
    padding:14px 14px calc(18px + env(safe-area-inset-bottom));
    transform:translateY(100%);transition:transform .25s cubic-bezier(.2,.8,.2,1);
  }
  .bottom-sheet.open{transform:none;}
  .bottom-sheet__grab{width:40px;height:4px;border-radius:2px;background:var(--line);margin:0 auto 12px;}
  .bottom-sheet a{
    display:block;padding:13px 14px;border-radius:14px;font:800 15px var(--font-ui);
    color:var(--ink);text-decoration:none;
  }
  .bottom-sheet a.active{background:var(--ctint);color:var(--cink);}
  .bottom-sheet a:hover{background:var(--hover-tint);}
  .bottom-scrim{position:fixed;inset:0;z-index:44;background:rgba(15,25,23,0.35);opacity:0;pointer-events:none;transition:opacity .2s;}
  .bottom-scrim.open{opacity:1;pointer-events:auto;}
}

footer .privacy-link{margin-top:10px;}
footer .privacy-link a{color:var(--muted);text-decoration:underline;text-underline-offset:2px;}
footer .privacy-link a:hover{color:var(--ink);}

/* ---- Skip link ---------------------------------------------------------
   Tabbing into any page meant tabbing through the whole two-row chrome first
   — back arrow, wordmark, course, streak, level, account, mute, theme, then
   every section tab — before reaching a word of content. On every page, every
   time. This is the escape hatch: parked off the top of the screen until it
   takes focus, at which point it drops into the corner as the first stop.

   Moved with a transform rather than display:none or visibility:hidden,
   because a hidden element cannot take focus, and the link would never
   receive the focus that is supposed to reveal it. */
.skip-link{
  position:fixed;top:0;left:0;z-index:100;
  transform:translateY(-150%);
  background:var(--accent);color:var(--on-accent-fill);
  font:900 14px var(--font-ui);
  padding:13px 22px;border-radius:0 0 var(--radius) 0;
  text-decoration:none;
  box-shadow:var(--shadow-pop);
}
.skip-link:focus{transform:translateY(0);}

/* The skip target is a plain container, so it is given tabindex="-1" to be
   focusable at all — otherwise the viewport jumps but the keyboard stays in
   the header, and the next Tab returns to the first nav tab: the exact loop
   the link exists to break. The ring a browser draws around a whole page
   section is noise rather than information, so it is suppressed here and only
   here; every element that is focusable in its own right keeps its own. */
[data-skip-target]:focus{outline:none;}

/* Visible to a screen reader, not on screen — for a label whose control is
   already self-evident sighted (a search box with a placeholder). */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;
}

.site-nav-fallback{font-size:13px;font-weight:700;color:var(--muted);margin-bottom:24px;font-family:var(--font-ui);}
.site-nav-fallback a{color:var(--accent);text-decoration:none;}
.site-nav-fallback a:hover{text-decoration:underline;}

@media (max-width:640px){
  .site-header__brand-row{flex:1 1 auto;}
  /* The tab row scrolls sideways here. The scrollbar is hidden, so without the
     mask it ends flush at the screen edge and the last sections are simply
     invisible — nothing on screen says there is more to the right. The fade
     lifts as soon as the row is scrolled to its end, so it never lingers over
     a row with nothing left to reveal. */
  .course-nav__inner{
    /* Snap points sit at each tab's left edge, so without scroll-padding the
       row snaps the first tab flush against the screen edge and eats the
       gutter. */
    scroll-snap-type:x proximity;
    scroll-padding-inline-start:clamp(18px,3.5vw,48px);
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 34px),transparent 100%);
    mask-image:linear-gradient(to right,#000 calc(100% - 34px),transparent 100%);
  }
  .course-nav__inner.at-end{-webkit-mask-image:none;mask-image:none;}
  .course-nav__link{scroll-snap-align:start;}
  .hub-back{display:none;} /* the wordmark goes to the hub too, and 360px of
                              width is better spent on the course name */
  .site-header__course{display:none;} /* the active bottom tab says where you are */
}

/* ==========================================================================
   7. Notices, footer, modal, print
   ========================================================================== */
.warning{
  background:var(--tint-amber);border:0;
  border-radius:var(--radius);padding:14px 18px;box-shadow:none;
  font-size:13.5px;font-weight:700;color:var(--ink);margin-bottom:32px;
}
.warning b{display:block;margin-bottom:4px;font-weight:900;}

footer{
  font-family:var(--font-ui);font-weight:600;
  margin-top:48px;font-size:12.5px;color:var(--muted);max-width:60ch;
}

::selection{background:var(--accent);color:var(--on-accent-fill);}
:focus-visible{outline:3px solid var(--accent);outline-offset:2px;border-radius:6px;}
html{scrollbar-color:var(--muted) transparent;}
::-webkit-scrollbar{width:10px;height:10px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px;}
::-webkit-scrollbar-thumb:hover{background:var(--accent);}

.auth-modal-overlay{
  position:fixed;inset:0;background:rgba(14,38,32,0.5);
  display:flex;align-items:center;justify-content:center;padding:20px;z-index:1000;
  opacity:0;pointer-events:none;transition:opacity .15s;
}
.auth-modal-overlay.open{opacity:1;pointer-events:auto;}
.auth-modal{
  position:relative;width:100%;max-width:380px;
  background:var(--white);border:var(--bw) solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-pop);padding:28px 26px 24px;
  font-family:var(--font-ui);color:var(--ink);
}
.auth-modal h2{margin:0 0 6px;font-size:21px;font-weight:900;}
.auth-modal-sub{margin:0 0 18px;font-size:13px;font-weight:600;color:var(--muted);line-height:1.5;}
.auth-modal-close{
  position:absolute;top:14px;right:14px;width:28px;height:28px;
  border:none;background:transparent;color:var(--muted);cursor:pointer;
  font-size:20px;line-height:1;border-radius:50%;
}
.auth-modal-close:hover{background:var(--hover-tint);color:var(--ink);}
.auth-modal form{display:flex;flex-direction:column;gap:12px;}
.auth-modal label{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:900;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;}
.auth-modal label[hidden]{display:none;}
.auth-modal input{
  font-family:inherit;font-size:14.5px;font-weight:700;padding:11px 13px;
  border:0;border-radius:var(--radius-sm);
  background:var(--surface2);color:var(--ink);
}
.auth-modal-msg{font-size:12.5px;font-weight:700;min-height:1.4em;}
.auth-modal-msg.error{color:var(--bad-text);}
.auth-modal-msg.success{color:var(--good-text);}
.auth-modal-submit{margin-top:4px;width:100%;padding:13px;font-size:14.5px;}
.auth-modal-toggle{margin:16px 0 0;font-size:12.5px;font-weight:700;color:var(--muted);text-align:center;}
.auth-modal-toggle button{
  border:none;background:transparent;color:var(--accent);font-family:inherit;
  font-weight:900;font-size:12.5px;cursor:pointer;padding:0;
}
.auth-modal-toggle button:hover{text-decoration:underline;}

@media print{
  #site-header,.course-nav,.site-nav-fallback,.theme-toggle,button,
  .start-btn,.review-btn,.domain-btn,.planner-row button,
  #searchBox,.print-btn,.auth-modal-overlay{display:none !important;}
  body{background:#fff !important;color:#000 !important;}
  a{color:#000 !important;text-decoration:underline;}
  .wrap,.xshell{max-width:100% !important;padding:0 !important;}
  .card,.panel,.stat-card,.tip-card{box-shadow:none !important;}
}

@media (max-width:900px){
  .stat-row{grid-template-columns:repeat(2,1fr);}
  /* One spine down the left, every label to its right. */
  .path{max-width:none;}
  .path::before{left:38px;}
  .node{grid-template-columns:76px 1fr;gap:14px;}
  .node .node-circle{grid-column:1;}
  .node.left .node-text,.node.right .node-text,.node.center .node-text{
    grid-column:2;justify-self:start;text-align:left;
  }
}

/* ==========================================================================
   7c. Textbook shell — a contents rail beside one chapter at a time.
   Used by ochem/learn.html and nremt/study-notes.html; the chapter body
   styles stay with each course, the frame and rail are shared.
   ========================================================================== */
.tb-shell{
  max-width:1180px;margin:0 auto;padding:0 clamp(18px,3.5vw,48px);
  display:grid;grid-template-columns:274px minmax(0,1fr);gap:clamp(24px,4vw,54px);
  align-items:start;
}

/* --- contents rail --- */
.tb-rail{
  position:sticky;top:calc(var(--site-header-h,112px) + 18px);
  max-height:calc(100vh - var(--site-header-h,112px) - 36px);
  display:flex;flex-direction:column;gap:14px;padding:22px 0 26px;
}
.tb-rail>:not(.tb-contents){flex:0 0 auto;}
.tb-rail-title{font:900 12px var(--font-ui);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin:0;}
.tb-progress-row{display:flex;justify-content:space-between;font:800 12.5px var(--font-ui);color:var(--muted);margin-bottom:6px;}
.tb-progress-track{height:6px;border-radius:99px;background:var(--line);overflow:hidden;}
.tb-progress-fill{height:100%;background:var(--accent);border-radius:99px;transition:width .25s ease;}
.tb-storage-warning{
  font:700 12px var(--font-ui);color:var(--bad-text,var(--bad));line-height:1.45;
  margin:8px 0 0;padding:8px 10px;border-radius:8px;
  border:var(--bw) solid var(--bad);background:color-mix(in srgb, var(--bad) 8%, transparent);
}
.tb-filter{
  width:100%;box-sizing:border-box;padding:9px 12px;border-radius:10px;
  border:var(--bw) solid var(--line);background:var(--white);color:var(--ink);
  font:700 13px var(--font-ui);
}
.tb-filter:focus{border-color:var(--accent);}
.tb-filter-hint{font:700 11px var(--font-ui);color:var(--muted);margin:-8px 0 0;line-height:1.4;}
.tb-contents{overflow-y:auto;overscroll-behavior:contain;flex:1 1 auto;min-height:0;margin-right:-8px;padding-right:8px;-webkit-overflow-scrolling:touch;}
.tb-toc-empty{font:700 13px var(--font-ui);color:var(--muted);}

.tb-toc-mod + .tb-toc-mod{margin-top:2px;}
.tb-toc-modhead{
  width:100%;display:flex;align-items:center;gap:9px;
  background:none;border:0;padding:8px 6px;border-radius:8px;cursor:pointer;
  font:800 13px var(--font-ui);color:var(--ink);text-align:left;
}
.tb-toc-modhead:hover{background:var(--hover-tint);}
.tb-toc-num{
  flex-shrink:0;width:20px;height:20px;border-radius:6px;
  display:flex;align-items:center;justify-content:center;
  background:var(--tint-accent);color:var(--accent);font:900 11px var(--font-mono);
}
.tb-toc-modtitle{flex:1;min-width:0;}
.tb-toc-count{flex-shrink:0;font:800 11px var(--font-mono);color:var(--muted);}
.tb-toc-count.complete{color:var(--accent);}
.tb-toc-topics{display:none;padding:0 0 6px 29px;}
.tb-toc-mod.open .tb-toc-topics{display:block;}
.tb-toc-topic{
  display:flex;align-items:center;gap:7px;padding:5px 6px;border-radius:7px;
  font:700 12.5px var(--font-ui);color:var(--muted);text-decoration:none;
}
.tb-toc-topic:hover{background:var(--hover-tint);color:var(--ink);}
.tb-toc-topic.current{color:var(--accent);background:var(--tint-accent);}
.tb-toc-tick{
  flex-shrink:0;width:13px;height:13px;border-radius:50%;
  border:2px solid var(--line);
}
.tb-toc-topic.read .tb-toc-tick{background:var(--accent);border-color:var(--accent);}
.tb-toc-topic.read .tb-toc-tick::after{
  content:"";display:block;width:4px;height:7px;margin:0 auto;
  border:solid var(--on-accent-fill);border-width:0 2px 2px 0;transform:rotate(45deg) translate(-1px,-1px);
}


/* --- the chapter frame --- */
.tb-main{padding:26px 0 60px;min-width:0;max-width:74ch;}
.tb-chapter-head{border-bottom:var(--bw) solid var(--line);padding-bottom:18px;margin-bottom:8px;}
.tb-chapter-eyebrow{font:900 11.5px var(--font-ui);letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin:0 0 6px;}
.tb-chapter-title{font:900 clamp(27px,4vw,36px) var(--font-ui);letter-spacing:-.02em;margin:0 0 8px;}
.tb-chapter-meta{font:700 13px var(--font-ui);color:var(--muted);margin:0;}


.tb-chapter-nav{display:flex;justify-content:space-between;gap:18px;margin-top:38px;}
.tb-chapter-link{
  display:flex;flex-direction:column;gap:4px;max-width:46%;
  padding:14px 18px;border:var(--bw) solid var(--line);border-radius:var(--radius-lg);
  background:var(--white);text-decoration:none;
}
.tb-chapter-link:hover{border-color:var(--accent);}
.tb-chapter-link.next{text-align:right;margin-left:auto;}
.tb-chapter-link span{font:800 11.5px var(--font-ui);color:var(--muted);}
.tb-chapter-link b{font:900 14.5px var(--font-ui);color:var(--ink);}


/* --- contents as a drawer once the rail no longer fits beside the text --- */
.tb-toc-btn{display:none;}
@media (max-width:900px){
  .tb-shell{grid-template-columns:minmax(0,1fr);gap:0;}
  .tb-toc-btn{
    display:inline-flex;align-items:center;gap:8px;margin:18px 0 0;
    padding:9px 15px;border-radius:var(--radius-pill);cursor:pointer;
    border:2px solid var(--line);background:var(--white);color:var(--ink);
    font:800 13px var(--font-ui);
  }
  .tb-toc-btn:hover{border-color:var(--accent);color:var(--accent);}
  .tb-rail{
    display:none;position:static;max-height:none;padding:14px 0 0;
    border-bottom:var(--bw) solid var(--line);
  }
  body.tb-toc-open .tb-rail{display:flex;}
  .tb-contents{max-height:58vh;}
  .tb-main{padding-top:16px;}
  .tb-chapter-link{max-width:48%;}
}

/* ==========================================================================
   8. Motion — what assets/motion.js drives, and the page-load rise
   ========================================================================== */
/* Everything above the fold rises into place on load. Transform only: the
   resting state is fully visible, so a thumbnail or a reader with the
   animation cut still sees the page. */
.hero,.xsection,.lesson-card,.panel,.card,.stat-row,.mode-grid,.wrap > .card{animation:levl-rise .5s cubic-bezier(.2,.8,.2,1) both;}
.xsection:nth-of-type(2){animation-delay:.06s} .xsection:nth-of-type(3){animation-delay:.12s} .xsection:nth-of-type(4){animation-delay:.18s}
@keyframes levl-rise{from{transform:translateY(10px)}to{transform:none}}
/* The "+N XP" chip that flies from where you answered to the level badge. */
.levl-xp-float{
  position:fixed;z-index:80;pointer-events:none;
  font:600 15px var(--font-mono);color:var(--accent-text);background:var(--tint-accent);
  padding:6px 12px;border-radius:var(--radius-pill);box-shadow:var(--lift);
  animation:levl-floatup 1.1s cubic-bezier(.2,.8,.2,1) forwards;
}
@keyframes levl-floatup{0%{transform:translate(0,0) scale(1);opacity:1}70%{opacity:1}100%{transform:translate(var(--dx),var(--dy)) scale(.6);opacity:0}}
.levl-pulse{animation:levl-pulse .6s cubic-bezier(.2,.8,.3,1.4);}
@keyframes levl-pulse{0%{transform:scale(1)}40%{transform:scale(1.18)}100%{transform:scale(1)}}
/* Level-up toast, bottom centre. */
.levl-toast{
  position:fixed;left:50%;bottom:calc(24px + env(safe-area-inset-bottom));z-index:85;transform:translate(-50%,20px);
  background:var(--navy);color:#fff;font:900 14.5px var(--font-ui);padding:14px 20px;border-radius:var(--radius);
  box-shadow:var(--shadow-pop);display:flex;align-items:center;gap:12px;opacity:0;
  transition:transform .35s cubic-bezier(.2,.8,.3,1.3),opacity .3s ease;max-width:calc(100vw - 32px);
}
.levl-toast.show{opacity:1;transform:translate(-50%,0);}
.levl-toast .ring{width:34px;height:34px;border-radius:50%;border:2.5px solid var(--accent-bright);color:var(--accent-bright);display:grid;place-items:center;font-size:12px;flex-shrink:0;}
.levl-toast small{display:block;font-weight:700;font-size:12.5px;opacity:.8;}
@media (max-width:640px){.levl-toast{bottom:calc(84px + env(safe-area-inset-bottom));}}
#levlConfetti{position:fixed;inset:0;pointer-events:none;z-index:90;}

/* Honor the OS "reduce motion" setting across the whole site.

   Every page in both courses loads this file, so one block covers all 173 of
   them — the hover lifts and colour fades here, the flash on a hit target in
   ochem.css, the spin on the body map's loading indicator, and any transition
   a page declares in its own inline <style>. Motion that JavaScript drives
   cannot be reached from CSS; those call sites ask window.LevlMotion.reduced()
   in site-chrome.js instead.

   Durations are cut to a hair rather than set to zero, which is the usual form
   of this rule: a transitionend or animationend listener still fires, so
   nothing that waits on one is left hanging. Animations are also pinned to a
   single iteration, so anything looping stops instead of flickering.

   The body map's spinner stops under this rule and that is intended — the
   panel it sits in already says "Loading 3D model…" in words beside it, so
   the state stays legible without anything moving. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:0.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.01ms !important;
    scroll-behavior:auto !important;
  }
  html{scroll-behavior:auto !important;}
}
