@import url("https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&family=Fraunces:opsz,wght@9..144,400..800&family=Literata:ital,opsz,wght@0,7..72,300..700;1,7..72,300..700&family=Bebas+Neue&family=IBM+Plex+Mono:wght@400;500;600&display=swap");

/* ------------------------------------------------------------------ *
 * UTB LMS stylesheet.
 *
 * The token block, base layer and utility layer that follow are carried
 * over from the original application design system (globals.css) with
 * the Tailwind wrappers removed, so the palette, type scale and
 * signature devices survive the move to PHP unchanged. Component
 * classes for the PHP markup are appended at the end of the file.
 * ------------------------------------------------------------------ */
:root {
  --font-figtree: "Figtree";
  --font-fraunces: "Fraunces";
  --font-literata: "Literata";
  --font-bebas: "Bebas Neue";
  --font-plex-mono: "IBM Plex Mono";

  --font-sans: var(--font-figtree), ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-display: var(--font-fraunces), Georgia, "Times New Roman", serif;
  --font-reading: var(--font-literata), Georgia, "Times New Roman", serif;
  --font-stat: var(--font-bebas), Impact, sans-serif;
  --font-mono: var(--font-plex-mono), ui-monospace, Consolas, monospace;

  --text-2xs: 0.6875rem;
  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-base: 0.875rem;
  --text-md: 0.9375rem;
  --text-lg: 1.0625rem;
  --text-xl: 1.1875rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;
  --text-4xl: 2.375rem;
}

