/*
 * Roots Playbook design tokens.
 *
 * One place for every colour, size, duration and shape in the interface. Components reference
 * tokens; they never spell out a hex, a pixel font size or a timing.
 *
 * APP APPEARANCE AND FIELD THEME ARE DIFFERENT THINGS. Everything in this file is the
 * application's chrome, and it follows `data-appearance` on <html> (light / dark, resolved from
 * the Light / Dark / System preference by theme/appearance.js). The football field has its own
 * five themes — Broadcast, Night Game, Coach Board, Neon, Team — which colour the canvas and
 * nothing else. A coach can run a Coach Board field inside a dark app, or a Neon field in a
 * light one, because the two were never the same choice.
 */

/*
 * ── The display face ────────────────────────────────────────────────────────────────
 *
 * Bebas Neue, self-hosted. One 13.7 KB woff2 in `public/fonts/`, precached by the service
 * worker like every other shipped file, so an installed app has it on a field with no signal.
 * It is never fetched from Google Fonts or any other CDN: `font-src 'self'` forbids it, and a
 * font that has to reach the network is a font the app does not have when it needs it.
 *
 * Licence: SIL Open Font License 1.1. Copyright 2019 The Bebas Neue Project Authors
 * (https://github.com/dharmatype/Bebas-Neue). The full licence ships beside the font at
 * `public/fonts/bebas-neue-OFL.txt`, which is what the OFL requires of anyone redistributing
 * it, and is named again in docs/THIRD_PARTY_LICENSES.md. Settings shows no attribution row:
 * the OFL asks for the notice and licence to travel with the Font Software, which that file
 * does, not for a credits screen.
 *
 * THE METRIC OVERRIDES ARE THE WHOLE TRICK, so they get explained rather than tuned.
 *
 * The face ships ascent 900 / descent 300 per 1000 units, with a cap height of 700. Dropped
 * into a line box, that leaves 200 units of air above the capitals and 300 below the baseline
 * that nothing ever occupies — an all-capital face has no descenders to put there. Every label
 * then sits about a pixel high in a row that centres it, which is the tell of a display face
 * that was pasted in rather than fitted.
 *
 * Overriding to 85 / 15 makes the box exactly one em and puts the same 0.15em above the caps
 * as below the baseline, so a capital is optically centred in ANY line box at ANY size, with
 * no per-label nudge and nothing to re-tune when a size changes. 0.15em still clears the
 * deepest mark this face puts under the baseline in ordinary use (a comma, at 0.12em).
 *
 * Safari below 17 ignores the overrides and falls back to the font's own metrics: one pixel
 * high, and nothing clipped.
 */
/* Bebas Neue. Copyright 2019 The Bebas Neue Project Authors
   (https://github.com/dharmatype/Bebas-Neue), licensed under the SIL Open Font License,
   Version 1.1. The full licence ships with the app at public/fonts/bebas-neue-OFL.txt and is
   precached with the shell, which is what the OFL asks for: the notice and licence travel with
   the font files, not on a screen. Settings deliberately shows no attribution row. Keep this
   notice, that file, and docs/THIRD_PARTY_LICENSES.md together with the .woff2 below. */
@font-face {
  font-family: "Bebas Neue";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../../public/fonts/bebas-neue-400-latin.woff2") format("woff2");
  ascent-override: 85%;
  descent-override: 15%;
  line-gap-override: 0%;
}

