/* ============================================================
   Trail Conditions — Design tokens
   The ONLY file in the project where a colour is written as a value (§7.53),
   enforced by scripts/check-palette.cjs. Every page loads it first, admin
   included. JavaScript never holds a hex: it refers to a colour by name, e.g.
   statusSolid(key) in js/common.js returns var(--st-<key>).

   ── Two themes (§7.55, v1.72.0) ──────────────────────────────
   Three viewer states, not two:
     - no choice made  → follow the OS, via prefers-color-scheme
     - chose light     → html[data-theme="light"], beats a dark OS
     - chose dark      → html[data-theme="dark"], beats a light OS
   The media query is therefore guarded with :not([data-theme="light"]), and the
   explicit dark block repeats the same values. That duplication is unavoidable in
   plain CSS — a media query can't share a rule body with a bare selector — so
   check-palette.cjs asserts the two dark blocks stay identical.

   ── Why the palette swap is enough ───────────────────────────
   A status needs four roles: the chip's tint, the chip's ink, the solid fill
   (pill, stripe, map pin) and the ink on that fill. Light mode gets away with two
   values because its solid works as both chip ink and pill fill. Dark can't: the
   tint's polarity flips, so ink has to be bright while a fill needs dark text.

   It still costs only three extra tokens, because in dark mode ink, fill and
   strong are all the same bright colour — so redefining --green etc. covers
   .s-*'s --s-color/--s-bg/--s-strong AND --st-* at once. What doesn't fall out
   is amber, which already needed the split in light mode (yellow can't carry
   white text): --caution-ink and --on-fill-caution exist for it, and --on-fill
   is the ink every other solid fill carries.

   Every dark pairing below was measured before it was written; the ratios are in
   the comments. Nothing here was chosen by eye.
   ============================================================ */

