/*
  The beat card's token contract, lifted out of `study.css`/`skills.css`
  (Lantern Phase 2, docs/design/2026-09-05-fable/05-handoff-roadmap.md).

  ## The seam this file is, and the one it deliberately is not

  Fourteen sheets in this app declare `:root`, in two families: the
  `--chalk` family (welcome, queue, reader, settings, progress, flashcards,
  tutorial, login, compare) and the `--ground` family (study, skills). This
  is NOT "one token sheet for all pages" -- that sweeping refactor was
  explicitly ruled out. It is the narrower thing: the tokens a BEAT needs,
  and nothing else, because a beat card is the only component that already
  renders on two host pages (`shared/beat_card.css`, since #1568) and #1759
  (Lantern) is the first time that card's own token list was large enough
  for the two copies to be worth naming a seam over.

  Nothing in the `--chalk` family moves here. Those nine pages keep
  declaring their own `:root` exactly as before.

  ## The contract, read from `beat_card.css`'s own header

  `shared/beat_card.css`'s header states its contract precisely: `--ink`,
  `--line`, `--muted`, `--accent`, `--surface`, `--raise`, `--ground`,
  `--ok`, `--ok-soft`, `--no`, `--no-soft` (plus `--mono`, `--serif`,
  `--sans-he` and `--milim-text-scale`, which are NOT here -- see below).
  Phase 1 (#1759) added four more this card reads the same way -- the two
  verdict halos, the bloom glow and the elevation shadow -- and six
  theme-independent motion properties several `beats/*.css` cards
  (`cloze.css`, `numeral_gender.css`, `pick_in_cue.css`, `picture.css`,
  `tense.css`, `word_search.css`, `shared/warm_up.css`) already read via
  `var(--dur-bloom)`/`var(--ease-out)`. All fourteen are declared ONCE,
  here, instead of twice (`study.css` and `skills.css` used to carry
  byte-identical light/dark blocks -- Phase 1's own scope note says so:
  "both host pages, same values").

  `--ok-halo` / `--no-halo` / `--ok-bloom`:
    `--shadow`   -- Lantern's own elevation device (02-directions.md,
                    "Elevation": a 1px `--line` ring plus a blurred drop in
                    dark, since a shadow alone is invisible on a near-black
                    ground; a plain double drop in light).
    `--dur-*` / `--ease-*` -- the six motion properties
                    (03-motion-system.md, "proposed additions"), declared
                    once and NOT re-declared in the light override below:
                    they are theme-independent, the same convention
                    `study.css`'s own `:root` used before this move.

  ## What does NOT move, and why

  `--faint`, `--known`, `--func`, `--glow`, `--accent-soft`, `--control`,
  `--control-ink`, `--scroll-hint` are page furniture `beat_card.css` never
  reads -- they stay in `study.css`/`skills.css`. `--serif`, `--mono` and
  `--ui` are typography, not this component's contract (beats read
  `--serif` because prose does, not because this card owns it), and stay on
  the host too. `--heb` and `--sans-he` are `shared/fonts.css`'s alone by a
  standing rule (`tests/test_hebrew_webfont.py`) -- this file does not
  declare either, on purpose, and never will. `--milim-text-scale` is that
  same file's.

  ## Shape

  One dark `:root` (this app's default, same as `study.css`'s own base
  block) plus a `@media (prefers-color-scheme: light)` override -- the
  shape `shared/fonts.css` already uses beside it, not a new convention.
  Values are copied verbatim from `study.css`'s pre-Phase-2 `:root` blocks,
  not re-derived: `tests/test_contrast_sweep.py` already scores every one of
  these composited against a host ground, and a value that did not change
  need not be re-measured.

  #2617 added `:root[data-theme="dark"]`/`["light"]` below the media block,
  the in-app override every stylesheet with a `prefers-color-scheme` rule now
  carries -- a SYNONYM of the two rules above (`test_data_theme_palettes_are_synonyms_of_the_media_palettes`
  pins that), not a third theme.

  ## Load order

  Both hosts load this sheet BEFORE their own `:root` and before
  `shared/beat_card.css` -- `study.html`/`skills.html`'s `<link>` order.
  Nothing here is more specific than a host's own `:root` override could
  be (there is nothing left in either host's `:root` for these fourteen
  names to override -- that is the point of the move), so there is no
  cascade race to reason about the way `beat_card.css`'s own header has to
  for `.opt`/`#ask .advance`.
*/

