/* ==========================================================================
   BASEPLAY — the design language for every tennis surface.

   THIS FILE IS THE ONE HOME FOR COLOUR AND TYPE. Per CLAUDE.md's one-home
   rule: a second copy of a palette drifts silently, because both copies
   render fine. Before this file there were three — style.css, intake.html's
   inline block and brief.html's inline block — each defining names like
   `--panel` and `--line` to different values, and `--muted` to different
   ROLES. No surface could borrow a component from another without it
   arriving the wrong colour.

   Three audiences, three themes, ONE vocabulary:

     court  Tim's console + the coaches' cut-down console. Dark. It is a
            tool, used courtside in the evening; no brand argument applies.
     brand  The public forms a parent fills in. Light, from Tim's Webflow
            site, because clicking "sign up" there must not throw a parent
            from white to near-black at the moment they are asked for their
            child's name, age and phone number.
     doc    Internal workflow documents (brief.html). Light, with automatic
            dark support — it is read at a desk, not on court.

   A theme is selected with `data-theme` on <html>. Every token below is
   defined in ALL THREE, so a component can move between surfaces without
   landing on an undefined variable and silently rendering transparent.
   (That exact bug shipped once: intake.html asked for `--card`/`--fg`,
   which existed nowhere, and the selected tab had no background for its
   whole life — distinguishable only by its border.)

   ------------------------------------------------------------------------
   THE ONE RULE THAT IS NOT A PREFERENCE

   `--accent` (#06c25e, Tim's brand green) is a FILL. It is NEVER text.

     white on #06c25e ....... 2.36:1  fails
     --on-accent on it ...... 7.79:1  passes
     #06c25e as text on white  2.36:1  fails

   So the most important control on the public form — the submit button — is
   his green with DARK text, and the obvious "green button, white text"
   would have been the least readable thing on the page. Where a green must
   BE text, use `--good-fg`, which is a contrast-safe tint per theme.

   `tests/unit/test_baseplay_tokens.py` enforces this by parsing the
   stylesheets: `--accent` appearing in a `color:` is a test failure, not a
   review note. It also measures every fg/bg pair in this file, so a value
   edited by eye cannot quietly drop below 4.5:1.
   ------------------------------------------------------------------------

   Values marked `derived` are not yet rendered by any shipped surface. They
   exist so the token set is complete in every theme, and they are contrast-
   checked like the rest rather than taken on trust.
   ========================================================================== */

/* --------------------------------------------------------- theme-invariant
   Type, space and motion do not change between a coach's tool and a
   parent's form. Only colour does. */
