/* ============================================================================
   Code One Recall — design tokens and component primitives
   ----------------------------------------------------------------------------
   ONE source of truth for colour, type, spacing, radii, shadow, motion and the
   handful of components that repeat across the site.

   Currently linked by: index.html only.
   Every other page still carries its own inline <style> block. See
   "MIGRATING A PAGE" at the bottom of this file before converting one.

   SPECIFICITY RULE
   Everything here is a single element or single class selector (0-0-1 or 0-1-0).
   No descendant chains, no ids, no !important. A page's own stylesheet can
   therefore always override a primitive with one class of its own, and section
   spacing never ends up fighting element spacing.
============================================================================= */


/* ────────────────────────────────────────────────────────────────────────────
   1 · COLOUR

   Structure, not a swatch collection:
     one deep anchor (--ink), one working brand blue, a cool neutral ground,
     and exactly two colours that carry meaning (--signal, --confirm).

   The old palette had eight blues and Tailwind's default slate ramp. Both are
   gone. If you need "a lighter blue", use an opacity or a tint token below
   rather than inventing a new hex.

   GROUND IS NEUTRAL, NOT WARM  (changed 2026-08-04)
   The ground used to be a warm off-white (#FAF8F5 / #F3EFE9 / #E4E0D9, running
   +5 to +11 on red-minus-blue). It read as beige, most strongly on the surfaces
   that repeat most often, and it was rejected. Every neutral below is now at or
   below 0 on red-minus-blue. Do not reintroduce a warm ground.

   Cards are WHITE on a light grey ground, rather than tinted on a near-white
   one. Same number of tokens, but a card now separates from the ground on its
   own fill (dL* 3.49, up from 2.35) instead of depending on a shadow to be seen.

   Contrast, measured on --paper / --surface. All pass WCAG AA for body text:
     ink 15.9/17.4 · ink-2 8.6/9.4 · ink-3 5.2/5.7 · blue 7.3/8.0
     signal 4.7/5.1 · confirm 5.9/6.5 · wrong 6.5/7.1
     white on ink 17.4 · on blue 8.0 · on signal 5.1 · on confirm 6.5
   Chips: signal 4.6 · confirm 5.6 · wrong 6.2 · blue on wash 6.9.
   Do not lighten any of these without re-measuring.

   MEASURING SURFACES: judge pale-on-pale separation in CIE L*, NOT in WCAG
   contrast ratio. Ratios compress at high lightness — two clearly distinct
   off-whites sit around 1.09:1, which reads as "invisible" and is wrong.
   A card needs roughly dL* >= 3 against its ground to read as a card.
───────────────────────────────────────────────────────────────────────────── */
:root {
  /* Anchor. Headings, nav, the dark band. */
  --ink:        #0B1A33;
  /* Secondary text: subheads, list descriptions. */
  --ink-2:      #3C4757;
  /* Muted text: meta lines, captions, footnotes. Never below this lightness. */
  --ink-3:      #5C6779;

  /* Brand blue, unchanged from the original site. Links, markers, focus. */
  --blue:       #1447B8;
  /* Hover and pressed states only. Not a second brand colour. */
  --blue-deep:  #0E3490;
  /* Faint blue tint for a surface that needs to read as "interactive area". */
  --blue-wash:  #E8EFFB;

  /* Ground. Light neutral grey — cards sit on top of this as white. */
  --paper:      #F4F5F7;
  /* The same ground with a blue cast, for alternating one section against the
     next without inventing a second neutral. White cards still separate on it. */
  --paper-blue: #EDF2FB;
  /* The raised surface. White, so a card separates on fill alone. */
  --surface:    #FFFFFF;
  /* Inset surface: form fields, wells, anything recessed rather than raised. */
  --sunken:     #EDEFF3;
  /* Hairlines and card edges. */
  --rule:       #E2E5EA;
  /* A rule that has to carry weight on its own (section breaks, table heads). */
  --rule-strong:#CFD5DE;

  /* MEANING COLOURS — spend these only on what they mean.
     --signal  = the streak flame and genuine attention. Nothing decorative,
                 and NOT for "you have not done this yet" — that is a neutral
                 prompt, not a warning, and orange makes it read as an error.
     --confirm = a correct answer, or something confirmed as included/free.
     If you find yourself reaching for either to make a section look livelier,
     that is the wrong tool: use --surface, spacing, or type size instead. */
  --signal:     #B4500E;
  --signal-bg:  #FBF0E4;
  --confirm:    #146B50;
  --confirm-bg: #E4F1EB;

  /* Wrong answer. Not in the palette proper — it appears in exactly one state. */
  --wrong:      #A8271D;
  --wrong-bg:   #FBECEA;

  --white:      #FFFFFF;


/* ────────────────────────────────────────────────────────────────────────────
   2 · TYPE

   Two families, four weights, one scale.

   Archivo is the display face and is used ONLY on h1/h2 and the question stem.
   It is a grotesque with enough width and weight to hold a 52px line without
   decoration. Source Sans 3 does everything else: humanist, legible at 15px,
   and it has true tabular numerals, which the streak counter needs.

   The scale is fluid and the jumps between levels are deliberately large —
   even steps are what make a page read as templated.
───────────────────────────────────────────────────────────────────────────── */
  --font-display: 'Archivo', system-ui, -apple-system, sans-serif;
  --font-body:    'Source Sans 3', system-ui, -apple-system, sans-serif;

  --step--1: clamp(0.8125rem, 0.79rem + 0.11vw, 0.875rem);  /* 13 → 14  meta, captions */
  --step-0:  clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);      /* 16 → 17  body */
  --step-1:  clamp(1.0625rem, 1.02rem + 0.23vw, 1.1875rem); /* 17 → 19  lead body */
  --step-2:  clamp(1.25rem, 1.16rem + 0.44vw, 1.5rem);      /* 20 → 24  small headings */
  --step-3:  clamp(1.5rem, 1.27rem + 1.1vw, 2.125rem);      /* 24 → 34  section headings */
  --step-4:  clamp(1.875rem, 1.45rem + 2.1vw, 3.25rem);     /* 30 → 52  the question stem */

  --lh-tight:  1.14;   /* display sizes */
  --lh-snug:   1.32;   /* subheads */
  --lh-body:   1.62;   /* prose */

  /* Measure caps. Prose past ~68 characters is hard to scan. */
  --measure:      66ch;
  --measure-wide: 78ch;


