/* OneOneTyping v6 — design tokens.
 *
 * Two lessons are baked into this file, both learned by measuring rather than
 * guessing.
 *
 * 1. THE ACCENT IS A GARNISH, NOT A SURFACE.
 *    On andromeld — the page whose green reads so well — only 91 elements out
 *    of thousands carry the green, and its total painted background is 42,000
 *    px² against 2,200,000 px² of near-neutral off-white. Every heading on that
 *    page is near-black (#101012). The accent shows up on kickers, small icon
 *    chips, buttons, caption indices and links, and nowhere else.
 *
 *    The previous revision of this file did the opposite: blue headings, a 2px
 *    blue border on every card. That is what made it look cheap. Here the
 *    accent is rationed the same way and headings are near-black again.
 *
 * 2. BLUE NEEDS TO BE DARKER THAN GREEN TO CARRY THE SAME WEIGHT.
 *    sRGB simply cannot hold a blue as chromatic as #0e8f45 at the same
 *    lightness. Matching on L* and contrast instead gives #0e7fd4:
 *
 *      andromeld green  #0e8f45   L* 52.0   C* 57.6   contrast-on-white 4.17
 *      our blue         #0e7fd4   L* 51.9   C* 51.6   contrast-on-white 4.20
 *
 *    and for the solid button fill, matching #0c7f3e (L* 46.5, 5.10):
 *
 *      andromeld button #0c7f3e   L* 46.5   C* 52.2   contrast 5.10
 *      our button       #0f74c4   L* 47.7   C* 49.1   contrast 4.87
 *
 * Four semantic roles, never mixed:
 *   structure = blue   (links, buttons, kickers, progress, active states)
 *   action    = gold   (the one primary CTA per page, VIP, medals)
 *   done      = green  (completed, correct glyphs)
 *   error     = red    (mistyped characters, error stats)
 */