*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, h4, p, figure, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img { max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

/* The theme is chosen by the learner, persisted, and applied to <html> before
   paint (see ThemeScript), so there is never a flash of the wrong palette. */

/* ==================================================================== *
 * Tokens
 *
 * Named by ROLE, never by value. Components say `bg-surface`, never
 * `bg-white`, so the light/dark swap happens in one place.
 *
 * The scheme is white and gold, set in black. Gold #F0A500 is the
 * University of Tampa Bay's own accent, lifted from their site; here it
 * carries the *surfaces* too — tinted panels, bands, rules, chips — so the
 * app reads as gold rather than as white with one gold button. Type is
 * black. There is no blue anywhere: the old navy read cold and fought the
 * gold, so the `brand` ramp is now graphite through black.
 *
 * The one rule that governs everything: gold on white is 2.08:1. Gold is a
 * FILL, never a letterform. Where gold must be read as text it darkens to
 * --accent-600 (5.9:1). See DESIGN.md.
 * ==================================================================== */
:root {
  color-scheme: light;

  /* Graphite → black. Fills, rules and any element that used to be navy.
     Every `bg-brand-600` in the app is paired with white type: 18.9:1. */
  --brand-50: #f7f6f4;
  --brand-100: #edebe7;
  --brand-200: #dbd8d1;
  --brand-300: #b8b3a9;
  --brand-400: #7c776e;
  --brand-500: #3a3a3e;
  --brand-600: #111111; /* primary */
  --brand-700: #0b0b0c;
  --brand-800: #070708;
  --brand-900: #000000;

  /* UTB gold — the signature, and the app's second surface. */
  --accent-100: #fef8ea;
  --accent-200: #fcefcf;
  --accent-300: #fbdf9c;
  --accent-400: #f7c34d;
  --accent-500: #f0a500; /* the gold */
  /* The one gold allowed to be a letterform. The site's #c88400 clears only
     3.1:1 on white; this reaches 5.9:1 and still reads as gold. */
  --accent-600: #8a5a00;
  --accent-700: #6b4500;

  /* White first, warmed. Every neutral leans gold, never blue, so white
     cards sit on the canvas as objects instead of dissolving into it. */
  --canvas: #fffdf9;
  --surface: #ffffff;
  --surface-2: #fbf6ec;
  --surface-3: #f5eedf;
  --overlay: rgb(20 16 8 / 0.45);

  /* Black type. ink-2 and ink-3 are neutral greys — a blue-slate secondary
     is what made the old palette read cold under the gold. */
  --ink: #0b0b0c;
  --ink-2: #3a3a3e;
  --ink-3: #63636a;
  --ink-inverse: #ffffff;

  --line: #e8e0d0;
  --line-strong: #d6c9ae;

  /* Status. Warning is the dark gold, so it stays inside the brand. */
  --success: #1b7a45;
  --success-soft: #e3f5ea;
  --warning: #8a5a00;
  --warning-soft: #fdf3de;
  --danger: #b02d1f;
  --danger-soft: #fbe5e1;
  --info: #3a3a3e;
  --info-soft: #f2f0ec;

  /* Ink set on the gold band. The band never inverts, so these hold the same
     values in both themes — .dark restates them to make that deliberate. */
  --ink-on-gold: #0b0b0c;
  --ink-on-gold-soft: rgb(11 11 12 / 0.78);
  --line-on-gold: rgb(11 11 12 / 0.18);

  /* Black, not gold: a gold ring on white is 2.08:1 and would be a focus
     indicator you cannot see. */
  --ring: #111111;

  /* Warm-cast shadows — a neutral grey shadow over a warm canvas reads as
     dirt. These are brown-black and stay inside the palette. */
  --shadow-xs: 0 1px 2px 0 rgb(60 44 16 / 0.05);
  --shadow-sm: 0 1px 3px 0 rgb(60 44 16 / 0.07), 0 1px 2px -1px rgb(60 44 16 / 0.05);
  --shadow-md: 0 8px 20px -6px rgb(60 44 16 / 0.1), 0 2px 6px -2px rgb(60 44 16 / 0.06);
  --shadow-lg: 0 22px 48px -14px rgb(60 44 16 / 0.16), 0 6px 16px -8px rgb(60 44 16 / 0.08);

  /* Their site's own radii, plus a 4px inner step for nested shapes (code
     chips, thumbnails inside cards). The whole vocabulary is 4 / 7 / 13 / full. */
  --radius-card: 13px;
  --radius-control: 7px;
  --radius-inner: 4px;

  /* Gold as material, not flat fill: a diagonal sheen and an inset edge
     light. Black type measured against the stops — accent-400 12.1:1,
     accent-500 9.45:1, #e09a00 8.2:1 — so the deepest corner still clears
     AAA. band-gold and the gold button consume this recipe. */
  --gold-sheen: linear-gradient(115deg, var(--accent-400) 0%, var(--accent-500) 45%, #e09a00 100%);
  --gold-highlight:
    inset 0 1px 0 0 rgb(255 255 255 / 0.35),
    inset 0 -1px 0 0 rgb(107 69 0 / 0.18);

  /* Lets block-size animate to `auto`, which is what makes <details> able to
     glide open to its natural height instead of snapping. */
  interpolate-size: allow-keywords;
}

/* Dark mode is neutral near-black, not a tinted navy. The gold survives
   untouched (9.4:1 on the canvas) and every type token is measured against
   its own ground — the palette inverts, legibility does not change. */
.dark {
  color-scheme: dark;

  --canvas: #0c0c0d;
  --surface: #151517;
  --surface-2: #1b1b1e;
  --surface-3: #26262a;
  --overlay: rgb(0 0 0 / 0.72);

  --ink: #f7f3ec;
  --ink-2: #c9c4bb;
  --ink-3: #9a958c;
  --ink-inverse: #0c0c0d;

  --line: #2a2a2e;
  --line-strong: #3d3d43;

  /* The ramp inverts, but brand-600 stays dark enough to keep the white type
     that is baked into every `bg-brand-600` call site legible (10.4:1). */
  --brand-50: #1b1b1e;
  --brand-100: #202024;
  --brand-200: #2f2f34;
  --brand-300: #d6d1c8; /* a light tone: this one is used as dark-mode text */
  --brand-400: #8b867d;
  --brand-500: #45454b;
  --brand-600: #3a3a3e;
  --brand-700: #2f2f34;
  --brand-800: #232327;
  --brand-900: #2a2a2e;

  /* Gold lightens only where it must be read as text. */
  --accent-600: #ffc24d;
  --accent-700: #ffd67f;

  --success: #4ec98a;
  --success-soft: #10241a;
  --warning: #ffc24d;
  --warning-soft: #2a2110;
  --danger: #f08a75;
  --danger-soft: #2e1512;
  --info: #c9c4bb;
  --info-soft: #202024;

  /* The gold band keeps its light-theme ink: it does not invert. */
  --ink-on-gold: #0b0b0c;
  --ink-on-gold-soft: rgb(11 11 12 / 0.78);
  --line-on-gold: rgb(11 11 12 / 0.18);

  --ring: #f0a500;

  /* A black drop shadow is invisible on a #0c0c0d canvas, so dark elevation
     comes from a 4% top edge light as well — the raised face catches it. */
  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.5), inset 0 1px 0 0 rgb(255 255 255 / 0.04);
  --shadow-sm:
    0 1px 3px 0 rgb(0 0 0 / 0.6), 0 1px 2px -1px rgb(0 0 0 / 0.5),
    inset 0 1px 0 0 rgb(255 255 255 / 0.04);
  --shadow-md:
    0 8px 20px -6px rgb(0 0 0 / 0.65), 0 2px 6px -2px rgb(0 0 0 / 0.5),
    inset 0 1px 0 0 rgb(255 255 255 / 0.04);
  --shadow-lg:
    0 22px 48px -14px rgb(0 0 0 / 0.8), 0 6px 16px -8px rgb(0 0 0 / 0.6),
    inset 0 1px 0 0 rgb(255 255 255 / 0.04);
}

/* `inline` emits var() into the utilities so they follow the theme swap above
   rather than being frozen at build time. */

/* ==================================================================== *
 * Base
 * ==================================================================== */
/* ==== base ==== */
* {
  border-color: var(--line);
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background-color: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  /* Real italic and bold cuts are loaded; a synthesized slant on the
     reading serif is the one thing that would cheapen the whole surface. */
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Paper grain — what lets a flat warm colour read as material. Fixed so it
   never scrolls, negative z-index so it sits behind all content and can
   never take a click. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.025;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* The near-black canvas swallows more of the texture, so it gets more. */
.dark body::before {
  opacity: 0.04;
}

/* Headings take the brand serif, as they do on the institution's site.
   Tracking tightens as size grows — a display serif set at 2rem needs the
   negative tracking that would close up a 1rem heading. */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 600;
  text-wrap: balance;
  color: var(--ink);
}

h1 {
  letter-spacing: -0.021em;
  line-height: 1.1;
}
h2 {
  letter-spacing: -0.016em;
  line-height: 1.18;
}
h3 {
  letter-spacing: -0.011em;
  line-height: 1.25;
}
h4 {
  letter-spacing: -0.006em;
  line-height: 1.3;
}

p,
li {
  text-wrap: pretty;
}

/* Anything clickable settles rather than snapping. Killed wholesale by the
   reduced-motion block below. */
a,
button,
summary,
input,
select,
textarea {
  transition:
    color 0.15s var(--ease-out-soft),
    background-color 0.15s var(--ease-out-soft),
    border-color 0.15s var(--ease-out-soft),
    box-shadow 0.15s var(--ease-out-soft),
    opacity 0.15s var(--ease-out-soft);
}

/* Disclosure content glides open to its natural height (interpolate-size
   on :root is what makes `auto` a legal transition endpoint). */
details::details-content {
  block-size: 0;
  overflow-y: clip;
  transition:
    content-visibility 300ms allow-discrete,
    block-size 300ms var(--ease-out-soft);
}

details[open]::details-content {
  block-size: auto;
}

/* Safari and Firefox support ::details-content but not interpolate-size,
   so block-size can never glide to `auto` there. Fallback: the content
   wrapper becomes a one-track grid and the track glides 0fr -> 1fr — the
   same 300ms settle, no markup changes, and Chromium keeps the branch
   above. (Every <details> in the app has a single content element after
   the summary, which is what the fr-track pattern needs.) */
@supports not (interpolate-size: allow-keywords) {
  details::details-content {
    display: grid;
    block-size: auto;
    grid-template-rows: 0fr;
    transition:
      content-visibility 300ms allow-discrete,
      grid-template-rows 300ms var(--ease-out-soft);
  }

  details[open]::details-content {
    grid-template-rows: 1fr;
  }

  details::details-content > * {
    min-block-size: 0;
    overflow-y: clip;
  }
}

/* One focus treatment everywhere. Never clipped, never removed. */
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

::selection {
  background: var(--accent-300);
  color: #0b0b0c;
}
.dark ::selection {
  background: var(--accent-500);
  color: #0b0b0c;
}

::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border: 3px solid var(--canvas);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--ink-3);
}