/* ────────────────────────────────────────────────────────────────────────────
   3 · SPACING

   One ramp. Section padding is intentionally NOT one value: vertical rhythm
   should vary with a section's importance. Identical section heights all the
   way down a page is one of the strongest "generated" tells.
───────────────────────────────────────────────────────────────────────────── */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.5rem;
  --space-6:  2rem;
  --space-7:  2.5rem;
  --space-8:  3.5rem;
  --space-9:  4.5rem;
  --space-10: 6rem;

  --section-tight: clamp(2.25rem, 4vw, 3rem);
  --section:       clamp(3.25rem, 6.5vw, 5rem);
  --section-loose: clamp(4.5rem, 9vw, 7.5rem);

  --gutter:    clamp(1.25rem, 5vw, 2.5rem);
  /* 1160 left ~380px dead on each side at 1920 while the layout inside it was
     already wasting a third of its own width. 1280 gives the two-column hero
     room to be genuinely two columns. */
  --page-max:  1280px;


/* ────────────────────────────────────────────────────────────────────────────
   4 · RADII AND SHADOW

   Floor is 12px on anything that behaves as a card. Every comparable product
   in this space (Brilliant 20–32px, Lecturio 15px, LITFL 10–12px) is softer
   than this site used to be, not sharper.

   Two shadows only, both diffuse, ambient and navy-cast. No hard directional
   drops. A surface needs EITHER a shadow OR a tinted fill to separate from the
   ground; a 1px border on white is the failure mode.
───────────────────────────────────────────────────────────────────────────── */
  --radius-xs: 6px;    /* inline chips, answer keys */
  --radius-sm: 10px;   /* buttons, inputs */
  --radius:    14px;   /* cards — the floor for any card surface */
  --radius-lg: 20px;   /* the hero surface and other large panels */
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgba(11,26,51,0.05), 0 8px 24px rgba(11,26,51,0.07);
  --shadow-2: 0 2px 4px rgba(11,26,51,0.06), 0 18px 48px rgba(11,26,51,0.12);


/* ────────────────────────────────────────────────────────────────────────────
   5 · MOTION AND FOCUS

   The page gets ONE orchestrated animated moment (the answer reveal on the
   homepage). Everything else is a state change under 180ms. There is no
   scroll-reveal system in this stylesheet on purpose: blanket fade-ups on
   every section are a tell, and they delay content for no benefit.
───────────────────────────────────────────────────────────────────────────── */
  --ease:      cubic-bezier(0.2, 0.7, 0.3, 1);
  --dur-fast:  120ms;
  --dur:       180ms;
  --dur-slow:  260ms;

  --focus-ring: 0 0 0 2px var(--paper), 0 0 0 4px var(--blue);
}


/* ────────────────────────────────────────────────────────────────────────────
   6 · BASE
───────────────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--lh-body);
  /* Numbers are data on this site. Treat them that way everywhere. */
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4, p, figure, ul, ol, dl, dd, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