:root {
  color-scheme: light;

  /* ---- Accent: matched to andromeld's green ---------------------------
     The green is #0e8f45: L* 52.0, chroma 57.6, 4.17:1 on white. A blue at
     that exact lightness only reaches chroma 51.6 — sRGB cannot hold more —
     and because saturated blues read lighter than their L* suggests
     (Helmholtz-Kohlrausch), an exact lightness match still feels washed out.

     Going a few steps deeper closes the gap:

       #0e7fd4   L* 51.9   C* 51.6   4.20:1   exact match, still looks pale
       #0d76c9   L* 48.6   C* 50.7   4.72:1   what we use
       #0c6dbd   L* 45.2   C* 49.3   5.33:1   button fill

     The deeper accent is what makes it read as a confident blue, and 4.72:1
     also clears AA for text where the exact match only scraped it. */
  --accent: #0d76c9;
  --accent-deep: #0c6dbd;          /* solid fills under white text (5.33:1) */
  --accent-hover: #0a5ca6;
  --accent-ink: #0a5ca6;           /* accent as text on white (6.79:1) */
  --accent-soft: rgba(13, 118, 201, 0.1);
  --accent-tint: #eaf4fd;          /* the palest blue surface */
  --accent-line: rgba(13, 118, 201, 0.24);
  --accent-mid: #8fc8f0;

  --glow-a: rgba(63, 165, 240, 0.16);
  --glow-b: rgba(90, 130, 230, 0.12);

  /* Kept as names because components already reference them. */
  --blue: var(--accent);
  --blue-deep: var(--accent-deep);
  --blue-hover: var(--accent-hover);
  --blue-dark: var(--accent-ink);
  --blue-soft: var(--accent-tint);
  --blue-mid: var(--accent-line);
  --blue-ink: var(--accent-ink);
  --banner: var(--accent);
  --banner-ink: #ffffff;

  /* ---- Gold: the CTA family, from typing.com --------------------------- */
  --gold-100: #fcf2d9;
  --gold-200: #f9e4b2;
  --gold-300: #f7d78c;
  --gold-400: #f4c965;
  --gold-500: #f1bc3f;
  --gold-600: #d0a74d;

  --gold: var(--gold-400);
  --gold-ink: #604b19;
  --gold-soft: var(--gold-100);
  --gold-soft-ink: #604b19;
  --gold-dark: var(--gold-500);
  --gold-lip: var(--gold-600);

  /* ---- Functional ------------------------------------------------------ */
  --green: #71b16b;
  --green-ink: #2f855a;

  /* GitHub's contribution ramp, light mode — measured from the live page so the
     calendar reads as the same object as the one people already know. */
  --cal-0: #eff2f5;
  --cal-1: #aceebb;
  --cal-2: #4ac26b;
  --cal-3: #2da44e;
  --cal-4: #116329;
  --cal-line: rgba(31, 35, 40, 0.05);
  --green-soft: #effaf0;
  --green-line: #ace7b6;

  --red: #eb5757;
  --red-ink: #c53030;
  --red-soft: #fdecec;

  --orange: #b7791f;
  --orange-soft: #fdf6e3;

  --sem-structure: var(--accent);
  --sem-action: var(--gold);
  --sem-done: var(--green);
  --sem-error: var(--red);
  --brand: var(--accent);

  /* ---- Surfaces: near-neutral, barely tinted --------------------------- */
  /* andromeld's floor is #f3f7f4 — white with the faintest green cast. Ours is
     the same idea one hue over, and it stays this quiet on purpose: the accent
     has to be the only saturated thing on the page. */
  --bg: #f6f8fa;
  --bg-elevated: #ffffff;
  --bg-soft: #f3f7fa;
  --bg-sunken: #eceff3;
  --bg-tint: var(--accent-tint);
  --line: rgba(0, 0, 0, 0.11);
  --line-soft: rgba(0, 0, 0, 0.07);
  --border: var(--line);
  --border-strong: rgba(0, 0, 0, 0.18);

  /* ---- Ink -------------------------------------------------------------- */
  /* Headings are near-black. This is the single biggest correction from the
     previous revision, which painted them blue. */
  --text: #56565e;                 /* 7.3:1 — body */
  --text-strong: #101012;          /* 18.9:1 — every heading */
  --text-muted: #63676e;           /* 5.7:1 */
  --text-dim: #6f7378;             /* 4.6:1 */
  --text-invert: #ffffff;

  /* ---- Typing surfaces --------------------------------------------------- */
  --lesson-ink: #4a4a4a;
  --correct: var(--green);
  --correct-ink: #5f9e59;
  --correct-soft: var(--green-soft);
  --wrong: var(--red);
  --wrong-ink: #c53030;
  --caret: #0099ff;
  --rule: #d9d9d9;              /* the hairline under each passage line */

  /* ---- Geometry ----------------------------------------------------------- */
  --radius-ctl: 6px;
  --radius-card: 12px;
  --radius-card-lg: 16px;
  --radius-pill: 9999px;
  --radius: var(--radius-card);
  --radius-sm: var(--radius-ctl);
  --radius-btn: 8px;

  /* Cards are defined by a hairline and a barely-there shadow, not a colour. */
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.05);
  --shadow-md: 0 4px 10px -2px rgba(16, 24, 40, 0.08),
    0 2px 4px -2px rgba(16, 24, 40, 0.05);
  --shadow-lg: 0 18px 32px -12px rgba(16, 24, 40, 0.18),
    0 4px 10px -4px rgba(16, 24, 40, 0.08);
  --shadow-banner: 0 1px 2px rgba(16, 24, 40, 0.06);
  --shadow-shot: 0 1px 2px rgba(16, 24, 40, 0.06),
    0 24px 48px -28px rgba(16, 24, 40, 0.35);
  --shadow-key: 0 1px 0 var(--line);
  --shot-border: rgba(0, 0, 0, 0.08);
  --focus-ring: 0 0 0 3px rgba(13, 118, 201, 0.26);

  /* ---- Motion -------------------------------------------------------------- */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-rise: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* ---- Type ---------------------------------------------------------------- */
  --font-sans: 'Quicksand', system-ui, -apple-system, BlinkMacSystemFont,
    'SF Pro SC', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei',
    'Noto Sans SC', sans-serif;
  --font-mono: 'Roboto Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo,
    Consolas, 'Courier New', monospace;
  --font-brand: var(--font-sans);

  --fs-xs: 11px;
  --fs-sm: 13px;
  --fs-md: 14px;
  --fs-lg: 17px;
  --fs-xl: 21px;
  --fs-2xl: 28px;
  --fs-display: clamp(34px, 5.4vw, 60px);

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* ---- Layout ---------------------------------------------------------------- */
  --max: 1120px;
  --max-wide: 1280px;
  --maxw: 1072px;
  --max-prose: 680px;
  --nav-h: 56px;

  --nav-bg: rgba(255, 255, 255, 0.85);
  --nav-ink: #101012;
}