:root {
  color-scheme: light;

  --forest:      #1a3d2b;
  /* --green and --orange were #2d8c4e and #c06020 until v1.60.1. Both failed
     WCAG AA in the two contexts the status pills use them in: as text on their
     own light tint (3.72:1 and 3.81:1) and as the hero pill's fill behind white
     text (4.22:1 and 4.26:1). Darkened to clear 4.5:1 on both axes — now
     4.80/5.45 and 4.87/5.45. Any future adjustment has to stay above 4.5:1 on
     BOTH: the same token is the ink in one place and the ground in the other.
     (Admin kept its own :root with the old values until v1.65.0, and
     qr/index.html until v1.71.1 — the drift this file exists to prevent.) */
  --green:       #277843;
  --green-lt:    #e6f4ec;
  --amber:       #eab308;   /* was #d4850a — shifted from orange-amber to true yellow so caution reads distinct from wet */
  --amber-lt:    #fef9c3;   /* was #fff8e6 — paler yellow tint to match */
  --amber-ink:   #4a3a00;   /* dark ink for text on yellow — contrast ~9:1 (WCAG AAA); yellow needs dark text */
  --orange:      #a5531c;   /* see the --green note above */
  --orange-lt:   #fdf0e6;
  --red:         #c0392b;
  --red-lt:      #fdf0f0;
  --blue:        #1a6b9a;
  --blue-lt:     #e8f4fb;
  --thaw:        #526e88;   /* spring-thaw ice-slate (docs/freeze-thaw.md) */
  --thaw-lt:     #e8eef4;
  --dirt:        #f5f0e8;
  --override-bg: #1a3d2b;
  --text:        #1a1a1a;
  --muted:       #5a5a5a;
  --border:      rgba(0,0,0,0.10);

  /* ── Surfaces ────────────────────────────────────────────────
     --surface was 32 separate `#fff` literals before v1.72.0. The scale runs
     from the page up: page → card → sub-block → inert well. */
  --surface:     #fff;      /* cards, rows, panels */
  --surface-2:   #faf9f7;   /* the hero's drainage-model sub-block */
  --surface-3:   #f0f0ee;   /* inert fills: report-about, drain-avg, hairlines */
  --track:       #e8e8e8;   /* bar tracks and empty bar wells */

  /* ── Ink scale ───────────────────────────────────────────────
     --ink-strong replaces #222 and #333 (ΔE < 1 apart, both "near-black body
     text"); --ink-soft replaces #444, #555 and #40453f, which were three ways of
     writing the same secondary grey. Consolidating them shifts four elements by
     an imperceptible amount and removes four accidental variants. */
  --ink-strong:  #222;
  --ink-soft:    #555;
  --on-fill:         #fff;             /* text on any solid status fill */
  --on-forest:       #fff;             /* text on --forest, which inverts in dark */
  --on-fill-caution: var(--amber-ink); /* except yellow, which needs dark ink */
  --caution-ink:     var(--amber-ink); /* the caution chip's text on its own tint */

  /* Favourite stars. #b8860b (the picker badge) and #e5a800 (the row star) were
     two golds; one token now. */
  --star:        #bbb;
  --star-fav:    #e5a800;
  --loading:     #ccc;   /* placeholder dot while a row's data is in flight */

  /* ── Branded bands (/about, /contact nav, page hero, footer) ──
     These stay DARK GREEN in both themes. They are the one place the site wears
     its identity as a surface rather than as ink, so inverting them to bright
     green — which is what var(--forest) now resolves to in dark mode — would turn
     a calm header into a glowing block. Because the surface keeps its polarity,
     all three of its inks are the same value in both themes.
     Measured on #1a3d2b: ink 12.03 · soft 6.34 · dim 6.77.
     Measured on #16281d: ink 15.49 · soft 8.16 · dim 8.72, band 1.14 vs page. */
  --brand-surface:   #1a3d2b;
  --on-brand:        #fff;
  --on-brand-soft:   #8fc9a5;
  --on-brand-dim:    #adc9b7;

  --bar-forecast:    #b8d8ec;   /* the hourly forecast bar on /about's example */
  --skeleton-a:      #e8e2d5;   /* loading shimmer, the two gradient stops */
  --skeleton-b:      #f0ebe0;
  --notice-border:   #e8c56a;   /* override notice, on --amber-lt */
  --notice-ink:      #7a5a00;
  --field-bg:        #fafafa;   /* form inputs */

  /* Admin chrome (admin/index.html keeps its CSS inline) */
  --disabled-bg:     #d8d8d8;
  --disabled-ink:    #999;
  --shadow-sm:       rgba(0,0,0,0.10);
  --wash:            rgba(0,0,0,0.06);   /* pressed / subtle fills */
  --border-strong:   rgba(0,0,0,0.15);

  /* ── Closed rows (§7.46 R2) ──────────────────────────────────
     Deliberately explicit colours rather than `opacity`, so the CLOSED badge
     keeps full contrast while the rest of the row recedes. */
  --closed-surface:  #faf9f7;
  --closed-stripe:   #c9c7c3;
  --closed-name:     #7d7a75;
  --closed-dist:     #9a9792;
  --closed-note:     #8a8782;
  --closed-star:     #cfcdc9;
  --closed-star-fav: #d9c48a;

  /* ── Component tints ─────────────────────────────────────────
     Deep inks that sit on a status tint, plus the pressed states. The four dark
     greens #1a5c30 / #1a5c34 / #1a6b30 / #1e5c38 were within ΔE ≈ 2 of each
     other and are now one token. */
  --green-ink-deep:  #1a5c30;
  --green-press:     #d9ecdf;   /* pivot row / directions :active */
  --green-deep-bg:   #14311f;
  --orange-tint:     #fff3e0;
  --orange-ink-deep: #8a4a00;   /* merged with #b06000, one step lighter */
  --amber-press:     #fdf3a8;
  --blue-ink-deep:   #0f4060;
  /* Rain that DEFINITELY fell, in the 7-Day History bars. It has to be the
     darkest blue in the scale in both themes: the reading is "100% certain",
     and the whole point of the ramp is that more certain = darker. Until
     v1.72.1 those bars used --blue, which dark mode makes BRIGHT because the
     same token is the rain chip's ink — so past rain rendered as the palest
     thing on the widget, exactly backwards. Own token now.
     --rain-bar is today's part-observed-part-forecast bar, one step lighter,
     and keeps its dashed border to say "not settled yet". */
  --rain-fell:       #1a6b9a;   /* = the old --blue value: no light-mode change */
  --rain-bar:        #6fa4c8;
  --alert-tint:      #fef5f5;
  --temp-cold:       #74b0e8;   /* the temp-range gradient reads the same either theme */
  --temp-warm:       #f5a742;

  /* Freeze-thaw strips (docs/freeze-thaw.md) */
  --frost-ink:        #2c4a63;
  --frost-frozen-bg:  #eaf3fb;
  --frost-frozen-ink: #1a4a6b;
  --frost-thaw-bg:    #dde7f0;
  --frost-thaw-ink:   #23384a;

  /* ── Status → solid colour ──────────────────────────────────
     One line per status key the API or an override can produce. Solid fills:
     the hero pill, map pins, dashboard dots, picker pills. JS reads these as
     var(--st-<key>) via statusSolid(); an unknown key falls back to grey in the
     var() itself. Keys are case-sensitive, hence --st-rideNow.

     Since §7.46 (v1.69.0) statusSolid() is only ever called with a GROUND key
     (open / caution / wet) or an override key, because the pill answers one
     question. --st-thaw, --st-rain and --st-rideNow stay because the row glyph
     and the answer line still reference that family. */
  --st-open:          var(--green);
  --st-caution:       var(--amber);
  --st-wet:           var(--orange);
  --st-thaw:          var(--thaw);
  --st-rain:          var(--blue);
  --st-rideNow:       var(--blue);   /* rain-family blue; the "come rain later" reason drives the colour */
  --st-issue:         var(--orange);
  --st-closed:        var(--red);
  --st-winter-open:   var(--blue);
  --st-winter-closed: var(--red);

  /* ── AQI strip fills ──────────────────────────────────────
     js/common.js aqiCategory() names these; the strip paints one behind its own
     text, so each has to clear 4.5:1 against the ink it carries. It returns that
     ink alongside the fill, because Moderate is yellow and yellow cannot carry
     white text — the same split the caution pill makes (--amber / --amber-ink).

     These six were hard-coded in aqiCategory() until v1.71.1, and three of them
     were the pre-v1.60.1 green, amber and orange that §7.53 replaced everywhere
     else: 4.22:1, 2.93:1 and 4.26:1 behind white. §7.53 fixed admin's stale
     :root and missed this function, which is the same drift one layer over.
     Only Sensitive was reachable (the strip gates at AQI >= 101); Good and
     Moderate were latent.

     Measured behind #fff: good 5.45 · sensitive 5.45 · unhealthy 5.44 ·
     very 9.56 · hazardous 10.99. Moderate is 1.92 behind white, so it takes
     --amber-ink instead, at 10.3. */
  --aqi-good:      var(--green);
  --aqi-moderate:  var(--amber);
  --aqi-sensitive: var(--orange);
  --aqi-unhealthy: var(--red);
  --aqi-very:      #7b0f7b;
  --aqi-hazardous: #7e0023;
}