/* ==================================================================== *
 * Utilities
 * ==================================================================== */
/* ==== utilities ==== */
/* The signature device: a controlled-document header rail. Mono, uppercase,
   widely tracked — the register of a batch record, not a web app. */
.control-strip {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Small caps label above a heading. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* The short rule under a page title — gold, 2.5rem, never full width. This
   is the one place gold appears on every page, and it is enough. */
.title-rule::after {
  content: "";
  display: block;
  width: 2.5rem;
  height: 3px;
  margin-top: 0.875rem;
  background: var(--accent-500);
  border-radius: 2px;
}

.font-display {
  font-family: var(--font-display);
}

.font-reading {
  font-family: var(--font-reading);
}

/* Big numerals, as on the institution's site. */
.stat-numeral {
  font-family: var(--font-stat);
  font-weight: 400;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}

.tabular {
  font-variant-numeric: tabular-nums;
}

/* A gold hairline above a block — for hero cards and earned states. */
.gold-cap {
  border-top: 3px solid var(--accent-500);
}

/* ---------------------------------------------------------------- *
 * Gold surfaces
 *
 * Gold carries the background language here, not just the accents. These
 * are the sanctioned ways to put it behind content — each keeps type on a
 * ground that still clears AA, which a flat --accent-500 panel would not.
 * ---------------------------------------------------------------- */

/* A tinted panel. Type on it stays black (18.3:1). */
.panel-gold {
  background: var(--accent-100);
  border: 1px solid var(--accent-200);
}

/* Dark keeps the gold cast rather than falling back to a neutral inset —
   7% of the accent mixed into the surface is the same panel, translated. */
.dark .panel-gold {
  background: color-mix(in oklab, var(--accent-500) 7%, var(--surface));
  border-color: color-mix(in oklab, var(--accent-500) 22%, var(--line));
}

/* A wash for hero and section grounds — gold that fades into the canvas. */
.wash-gold {
  background: linear-gradient(160deg, var(--accent-100) 0%, var(--canvas) 62%);
}

.dark .wash-gold {
  background: linear-gradient(160deg, color-mix(in oklab, var(--accent-500) 9%, var(--canvas)) 0%, var(--canvas) 62%);
}

/* The full-strength gold band, for a single deliberate moment per page.
   The diagonal sheen is what makes the gold read as material rather than
   flat fill. Always sets its own black type, in both themes, because the
   band does not invert — black measures 12.1:1 at the light end of the
   sheen and 8.2:1 at the deep corner, AAA throughout. */
.band-gold {
  background: var(--gold-sheen);
  color: var(--ink-on-gold);
}

.band-gold .eyebrow,
.band-gold .control-strip {
  color: rgb(11 11 12 / 0.72);
}

/* The reusable recipe behind every solid-gold element: sheen plus inset
   edge light. The gold button is this with a radius and its own states. */
.gold-material {
  background: var(--gold-sheen);
  box-shadow: var(--gold-highlight);
}

/* A hairline rule in gold, for separating sections without a heavy border. */
.rule-gold {
  border: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-500), transparent);
}

/* Lift on hover for anything that behaves like a card-sized target. */
.lift {
  transition:
    transform 0.18s var(--ease-out-soft),
    box-shadow 0.18s var(--ease-out-soft),
    border-color 0.18s var(--ease-out-soft);
}

