/**
 * TubeSpanner design tokens: the single source of truth for colour, type,
 * spacing, radii and shadows across the estate (TS-5129, epic TS-5127).
 *
 * Values were signed off 2026-07-23; the workings, including every contrast
 * measurement, are in docs/styling-review-2026-07/decision-doc.md.
 *
 * Three rules that this file exists to enforce:
 *
 * 1. Every colour that carries text ships as a BG/FG PAIR. The old palette
 *    failed because white was the silent default label colour for any new
 *    background. Use the pair, never a background on its own.
 * 2. Two contrast thresholds are checked, not one: label-on-fill >= 4.5:1
 *    (WCAG 1.4.3) and fill-against-the-page >= 3:1 (1.4.11). Checking only
 *    the first is how buttons passed review and still vanished in practice.
 * 3. Names are dark-ready. Dark mode is a later phase of this epic, but a
 *    token named for its ROLE (--ts-btn-go-bg) survives a theme switch,
 *    whereas one named for its appearance (--ts-green) does not. Nothing
 *    downstream should hardcode a hex; then dark mode is a value swap here
 *    rather than another estate-wide repaint.
 *
 * Names deliberately match the browser extension's GlobalCSSVars.jsx so the
 * two codebases converge on one vocabulary.
 *
 * This file only DEFINES tokens. It intentionally changes nothing on screen:
 * the existing theme variables keep their own values until each surface is
 * migrated by its own ticket. That keeps this foundation risk-free to deploy.
 */