/* ── DARK VALUES ─────────────────────────────────────────────
   Kept in one list, applied twice: once behind prefers-color-scheme for viewers
   who have made no choice, once behind [data-theme="dark"] for viewers who have.
   The two bodies MUST stay identical — check-palette.cjs asserts it.

   Measured (all against #24221e unless noted):
     text 13.32  muted 6.35  forest 8.37
     chip ink on its own tint: open 6.67  caution 9.32  wet 6.40  closed 6.05
                               rain 7.11  thaw 7.45
     --on-fill #17150f on each bright fill: 9.22 / 12.25 / 8.09 / 7.51 / 9.55 / 9.88
     stripe & pin vs card: 8.02 / 10.66 / 7.04 / 6.53 / 8.31 / 8.60  (need 3.0)
     chip tint vs card: 1.08–1.20, matching light mode's own 1.07–1.14 — the
       tint reads as a chip, the ink carries legibility.
   The ground is warm-biased because the light ground is warm cream, not because
   a neutral charcoal would fail. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --forest:      #8fc9a5;
    --green:       #6fcb8d;
    --green-lt:    #1d3527;
    --amber:       #f2d24b;
    --amber-lt:    #342c0e;
    --amber-ink:   #f2d24b;
    --orange:      #eb9a5c;
    --orange-lt:   #37261b;
    --red:         #f08a7e;
    --red-lt:      #3a221e;
    --blue:        #79c5ea;
    --blue-lt:     #1c3040;
    --thaw:        #a8c2d8;
    --thaw-lt:     #252e38;
    --dirt:        #1a1816;
    --override-bg: #1d3527;
    --text:        #ecebe8;
    --muted:       #a9a39b;
    --border:      rgba(255,255,255,0.12);

    --surface:     #24221e;
    --surface-2:   #2c2925;
    --surface-3:   #322e29;
    --track:       #3a3631;

    --ink-strong:  #ecebe8;
    --ink-soft:    #b3aea6;
    --on-fill:         #17150f;
    --on-forest:       #17150f;
    --on-fill-caution: #17150f;
    --caution-ink:     var(--amber);

    --star:        #6b665f;
    --star-fav:    #e5c158;
    --loading:     #4a463f;

    --brand-surface:   #16281d;
    --on-brand:        #fff;
    --on-brand-soft:   #8fc9a5;
    --on-brand-dim:    #adc9b7;

    --bar-forecast:    #44779a;   /* 3.29:1 on the card */
    --skeleton-a:      #2a2724;
    --skeleton-b:      #34302b;
    --notice-border:   #6b5a1e;
    --notice-ink:      #f2d24b;   /* 9.32:1 on the dark amber tint */
    --field-bg:        #2c2925;

    --disabled-bg:     #35312c;
    --disabled-ink:    #7a746c;
    --shadow-sm:       rgba(0,0,0,0.45);
    --wash:            rgba(255,255,255,0.06);
    --border-strong:   rgba(255,255,255,0.18);

    --closed-surface:  #201e1b;
    --closed-stripe:   #4a463f;
    --closed-name:     #8a857d;
    --closed-dist:     #6b665f;
    --closed-note:     #8a857d;
    --closed-star:     #4a463f;
    --closed-star-fav: #7a6f52;

    --green-ink-deep:  #8fd8a8;
    --green-press:     #1f3b2a;
    --green-deep-bg:   #1d3527;
    --orange-tint:     #37261b;
    --orange-ink-deep: #eb9a5c;
    --amber-press:     #3d3410;
    --blue-ink-deep:   #79c5ea;
    --rain-fell:       #155a86;   /* 2.15:1 on the card; the track + outline carry it */
    --rain-bar:        #2f7ba8;   /* 3.42:1 — today, still partly forecast */
    --alert-tint:      #3a221e;

    --frost-ink:        #a8c2d8;
    --frost-frozen-bg:  #1c3040;
    --frost-frozen-ink: #79c5ea;
    --frost-thaw-bg:    #252e38;
    --frost-thaw-ink:   #a8c2d8;

    --aqi-very:      #d89ae0;
    --aqi-hazardous: #f2a09a;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --forest:      #8fc9a5;
  --green:       #6fcb8d;
  --green-lt:    #1d3527;
  --amber:       #f2d24b;
  --amber-lt:    #342c0e;
  --amber-ink:   #f2d24b;
  --orange:      #eb9a5c;
  --orange-lt:   #37261b;
  --red:         #f08a7e;
  --red-lt:      #3a221e;
  --blue:        #79c5ea;
  --blue-lt:     #1c3040;
  --thaw:        #a8c2d8;
  --thaw-lt:     #252e38;
  --dirt:        #1a1816;
  --override-bg: #1d3527;
  --text:        #ecebe8;
  --muted:       #a9a39b;
  --border:      rgba(255,255,255,0.12);

  --surface:     #24221e;
  --surface-2:   #2c2925;
  --surface-3:   #322e29;
  --track:       #3a3631;

  --ink-strong:  #ecebe8;
  --ink-soft:    #b3aea6;
  --on-fill:         #17150f;
  --on-forest:       #17150f;
  --on-fill-caution: #17150f;
  --caution-ink:     var(--amber);

  --star:        #6b665f;
  --star-fav:    #e5c158;
  --loading:     #4a463f;

  --brand-surface:   #16281d;
  --on-brand:        #fff;
  --on-brand-soft:   #8fc9a5;
  --on-brand-dim:    #adc9b7;

  --bar-forecast:    #44779a;   /* 3.29:1 on the card */
  --skeleton-a:      #2a2724;
  --skeleton-b:      #34302b;
  --notice-border:   #6b5a1e;
  --notice-ink:      #f2d24b;   /* 9.32:1 on the dark amber tint */
  --field-bg:        #2c2925;

  --disabled-bg:     #35312c;
  --disabled-ink:    #7a746c;
  --shadow-sm:       rgba(0,0,0,0.45);
  --wash:            rgba(255,255,255,0.06);
  --border-strong:   rgba(255,255,255,0.18);

  --closed-surface:  #201e1b;
  --closed-stripe:   #4a463f;
  --closed-name:     #8a857d;
  --closed-dist:     #6b665f;
  --closed-note:     #8a857d;
  --closed-star:     #4a463f;
  --closed-star-fav: #7a6f52;

  --green-ink-deep:  #8fd8a8;
  --green-press:     #1f3b2a;
  --green-deep-bg:   #1d3527;
  --orange-tint:     #37261b;
  --orange-ink-deep: #eb9a5c;
  --amber-press:     #3d3410;
  --blue-ink-deep:   #79c5ea;
  --rain-fell:       #155a86;   /* 2.15:1 on the card; the track + outline carry it */
  --rain-bar:        #2f7ba8;   /* 3.42:1 — today, still partly forecast */
  --alert-tint:      #3a221e;

  --frost-ink:        #a8c2d8;
  --frost-frozen-bg:  #1c3040;
  --frost-frozen-ink: #79c5ea;
  --frost-thaw-bg:    #252e38;
  --frost-thaw-ink:   #a8c2d8;

  --aqi-very:      #d89ae0;
  --aqi-hazardous: #f2a09a;
}