.lift:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--line-strong);
}

/* ---------------------------------------------------------------- *
 * Reading surface
 *
 * The lessons are the product: fifty pages of technical prose per topic.
 * This is the most important typographic surface in the app, so it gets a
 * measure, an optical size, and a rhythm rather than default paragraphs.
 * ---------------------------------------------------------------- */
.prose-teaching {
  font-family: var(--font-reading);
  font-size: 1.0625rem;
  line-height: 1.75;
  /* Black, not a softened grey. These are the notes: a learner reads fifty
     pages of them per topic and every one is set at full strength. */
  color: var(--ink);
  max-width: 66ch;
  hanging-punctuation: first last;
}

.prose-teaching > * + * {
  margin-top: 1.15em;
}

/* The lede: the opening paragraph is set a step larger, the way a printed
   chapter opens, so a topic never starts at running-text pitch. */
.prose-teaching > p:first-of-type {
  font-size: 1.1875rem;
  line-height: 1.65;
}

.prose-teaching strong {
  color: var(--ink);
  font-weight: 600;
}

.prose-teaching em {
  font-style: italic;
}

.prose-teaching h2,
.prose-teaching h3,
.prose-teaching h4 {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: -0.012em;
  margin-top: 1.9em;
  margin-bottom: 0.6em;
}

.prose-teaching h2 {
  font-size: 1.375rem;
  font-weight: 600;
}

.prose-teaching h3 {
  font-size: 1.125rem;
  font-weight: 600;
}

.prose-teaching h4 {
  font-size: 1rem;
  font-weight: 600;
}

.prose-teaching ul,
.prose-teaching ol {
  padding-left: 1.4em;
}

.prose-teaching ul {
  list-style: disc;
}
.prose-teaching ol {
  list-style: decimal;
}

.prose-teaching li + li {
  margin-top: 0.5em;
}

.prose-teaching li::marker {
  color: var(--accent-600);
}

.prose-teaching blockquote {
  border-left: 3px solid var(--accent-500);
  padding-left: 1.1em;
  color: var(--ink);
  font-style: italic;
}

.prose-teaching code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-inner);
  padding: 0.1em 0.35em;
}

.prose-teaching pre {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  padding: 1em 1.25em;
  overflow-x: auto;
}

/* Inside a pre the inline-code chrome would double the box. */
.prose-teaching pre code {
  font-size: inherit;
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
}

/* Data inside prose is apparatus, not voice: it switches to the sans. */
.prose-teaching table {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  line-height: 1.55;
  border-collapse: collapse;
}

.prose-teaching th {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-3);
  text-align: left;
  background: var(--surface-2);
  padding: 0.6em 0.9em;
  border-bottom: 1px solid var(--line-strong);
}

.prose-teaching td {
  padding: 0.6em 0.9em;
  border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}

.prose-teaching figcaption {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 0.75em;
}

.prose-teaching hr {
  border: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-500), transparent);
}

/* Links stay black and are marked by a gold underline rather than a colour
   change, so a link inside a paragraph does not break the black setting. */
.prose-teaching a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent-500);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: text-decoration-color 0.15s var(--ease-out-soft);
}

.prose-teaching a:hover {
  text-decoration-color: var(--accent-600);
}

/* Reading distance grows with the viewport; the type follows it up. */
@media (min-width: 1024px) {
  .prose-teaching {
    font-size: 1.125rem;
  }
}

/* ---------------------------------------------------------------- *
 * Type roles
 *
 * Serif is the teaching voice; sans is the apparatus — labels, panels,
 * tables, chrome. Fixed face + size + leading, so a surface never drifts
 * between the two registers.
 * ---------------------------------------------------------------- */
.reading-body {
  font-family: var(--font-reading);
  font-size: 1.0625rem;
  line-height: 1.75;
}

.panel-body {
  font-family: var(--font-sans);
  font-size: 0.875rem;
  line-height: 1.55;
}

.panel-title {
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.35;
  font-weight: 600;
}

.panel-label {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  line-height: 1.45;
  font-weight: 500;
  color: var(--ink-3);
}

.caption {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--ink-3);
}

/* Screen-reader-only, but still focusable when it needs to be. */
.sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

.animate-rise {
  animation: rise 0.4s var(--ease-out-soft) both;
}
.animate-fade {
  animation: fade 0.25s var(--ease-out-soft) both;
}

/* Entrances, one per surface: the page settles up, sheets drop from the
   top edge, menus unfold from their trigger corner, reader pages turn in
   the direction of travel, flashcards flip. */
.animate-page-enter {
  animation: page-enter 0.24s var(--ease-out-soft) both;
}
.animate-sheet-in {
  animation: sheet-in 0.28s var(--ease-out-soft) both;
}
.animate-menu-in {
  transform-origin: top right;
  animation: menu-in 0.18s var(--ease-out-soft) both;
}
.animate-turn-forward {
  animation: turn-forward 0.22s var(--ease-out-soft) both;
}
.animate-turn-back {
  animation: turn-back 0.22s var(--ease-out-soft) both;
}
.animate-card-flip {
  animation: card-flip 0.35s var(--ease-out-soft) both;
}

/* An inline "working" spinner for submit buttons. Two opposed arcs, so the
   rotation shares the shimmer's 1.6s clock yet reads at a brisk 0.8s visual
   period. Reduced motion freezes it into a static badge — still a signal. */