:root {
  /* ---- Typography ------------------------------------------------------------------ */
  /*
   * TWO FACES, TWO JOBS, AND A RULE ABOUT WHICH IS WHICH.
   *
   * `--font-ui` is the interface: every label, every sentence, every value, everything a coach
   * reads rather than glances at. `--font-display` is an accent — the football vocabulary the
   * app repeats on every screen, set in capitals at a small size.
   *
   * The rule is SEMANTIC, never "this string happens to be uppercase". A class earns the
   * display face because of what it names — a section, a football category, a phase of a play —
   * not because of the letters that landed in it. Nothing detects case at runtime.
   *
   * And the display face never sets USER CONTENT. A play's name, a player's name and a coach's
   * note go in `--font-ui` wherever they appear, including the one small-caps row that shows a
   * player's label (see `.timing-player__name`). The bundled subset is Latin-1; the vocabulary
   * it is allowed to set is a fixed English list that fits inside it.
   */
  --font-ui: ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-display: "Bebas Neue", var(--font-ui);
  /* Timings, jersey numbers, yardages: tabular so a changing digit never shifts the layout. */
  --font-num: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  /* Roles, not sizes. `screen` is the one big thing on a screen; everything else steps down.
     The scale is deliberately short — six sizes is enough, and more is how labels end up
     clipping because two of them are a pixel apart and both were used. */
  --fs-screen: 26px;   --lh-screen: 31px;   /* Home / library screen title */
  --fs-title: 20px;    --lh-title: 25px;    /* App bar, sheet, card title */
  --fs-label: 16px;    --lh-label: 21px;    /* Primary label, list row title, control text */
  --fs-body: 15px;     --lh-body: 20px;     /* Body copy */
  --fs-secondary: 14px; --lh-secondary: 19px; /* Row meta, summary values */
  --fs-caption: 12px;  --lh-caption: 16px;  /* Captions, hints, tags */
  /* Section headers are small caps with tracking, so they need their own pair. */
  --fs-section: 12px;  --lh-section: 16px;  --tracking-section: 0.06em;

  /*
   * The display label: ONE size, and it sits in a line box the scale already has.
   *
   * 16px is `--lh-section` and `--lh-caption` both, which is every line box a display label
   * currently lands in — so swapping a label to the display face changes the letters and
   * nothing else. No row grows, no chip gets taller, no fixed height needs revisiting, and the
   * 8px dot pinned beside a phase label stays where it was.
   *
   * 14 rather than 12 because the face is CONDENSED, not because it is bigger. Cap heights
   * match almost exactly — 0.70em against the system face's 0.705 — so at equal size the
   * capitals are the same HEIGHT, but each one is about 55% of the width, and a label that
   * narrow reads lighter than the one it replaced. Two points buys the mass back, and the
   * label is still a third narrower than it was.
   *
   * 0.05em, just under the interface's 0.06em: a condensed face needs its counters opened at
   * this size, and it needs less help than a normal-width one. Tracked out further this stops
   * being a football app and starts being a poster.
   *
   * `--display` is the LABEL step: eyebrows, category labels, phase labels.
   */
  --fs-display: 14px;  --lh-display: 16px;  --tracking-display: 0.05em;

  /*
   * ...and the two HEADING steps, for text that is the biggest thing on its screen.
   *
   * Same rule as the label step: each sits in a line box the scale already has — 25 and 31,
   * which are `--lh-title` and `--lh-screen` — so a heading that takes the display face changes
   * face and nothing else. An app bar does not get taller.
   *
   * SIZED BY EYE, NOT BY MATCHING THE OLD NUMBER. Two points over the interface size, not the
   * seventeen percent the label step needed, because a heading gets its presence back from two
   * things the small labels do not have: every letter is at cap height once the face is
   * all-capital, where the sentence-case original spent most of its letters at x-height, and at
   * this size the condensing reads as character rather than as thinness. Pushed further this
   * stops being a title and becomes a banner — "Roots Playbook" should feel as prominent as it
   * did, in a better face, not louder.
   *
   * Tracking keeps falling as size rises, which is the ordinary optical rule: 0.05 → 0.02 → 0.01.
   */
  --fs-display-md: 22px;  --lh-display-md: 25px;  --tracking-display-md: 0.02em;  /* app bar, empty-state heading */
  --fs-display-lg: 28px;  --lh-display-lg: 31px;  --tracking-display-lg: 0.01em;  /* the one big thing on a screen */

  --fw-regular: 400;
  --fw-medium: 550;
  --fw-semibold: 650;
  --fw-bold: 750;

  /* ---- Spacing (4px grid) ----------------------------------------------------------- */
  --space-0: 0px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;

  /* Screen gutter. Widens once there is room for it rather than at every breakpoint. */
  --gutter: 16px;

  /* ---- Shape ------------------------------------------------------------------------ */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 18px;
  --radius-xl: 24px;
  --radius-sheet: 22px;
  --radius-pill: 999px;

  --border-width: 1px;

  /* ---- Controls --------------------------------------------------------------------- */
  --control-h: 44px;      /* the default: also the minimum comfortable touch target */
  --control-h-sm: 34px;   /* dense rows inside a section that is already indented */
  --control-h-lg: 52px;   /* a screen's primary action */
  --tap-min: 44px;

  --icon-sm: 18px;
  --icon-md: 20px;
  --icon-lg: 24px;
  --icon-stroke: 1.75;

  /* ---- Motion ----------------------------------------------------------------------- */
  /* Short and purposeful. The longest thing in the interface is a sheet travelling the height
     of a phone; nothing decorative gets a duration at all. */
  --dur-instant: 90ms;
  --dur-fast: 140ms;
  --dur-base: 200ms;
  --dur-slow: 300ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-emphasized: cubic-bezier(0.3, 0, 0, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);

  /* ---- Safe areas ------------------------------------------------------------------- */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/*
 * DARK — the default, and the one a coach uses on a sideline at night.
 *
 * Surfaces step up as they come forward: the app background is the darkest thing on screen and
 * a sheet is the lightest, so depth reads without a border on every edge.
 */
:root,
:root[data-appearance="dark"] {
  color-scheme: dark;

  --bg: #0B0F17;
  --surface: #141A24;
  --surface-2: #1B2230;
  --surface-3: #232B3A;
  --surface-sunken: #070A11;
  --surface-hover: rgba(255, 255, 255, 0.06);
  --surface-press: rgba(255, 255, 255, 0.10);

  --hairline: rgba(255, 255, 255, 0.10);
  --hairline-strong: rgba(255, 255, 255, 0.18);

  --text: #F2F5F9;
  --text-2: #A3AFC2;
  --text-3: #7D8AA0;
  --text-on-accent: #FFFFFF;

  --accent: #4C8DFF;
  --accent-press: #3A7AEC;
  --accent-soft: rgba(76, 141, 255, 0.16);
  --accent-line: rgba(76, 141, 255, 0.45);

  --success: #3DD68C;
  --warning: #F5A524;
  --warning-soft: rgba(245, 165, 36, 0.18);
  --warning-line: rgba(245, 165, 36, 0.55);
  --danger: #FF6B81;
  --danger-soft: rgba(255, 107, 129, 0.16);
  --danger-line: rgba(255, 107, 129, 0.55);

  /* Side identity. Never the only signal — every offense/defense state also carries a label,
     a shape or an icon (see DESIGN_SYSTEM.md, "non-colour state"). */
  --offense: #4C8DFF;
  --defense: #FF6B81;
  --offense-soft: rgba(76, 141, 255, 0.16);
  --defense-soft: rgba(255, 107, 129, 0.16);

  --scrim: rgba(3, 6, 12, 0.6);
  /* Selective translucency: navigation and floating controls only, never a full-screen pane
     and never over the canvas. */
  --glass: rgba(20, 26, 36, 0.78);
  --glass-blur: 20px;

  --focus-ring: #7FB2FF;

  /* Controls that float over the football field. The field has its own theme, independent of
     the app's — a Coach Board whiteboard inside a dark app is a normal thing to want — so an
     overlay cannot borrow the turf's colour, and it cannot assume the app background is behind
     it either. It carries its own opaque surface, a hairline and a shadow, and is legible on
     every one of the five field themes. */
  --field-overlay: rgba(20, 26, 36, 0.94);

  --elev-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --elev-2: 0 6px 16px rgba(0, 0, 0, 0.42);
  --elev-3: 0 18px 44px rgba(0, 0, 0, 0.52);
}

/*
 * LIGHT — designed, not inverted.
 *
 * The background is a cool grey and cards are white, the way a grouped list reads on paper and
 * on both mobile platforms. Inverting the dark palette instead would have given white text
 * surfaces floating on a lighter background, which is the tell of a bolted-on light mode.
 */
:root[data-appearance="light"] {
  color-scheme: light;

  /*
   * FOUR LEVELS, EACH TELLABLE FROM THE OTHERS — the page, paper, a control, a well.
   *
   * `--surface-3` and `--surface-sunken` used to be #EBEFF5 and #E4E9F0, three percent apart
   * from each other and four from the page, which is how light mode became a field of slightly
   * different pale-grey rectangles that all read as the same non-colour. It mattered more once
   * the refinement pass took the cards away: a chip or a switch track that used to sit on white
   * now sits on the page itself, and at #EBEFF5 on #F1F4F8 it was invisible. Each step down is
   * now worth seeing, and there are no more of them than there were.
   */
  --bg: #F2F5F9;
  --surface: #FFFFFF;
  --surface-2: #FFFFFF;
  --surface-3: #E6EBF2;
  --surface-sunken: #DCE3EC;
  --surface-hover: rgba(16, 24, 40, 0.04);
  --surface-press: rgba(16, 24, 40, 0.08);

  --hairline: rgba(16, 24, 40, 0.10);
  --hairline-strong: rgba(16, 24, 40, 0.20);

  --text: #101828;
  --text-2: #475467;
  --text-3: #667085;
  --text-on-accent: #FFFFFF;

  --accent: #1D5BD6;
  --accent-press: #17489F;
  --accent-soft: rgba(29, 91, 214, 0.10);
  --accent-line: rgba(29, 91, 214, 0.35);

  --success: #067647;
  --warning: #B54708;
  --warning-soft: rgba(181, 71, 8, 0.12);
  --warning-line: rgba(181, 71, 8, 0.45);
  --danger: #B42318;
  --danger-soft: rgba(180, 35, 24, 0.10);
  --danger-line: rgba(180, 35, 24, 0.45);

  --offense: #1D5BD6;
  --defense: #B42318;
  --offense-soft: rgba(29, 91, 214, 0.10);
  --defense-soft: rgba(180, 35, 24, 0.10);

  --scrim: rgba(16, 24, 40, 0.32);
  --glass: rgba(255, 255, 255, 0.82);
  --glass-blur: 20px;

  --focus-ring: #1D5BD6;

  --field-overlay: rgba(255, 255, 255, 0.95);

  --elev-1: 0 1px 2px rgba(16, 24, 40, 0.06);
  --elev-2: 0 6px 16px rgba(16, 24, 40, 0.10);
  --elev-3: 0 18px 44px rgba(16, 24, 40, 0.16);
}

/*
 * Legacy aliases.
 *
 * The editor and component stylesheets were written against the old names and are being moved
 * over screen by screen. Mapping them here means the two systems describe the same colours
 * during the move instead of drifting apart — and when the last use goes, so does this block.
 */
:root {
  --panel: var(--surface);
  --panel-elevated: var(--surface-2);
  --panel-border: var(--hairline);
  --control: var(--surface-3);
  --control-active: var(--accent);
  --accent-2: var(--accent);
  --highlight: var(--warning);
  --radius: var(--radius-md);
  --gap: var(--space-3);
  --pad: var(--space-4);
  --shadow: var(--elev-3);
}

/* More room to breathe once there is room to breathe in. */
@media (min-width: 700px) {
  :root {
    --gutter: 24px;
  }
}

@media (min-width: 1200px) {
  :root {
    --gutter: 32px;
    --fs-screen: 30px;
    --lh-screen: 36px;
  }
}

/*
 * Reduced motion.
 *
 * Durations are collapsed at the token, so every transition and animation defined in terms of
 * them stops at once — including ones added later, which is the part a per-component override
 * keeps getting wrong. Football playback is driven by the canvas and its own clock, not by CSS,
 * so a coach who turns motion down still sees the play run.
 */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-instant: 0ms;
    --dur-fast: 0ms;
    --dur-base: 0ms;
    --dur-slow: 0ms;
  }
}