:root {
  --font-ui: system-ui, -apple-system, "PingFang SC", "Noto Sans SC", sans-serif;
  /* The public form leads with Helvetica for Latin text — closer to Tim's
     Arial site — but keeps the Chinese faces ahead of any Latin fallback.
     Matching his font outright would be a downgrade for most of the people
     who read that page. */
  --font-brand: "Helvetica Neue", Helvetica, Arial, "PingFang SC",
                "Noto Sans SC", sans-serif;
  /* Workflow documents read at a desk, not on a phone or a court. */
  --font-doc: ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-num: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Anything numeric takes --font-num AND font-variant-numeric: tabular-nums.
     The face exists for the numerals; shipping one without the other is a
     bug that has already happened once in this repo (cyclana, #373). */

  --step-micro: 11px;   /* eyebrow / label caps */
  --step-sm:    12px;
  --step-base:  14px;   /* console body */
  --step-form:  15px;   /* public form body — bigger, it is read once */
  --step-lg:    16px;
  --step-title: 27px;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 18px;
  --space-5: 22px;

  --radius-sm:   7px;
  --radius:     10px;
  --radius-lg:  16px;
  --radius-pill: 999px;

  --measure: 62ch;
  --motion: 120ms ease;   /* @kind other */

  /* The wordmark ball, from icon.svg. Identical in every theme — it is the
     mark, not a themeable surface. */
  --mark: #c8e05a;
}

/* ---------------------------------------------------------------- court
   Tim's console and the coaches' console. Dark forest green.
   From style.css (the Aug 2026 Courtside redesign). */
[data-theme="court"] {
  --bg:         #0d1512;
  --surface:    #16241c;
  --surface-2:  #1c2f24;
  --field:      #0d1512;   /* inputs sit on the page ground, not the card */
  --rail:       #111c16;
  --hero: linear-gradient(180deg, #1b2c22, #16241c);   /* @kind color */

  --line:       #2c4636;
  --line-soft:  #22352a;
  --line-rail:  #1e2f26;

  --text:  #e9f2ec;
  --body:  #c6d6cb;
  --dim:   #9db3a5;
  --muted: #6e8578;

  --accent:        #06c25e;   /* FILL ONLY — see the rule above */
  --on-accent:     #10160a;
  /* The old accent, demoted: meters and surfaces only, never a button or a
     status — it shares a hue with the ground and disappears as one. */
  --accent-muted:  #2f9e5f;
  --link:          #06c25e;
  --link-hover:    #dcec9a;

  --good-fg: #6fe3a8;
  --good-bg: #0d3320;
  --warn:      #d9a13c;
  --warn-fg:   #ecd3a2;
  --warn-bg:   #33270f;   /* derived */
  --warn-line: #6e5a26;   /* derived */
  --danger:    #d05f5f;
  --danger-fg: #e8b3b3;
  --danger-bg: #3a1f1f;
  --info:    #4f8fd0;     /* derived */
  --info-fg: #b9cfc0;
  --info-bg: #1f3229;
  --neutral-bg: #1c2f24;  /* derived */
  --neutral-fg: #9db3a5;  /* derived */
}

/* ---------------------------------------------------------------- brand
   The public forms. Light, from baseplay.webflow.shared.css:
     --main #06c25e  --dark #151515  --grey-4 #e6e6e6  --haze #f6f6f6
     --color-1 #ffa32d  --color-2 #fa345a  --color-3 #5d66fe

   Two deliberate departures from his site, both measured rather than judged
   by eye:
     1. His green is a fill, never text (the rule at the top of this file).
     2. --dim is #666 (5.31:1), not his --grey-2 #777, which lands at 4.14:1
        and fails on the labels of a form. #777 survives only as --muted, on
        an inactive tab, which is not information. */
[data-theme="brand"] {
  --bg:        #f6f6f6;   /* his --haze */
  --surface:   #ffffff;   /* cards lift off it */
  --surface-2: #eeeeee;
  --field:     #fbfbfb;   /* so fields read as fields on white */
  --rail:      #ffffff;   /* derived */
  /* The public hero is flat, not a gradient. */
  --hero:      #ffffff;   /* @kind color */

  --line:      #e6e6e6;   /* his --grey-4 */
  --line-soft: #f0f0ee;
  --line-rail: #e6e6e6;   /* derived */

  --text:  #151515;       /* his --dark, 16.9:1 on the page */
  --body:  #444444;
  --dim:   #666666;
  --muted: #777777;

  --accent:       #06c25e;  /* his --main. FILL ONLY */
  --on-accent:    #10160a;
  --accent-muted: #00a850;  /* derived */
  --link:         #00a850;
  --link-hover:   #0b6b38;  /* derived */

  --good-fg: #0b6b38;       /* green AS text: 7.4:1 on the page */
  --good-bg: #eefaf2;
  --warn:      #ffa32d;     /* his --color-1 */
  --warn-fg:   #8a5200;
  --warn-bg:   #fff4e2;
  --warn-line: #e8c48a;     /* derived */
  --danger:    #fa345a;     /* his --color-2 */
  --danger-fg: #a3102c;     /* derived */
  --danger-bg: #ffeef1;     /* derived */
  --info:    #5d66fe;       /* his --color-3 */
  --info-fg: #2b32c4;       /* derived */
  --info-bg: #eef0ff;       /* derived */
  --neutral-bg: #f0f0ee;
  --neutral-fg: #666666;
}

/* ------------------------------------------------------------------ doc
   Internal workflow documents. A THIRD palette rather than a reskin of
   brand: it is read at a desk and supports dark, which the public form
   deliberately does not. Values from brief.html. */
[data-theme="doc"] {
  --bg:        #f3f7f4;
  --surface:   #ffffff;
  --surface-2: #eef4f0;   /* derived */
  --field:     #ffffff;   /* derived */
  --rail:      #ffffff;   /* derived */
  --hero:      #ffffff;   /* @kind color */  /* derived */

  --line:      #d6e2da;
  --line-soft: #e6efe9;   /* derived */
  --line-rail: #d6e2da;   /* derived */

  --text:  #16241c;
  --body:  #2d4034;       /* derived */
  --dim:   #5b6f63;
  --muted: #5b6f63;

  --accent:       #06c25e;
  --on-accent:    #10160a;
  --accent-muted: #24884f;   /* fill only, never ink */
  --link:         #1c7241;   /* 5.94:1 on --surface; tracks --good-fg */
  --link-hover:   #16241c;  /* derived */

  /* Darkened 2026-09-07. These were 4.12:1 / 3.95:1 / 3.63:1 against their
     own grounds — the contrast test had never measured the light doc theme
     (its parser merged the dark block over it), so nothing said so. */
  --good-fg: #1c7241;     /* 5.26:1 on --good-bg, 5.50:1 on --bg */
  --good-bg: #e8f4ed;     /* derived */
  --warn:      #d9a13c;
  --warn-fg:   #8a5f14;   /* 4.80:1 on --warn-bg */
  --warn-bg:   #f7ecd4;
  --warn-line: #d9b563;
  --danger:    #c0392b;   /* derived */
  --danger-fg: #a3102c;   /* derived */
  --danger-bg: #fdecea;   /* derived */
  --info:    #4f8fd0;     /* derived */
  --info-fg: #1f5c93;     /* derived */
  --info-bg: #e8f1fa;     /* derived */
  --neutral-bg: #eef4f0;  /* derived */
  --neutral-fg: #5b6f63;  /* derived */

  /* The doc theme shows the console's own colours inside diagrams, so it
     carries the court ground as a named inset rather than a literal. */
  --court:      #0f1a14;
  --court-line: #2c4636;
  /* Ink for text ON that inset. It cannot be --dim: the panel stays dark in
     both modes, so the light theme's --dim (#5b6f63) reads 3.30:1 there. */
  --court-dim:  #93a89b;   /* 7.04:1 on --court */
}

/* The doc theme is the only one that follows the reader's system setting.
   court is dark by definition and brand is light by decision, so neither
   takes a prefers-color-scheme override. */
@media (prefers-color-scheme: dark) {
  [data-theme="doc"] {
    --bg:        #0c1510;
    --surface:   #14231a;
    --surface-2: #1b2f23;   /* derived */
    --field:     #14231a;   /* derived */
    --rail:      #14231a;   /* derived */
    --hero:      #14231a;   /* @kind color */  /* derived */

    --line:      #243c2e;
    --line-soft: #1e3226;   /* derived */
    --line-rail: #243c2e;   /* derived */

    --text:  #e7f0ea;
    --body:  #c6d6cb;       /* derived */
    --dim:   #93a89b;
    --muted: #93a89b;

    --accent-muted: #3fb371;
    --link:         #3fb371;
    --link-hover:   #dcec9a;  /* derived */

    --good-fg: #3fb371;
    --good-bg: #0d3320;     /* derived */
    --warn:      #d9a13c;
    --warn-fg:   #d9a13c;
    --warn-bg:   #241d0e;
    --warn-line: #6e5a26;
    --danger-fg: #e8b3b3;   /* derived */
    --danger-bg: #3a1f1f;   /* derived */
    --info-fg: #b9cfc0;     /* derived */
    --info-bg: #1f3229;     /* derived */
    --neutral-bg: #1b2f23;  /* derived */
    --neutral-fg: #93a89b;  /* derived */
  }
}

/* ------------------------------------------------------------------ base
   Shared across every surface. Anything below here must render correctly in
   all three themes — that is the test for whether a rule belongs in this
   file at all. */
* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-ui);
  background: var(--bg);
  color: var(--text);
}

button { font-family: inherit; cursor: pointer; }
button:disabled { cursor: default; }

/* One focus ring for every surface. It was previously the browser default
   everywhere, which is invisible on the court theme's dark ground. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Numerals. The pair is the point — see the note under --font-num. */
.num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