.spinner {
  display: inline-block;
  inline-size: 1em;
  block-size: 1em;
  border: 2px solid;
  border-color: currentColor transparent;
  border-radius: 999px;
  animation: spin 1.6s linear infinite;
}

/* Skeleton ground. The sweep is a lighter band crossing a surface-2 field. */
.animate-shimmer {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.6s linear infinite;
}

/* A 35ms ramp deep enough for a 12-item grid — a flat cap after item 4
   makes the back half of a grid pop in as one lump. */
.stagger > * {
  animation: rise 0.4s var(--ease-out-soft) both;
}
.stagger > *:nth-child(1) {
  animation-delay: 0.035s;
}
.stagger > *:nth-child(2) {
  animation-delay: 0.07s;
}
.stagger > *:nth-child(3) {
  animation-delay: 0.105s;
}
.stagger > *:nth-child(4) {
  animation-delay: 0.14s;
}
.stagger > *:nth-child(5) {
  animation-delay: 0.175s;
}
.stagger > *:nth-child(6) {
  animation-delay: 0.21s;
}
.stagger > *:nth-child(7) {
  animation-delay: 0.245s;
}
.stagger > *:nth-child(8) {
  animation-delay: 0.28s;
}
.stagger > *:nth-child(9) {
  animation-delay: 0.315s;
}
.stagger > *:nth-child(10) {
  animation-delay: 0.35s;
}
.stagger > *:nth-child(11) {
  animation-delay: 0.385s;
}
.stagger > *:nth-child(n + 12) {
  animation-delay: 0.42s;
}