/* ── Status custom properties (consumed by rows, pills, labels) ──
   --s-color: the chip's text on --s-bg
   --s-bg: the chip's tint
   --s-strong: vivid solid for dots, stripes, chip fills
   These bodies are theme-agnostic: every value they read is redefined above, and
   in dark mode ink, fill and strong all resolve to the same bright colour. Only
   caution needs a role token (--caution-ink), because yellow's ink is dark in
   light mode and bright in dark.

   A status gets .s-<key> directly — statusClass() in js/common.js derives it
   with no table. The two tables that used to map it (STATUS_CLASS in js/index.js
   and its duplicate STATUS_CLASS_MAP in js/plan.js) existed only to encode
   thaw → s-wet and rideNow → s-rain, the borrowings §7.46 flagged: they painted
   the best case the same blue as the discouraging one. Both are gone. */
.s-open          { --s-color: var(--green);        --s-bg: var(--green-lt);  --s-strong: var(--green);  }
.s-caution       { --s-color: var(--caution-ink);  --s-bg: var(--amber-lt);  --s-strong: var(--amber);  }
.s-wet           { --s-color: var(--orange);       --s-bg: var(--orange-lt); --s-strong: var(--orange); }
.s-rain          { --s-color: var(--blue);         --s-bg: var(--blue-lt);   --s-strong: var(--blue);   }
.s-issue         { --s-color: var(--orange);       --s-bg: var(--orange-lt); --s-strong: var(--orange); }
.s-closed        { --s-color: var(--red);          --s-bg: var(--red-lt);    --s-strong: var(--red);    }
/* Override-only statuses — used by admin's override list. */
.s-winter-open   { --s-color: var(--blue);         --s-bg: var(--blue-lt);   --s-strong: var(--blue);   }
.s-winter-closed { --s-color: var(--red);          --s-bg: var(--red-lt);    --s-strong: var(--red);    }