/* Dark theme — same roles, re-pitched. The accent lifts so it still reads as
   the one saturated thing on the page. */
html[data-theme='dark'] {
  color-scheme: dark;

  --accent: #3d9ae4;
  --accent-deep: #1a659e;
  --accent-hover: #14507c;
  --accent-ink: #74bcf0;
  --accent-soft: rgba(61, 154, 228, 0.14);
  --accent-tint: #13202c;
  --accent-line: rgba(61, 154, 228, 0.28);
  --accent-mid: #2b5f8a;

  --glow-a: rgba(63, 159, 232, 0.14);
  --glow-b: rgba(90, 130, 230, 0.1);

  --gold-100: #33280f;
  --gold-200: #4a3a15;
  --gold-300: #6b5320;
  --gold-400: #e8b93d;
  --gold-500: #f0cd6a;
  --gold-600: #b8912f;

  --gold: var(--gold-400);
  --gold-ink: #2a2212;
  --gold-soft: var(--gold-100);
  --gold-soft-ink: var(--gold-500);
  --gold-dark: var(--gold-500);
  --gold-lip: var(--gold-600);

  --green: #57b957;
  --green-ink: #8ed08c;
  --cal-0: #21262d;
  --cal-1: #0e4429;
  --cal-2: #006d32;
  --cal-3: #26a641;
  --cal-4: #39d353;
  --cal-line: rgba(240, 246, 252, 0.06);
  --green-soft: #16331a;
  --green-line: #2f5c39;

  --red: #fc8181;
  --red-ink: #fc8181;
  --red-soft: #3a2224;
  --orange: #e0a34a;
  --orange-soft: #33260f;

  --bg: #101113;
  --bg-elevated: #17191c;
  --bg-soft: #131518;
  --bg-sunken: #0b0c0d;
  --bg-tint: #13202c;
  --line: rgba(255, 255, 255, 0.13);
  --line-soft: rgba(255, 255, 255, 0.08);
  --border: var(--line);
  --border-strong: rgba(255, 255, 255, 0.22);

  --text: #b9b9bf;
  --text-strong: #f4f4f5;
  --text-muted: #a1a1a8;
  --text-dim: #8e8e96;
  --text-invert: #101113;

  --lesson-ink: #c9c9ce;
  --correct-ink: #8ed08c;
  --wrong-ink: #fc8181;
  --caret: #63b3ed;
  --rule: rgba(255, 255, 255, 0.14);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 18px 40px rgba(0, 0, 0, 0.55);
  --shadow-shot: 0 1px 2px rgba(0, 0, 0, 0.5),
    0 24px 50px -26px rgba(0, 0, 0, 0.8);
  --shadow-key: 0 1px 0 rgba(255, 255, 255, 0.06);
  --shot-border: rgba(255, 255, 255, 0.12);

  --nav-bg: rgba(16, 17, 19, 0.85);
  --nav-ink: #f4f4f5;
  --focus-ring: 0 0 0 3px rgba(63, 159, 232, 0.35);
}