.scrollbar-none {
  scrollbar-width: none;
}
.scrollbar-none::-webkit-scrollbar {
  display: none;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes page-enter {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes sheet-in {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes menu-in {
  from {
    opacity: 0;
    transform: scale(0.98) translateY(-4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes turn-forward {
  from {
    opacity: 0;
    transform: translateX(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes turn-back {
  from {
    opacity: 0;
    transform: translateX(-8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes card-flip {
  from {
    opacity: 0;
    transform: perspective(1200px) rotateY(-90deg);
  }
  to {
    opacity: 1;
    transform: perspective(1200px) rotateY(0deg);
  }
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes shimmer {
  from {
    background-position: 200% 0;
  }
  to {
    background-position: -200% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==================================================================== *
 * Print — certificates render edge to edge with no app chrome
 * ==================================================================== */
@media print {
  @page {
    size: A4 landscape;
    margin: 0;
  }
  body {
    background: #fff !important;
  }
  .no-print {
    display: none !important;
  }
  /* The signed-in shell's <main> keeps its 1280px column and padding on
     screen; on paper the sheet must own the whole page, so the column
     constraints go with the chrome. */
  main#main {
    max-width: none !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  .print-sheet {
    box-shadow: none !important;
    border: none !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: none !important;
    border-radius: 0 !important;
    break-inside: avoid;
  }
}

/* ==================================================================== *
 * Components — the vocabulary the PHP markup uses. Every value is a
 * token from the block above, so the palette stays in one place.
 * ==================================================================== */
body { font-size: var(--text-base); line-height: 1.55; min-height: 100vh; display: flex; flex-direction: column; }

.shell { width: 100%; max-width: 1180px; margin-inline: auto; padding-inline: 1.25rem; }
.shell-narrow { max-width: 780px; }
.shell-wide { max-width: 1400px; }
main.page { flex: 1 0 auto; padding-block: 2rem 4rem; }

/* ------------------------------------------------------------- header */
.masthead {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--line);
}
.masthead-inner { display: flex; align-items: center; gap: 1.25rem; height: 62px; position: relative; }
.mark { display: flex; align-items: center; gap: 0.7rem; flex-shrink: 0; }
.mark-tile {
  position: relative; width: 36px; height: 36px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: var(--radius-control);
  background: var(--brand-800); box-shadow: var(--shadow-xs);
}
.dark .mark-tile { background: var(--brand-700); }
.mark-tile span { font-family: var(--font-display); font-weight: 700; font-size: var(--text-xs); letter-spacing: 0.02em; color: #fff; line-height: 1; }
.mark-tile::after { content: ""; position: absolute; left: 7px; right: 7px; bottom: 6px; height: 2px; border-radius: 999px; background: var(--accent-500); }
.mark-text { display: flex; flex-direction: column; line-height: 1; }
.mark-name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); letter-spacing: -0.01em; }
.mark-sub { margin-top: 0.35rem; }

.nav { display: flex; align-items: center; gap: 0.15rem; margin-left: auto; }
.nav a.nav-link {
  display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.45rem 0.7rem;
  border-radius: var(--radius-control); font-size: var(--text-sm); font-weight: 600; color: var(--ink-2);
}
.nav a.nav-link:hover { background: var(--surface-2); color: var(--ink); }
.nav a.nav-link.is-active { background: var(--accent-200); color: var(--ink); }
.dark .nav a.nav-link.is-active { background: var(--surface-3); }
.nav-sep { width: 1px; height: 22px; background: var(--line); margin-inline: 0.4rem; }
.avatar {
  width: 34px; height: 34px; border-radius: 999px; display: grid; place-items: center;
  background: var(--brand-600); color: #fff; font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.03em;
}
.nav-toggle { display: none; background: none; border: 1px solid var(--line); border-radius: var(--radius-control); padding: 0.35rem 0.55rem; cursor: pointer; }
@media (max-width: 980px) {
  .nav-toggle { display: inline-flex; margin-left: auto; }
  .nav { display: none; position: absolute; top: 62px; left: -1.25rem; right: -1.25rem; flex-direction: column; align-items: stretch; gap: 0.2rem;
         background: var(--surface); border-bottom: 1px solid var(--line); padding: 0.75rem 1.25rem 1rem; box-shadow: var(--shadow-md); }
  .nav.is-open { display: flex; }
  .nav-sep { display: none; }
}

/* -------------------------------------------------------------- footer */
.site-foot { border-top: 1px solid var(--line); background: var(--surface); padding-block: 1.5rem; font-size: var(--text-xs); color: var(--ink-3); }
.site-foot .shell { display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; align-items: center; justify-content: space-between; }
.site-foot a:hover { color: var(--ink); }

/* --------------------------------------------------------------- text */
.h1 { font-family: var(--font-display); font-size: var(--text-3xl); font-weight: 600; letter-spacing: -0.021em; }
.h2 { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 600; letter-spacing: -0.016em; }
.h3 { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; }
.h4 { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; }
.lede { font-size: var(--text-md); color: var(--ink-2); max-width: 68ch; }
.muted { color: var(--ink-3); }
.small { font-size: var(--text-xs); }
.center { text-align: center; }
.mono { font-family: var(--font-mono); }
.page-head { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-end; justify-content: space-between; margin-bottom: 1.5rem; }
.page-head .lede { margin-top: 0.4rem; }
.stack > * + * { margin-top: 0.75rem; }
.stack-lg > * + * { margin-top: 1.5rem; }
.stack-xl > * + * { margin-top: 2.5rem; }
.row { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.row-between { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; justify-content: space-between; }
.push { margin-left: auto; }

/* -------------------------------------------------------------- cards */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-xs); }
.card-pad { padding: 1.15rem 1.25rem; }
.card-head { padding: 1rem 1.25rem; border-bottom: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; justify-content: space-between; }
.card-body { padding: 1.15rem 1.25rem; }
.card-foot { padding: 0.85rem 1.25rem; border-top: 1px solid var(--line); background: var(--surface-2); border-radius: 0 0 var(--radius-card) var(--radius-card); }
.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.split { display: grid; gap: 1.5rem; grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr); align-items: start; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- badges */
.badge {
  display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.2rem 0.55rem;
  border-radius: 999px; font-size: var(--text-2xs); font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; font-family: var(--font-mono);
  background: var(--surface-3); color: var(--ink-2); border: 1px solid var(--line);
}
.badge-gold { background: var(--accent-200); border-color: var(--accent-300); color: #0b0b0c; }
.dark .badge-gold { background: var(--surface-3); color: var(--accent-600); border-color: var(--line-strong); }
.badge-success { background: var(--success-soft); color: var(--success); border-color: transparent; }
.badge-danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.badge-warning { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.badge-info { background: var(--info-soft); color: var(--info); border-color: transparent; }

/* ------------------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  padding: 0.55rem 1rem; border-radius: var(--radius-control); border: 1px solid var(--line);
  font-size: var(--text-sm); font-weight: 650; cursor: pointer; background: var(--surface-2); color: var(--ink);
  text-align: center;
}
.btn:hover { background: var(--surface-3); }
.btn-primary { background: var(--brand-600); color: #fff; border-color: var(--brand-600); }
.btn-primary:hover { background: var(--brand-500); }
.btn-gold { background: var(--gold-sheen); color: #0b0b0c; border-color: var(--accent-500); box-shadow: var(--gold-highlight); }
.btn-gold:hover { filter: brightness(1.04); }
.btn-ghost { background: transparent; }
.btn-ghost:hover { background: var(--surface-2); }
.btn-danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.btn-sm { padding: 0.35rem 0.7rem; font-size: var(--text-xs); }
.btn-lg { padding: 0.75rem 1.4rem; font-size: var(--text-md); }
.btn-block { width: 100%; }
.btn[disabled], .btn.is-disabled { opacity: 0.55; cursor: not-allowed; }

/* -------------------------------------------------------------- forms */
.field { display: block; margin-bottom: 0.9rem; }
.field > .label, label.label { display: block; font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.02em; color: var(--ink-2); margin-bottom: 0.3rem; }
.input, .select, .textarea {
  width: 100%; padding: 0.55rem 0.7rem; border-radius: var(--radius-control);
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink); font-size: var(--text-base);
}
.input:focus, .select:focus, .textarea:focus { outline: 2px solid var(--ring); outline-offset: 1px; }
.textarea { min-height: 130px; resize: vertical; font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.6; }
.hint { font-size: var(--text-xs); color: var(--ink-3); margin-top: 0.3rem; }
.form-grid { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

/* ------------------------------------------------------------ notices */
.notice { border-radius: var(--radius-card); padding: 0.8rem 1rem; font-size: var(--text-sm); border: 1px solid var(--line); background: var(--surface-2); margin-bottom: 1rem; }
.notice-success { background: var(--success-soft); border-color: transparent; color: var(--success); }
.notice-error { background: var(--danger-soft); border-color: transparent; color: var(--danger); }
.notice-info { background: var(--info-soft); border-color: transparent; }
.empty { padding: 2.5rem 1rem; text-align: center; color: var(--ink-3); border: 1px dashed var(--line-strong); border-radius: var(--radius-card); }

/* ------------------------------------------------------------- tables */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
table.data { width: 100%; border-collapse: collapse; font-size: var(--text-sm); background: var(--surface); }
table.data th {
  text-align: left; font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--ink-3); font-weight: 600; padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line-strong); background: var(--surface-2); white-space: nowrap;
}
table.data td { padding: 0.65rem 0.8rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--surface-2); }

/* ------------------------------------------------------------ metrics */
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 0.95rem 1.05rem; }
.stat .k { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-3); }
.stat .v { font-family: var(--font-stat); font-size: 2rem; line-height: 1.05; margin-top: 0.35rem; letter-spacing: 0.01em; }
.stat .s { font-size: var(--text-xs); color: var(--ink-3); }

.meter { height: 8px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: 999px; background: var(--gold-sheen); }
.meter-lg { height: 12px; }

/* --------------------------------------------------------------- hero */
.hero { border-radius: var(--radius-card); padding: 2.75rem 2rem; background: var(--gold-sheen); box-shadow: var(--gold-highlight); color: #0b0b0c; }
.hero .h1, .hero h1 { color: #0b0b0c; }
.hero p { color: rgb(11 11 12 / 0.78); }
.hero .badge { background: rgb(255 255 255 / 0.55); border-color: rgb(11 11 12 / 0.18); color: #0b0b0c; }

/* ------------------------------------------------------- lesson reader */
.reader { display: grid; gap: 1.75rem; grid-template-columns: minmax(230px, 270px) minmax(0, 1fr); align-items: start; }
@media (max-width: 1000px) { .reader { grid-template-columns: 1fr; } }
.toc { position: sticky; top: 80px; max-height: calc(100vh - 110px); overflow-y: auto; }
.toc a { display: block; padding: 0.4rem 0.6rem; border-radius: var(--radius-inner); font-size: var(--text-xs); color: var(--ink-2); border-left: 2px solid transparent; }
.toc a:hover { background: var(--surface-2); }
.toc a.is-active { background: var(--accent-200); color: var(--ink); border-left-color: var(--accent-500); font-weight: 650; }
.dark .toc a.is-active { background: var(--surface-3); }
.toc .done-tick { color: var(--success); float: right; }

.lesson-body { font-family: var(--font-reading); font-size: 1rem; line-height: 1.75; color: var(--ink); max-width: 74ch; }
.lesson-body p + p { margin-top: 1rem; }
.lesson-body strong { font-weight: 700; }
.block + .block { margin-top: 1.5rem; }
.block-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; margin-bottom: 0.6rem; }

.callout { border-radius: var(--radius-card); border: 1px solid var(--line); border-left: 3px solid var(--accent-500); background: var(--surface-2); padding: 1rem 1.15rem; }
.callout .callout-head { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3); margin-bottom: 0.4rem; }
.callout-warning { border-left-color: var(--danger); background: var(--danger-soft); }
.callout-tip { border-left-color: var(--success); background: var(--success-soft); }
.callout-regulation { border-left-color: var(--brand-600); background: var(--surface-3); }
.callout-ai { border-left-color: var(--accent-500); background: var(--accent-100); }
.dark .callout-ai { background: var(--surface-3); }
.callout-quote { border-left-color: var(--line-strong); font-family: var(--font-reading); font-style: italic; }

.definition { display: grid; gap: 0.25rem; padding: 0.85rem 1rem; border-radius: var(--radius-control); background: var(--surface-2); border: 1px solid var(--line); }
.definition dt { font-weight: 700; font-family: var(--font-sans); }
.definition dd { margin: 0; color: var(--ink-2); }

.steps { counter-reset: step; }
.steps li { position: relative; padding-left: 2.4rem; }
.steps li + li { margin-top: 0.9rem; }
.steps li::before {
  counter-increment: step; content: counter(step);
  position: absolute; left: 0; top: 0; width: 1.7rem; height: 1.7rem; border-radius: 999px;
  display: grid; place-items: center; background: var(--accent-300); color: #0b0b0c;
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 700;
}
.bullets li { position: relative; padding-left: 1.2rem; }
.bullets li + li { margin-top: 0.4rem; }
.bullets li::before { content: ""; position: absolute; left: 0.15rem; top: 0.62em; width: 5px; height: 5px; border-radius: 999px; background: var(--accent-500); }
ol.numbered { list-style: decimal; padding-left: 1.3rem; }
ol.numbered li + li { margin-top: 0.4rem; }

details.disclosure { border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); padding: 0.2rem 0.9rem; }
details.disclosure + details.disclosure { margin-top: 0.5rem; }
details.disclosure > summary { cursor: pointer; padding: 0.65rem 0; font-weight: 650; font-size: var(--text-sm); list-style: none; }
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::before { content: "\25B8  "; color: var(--accent-600); }
details.disclosure[open] > summary::before { content: "\25BE  "; }
details.disclosure .disclosure-body { padding-bottom: 0.8rem; color: var(--ink-2); font-size: var(--text-sm); }

.chart-flow { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chart-flow .stage { flex: 1 1 175px; border: 1px solid var(--line); border-radius: var(--radius-control); padding: 0.7rem 0.8rem; background: var(--surface-2); }
.chart-flow .stage .n { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--accent-600); }
.chart-flow .stage .l { font-weight: 650; font-size: var(--text-sm); margin-top: 0.15rem; }
.chart-flow .stage .d { font-size: var(--text-xs); color: var(--ink-3); margin-top: 0.25rem; }

.bars { display: grid; gap: 0.5rem; }
.bars .bar-row { display: grid; grid-template-columns: minmax(90px, 170px) 1fr auto; gap: 0.6rem; align-items: center; font-size: var(--text-xs); }
.bars .bar-track { height: 10px; background: var(--surface-3); border-radius: 999px; overflow: hidden; }
.bars .bar-fill { height: 100%; background: var(--gold-sheen); border-radius: 999px; }

.timeline { border-left: 2px solid var(--line-strong); padding-left: 1rem; }
.timeline li + li { margin-top: 0.9rem; }
.timeline .at { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--accent-600); }
.timeline .lbl { font-weight: 650; font-size: var(--text-sm); }
.timeline .dt { font-size: var(--text-xs); color: var(--ink-3); }

.chart-note { font-size: var(--text-2xs); color: var(--ink-3); font-style: italic; margin-top: 0.5rem; }

.tbl-block { width: 100%; border-collapse: collapse; font-size: var(--text-xs); font-family: var(--font-sans); }
.tbl-block th { text-align: left; padding: 0.5rem 0.65rem; background: var(--surface-3); border: 1px solid var(--line); font-weight: 700; }
.tbl-block td { padding: 0.5rem 0.65rem; border: 1px solid var(--line); vertical-align: top; }

/* ---------------------------------------------------------- assessment */
.question { border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); padding: 1.1rem 1.25rem; }
.question + .question { margin-top: 1rem; }
.question .qno { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3); }
.question .stem { font-weight: 600; font-size: var(--text-md); margin: 0.4rem 0 0.8rem; }
.option { display: flex; gap: 0.6rem; align-items: flex-start; padding: 0.6rem 0.75rem; border: 1px solid var(--line); border-radius: var(--radius-control); cursor: pointer; }
.option + .option { margin-top: 0.4rem; }
.option:hover { background: var(--surface-2); }
.option input { margin-top: 0.25rem; accent-color: var(--brand-600); }
.option.is-correct { background: var(--success-soft); border-color: var(--success); }
.option.is-wrong { background: var(--danger-soft); border-color: var(--danger); }
.explanation { margin-top: 0.7rem; padding: 0.7rem 0.85rem; border-radius: var(--radius-control); background: var(--surface-2); font-size: var(--text-sm); color: var(--ink-2); }
.score-ring { font-family: var(--font-stat); font-size: 3.2rem; line-height: 1; }

/* --------------------------------------------------------- certificate */
.certificate {
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-card);
  padding: 3rem 3.25rem; position: relative; box-shadow: var(--shadow-lg); max-width: 900px; margin-inline: auto;
}
.certificate::before { content: ""; position: absolute; inset: 12px; border: 1px solid var(--accent-300); border-radius: 8px; pointer-events: none; }
.certificate-inner { position: relative; text-align: center; }
.certificate .cert-name { font-family: var(--font-display); font-size: var(--text-4xl); margin: 1.2rem 0 0.4rem; }
.certificate .cert-course { font-family: var(--font-reading); font-size: var(--text-xl); color: var(--ink-2); }
.certificate .cert-rule { height: 3px; width: 120px; margin: 1.4rem auto; background: var(--gold-sheen); border-radius: 999px; }
.certificate .cert-meta { display: flex; flex-wrap: wrap; gap: 1.5rem; justify-content: center; margin-top: 2rem; font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-3); }
@media print {
  .masthead, .site-foot, .no-print { display: none !important; }
  body { background: #fff; }
  .certificate { box-shadow: none; border-color: #c8b27a; }
}

/* --------------------------------------------------------------- misc */
.pill-row { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.link-gold { color: var(--accent-600); font-weight: 650; }
.link-gold:hover { text-decoration: underline; }
.divider { height: 1px; background: var(--line); margin-block: 1.25rem; }
.tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--line); margin-bottom: 1.25rem; flex-wrap: wrap; }
.tabs a { padding: 0.55rem 0.9rem; font-size: var(--text-sm); font-weight: 650; color: var(--ink-3); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs a.is-active { color: var(--ink); border-bottom-color: var(--accent-500); }
.tabs a:hover { color: var(--ink); }
.breadcrumb { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-3); margin-bottom: 0.6rem; }
.breadcrumb a:hover { color: var(--ink); }
.sidebar-list a { display: block; padding: 0.5rem 0.6rem; border-radius: var(--radius-inner); font-size: var(--text-sm); }
.sidebar-list a:hover { background: var(--surface-2); }
.sidebar-list a.is-active { background: var(--accent-200); font-weight: 650; }
.dark .sidebar-list a.is-active { background: var(--surface-3); }
.module-row { display: flex; gap: 0.9rem; align-items: flex-start; padding: 0.9rem 0; border-bottom: 1px solid var(--line); }
.module-row:last-child { border-bottom: 0; }
.module-no { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--accent-600); width: 3.2rem; flex-shrink: 0; padding-top: 0.2rem; }