:root {
  /* ---------------------------------------------------------------------
   * Brand and button roles
   *
   * Roles, not colours: green = Go (the full-auto action), orange =
   * secondary, purple = everything else, red = danger.
   * ------------------------------------------------------------------ */

  /* Primary / brand. 9.63:1 with white, 8.42:1 against the page tint. */
  --ts-btn-primary-bg: #672c72;
  --ts-btn-primary-fg: #ffffff;
  --ts-btn-primary-hover-bg: #521f5a;

  /* Go: the full-auto action. A bright green cannot carry white on a light
     page, so light mode uses a deep green; the bright one is the dark-mode
     member of the pair (see the dark scaffold at the end of this file). */
  --ts-btn-go-bg: #178055;
  --ts-btn-go-fg: #ffffff;

  /* Secondary. Note this is NOT the brand orange: #f26419 carries white at
     only 3.18:1, which was a live AA failure until TS-5128. The brand orange
     survives below as an illustration accent, where nothing sits on top. */
  --ts-btn-secondary-bg: #c2410c;
  --ts-btn-secondary-fg: #ffffff;

  /* Danger fill, used for confirm dialogs and destructive text. Danger
     BUTTONS additionally carry the hazard tape treatment below, so that
     danger is distinguishable from secondary without relying on hue: red
     and orange are exactly the pair that colour-blind users lose. */
  --ts-btn-danger-bg: #c62828;
  --ts-btn-danger-fg: #ffffff;

  /* Hazard tape, for the leading edge of destructive buttons. */
  --ts-hazard-stripe-a: #f5c400;
  --ts-hazard-stripe-b: #1a1a1a;

  /* ---------------------------------------------------------------------
   * Score grades (TS-5170)
   *
   * Six bands matching getScoreGrade, which is the single source of the
   * boundaries. Solid fill with a white label, chosen 2026-07-28 over a
   * tinted chip: white labels and dark-text-on-tint impose the same
   * darkness floor, so neither option can be brighter, but a filled chip
   * gives the grade real presence where the judgement lives.
   *
   * These are for the LETTER GRADE ONLY. The word label ("Above Average")
   * sits beside the chip as muted text. Six saturated chips each carrying a
   * full phrase is exhausting in a list, and a red F chip is punishing
   * enough as a single letter.
   *
   * The palette they replace failed AA on all seven values, because label
   * text was drawn in the band colour on that same colour at 8% over white:
   * effectively coloured text on near-white. The worst two measured 1.51
   * and 1.60 and served the middle of the score distribution.
   *
   * Every value clears 4.5:1 with its white label and 3:1 against the page.
   * Note the Go token #178055 measures 4.45 on its own tint, marginally
   * under AA, which is why the A band does not simply reuse it.
   * ------------------------------------------------------------------ */
  --ts-score-a-plus-bg: #12703f;   /* white label 6.15, vs page 5.38 */
  --ts-score-a-bg: #1b7a3e;        /* 5.38 / 4.71 */
  --ts-score-b-bg: #4f7a12;        /* 5.09 / 4.45 */
  --ts-score-c-bg: #9a6207;        /* 5.09 / 4.45 */
  --ts-score-d-bg: #c2410c;        /* 5.18 / 4.53, the house secondary value */
  --ts-score-f-bg: #b42318;        /* 6.57 / 5.75, contrast-tested by the Kim panel work */
  --ts-score-fg: #ffffff;

  /* ---------------------------------------------------------------------
   * Outcome states
   *
   * For panels that report what happened rather than what something scored:
   * the dashboard channel health headline is the first, and it will not be
   * the last. Six states, one hue each, because they have to be told apart at
   * a glance and a shared hue is how a win and an emergency end up looking
   * the same.
   *
   * Every value is already in this file or on the tool row. The estate does
   * not need a second green, and a status palette invented in isolation is
   * how it would get one.
   *
   * Three rules these encode:
   *
   * 1. LOUDNESS RUNS OPPOSITE TO FREQUENCY. incomplete, steady and quick_win
   *    carry most of the traffic, so they are quiet. win, regression and
   *    urgent are rare and are allowed to be emphatic. A palette tuned on the
   *    rare states shouts at everyone every day.
   *
   * 2. INCOMPLETE IS NOT A FAILURE. Momentum cannot be scored for roughly
   *    three quarters of channels, so this is the state most people meet
   *    first. It takes the muted tone, never a warning one: absence of data
   *    is not bad news, and dressing it as bad news is the thing that makes a
   *    new account look broken.
   *
   * 3. COLOUR IS NEVER THE ONLY SIGNAL. win and urgent are the pair that must
   *    never be confused, and green against red is exactly the pair that
   *    fails for the most common colour blindness. They must also differ in
   *    wording, in motion, and in shape.
   *
   * Each state ships an accent (rails, icons, arrows), a tint to sit it on,
   * and the ink for text on that tint. Contrast verified at both thresholds:
   * ink on tint at least 4.5, accent against both the card and the page tint
   * at least 3. Measured values in the comments.
   * ------------------------------------------------------------------ */

  /* Something improved. The A-band green. 4.82 ink / 5.38 card / 4.71 page. */
  --ts-state-win-accent: #1b7a3e;
  --ts-state-win-tint: #edf4f0;
  --ts-state-win-ink: #1b7a3e;

  /* An outcome went backwards. The D-band orange, which is also the house
     secondary. Deliberately not the urgent red: a drop is news, not an
     emergency, and spending red here leaves nothing louder for the state
     that does need action. 4.62 / 5.18 / 4.53. */
  --ts-state-regression-accent: #c2410c;
  --ts-state-regression-tint: #faf0ec;
  --ts-state-regression-ink: #c2410c;

  /* An outcome is in trouble. The F-band red, the loudest thing here, and the
     only state that earns it. 5.75 / 6.57 / 5.75. */
  --ts-state-urgent-accent: #b42318;
  --ts-state-urgent-tint: #f9eded;
  --ts-state-urgent-ink: #b42318;

  /* Something cheap is worth fixing. Brand purple: an opportunity, not a
     result, so it takes the colour of an action rather than of a verdict.
     Green here would congratulate the user for work they have not done yet.
     8.42 / 9.63 / 8.42. */
  --ts-state-quick-win-accent: #672c72;
  --ts-state-quick-win-tint: #f3eef4;
  --ts-state-quick-win-ink: #672c72;

  /* Nothing new, here is the stretch goal. The Process-stage blue from the
     tool row: informational and calm, and distinct from the purple next to
     it so the two common states do not blur. 5.88 / 6.63 / 5.79. */
  --ts-state-steady-accent: #1f5f9b;
  --ts-state-steady-tint: #edf2f7;
  --ts-state-steady-ink: #1f5f9b;

  /* Main scores cannot be measured yet. The house muted tone. See rule 2
     above: this is the most-seen state, and it reports a gap in the data, not
     a problem with the channel. 4.84 / 5.36 / 4.69. */
  --ts-state-incomplete-accent: #6b6880;
  --ts-state-incomplete-tint: #f3f3f5;
  --ts-state-incomplete-ink: #6b6880;

  /* ---------------------------------------------------------------------
   * Text
   * ------------------------------------------------------------------ */

  /* Headings. 13.52:1 on white. */
  --ts-color-ink: #3e2155;

  /* Body-secondary. Replaces #858B98, which failed AA at body size (3.42:1
     on white, 2.99:1 on the page tint). This one is 5.36:1 / 4.69:1. */
  --ts-color-muted: #6b6880;

  /* Eyebrow labels. Both lavenders previously in use failed at 11px
     (#A098C9 at 2.68:1, #9a8fc0 at 2.97:1). This one is 5.43:1 / 4.74:1. */
  --ts-color-eyebrow: #6d648f;

  /* ---------------------------------------------------------------------
   * Surfaces
   *
   * Two tint steps only. Three near-identical lavenders were in service
   * before this file; the component tint is one step deeper than the page
   * tint so that pills and chips read as raised against the page.
   * ------------------------------------------------------------------ */
  --ts-tint-page: #f2eef8;
  --ts-tint-component: #efedf7;
  --ts-surface-card: #ffffff;

  /* Two different jobs, two different values, and conflating them is how a
   * control ends up with a boundary nobody can see.
   *
   * --ts-border-quiet is a DIVIDER. It separates by position, so it is
   * allowed to be faint: it measures 1.21:1 over white, and that is correct
   * for a hairline between stacked rows.
   *
   * --ts-border-control is the edge of a CONTROL: a pale button, a filter
   * chip, a form field. WCAG 2.1 asks 3:1 of any non-text boundary, and this
   * measures 3.04:1 over white, the darkest a border can be while still
   * reading as quiet rather than as an outlined button.
   *
   * Reaching for the divider value on a control is the single most repeated
   * defect in this codebase: it turned up in a role class the theme never
   * defined, an inline JSX style, a border set to its own fill, two shared
   * form-field rules, and a module shipping its own pale literal. Use this
   * token rather than a new literal. */
  --ts-border-quiet: rgba(62, 33, 85, 0.10);
  --ts-border-control: #6f6786;
  --ts-shadow-card: 0 1px 3px rgba(62, 33, 85, 0.08);

  /* ---------------------------------------------------------------------
   * Illustrations
   *
   * Deliberately independent of the brand purple. The duotone line art is
   * already one consistent system across the CMS and the extension, so
   * these two values let artwork be retinted centrally without redrawing
   * SVGs, and without being dragged along by a brand-colour change.
   * Decorative only, so no contrast requirement applies.
   * ------------------------------------------------------------------ */
  --ts-ill-primary: #4a30b5;
  --ts-ill-accent: #f5821f;

  /* ---------------------------------------------------------------------
   * Type
   *
   * Satoshi is the UI and body face. Satoshi 900 is the display face for
   * page and card headlines. Comedik is the decorative accent face: it is
   * for celebratory and hero moments only, never UI labels or body text.
   * ------------------------------------------------------------------ */
  --ts-font-body: 'Satoshi', system-ui, -apple-system, sans-serif;
  --ts-font-display: 'Satoshi', system-ui, -apple-system, sans-serif;
  --ts-font-display-weight: 900;
  --ts-font-decorative: 'Comedik', 'Satoshi', cursive;

  --ts-text-display: 2.5rem;
  --ts-text-h1: 2rem;
  --ts-text-h2: 1.5rem;
  --ts-text-h3: 1.25rem;
  --ts-text-body: 1rem;
  --ts-text-small: 0.875rem;
  --ts-text-caption: 0.75rem;

  /* Eyebrows are small, heavy and letter-spaced; the tracking is what makes
     uppercase text at this size legible rather than a smear. */
  --ts-text-eyebrow: 0.6875rem;
  --ts-eyebrow-weight: 700;
  --ts-eyebrow-tracking: 0.08em;

  /* ---------------------------------------------------------------------
   * Spacing: a 4px scale. Section rhythm and card padding pick steps from
   * here rather than each page choosing its own value, which is how the
   * estate ended up with card padding ranging from 0 to 30px.
   * ------------------------------------------------------------------ */
  --ts-space-1: 4px;
  --ts-space-2: 8px;
  --ts-space-3: 12px;
  --ts-space-4: 16px;
  --ts-space-5: 24px;
  --ts-space-6: 32px;
  --ts-space-7: 48px;
  --ts-space-8: 64px;
  --ts-space-9: 96px;

  /* ---------------------------------------------------------------------
   * Radii. 12px is the house card; the pill is fully rounded so that chips,
   * score pills and badges cannot drift to three different radii again.
   * ------------------------------------------------------------------ */
  --ts-radius-card: 12px;
  --ts-radius-control: 10px;
  --ts-radius-input: 8px;
  --ts-radius-pill: 999px;
}

/*
 * Dark mode scaffold.
 *
 * Deliberately inert: the selector is commented out because dark mode is a
 * later phase, and the values below still need verifying against a real
 * dark page background before anything ships. They are recorded here so the
 * pairing work already done is not lost, and so it is obvious that every
 * role above has a dark counterpart waiting.
 *
 * :root[data-theme="dark"] {
 *   --ts-btn-primary-bg: #c983d1;
 *   --ts-btn-primary-fg: #220e25;
 *   --ts-btn-go-bg: #2bc485;
 *   --ts-btn-go-fg: #0a2a1d;
 *   --ts-btn-secondary-bg: #f26419;
 *   --ts-btn-secondary-fg: #2a0f04;
 *   --ts-btn-danger-bg: #ef5350;
 *   --ts-btn-danger-fg: #2d0606;
 * }
 */
