/* =========================================================================
   tokens.css — the one place every Rungs surface gets its values from.

   Three layers, borrowed from Material 3's token ARCHITECTURE and only that.
   M3's palette, its components and its tonal-elevation model are deliberately
   not adopted — see DESIGN.md §1 for why the identity stays ours.

     ref     raw values. The ONLY place in this repo a hex literal may appear.
             A skin overrides this block and nothing else.
     sys     semantic roles: what a value MEANS. Components use these, always.
     scale   radius / type / spacing steps, so "a bit rounder" stops being a
             free parameter every component answers on its own.

   Why this exists: the palette was copy-pasted into SEVEN :root blocks —
   climb.css, admin.css, and page-local <style> in auth.html, invite.html,
   landing.html, profile.html and site_home.html — carrying 23 / 21 / 15 / 15 /
   15 / 15 / 15 tokens respectively. Every shared name still agreed on its
   value, but coverage had drifted badly, and site_home.html had started writing
   `var(--divider,#16191f)` — inlining the value it was missing rather than
   fixing where it came from. That is where that road ends.

   static/bracket.css was already written against tokens only, with no :root and
   no hex of its own. It is the model this file generalises, and it needed no
   change at all.
   ========================================================================= */

/* -------------------------------------------------------------------------
   LAYER 1 — ref: raw values

   Named for what they ARE, never for what they are used for. Tone numbers are
   approximate lightness on a 0-100 scale, so a skin can keep every name while
   moving every value.
   ------------------------------------------------------------------------- */
:root {
  /* Neutral ramp, darkest first. Charcoal rather than the old near-black: the
     ramp starts at #0E0E10 and the card sits a full step above the page, which
     is what stops a dark UI reading as a void. */
  --ref-neutral-00: #0E0E10;
  --ref-neutral-05: #18181B;
  --ref-neutral-08: #1e1e22;
  --ref-neutral-12: #222227;
  --ref-neutral-16: #2A2A2F;
  --ref-neutral-20: #33333A;
  --ref-neutral-24: #3a3a40;
  --ref-neutral-30: #4b4b52;
  --ref-neutral-38: #5F5F68;
  --ref-neutral-46: #71717A;
  --ref-neutral-48: #7A7A83;
  --ref-neutral-56: #8B8B94;
  --ref-neutral-78: #C4C4CC;
  --ref-neutral-100: #ffffff;

  /* brand hues */
  --ref-green:     #4DFF6E;   /* the accent */
  --ref-green-ink: #0B160D;   /* the only readable text on it */
  --ref-red:       #ff5a4d;
  --ref-amber:     #ffb84d;

  /* podium */
  --ref-gold:   #E8B923;
  --ref-silver: #AEB4BE;
  --ref-bronze: #C67C48;

  /* Type families. The fallbacks matter and were not consistent: five of the
     seven old copies fell back to generic sans / monospace rather than to
     Archivo and ui-monospace, which renders differently whenever the webfont is
     slow, blocked or absent. One definition, the better fallback. */
  --ref-family-sans: 'Archivo', system-ui, sans-serif;
  --ref-family-cond: 'Saira Condensed', 'Archivo', sans-serif;
  --ref-family-mono: 'JetBrains Mono', ui-monospace, monospace;
}

/* -------------------------------------------------------------------------
   LAYER 2 — sys: semantic roles

   These keep the names the app already uses. Renaming them to M3's
   primary/secondary/tertiary was considered and rejected: this product's roles
   are win / loss / challenge / caution, M3 offers no `success` or `warning`, and
   a LOSS here is neutral grey while an ERROR is red — so a single M3 role would
   have had to mean both `error` and `on-surface-variant`. M3's own answer to
   that is extended colors, which is the shape used below: every domain hue gets
   the same four slots, every time.

   `--surface-2` keeps its name rather than becoming `--surface-low`, because the
   relationship is not stable across palettes: it is LIGHTER than --surface here
   and was DARKER under the old one. It means "inset / chip surface", which is
   true either way.
   ------------------------------------------------------------------------- */