h1, h2 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: -0.022em;
}
h3, h4 {
  font-family: var(--font-body);
  font-weight: 600;
  line-height: var(--lh-snug);
  letter-spacing: -0.005em;
}

a { color: var(--blue); text-decoration: none; }
a:hover { color: var(--blue-deep); }

img, svg { max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

/* One visible focus treatment, everywhere, on keyboard focus only.
   Deliberately does NOT set border-radius: the ring is a box-shadow, so it
   already follows whatever radius the element has. Setting one here would snap
   a 14px card down to 6px the instant it took focus. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Skip link — visible the moment it takes focus. */
.skip-link {
  position: absolute; left: var(--space-4); top: var(--space-4);
  z-index: 999;
  transform: translateY(-160%);
  padding: var(--space-3) var(--space-5);
  background: var(--ink); color: var(--white);
  border-radius: var(--radius-sm);
  font-weight: 600;
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus-visible { transform: translateY(0); color: var(--white); }


/* ────────────────────────────────────────────────────────────────────────────
   7 · LAYOUT PRIMITIVES
───────────────────────────────────────────────────────────────────────────── */
.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Three section rhythms rather than one. Pick by importance, not by position. */
.section       { padding-block: var(--section); }
.section-tight { padding-block: var(--section-tight); }
.section-loose { padding-block: var(--section-loose); }

.measure      { max-width: var(--measure); }
.measure-wide { max-width: var(--measure-wide); }

/* A hairline that belongs to the page, not to a card. */
.rule { border: 0; border-top: 1px solid var(--rule); }


/* ────────────────────────────────────────────────────────────────────────────
   8 · TYPE PRIMITIVES
───────────────────────────────────────────────────────────────────────────── */
/* Small structural label. 600 weight, modest tracking. Deliberately NOT
   monospace and never above 0.07em: wide-tracked mono overlines read as
   generated. */
.meta {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.meta-plain { text-transform: none; letter-spacing: 0.01em; }

.lead    { font-size: var(--step-1); color: var(--ink-2); }
.quiet   { color: var(--ink-3); }
.small   { font-size: var(--step--1); }

.h-section { font-size: var(--step-3); }
.h-sub     { font-size: var(--step-2); }


/* ────────────────────────────────────────────────────────────────────────────
   9 · BUTTONS
───────────────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  padding: 0.7em 1.35em;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.btn--primary { background: var(--blue); color: var(--white); }
.btn--primary:hover { background: var(--blue-deep); color: var(--white); }

.btn--quiet {
  background: transparent; color: var(--ink);
  border-color: var(--rule);
}
.btn--quiet:hover { background: var(--surface); color: var(--ink); border-color: var(--ink-3); }

.btn--link {
  padding: 0; background: none; border: 0;
  color: var(--blue); font-weight: 600;
}
.btn--link:hover { color: var(--blue-deep); }

/* Sizes. --sm is the nav; --lg is a section's main action, where the button has
   to hold its own against a heading rather than sit beside body copy. */
.btn--sm { padding: 0.45em 0.95em; font-size: var(--step--1); }
.btn--lg { padding: 0.85em 1.6em; font-size: var(--step-1); }

/* Arrow that nudges on hover. The one flourish buttons get. */
.btn-arrow { transition: transform var(--dur) var(--ease); }
.btn:hover .btn-arrow, a:hover > .btn-arrow { transform: translateX(3px); }


/* ────────────────────────────────────────────────────────────────────────────
   10 · SURFACES
───────────────────────────────────────────────────────────────────────────── */
/* The default card. White on the grey ground, so the FILL does the separating
   (dL* 3.49) and the shadow only has to suggest height. Under the old warm
   palette this was reversed — a tinted card on near-white — and cards were
   relying on a 0.04-alpha shadow to be visible at all. */
.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: var(--space-5);
  box-shadow: var(--shadow-1);
}
/* Recessed instead of raised: form fields, wells, quiet grouping. */
.card--sunken {
  background: var(--sunken);
  border: 1px solid var(--rule);
  box-shadow: none;
}
/* Flat card for when several sit in a dense grid and shadows would stack up
   into noise. Keeps the fill, drops the height. */
.card--flat { box-shadow: none; border: 1px solid var(--rule); }

.card--lift { transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease); }
.card--lift:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }

/* ── ROWS ───────────────────────────────────────────────────────────────────
   A list of links that has to read as a list of links. The homepage's clinical
   content list previously had no fill, no border and no shadow at rest — it was
   plain text on the ground (dL* 0.00) and gave a visitor no signal that any of
   it was clickable. Anything that behaves as a navigable row uses this.
─────────────────────────────────────────────────────────────────────────── */
.rows { display: flex; flex-direction: column; gap: var(--space-2); }
.row {
  display: block;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  transition: border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.row:hover {
  border-color: var(--blue);
  box-shadow: var(--shadow-1);
  transform: translateY(-1px);
}

/* Full-bleed dark band. Uses the anchor colour, not a gradient. */
.band-ink { background: var(--ink); color: var(--white); }
.band-ink a { color: #A9C4F5; }
.band-ink a:hover { color: var(--white); }

.chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 0.25em 0.7em;
  border-radius: var(--radius-pill);
  font-size: var(--step--1);
  font-weight: 600;
}
.chip--signal  { background: var(--signal-bg);  color: var(--signal); }
.chip--confirm { background: var(--confirm-bg); color: var(--confirm); }
/* Neutral chip. Now that --surface is white it needs a border to be seen on a
   white card, so this uses the sunken tint plus a rule instead. */
.chip--quiet   { background: var(--sunken); color: var(--ink-2); border: 1px solid var(--rule); }
.chip--brand   { background: var(--blue-wash); color: var(--blue); }


/* ── FIELDS ─────────────────────────────────────────────────────────────────
   An input has to look like somewhere you can type. Recessed fill plus a real
   border — the old build filled inputs with the page's own surface tint, which
   on a near-white ground read as a disabled control rather than an empty one.
─────────────────────────────────────────────────────────────────────────── */
.field {
  width: 100%;
  padding: 0.7rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  color: var(--ink);
  outline: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field::placeholder { color: var(--ink-3); }
.field:hover { border-color: var(--ink-3); }
.field:focus { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-wash); }


/* ────────────────────────────────────────────────────────────────────────────
   11 · REDUCED MOTION

   One block, applied globally, so no component has to remember. Covers the
   homepage reveal animation as well as every transition above.
───────────────────────────────────────────────────────────────────────────── */
@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;
  }
}


/* ============================================================================
   MIGRATING A PAGE ONTO THIS STYLESHEET

   1. Add, in <head>, before the page's own <style>:
        <link rel="stylesheet" href="assets/cor.css">
      and replace the Google Fonts link with:
        Archivo 600,700 + Source Sans 3 400,600
      (fonts.googleapis.com and fonts.gstatic.com are already allow-listed in
      _headers, so no CSP change is needed.)

   2. Delete from the page's own <style>: the whole :root block, the
      *,*::before,*::after reset, the body font/colour rules, .container,
      the .btn-primary/.btn-ghost definitions, and any .fade-up / .delay-*
      scroll-reveal system.

   3. Rename the old tokens. Direct replacements:

        --navy, --navy-mid           → --ink
        --blue, --blue-mid           → --blue / --blue-deep
        --blue-light (#2563eb)       → --blue        (Tailwind default, drop it)
        --sky, --sky-mid, --sky-pale → --blue-wash   (one tint, not three)
        --white (#fff) as a ground   → --paper       (the grey ground)
        --white (#fff) as a CARD     → --surface     (still white — see below)
        --off-white, --slate-100     → --sunken      (recessed, not raised)
        --slate-200, --slate-300     → --rule
        --slate-400, --slate-500     → --ink-3
        --slate-700                  → --ink-2
        --slate-900                  → --ink

      NOTE, and this trips people up: --surface is now WHITE and --paper is the
      grey. A card keeps its white fill and the PAGE gets darker around it. If
      you find yourself setting `background: white` on a card, you want
      --surface, and the page behind it should already be --paper.
        --green / --green-bg         → --confirm / --confirm-bg
        --red                        → --wrong
        --radius-sm/--radius/--radius-md/--radius-lg
                                     → --radius-xs/--radius-sm/--radius/--radius-lg
        --shadow-sm/--shadow/--shadow-md/--shadow-blue
                                     → --shadow-1 / --shadow-2   (two, not five)

   4. Swap `.container` for `.wrap`, and section padding for one of
      `.section-tight` / `.section` / `.section-loose` — chosen by how much
      that section actually matters, not to make everything match.

   5. Headings: remove `font-family: 'Instrument Serif'` and any
      `h1 em { font-style: italic; color: blue }` accent rule. Headings are
      Archivo 700 in --ink. There is no italic accent word anywhere.

   6. Check contrast on anything you tint yourself. The ratios at the top of
      this file are measured; new colours are not.

   7. The ground is NEUTRAL. If a page still carries a warm off-white
      (#faf8f5, #f3efe9, #e4e0d9 and relatives), that is the old palette —
      replace it, do not preserve it. Anything you add should sit at or below
      zero on red-minus-blue.
============================================================================= */