:root {
  --ground:#0C0E12; --surface:#171A20; --line:#2A2F39; --raise:#1F232B;
  --ink:#F0EDE6; --muted:#9AA2AD;
  /* #1759: dark `--accent` only -- light's B value (#8A6410, below) is
     already what this theme's `--accent` was set to before Lantern, so
     the move here is only the dark literal. `study.css`/`skills.css` keep
     `--glow` and `--accent-soft` beside their own `--ink`/`--muted` --
     `--accent-soft` tracks THIS token's RGB by the owner's own rule
     (2026-09-06 worksheet: "match them ... so just do it"), `--glow`
     deliberately does not (tuned per #935/#1202, stays on the pre-Lantern
     RGB) -- see study.css's own `:root` for both. */
  --accent:#FFCB57;
  --ok:#3FDC7C; --ok-soft:rgba(63,220,124,.16);
  --no:#FF7466; --no-soft:rgba(255,116,102,.16);
  --ok-halo:rgba(63,220,124,.26); --ok-bloom:rgba(63,220,124,.30);
  --no-halo:rgba(255,116,102,.26);
  --shadow:0 0 0 1px var(--line), 0 8px 24px rgba(0,0,0,.35);
  --dur-fast:120ms; --dur-base:220ms; --dur-slow:340ms; --dur-bloom:540ms;
  --ease-out:cubic-bezier(.2,.7,.3,1); --ease-spring:cubic-bezier(.2,1.5,.4,1);
  /* #3029: the card's reading sizes, declared ONCE and theme-independent (like
     the motion properties above, so NOT repeated in the light blocks).
     A brand-new tester said three times in eight minutes that the text was too
     small "given all the blank screen area". Measured on the first cards at
     390x844 before this: English translation 14px, option text 15.5px, the
     Hebrew line 30px -- with the lower 60% of the screen empty -- and the same
     fixed px at 820x1180, where the column (`.phone`, max-width 430px) kept
     every size and left the rest of the glass blank.
     Each is `clamp(phone floor, base + a vw term, cap)`. The floor is the
     modest phone bump (translation 14 -> 17, option 15.5 -> 16.5, Hebrew held
     at 30); the vw term only starts to matter on a wider glass; the cap keeps
     a desktop window from growing a 430px column's text past what it can hold.
     The Hebrew stays the larger of the pair at every width (30.2/17.2 = 1.76
     at 390, 39.2/22.3 = 1.76 at 820). `--fs-cue` and `--fs-target` are the
     Hebrew's: the rules that read them multiply by `--milim-text-scale` as
     before, so the learner's own text size setting (#886) still stacks on top.
     The English never read that token and still does not.
     The option floor is 16.5 and not 17 because of what the fit probe said:
     `scripts/study_layout_probe.py` over all 316 ask cards at a true 393 wide
     (the Hebrew and English at their 390-wide values) cuts no cue at the
     default text size with either, but at the 1.15 text-size maximum a 17.18px
     option cut 6 cards by up to 1.3 lines and 16.5px cuts 1 card by 0.2 line
     (the baseline cuts none). One more pixel on four buttons is what it cost. */
  --fs-translation:clamp(17px, calc(12.5px + 1.2vw), 24px);
  --fs-option:clamp(16.5px, calc(13px + 0.9vw), 22px);
  --fs-cue:clamp(30px, calc(22px + 2.1vw), 44px);
  --fs-target:clamp(22px, calc(14px + 2vw), 32px);
}
@media (prefers-color-scheme: light) {
  :root {
    --ground:#F6F4EE; --surface:#FFFFFF; --line:#E0DBD0; --raise:#FFFFFF;
    --ink:#16181C; --muted:#5B6270;
    --accent:#8A6410;
    /* #533: 2E7A4D measured 4.64:1 on this theme's `--ground` (#F3F1EC) --
       the owner's call, 2026-08-17 worksheet Q2, was to raise the token
       rather than record an under-AA allowance for the three rules that
       read it (study.css's `.verdict.yes`/`.moved-claim:hover`,
       beats/safe_cracker.css's `.cracker-verdict.cracker-crack`). Defined
       HERE ONLY -- those rules all consume it via `var(--ok)`, which is
       why moving this one declaration moves all three. `--ok-soft` is a
       background tint, not text, and keeps its own separate value. */
    --ok:#137A42; --ok-soft:rgba(19,122,66,.14);
    --no:#C2412D; --no-soft:rgba(194,65,45,.14);
    --ok-halo:rgba(19,122,66,.22); --ok-bloom:rgba(19,122,66,.28);
    --no-halo:rgba(194,65,45,.22);
    --shadow:0 1px 2px rgba(20,22,26,.06), 0 6px 18px rgba(20,22,26,.08);
  }
}
/* #2617: the in-app theme override, same reasoning as settings.css's own
   `[data-theme]` pair (see that file's header) -- an unconditional
   attribute selector on `:root` outranks both the bare rule and the
   `@media` rule above on specificity alone, so whichever is present always
   wins over the OS and neither is present for `auto`. This file's base
   `:root` above is already dark (no dark media block exists because there
   is nothing to override), so the dark block here just restates the base's
   own values for the tokens the light block overrides; the light block is
   that `@media` block above, unchanged. The six motion properties are
   THEME-INDEPENDENT (this file's own header) and stay out of both, the
   same as they stay out of the light media block above. */
:root[data-theme="dark"] {
  --ground:#0C0E12; --surface:#171A20; --line:#2A2F39; --raise:#1F232B;
  --ink:#F0EDE6; --muted:#9AA2AD;
  --accent:#FFCB57;
  --ok:#3FDC7C; --ok-soft:rgba(63,220,124,.16);
  --no:#FF7466; --no-soft:rgba(255,116,102,.16);
  --ok-halo:rgba(63,220,124,.26); --ok-bloom:rgba(63,220,124,.30);
  --no-halo:rgba(255,116,102,.26);
  --shadow:0 0 0 1px var(--line), 0 8px 24px rgba(0,0,0,.35);
}
:root[data-theme="light"] {
  --ground:#F6F4EE; --surface:#FFFFFF; --line:#E0DBD0; --raise:#FFFFFF;
  --ink:#16181C; --muted:#5B6270;
  --accent:#8A6410;
  --ok:#137A42; --ok-soft:rgba(19,122,66,.14);
  --no:#C2412D; --no-soft:rgba(194,65,45,.14);
  --ok-halo:rgba(19,122,66,.22); --ok-bloom:rgba(19,122,66,.28);
  --no-halo:rgba(194,65,45,.22);
  --shadow:0 1px 2px rgba(20,22,26,.06), 0 6px 18px rgba(20,22,26,.08);
}