:root {
  /* --- surfaces --- */
  --screen:    var(--ref-neutral-00);   /* the page itself */
  --surface:   var(--ref-neutral-05);   /* cards, panels */
  --surface-2: var(--ref-neutral-12);   /* insets, wells, chips */
  --tile:      var(--ref-neutral-05);   /* stat tiles — same as surface */

  /* --- outlines and dividers --- */
  --border:    var(--ref-neutral-16);   /* default hairline */
  --border-2:  var(--ref-neutral-20);   /* stronger / hover */
  --divider:   var(--ref-neutral-08);   /* row separators */
  --divider-2: var(--ref-neutral-12);   /* slightly stronger separator */

  /* --- text ramp, high to dim.
     All seven steps are kept. M3 offers roughly four neutral foreground roles;
     the extra resolution is used to rank three or four kinds of information
     inside one dense data row, and collapsing it would flatten those rows. --- */
  --t-hi:      var(--ref-neutral-100);
  --t-body:    var(--ref-neutral-78);
  --t-muted:   var(--ref-neutral-56);
  --t-muted-2: var(--ref-neutral-46);
  --t-dim:     var(--ref-neutral-38);
  --t-dim-2:   var(--ref-neutral-30);
  --t-dim-3:   var(--ref-neutral-24);

  /* --- domain hues, each an M3-style extended colour with four slots:
           --X            the colour itself
           --on-X         text/icon that sits ON it (a contrast promise)
           --X-wash       subtle tint for a whole row or card
           --X-container  stronger tint for a pill, badge or chip
           --X-line       border on anything tinted

     Three steps replace 40 improvised percentages across 85 call sites. The old
     values already clustered into exactly these three intents — 6-12% row
     washes, 14-22% chip fills, 26-55% borders — so this is a snap onto the
     nearest step rather than a new look. Within "border" the 26-to-55 spread was
     carrying no meaning at all; a tinted border is now one value.

     All three mix with `transparent` rather than with a surface, deliberately.
     `color-mix(C 10%, transparent)` composited over B resolves to
     0.1*C + 0.9*B — arithmetically identical to `color-mix(C 10%, B)` — so the
     transparent form is the same colour on a card AND correct on anything else,
     where the baked-in form would be subtly wrong. --- */

  /* win / positive / active — use sparingly, scarcity is the whole effect */
  --acc:           var(--ref-green);
  /* REQUIRED on any accent background (DESIGN.md). White on neon green is
     unreadable — this is the one contrast promise the system cannot bend. */
  --on-acc:        var(--ref-green-ink);
  --acc-wash:      color-mix(in srgb, var(--acc) 10%, transparent);
  --acc-container: color-mix(in srgb, var(--acc) 14%, transparent);
  --acc-line:      color-mix(in srgb, var(--acc) 40%, transparent);

  /* A LOST MATCH, a dropped rank, a downward trend. An outcome, not a fault, and
     therefore NEUTRAL GREY rather than red: losses are not punished. This is a
     product decision, not a palette detail — it is why --danger below had to be
     split out, so an invalid form stays red while a defeat does not. */
  --neg:           var(--ref-neutral-48);
  --on-neg:        var(--screen);   /* dark ink beats white on mid-grey */
  --neg-wash:      color-mix(in srgb, var(--neg) 10%, transparent);
  --neg-container: color-mix(in srgb, var(--neg) 14%, transparent);
  --neg-line:      color-mix(in srgb, var(--neg) 40%, transparent);

  /* SOMETHING IS WRONG, or is about to be destroyed: a validation error, a
     failed action, an overdue match, a delete control, bad ladder health. Stays
     red under every palette, because "your form is invalid" cannot be styled as
     encouragement. */
  --danger:        var(--ref-red);
  --on-danger:     var(--screen);
  --danger-wash:   color-mix(in srgb, var(--danger) 10%, transparent);
  --danger-container: color-mix(in srgb, var(--danger) 14%, transparent);
  --danger-line:   color-mix(in srgb, var(--danger) 40%, transparent);

  /* caution / lock / pending */
  --amb:           var(--ref-amber);
  --on-amb:        var(--screen);
  --amb-wash:      color-mix(in srgb, var(--amb) 10%, transparent);
  --amb-container: color-mix(in srgb, var(--amb) 14%, transparent);
  --amb-line:      color-mix(in srgb, var(--amb) 40%, transparent);

  /* Challenge. Unified with the accent rather than kept as a separate blue: one
     electric colour per screen is the whole premise, and a challenge IS the
     positive action. */
  --chal:           var(--ref-green);
  --on-chal:        var(--ref-green-ink);
  --chal-wash:      color-mix(in srgb, var(--chal) 10%, transparent);
  --chal-container: color-mix(in srgb, var(--chal) 14%, transparent);
  --chal-line:      color-mix(in srgb, var(--chal) 40%, transparent);

  /* The badge with no semantic colour at all — "archived", "n/a". Neutral so it
     reads as absence of state rather than as a state. */
  --neutral-container: color-mix(in srgb, var(--t-dim) 22%, transparent);

  /* Podium. Only the top three ranks, and only on a leaderboard. */
  --gold:   var(--ref-gold);
  --silver: var(--ref-silver);
  --bronze: var(--ref-bronze);

  /* --- type families --- */
  --sans: var(--ref-family-sans);
  --cond: var(--ref-family-cond);
  --mono: var(--ref-family-mono);
}

/* -------------------------------------------------------------------------
   LAYER 3 — scales

   Declared here, applied progressively. Before this file the app used 12
   distinct border-radius values and 16+ distinct font sizes, including
   half-pixel steps (9.5 / 10.5 / 11.5 / 12.5 / 13.5px), while DESIGN.md
   described three radius bands. A component should pick a step, not a number.
   ------------------------------------------------------------------------- */
:root {
  /* Radius: 12 observed values collapse onto 5. Three of the five steps are the
     exact existing mode for their band (6px pills, 9px buttons, 12px rows,
     16px cards), so nothing moves more than 2px except the three stray 20px
     corners, which come down to 16. */
  --r-xs:   6px;    /* pills, badges, small chips  (was 4/5/6/7) */
  --r-s:    9px;    /* buttons, inputs            (was 8/9/10) */
  --r-m:   12px;    /* rows, tiles                (was 11/12/14) */
  --r-l:   16px;    /* cards, panels              (was 15/16/20) */
  --r-xl:  24px;    /* bottom sheet / modal — deliberately larger than a card */
  --r-full: 999px;  /* fully round */

  /* Type scale. Declared here, applied by the stylesheet rewrites rather than
     by a mechanical sweep: there are 16+ sizes today including half-pixel steps,
     and snapping a font size changes how text wraps. Each one gets chosen when
     its sheet is rewritten, not guessed at in bulk. */
  --fs-micro:    9px;   /* mono eyebrows, tiny tags */
  --fs-label:   11px;   /* labels, meta */
  --fs-body:    13px;   /* body copy, row text */
  --fs-lead:    15px;   /* emphasised row text */
  --fs-title:   18px;   /* panel and block titles */
  --fs-display: 30px;   /* page titles, big stats */
  --fs-hero:    60px;   /* the one number per screen */

  /* spacing, 4px step */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 22px;
  --sp-6: 28px;

  /* layout */
  --maxw: 600px;   /* app column; widened at >=880px by climb.css */
}
