/* ============================================================================
   theme.css — THE THEMING LAYER (light / dark / future themes)

   WHY THIS FILE EXISTS AND WHY IT IS NOT tokens.css
   -------------------------------------------------
   tokens.css is copied verbatim from the delivered prototype and is on the
   DO-NOT-EDIT list, so the light palette cannot be moved into a theme system in
   place. This sheet loads AFTER it and RE-VALUES the same custom property names.
   Nothing is renamed, nothing is deleted: every --c-* token that existed before
   still exists, still means what it meant, and in the light theme still computes
   to the exact hex tokens.css declared. A themed site therefore needs no edit to
   any of the other stylesheets, and no edit to any view.

   IT ONLY SETS CUSTOM PROPERTIES — with one bounded exception (section 5), which
   swaps fifteen hard-coded `color:#fff` declarations for a token that EQUALS
   #fff in the light theme. That is why this sheet is safe to load last: it
   cannot restyle a component, only re-colour one.

   FOUR LAYERS, IN THIS ORDER
   --------------------------
     1. PALETTE            --p-*    raw colour, no meaning, never used by a view
     2. THEME DEFINITIONS  --th-*   one block per theme: role -> palette entry
     3. ACTIVE THEME       --t-*    which theme's block is in force right now
     4. BRIDGE             --c-*    the names the existing 29 stylesheets use

   A view NEVER reads --p-*. A theme NEVER hard-codes a hex. The bridge is
   written once and is theme-agnostic, which is what makes a third theme cheap.

   HOW TO ADD A THEME (no refactor, no edit to layers 1, 3 or 4)
   ------------------------------------------------------------
     a. Add any missing colours to the palette in section 1.
     b. Add a `--th-<name>-*` block in section 2 covering EVERY role. Copying the
        light or dark block and editing values is the intended way.
     c. Add one `:root.theme-<name> { }` block in section 3 re-pointing --t-* at
        `--th-<name>-*`. It is a mechanical copy: no colour appears in it.
     d. Add "<name>" to THEMES in tools/theme-contrast.mjs and run it. The
        checker reads THIS FILE, so it fails if a role was missed or a pairing
        drops below its WCAG threshold.
   The `theme-` class prefix is the contract: section 3's OS-preference rule
   deliberately stands down for ANY class starting `theme-`, so a new theme is
   never quietly overpainted by the operating system's preference.

   NO JAVASCRIPT ON FIRST PAINT
   ----------------------------
   Two independent mechanisms, in priority order:
     - `@media (prefers-color-scheme: dark)` — the operating system's setting,
       honoured with no script at all, on the very first request.
     - `.theme-dark` / `.theme-light` on <html> — an explicit choice, which wins.
       _Layout.cshtml writes that class SERVER-SIDE from the wands-theme cookie,
       so an explicit preference is also in the first byte of HTML. There is no
       flash of the wrong theme and no blocking head script, and the toggle
       itself is a plain form POST that works with scripting switched off.

   CONTRAST IS CHECKED, NOT CLAIMED
   --------------------------------
   `node tools/theme-contrast.mjs` parses the palette and every theme block out
   of this file, resolves each pairing and computes the WCAG 2.1 ratio: 4.5:1 for
   body text, 3:1 for large text and for UI component boundaries. Ratios quoted
   in the comments below came from that run. Change a value here and re-run it.
   ============================================================================ */


/* ============================================================================
   1. PALETTE — raw colour. No semantics. Never referenced outside section 2.
   ----------------------------------------------------------------------------
   The light ramps are the USWDS/MDE values tokens.css already used, kept to the
   digit so the light theme is not a redesign. The dark ramps are new, cool-tinted
   and deliberately stop short of #000: a pure-black surface makes the halation
   around light text worse, not better, on the LCD panels MDE issues.
   ============================================================================ */
:root {
  /* -- neutral, light end ------------------------------------------------- */
  --p-white:        #ffffff;
  --p-gray-2:       #f9f9f9;
  --p-gray-5:       #f0f0f0;
  --p-gray-10:      #e6e6e6;
  --p-gray-15:      #dfe1e2;
  --p-gray-25:      #c9c9c9;
  --p-gray-30:      #adadad;
  --p-gray-35:      #898989;   /* 3.5:1 on white — the lightest grey a control
                                  boundary may legally be (WCAG 1.4.11) */
  --p-gray-45:      #757575;
  --p-gray-50:      #71767a;
  --p-gray-52:      #686d72;   /* replaces gray-50 for subtle TEXT: gray-50 is
                                  4.6:1 on white but only 4.36:1 on the page and
                                  4.03:1 on the alt surface, and the page is
                                  never white. See the note in the light block. */
  --p-gray-60:      #565c65;
  --p-gray-90:      #1b1b1b;

  /* -- neutral, dark end (cool slate) ------------------------------------- */
  --p-slate-98:     #0b0f14;
  --p-slate-95:     #141a21;
  --p-slate-90:     #1d242c;
  --p-slate-85:     #232b34;
  --p-slate-80:     #2f3945;
  --p-slate-70:     #3a4552;
  --p-slate-60:     #47525f;
  --p-slate-50:     #6b7885;   /* 3.4:1 on the lightest dark surface */
  --p-slate-35:     #8b97a5;   /* control boundaries in dark: 5.3:1 */
  --p-slate-40:     #7b8794;
  --p-slate-30:     #97a3b0;
  --p-slate-20:     #b9c3ce;
  --p-slate-05:     #f2f5f8;

  /* -- blue (MDE primary) ------------------------------------------------- */
  --p-blue-5:       #d9e8f6;
  --p-blue-30:      #73b3e7;
  --p-blue-35:      #7cbcf5;
  --p-blue-40:      #8ec8ff;
  --p-blue-45:      #a8d3fa;
  --p-blue-50:      #cbe5fd;
  --p-blue-55:      #0076d6;   /* the focus indicator. USWDS's #2491ff reaches
                                  only 2.81:1 against the alt surface, and a
                                  focus ring is the one thing that must never be
                                  hard to see (WCAG 1.4.11). This is USWDS
                                  blue-50v — still a USWDS colour, 4.0:1 there. */
  --p-blue-60:      #005ea2;
  --p-blue-65:      #0050d8;
  --p-blue-70:      #1a4480;
  --p-blue-80:      #162e51;
  --p-blue-tint:    #16283a;
  --p-blue-muted:   #3d5f80;

  /* -- green -------------------------------------------------------------- */
  --p-green-5:      #ecf3ec;
  --p-green-40:     #6ee87f;
  --p-green-45:     #7ddc8a;
  --p-green-50:     #4fc95e;
  --p-green-55:     #00a91c;
  --p-green-60:     #008817;
  --p-green-70:     #216e1f;
  --p-green-tint:   #12291a;

  /* -- yellow / gold ------------------------------------------------------ */
  --p-gold-5:       #faf3d1;
  --p-gold-40:      #f7c948;
  --p-gold-45:      #f2c14e;
  --p-gold-50:      #f0b429;
  --p-gold-55:      #ffbe2e;
  --p-gold-60:      #e5a000;
  --p-gold-70:      #8a6832;   /* was #936f38, which is 4.11:1 on its own alert
                                  panel and 4.36:1 on the page — below AA for the
                                  8 places it is used as body text. Darkened by
                                  the smallest amount that clears 4.5:1 on the
                                  worst of its backgrounds. */
  --p-gold-tint:    #2b2410;

  /* -- red ---------------------------------------------------------------- */
  --p-red-5:        #f4e3db;
  --p-red-40:       #ff9c8f;
  --p-red-45:       #ffc0b5;
  --p-red-50:       #f2705a;
  --p-red-55:       #d54309;
  --p-red-60:       #b50909;
  --p-red-70:       #8b0a03;
  --p-red-tint:     #331813;

  /* -- cyan --------------------------------------------------------------- */
  --p-cyan-5:       #e7f6f8;
  --p-cyan-40:      #66d9ee;
  --p-cyan-45:      #6fc9dd;
  --p-cyan-50:      #33c9e0;
  --p-cyan-55:      #00bde3;
  --p-cyan-70:      #2e6276;
  --p-cyan-tint:    #0f2a31;

  /* -- purple ------------------------------------------------------------- */
  --p-purple-5:     #ede3fa;
  --p-purple-40:    #c9a9ff;
  --p-purple-70:    #54278f;
  --p-purple-tint:  #241a3a;

  /* -- teal (the sixth form colour, declared in prototype-app.css) -------- */
  --p-teal-5:       #e8f5f6;
  --p-teal-40:      #5fd9e3;
  --p-teal-70:      #0f6e78;
  --p-teal-tint:    #10262a;
}


/* ============================================================================
   2. THEME DEFINITIONS — role -> palette. One block per theme, values live here
      and ONLY here. Every block must define every role.
   ----------------------------------------------------------------------------
   ROLE VOCABULARY (semantic: what the colour is FOR, never what it looks like —
   "surface" and "text-muted", never "gray-5" or "light-blue")

     page surface surface-alt surface-sunken overlay
     text text-muted text-subtle text-inverse text-disabled
     line line-strong line-subtle
     accent accent-strong accent-stronger accent-soft accent-vivid
       accent-surface on-accent
     <status>-text <status>-strong <status>-line <status>-solid
       <status>-surface on-<status>          for status in success warning danger info
     disabled-surface disabled-line disabled-text
     focus-inner focus-outer
     form-<code> form-<code>-surface         for code in green yellow white blue purple teal
     on-form-purple

   THE TWO-SIDED ROLES ARE THE WHOLE DIFFICULTY. `accent` is used by the existing
   sheets BOTH as text on the page (12 declarations) and as a button background
   carrying light text (10 declarations). No single colour can satisfy both at
   4.5:1 — white-on-it needs relative luminance <= 0.183 while it-on-a-dark-surface
   needs >= 0.222. The dark theme resolves this the way every credible dark theme
   does: the accent becomes LIGHT, and `on-accent` becomes near-black. Section 5
   is what makes the fifteen affected components honour `on-accent`.
   ============================================================================ */
:root {

  /* ---------------------------------------------------------------------- *
   * LIGHT — the site exactly as it renders today. Every value below equals *
   * the hex tokens.css declares for the token it ends up feeding, so       *
   * switching this system on changes nothing visible in light mode.        *
   * ---------------------------------------------------------------------- */
  --th-light-page:              var(--p-gray-2);
  --th-light-surface:           var(--p-white);
  --th-light-surface-alt:       var(--p-gray-5);
  --th-light-surface-sunken:    var(--p-gray-2);
  --th-light-overlay:           var(--p-white);

  --th-light-text:              var(--p-gray-90);   /* 15.3:1 on surface */
  --th-light-text-muted:        var(--p-gray-60);   /*  6.6:1 */
  --th-light-text-subtle:       var(--p-gray-52);   /*  5.2:1 on the card,
                                  4.6:1 on the alt surface. tokens.css used
                                  gray-50 here and annotated it "4.6:1 (min for
                                  body)" — true against WHITE, but body sits on
                                  the sunken paper, where it was 4.36:1. */
  --th-light-text-inverse:      var(--p-white);
  --th-light-text-disabled:     var(--p-gray-45);

  --th-light-line:              var(--p-gray-15);   /* decorative divider */
  --th-light-line-strong:       var(--p-gray-35);   /* structural rule */
  --th-light-line-subtle:       var(--p-gray-10);
  --th-light-control-line:      var(--p-gray-60);   /* what .inp already hard-codes */

  --th-light-accent:            var(--p-blue-60);   /*  5.1:1 as text, and white on it 5.1:1 */
  --th-light-accent-strong:     var(--p-blue-70);   /*  8.2:1 */
  --th-light-accent-stronger:   var(--p-blue-80);   /* 11.9:1 */
  --th-light-accent-soft:       var(--p-blue-30);
  --th-light-accent-vivid:      var(--p-blue-65);
  --th-light-accent-surface:    var(--p-blue-5);
  --th-light-on-accent:         var(--p-white);

  --th-light-success-text:      var(--p-green-70);
  --th-light-success-strong:    var(--p-green-70);
  --th-light-success-line:      var(--p-green-55);
  --th-light-success-solid:     var(--p-green-60);
  --th-light-success-surface:   var(--p-green-5);
  --th-light-on-success:        var(--p-white);

  --th-light-warning-text:      var(--p-gold-70);
  --th-light-warning-strong:    var(--p-gold-70);
  --th-light-warning-line:      var(--p-gold-55);
  --th-light-warning-solid:     var(--p-gold-60);
  --th-light-warning-surface:   var(--p-gold-5);
  --th-light-on-warning:        var(--p-gray-90);   /* gold cannot carry white */

  --th-light-danger-text:       var(--p-red-60);
  --th-light-danger-strong:     var(--p-red-70);
  --th-light-danger-line:       var(--p-red-55);
  --th-light-danger-solid:      var(--p-red-60);
  --th-light-danger-surface:    var(--p-red-5);
  --th-light-on-danger:         var(--p-white);

  --th-light-info-text:         var(--p-cyan-70);
  --th-light-info-strong:       var(--p-cyan-70);
  --th-light-info-line:         var(--p-cyan-55);
  --th-light-info-solid:        var(--p-cyan-70);
  --th-light-info-surface:      var(--p-cyan-5);
  --th-light-on-info:           var(--p-white);

  --th-light-disabled-surface:  var(--p-gray-5);
  --th-light-disabled-line:     var(--p-gray-25);
  --th-light-disabled-text:     var(--p-gray-45);

  --th-light-focus-inner:       var(--p-white);
  --th-light-focus-outer:       var(--p-blue-55);

  --th-light-form-green:          var(--p-green-70);
  --th-light-form-green-surface:  var(--p-green-5);
  --th-light-form-yellow:         var(--p-gold-70);
  --th-light-form-yellow-surface: var(--p-gold-5);
  --th-light-form-white:          var(--p-gray-60);
  --th-light-form-white-surface:  var(--p-gray-5);
  --th-light-form-blue:           var(--p-cyan-70);
  --th-light-form-blue-surface:   var(--p-cyan-5);
  --th-light-form-purple:         var(--p-purple-70);
  --th-light-form-purple-surface: var(--p-purple-5);
  --th-light-form-teal:           var(--p-teal-70);
  --th-light-form-teal-surface:   var(--p-teal-5);
  --th-light-on-form-purple:      var(--p-white);

  /* ---------------------------------------------------------------------- *
   * DARK                                                                   *
   * The accents invert: what was the DARKEST blue in light (accent-stronger,*
   * used for headings and the app bar) becomes the LIGHTEST in dark, because*
   * in both themes its job is "the most emphatic accent against the page".  *
   * That is the payoff of naming roles by duty rather than by lightness —   *
   * `--c-primary-darker` keeps its 26 text uses readable without one of     *
   * them being touched, including the ones written inline in Razor views,   *
   * which no stylesheet could have overridden.                              *
   * ---------------------------------------------------------------------- */
  --th-dark-page:               var(--p-slate-98);
  --th-dark-surface:            var(--p-slate-95);
  --th-dark-surface-alt:        var(--p-slate-90);
  --th-dark-surface-sunken:     var(--p-slate-98);
  --th-dark-overlay:            var(--p-slate-90);

  --th-dark-text:               var(--p-slate-05);
  --th-dark-text-muted:         var(--p-slate-20);
  --th-dark-text-subtle:        var(--p-slate-30);
  --th-dark-text-inverse:       var(--p-slate-98);
  --th-dark-text-disabled:      var(--p-slate-40);

  --th-dark-line:               var(--p-slate-80);
  --th-dark-line-strong:        var(--p-slate-50);
  --th-dark-line-subtle:        var(--p-slate-85);
  --th-dark-control-line:       var(--p-slate-35);

  --th-dark-accent:             var(--p-blue-35);
  --th-dark-accent-strong:      var(--p-blue-45);
  --th-dark-accent-stronger:    var(--p-blue-50);
  --th-dark-accent-soft:        var(--p-blue-muted);
  --th-dark-accent-vivid:       var(--p-blue-40);
  --th-dark-accent-surface:     var(--p-blue-tint);
  --th-dark-on-accent:          var(--p-slate-98);

  --th-dark-success-text:       var(--p-green-40);
  --th-dark-success-strong:     var(--p-green-45);
  --th-dark-success-line:       var(--p-green-50);
  --th-dark-success-solid:      var(--p-green-40);
  --th-dark-success-surface:    var(--p-green-tint);
  --th-dark-on-success:         var(--p-slate-98);

  --th-dark-warning-text:       var(--p-gold-40);
  --th-dark-warning-strong:     var(--p-gold-45);
  --th-dark-warning-line:       var(--p-gold-50);
  --th-dark-warning-solid:      var(--p-gold-40);
  --th-dark-warning-surface:    var(--p-gold-tint);
  --th-dark-on-warning:         var(--p-slate-98);

  --th-dark-danger-text:        var(--p-red-40);
  --th-dark-danger-strong:      var(--p-red-45);
  --th-dark-danger-line:        var(--p-red-50);
  --th-dark-danger-solid:       var(--p-red-40);
  --th-dark-danger-surface:     var(--p-red-tint);
  --th-dark-on-danger:          var(--p-slate-98);

  --th-dark-info-text:          var(--p-cyan-40);
  --th-dark-info-strong:        var(--p-cyan-45);
  --th-dark-info-line:          var(--p-cyan-50);
  --th-dark-info-solid:         var(--p-cyan-40);
  --th-dark-info-surface:       var(--p-cyan-tint);
  --th-dark-on-info:            var(--p-slate-98);

  --th-dark-disabled-surface:   var(--p-slate-85);
  --th-dark-disabled-line:      var(--p-slate-70);
  --th-dark-disabled-text:      var(--p-slate-40);

  --th-dark-focus-inner:        var(--p-slate-98);
  --th-dark-focus-outer:        var(--p-blue-40);

  --th-dark-form-green:           var(--p-green-45);
  --th-dark-form-green-surface:   var(--p-green-tint);
  --th-dark-form-yellow:          var(--p-gold-45);
  --th-dark-form-yellow-surface:  var(--p-gold-tint);
  --th-dark-form-white:           var(--p-slate-20);
  --th-dark-form-white-surface:   var(--p-slate-90);
  --th-dark-form-blue:            var(--p-cyan-45);
  --th-dark-form-blue-surface:    var(--p-cyan-tint);
  --th-dark-form-purple:          var(--p-purple-40);
  --th-dark-form-purple-surface:  var(--p-purple-tint);
  --th-dark-form-teal:            var(--p-teal-40);
  --th-dark-form-teal-surface:    var(--p-teal-tint);
  --th-dark-on-form-purple:       var(--p-slate-98);
}


/* ============================================================================
   3. ACTIVE THEME — which block is in force.
   ----------------------------------------------------------------------------
   Every rule in this section is PURELY MECHANICAL: it contains no colour, only
   the theme name. That is deliberate. The dark mapping necessarily appears twice
   (an at-rule cannot share a declaration block with a bare selector, and doing
   it in one place would require JavaScript on first paint, which the whole
   design is here to avoid) — but because the repeated text holds no colour
   decision, the worst a divergence can produce is a MISSING role, never a wrong
   one. tools/theme-contrast.mjs asserts the two dark blocks are identical, so
   even that cannot ship silently.

   PRECEDENCE, weakest first:
     :root                                  light, the default
     @media (prefers-color-scheme: dark)    the operating system's preference
     :root.theme-*                          the person's explicit choice
     @media print                           paper always wins
   ============================================================================ */

/* -- light: the default, and what a browser with no preference gets --------- */
:root {
  color-scheme: light;
  --t-page:             var(--th-light-page);
  --t-surface:          var(--th-light-surface);
  --t-surface-alt:      var(--th-light-surface-alt);
  --t-surface-sunken:   var(--th-light-surface-sunken);
  --t-overlay:          var(--th-light-overlay);
  --t-text:             var(--th-light-text);
  --t-text-muted:       var(--th-light-text-muted);
  --t-text-subtle:      var(--th-light-text-subtle);
  --t-text-inverse:     var(--th-light-text-inverse);
  --t-text-disabled:    var(--th-light-text-disabled);
  --t-line:             var(--th-light-line);
  --t-line-strong:      var(--th-light-line-strong);
  --t-line-subtle:      var(--th-light-line-subtle);
  --t-control-line:     var(--th-light-control-line);
  --t-accent:           var(--th-light-accent);
  --t-accent-strong:    var(--th-light-accent-strong);
  --t-accent-stronger:  var(--th-light-accent-stronger);
  --t-accent-soft:      var(--th-light-accent-soft);
  --t-accent-vivid:     var(--th-light-accent-vivid);
  --t-accent-surface:   var(--th-light-accent-surface);
  --t-on-accent:        var(--th-light-on-accent);
  --t-success-text:     var(--th-light-success-text);
  --t-success-strong:   var(--th-light-success-strong);
  --t-success-line:     var(--th-light-success-line);
  --t-success-solid:    var(--th-light-success-solid);
  --t-success-surface:  var(--th-light-success-surface);
  --t-on-success:       var(--th-light-on-success);
  --t-warning-text:     var(--th-light-warning-text);
  --t-warning-strong:   var(--th-light-warning-strong);
  --t-warning-line:     var(--th-light-warning-line);
  --t-warning-solid:    var(--th-light-warning-solid);
  --t-warning-surface:  var(--th-light-warning-surface);
  --t-on-warning:       var(--th-light-on-warning);
  --t-danger-text:      var(--th-light-danger-text);
  --t-danger-strong:    var(--th-light-danger-strong);
  --t-danger-line:      var(--th-light-danger-line);
  --t-danger-solid:     var(--th-light-danger-solid);
  --t-danger-surface:   var(--th-light-danger-surface);
  --t-on-danger:        var(--th-light-on-danger);
  --t-info-text:        var(--th-light-info-text);
  --t-info-strong:      var(--th-light-info-strong);
  --t-info-line:        var(--th-light-info-line);
  --t-info-solid:       var(--th-light-info-solid);
  --t-info-surface:     var(--th-light-info-surface);
  --t-on-info:          var(--th-light-on-info);
  --t-disabled-surface: var(--th-light-disabled-surface);
  --t-disabled-line:    var(--th-light-disabled-line);
  --t-disabled-text:    var(--th-light-disabled-text);
  --t-focus-inner:      var(--th-light-focus-inner);
  --t-focus-outer:      var(--th-light-focus-outer);
  --t-form-green:           var(--th-light-form-green);
  --t-form-green-surface:   var(--th-light-form-green-surface);
  --t-form-yellow:          var(--th-light-form-yellow);
  --t-form-yellow-surface:  var(--th-light-form-yellow-surface);
  --t-form-white:           var(--th-light-form-white);
  --t-form-white-surface:   var(--th-light-form-white-surface);
  --t-form-blue:            var(--th-light-form-blue);
  --t-form-blue-surface:    var(--th-light-form-blue-surface);
  --t-form-purple:          var(--th-light-form-purple);
  --t-form-purple-surface:  var(--th-light-form-purple-surface);
  --t-form-teal:            var(--th-light-form-teal);
  --t-form-teal-surface:    var(--th-light-form-teal-surface);
  --t-on-form-purple:       var(--th-light-on-form-purple);
}

/* -- the operating system's preference, honoured with ZERO JavaScript -------
   `:not([class*="theme-"])` is the stand-down rule: the moment ANY theme class
   is present on <html> the person has expressed a choice, and the OS no longer
   gets a vote. Writing it as a prefix test rather than `:not(.theme-light)` is
   what lets a future third theme be added without revisiting this block. */
@media (prefers-color-scheme: dark) {
  :root:not([class*="theme-"]) {
    color-scheme: dark;
    --t-page:             var(--th-dark-page);
    --t-surface:          var(--th-dark-surface);
    --t-surface-alt:      var(--th-dark-surface-alt);
    --t-surface-sunken:   var(--th-dark-surface-sunken);
    --t-overlay:          var(--th-dark-overlay);
    --t-text:             var(--th-dark-text);
    --t-text-muted:       var(--th-dark-text-muted);
    --t-text-subtle:      var(--th-dark-text-subtle);
    --t-text-inverse:     var(--th-dark-text-inverse);
    --t-text-disabled:    var(--th-dark-text-disabled);
    --t-line:             var(--th-dark-line);
    --t-line-strong:      var(--th-dark-line-strong);
    --t-line-subtle:      var(--th-dark-line-subtle);
    --t-control-line:     var(--th-dark-control-line);
    --t-accent:           var(--th-dark-accent);
    --t-accent-strong:    var(--th-dark-accent-strong);
    --t-accent-stronger:  var(--th-dark-accent-stronger);
    --t-accent-soft:      var(--th-dark-accent-soft);
    --t-accent-vivid:     var(--th-dark-accent-vivid);
    --t-accent-surface:   var(--th-dark-accent-surface);
    --t-on-accent:        var(--th-dark-on-accent);
    --t-success-text:     var(--th-dark-success-text);
    --t-success-strong:   var(--th-dark-success-strong);
    --t-success-line:     var(--th-dark-success-line);
    --t-success-solid:    var(--th-dark-success-solid);
    --t-success-surface:  var(--th-dark-success-surface);
    --t-on-success:       var(--th-dark-on-success);
    --t-warning-text:     var(--th-dark-warning-text);
    --t-warning-strong:   var(--th-dark-warning-strong);
    --t-warning-line:     var(--th-dark-warning-line);
    --t-warning-solid:    var(--th-dark-warning-solid);
    --t-warning-surface:  var(--th-dark-warning-surface);
    --t-on-warning:       var(--th-dark-on-warning);
    --t-danger-text:      var(--th-dark-danger-text);
    --t-danger-strong:    var(--th-dark-danger-strong);
    --t-danger-line:      var(--th-dark-danger-line);
    --t-danger-solid:     var(--th-dark-danger-solid);
    --t-danger-surface:   var(--th-dark-danger-surface);
    --t-on-danger:        var(--th-dark-on-danger);
    --t-info-text:        var(--th-dark-info-text);
    --t-info-strong:      var(--th-dark-info-strong);
    --t-info-line:        var(--th-dark-info-line);
    --t-info-solid:       var(--th-dark-info-solid);
    --t-info-surface:     var(--th-dark-info-surface);
    --t-on-info:          var(--th-dark-on-info);
    --t-disabled-surface: var(--th-dark-disabled-surface);
    --t-disabled-line:    var(--th-dark-disabled-line);
    --t-disabled-text:    var(--th-dark-disabled-text);
    --t-focus-inner:      var(--th-dark-focus-inner);
    --t-focus-outer:      var(--th-dark-focus-outer);
    --t-form-green:           var(--th-dark-form-green);
    --t-form-green-surface:   var(--th-dark-form-green-surface);
    --t-form-yellow:          var(--th-dark-form-yellow);
    --t-form-yellow-surface:  var(--th-dark-form-yellow-surface);
    --t-form-white:           var(--th-dark-form-white);
    --t-form-white-surface:   var(--th-dark-form-white-surface);
    --t-form-blue:            var(--th-dark-form-blue);
    --t-form-blue-surface:    var(--th-dark-form-blue-surface);
    --t-form-purple:          var(--th-dark-form-purple);
    --t-form-purple-surface:  var(--th-dark-form-purple-surface);
    --t-form-teal:            var(--th-dark-form-teal);
    --t-form-teal-surface:    var(--th-dark-form-teal-surface);
    --t-on-form-purple:       var(--th-dark-on-form-purple);
  }
}

/* -- an explicit choice. `.theme-light` needs no block of its own: it wins by
   suppressing the OS rule above, leaving :root's light mapping in force. -----
   Specificity here is (0,1,1), the same as the OS rule's, so this block wins on
   source order — it MUST stay below the @media above. */
:root.theme-dark {
  color-scheme: dark;
  --t-page:             var(--th-dark-page);
  --t-surface:          var(--th-dark-surface);
  --t-surface-alt:      var(--th-dark-surface-alt);
  --t-surface-sunken:   var(--th-dark-surface-sunken);
  --t-overlay:          var(--th-dark-overlay);
  --t-text:             var(--th-dark-text);
  --t-text-muted:       var(--th-dark-text-muted);
  --t-text-subtle:      var(--th-dark-text-subtle);
  --t-text-inverse:     var(--th-dark-text-inverse);
  --t-text-disabled:    var(--th-dark-text-disabled);
  --t-line:             var(--th-dark-line);
  --t-line-strong:      var(--th-dark-line-strong);
  --t-line-subtle:      var(--th-dark-line-subtle);
  --t-control-line:     var(--th-dark-control-line);
  --t-accent:           var(--th-dark-accent);
  --t-accent-strong:    var(--th-dark-accent-strong);
  --t-accent-stronger:  var(--th-dark-accent-stronger);
  --t-accent-soft:      var(--th-dark-accent-soft);
  --t-accent-vivid:     var(--th-dark-accent-vivid);
  --t-accent-surface:   var(--th-dark-accent-surface);
  --t-on-accent:        var(--th-dark-on-accent);
  --t-success-text:     var(--th-dark-success-text);
  --t-success-strong:   var(--th-dark-success-strong);
  --t-success-line:     var(--th-dark-success-line);
  --t-success-solid:    var(--th-dark-success-solid);
  --t-success-surface:  var(--th-dark-success-surface);
  --t-on-success:       var(--th-dark-on-success);
  --t-warning-text:     var(--th-dark-warning-text);
  --t-warning-strong:   var(--th-dark-warning-strong);
  --t-warning-line:     var(--th-dark-warning-line);
  --t-warning-solid:    var(--th-dark-warning-solid);
  --t-warning-surface:  var(--th-dark-warning-surface);
  --t-on-warning:       var(--th-dark-on-warning);
  --t-danger-text:      var(--th-dark-danger-text);
  --t-danger-strong:    var(--th-dark-danger-strong);
  --t-danger-line:      var(--th-dark-danger-line);
  --t-danger-solid:     var(--th-dark-danger-solid);
  --t-danger-surface:   var(--th-dark-danger-surface);
  --t-on-danger:        var(--th-dark-on-danger);
  --t-info-text:        var(--th-dark-info-text);
  --t-info-strong:      var(--th-dark-info-strong);
  --t-info-line:        var(--th-dark-info-line);
  --t-info-solid:       var(--th-dark-info-solid);
  --t-info-surface:     var(--th-dark-info-surface);
  --t-on-info:          var(--th-dark-on-info);
  --t-disabled-surface: var(--th-dark-disabled-surface);
  --t-disabled-line:    var(--th-dark-disabled-line);
  --t-disabled-text:    var(--th-dark-disabled-text);
  --t-focus-inner:      var(--th-dark-focus-inner);
  --t-focus-outer:      var(--th-dark-focus-outer);
  --t-form-green:           var(--th-dark-form-green);
  --t-form-green-surface:   var(--th-dark-form-green-surface);
  --t-form-yellow:          var(--th-dark-form-yellow);
  --t-form-yellow-surface:  var(--th-dark-form-yellow-surface);
  --t-form-white:           var(--th-dark-form-white);
  --t-form-white-surface:   var(--th-dark-form-white-surface);
  --t-form-blue:            var(--th-dark-form-blue);
  --t-form-blue-surface:    var(--th-dark-form-blue-surface);
  --t-form-purple:          var(--th-dark-form-purple);
  --t-form-purple-surface:  var(--th-dark-form-purple-surface);
  --t-form-teal:            var(--th-dark-form-teal);
  --t-form-teal-surface:    var(--th-dark-form-teal-surface);
  --t-on-form-purple:       var(--th-dark-on-form-purple);
}


/* ============================================================================
   4. BRIDGE — the existing token names, re-pointed at the active theme.
   ----------------------------------------------------------------------------
   This is the layer that makes the other 29 stylesheets and every view themed
   without being edited. It is written ONCE and mentions no theme.

   EACH TOKEN IS MAPPED BY THE DUTY IT ACTUALLY PERFORMS in the codebase, counted
   rather than assumed (`color:` uses vs `background:` uses vs border uses). That
   is why --c-error-dark maps to danger-TEXT (7 text uses, 1 background) while
   --c-success-dark maps to success-SOLID (background only). Mapping by name
   instead of by duty is how dark themes end up with unreadable text.
   ============================================================================ */
:root {
  /* -- surfaces (paper): background duty only, 66 declarations -------------- */
  --c-paper:            var(--t-surface);
  --c-paper-alt:        var(--t-surface-alt);
  --c-paper-sunken:     var(--t-surface-sunken);

  /* -- text (ink): colour duty only, 126 declarations ---------------------- */
  --c-ink:              var(--t-text);
  --c-ink-muted:        var(--t-text-muted);
  --c-ink-subtle:       var(--t-text-subtle);

  /* -- accent: the two-sided family. See section 2's note and section 5. ---- */
  --c-primary:          var(--t-accent);
  --c-primary-dark:     var(--t-accent-strong);
  --c-primary-darker:   var(--t-accent-stronger);
  --c-primary-light:    var(--t-accent-soft);
  --c-primary-lighter:  var(--t-accent-surface);
  --c-primary-vivid:    var(--t-accent-vivid);

  /* -- status. The `-light` members are tinted BACKGROUNDS (0 text uses each),
        the `-darker` members are TEXT (24 text uses between them). ---------- */
  --c-success:          var(--t-success-line);
  --c-success-dark:     var(--t-success-solid);
  --c-success-darker:   var(--t-success-text);
  --c-success-light:    var(--t-success-surface);
  --c-warning:          var(--t-warning-line);
  --c-warning-dark:     var(--t-warning-solid);
  --c-warning-darker:   var(--t-warning-text);
  --c-warning-light:    var(--t-warning-surface);
  --c-error:            var(--t-danger-line);
  --c-error-dark:       var(--t-danger-text);
  --c-error-darker:     var(--t-danger-strong);
  --c-error-light:      var(--t-danger-surface);
  --c-info:             var(--t-info-line);
  --c-info-darker:      var(--t-info-text);
  --c-info-light:       var(--t-info-surface);

  /* -- disabled ------------------------------------------------------------ */
  --c-disabled:         var(--t-disabled-line);
  --c-disabled-ink:     var(--t-disabled-text);

  /* -- the form colour-coding, which is how a driller tells the Green form
        from the Yellow one. Hue is preserved across themes on purpose. ------ */
  --c-form-green:       var(--t-form-green);
  --c-form-green-bg:    var(--t-form-green-surface);
  --c-form-yellow:      var(--t-form-yellow);
  --c-form-yellow-bg:   var(--t-form-yellow-surface);
  --c-form-white:       var(--t-form-white);
  --c-form-white-bg:    var(--t-form-white-surface);
  --c-form-blue:        var(--t-form-blue);
  --c-form-blue-bg:     var(--t-form-blue-surface);
  --c-form-purple:      var(--t-form-purple);
  --c-form-purple-bg:   var(--t-form-purple-surface);
  --c-form-teal:        var(--t-form-teal);
  --c-form-teal-bg:     var(--t-form-teal-surface);

  /* -- REFERENCED, BUT DECLARED NOWHERE IN THIS CASCADE (until now).
        The only file that declares these is prototype-final.css, which the main
        layout deliberately does not load. Counted in the twelve sheets _Layout
        actually loads, the uses are: --c-border 4 (site-enhance.css — the SDAT
        suggestion dropdown, the map frame, the typed-coordinates fallback and the
        input-group addon), --c-focus 1 (the suggestion row's focus outline), and
        --c-line / --c-surface / --c-surface-alt ZERO. No Razor view references
        any of them inline either. They are defined here so the names are whole
        and themeable wherever they are next used, not to repair a live break.

        NOTHING WAS BROKEN: every one of those five uses carries a fallback —
        `var(--c-border, #adadad)`, `var(--c-focus, #2491ff)` — so the
        substitution was always valid and the fallback is what has been painting.
        Defining the tokens therefore DOES change light mode, in exactly two
        places, and both are deliberate:

          --c-border  #adadad (2.24:1 on white) -> --t-line-strong #898989
                      (3.50:1). NOT --t-line: at #dfe1e2 that is 1.27:1 and would
                      visibly wash out four component boundaries. These are
                      boundaries, not dividers — a dropdown floating over content
                      and a map frame are what 1.4.11 means by a UI component —
                      so they take the role the verifier asserts at >= 3:1 in
                      every theme, which lands a shade darker than the old value
                      rather than lighter.
          --c-focus   #2491ff -> --t-focus-outer #0076d6 (4.60:1 on white). The
                      old fallback was not a clean failure and not a clean pass:
                      3.20:1 on white, 3.04:1 on the page, but 2.81:1 on the
                      sunken surface (#f0f0f0) — under 1.4.11's 3:1 on the exact
                      surface that inputs and inset panels sit on, which is where
                      a focus ring is seen most. That margin is why --p-blue-55
                      was re-valued in section 1; #0076d6 clears 3:1 on all five
                      light surfaces (worst case 4.04:1) instead of two of them.

        --c-line keeps --t-line because its name says divider and it has no use
        to preserve; if it is ever put on a real boundary, use --c-border. --- */
  --c-line:             var(--t-line);
  --c-border:           var(--t-line-strong);
  --c-surface:          var(--t-surface);
  --c-surface-alt:      var(--t-surface-alt);
  --c-focus:            var(--t-focus-outer);

  /* -- the second token family, from wands-prototype.css ------------------- */
  --wands-ink:          var(--t-text);
  --wands-ink-soft:     var(--t-text-muted);
  --wands-line:         var(--t-line);

  /* -- the focus ring is a composed shadow, so it is rebuilt rather than
        aliased. Inner ring = the page it sits on, outer = the focus colour;
        both flip with the theme so the ring stays visible on a dark surface. - */
  --focus-ring: 0 0 0 2px var(--t-focus-inner), 0 0 0 6px var(--t-focus-outer);
}


/* ============================================================================
   5. SOLID-ACCENT REPAIR — the only rules in this file that are not custom
      properties, and the reason the accent family can inverate safely.
   ----------------------------------------------------------------------------
   Fifteen rules across five stylesheets set a token BACKGROUND and a hard-coded
   `color:#fff`. In light that is correct; in dark the background becomes light
   and white-on-light is unreadable. Each is re-pointed at the matching `on-*`
   token, which EQUALS #fff in the light theme — so this section is a no-op in
   light mode by construction, not by promise.

   THE SELECTORS ARE COPIED, NOT INVENTED, and nothing is removed: the stepper
   rules below are the form step indicators, and the only property touched is
   `color`. Every step, state and placeholder those rules define stays exactly
   as it is. If a new stepper or step state is added later it inherits the same
   treatment by adding its selector to the matching list here.

   Specificity is matched to the original, not inflated, and this sheet loads
   after all five — so source order alone carries it. No `!important`.
   ============================================================================ */

/* -- on an accent background (tokens.css x9, prototype-app.css, site-enhance.css,
      signatures.css, font-switch.css) ------------------------------------------ */
.skip-link,
.brand__seal,
.menubar__btn[aria-expanded="true"],
.menubar__btn[aria-current="page"],
.menubar__btn.is-plain[aria-current="page"],
.btn,
.btn:hover,
.pager__btn[aria-current="true"],
.stepper li[data-state="current"] button .n,
.stepper__btn[aria-current="step"],
.tabs button .badge,
.toast,
.sig-ladder__step--current > .sig-ladder__icon,
.font-switch .btn[aria-pressed="true"] {
  color: var(--t-on-accent);
}

/* -- on a success background: the COMPLETED form step -------------------- */
.stepper li[data-state="done"] button .n {
  color: var(--t-on-success);
}

/* -- on the purple form-code background ---------------------------------- */
.office-zone__tag {
  color: var(--t-on-form-purple);
}

/* -- .btn variants that are NOT solid accent must keep their own colour.
      tokens.css gives .btn the solid treatment and then overrides it for the
      ghost/outline variants; those overrides come earlier in the cascade than
      this file, so they have to be restated or the list above would repaint
      them. Restated with the theme's accent, which is what they already used. */
.btn--ghost,
.btn--outline,
.btn--ghost:hover,
.btn--outline:hover {
  color: var(--t-accent);
}

/* -- .btn--secondary IS THE SAME CASE AND WAS MISSED, because it is the one
      non-solid .btn variant that does NOT live in tokens.css beside the others —
      it is declared alone in prototype-app.css:192 (`background: var(--c-paper)`,
      `color: var(--c-primary-darker)`), so reading tokens.css's .btn family did
      not reveal it. Same specificity as the `.btn` rule above and an earlier
      sheet, so `--t-on-accent` won and painted the label the FILL colour on a
      SURFACE background: #fff on #fff in light and #0b0f14 on #141a21 in dark —
      about 1:1 both ways. The landing page's "Help and FAQ" button was the one
      place it renders (Views/Home/Index.cshtml:1076).

      Restated at --t-accent-stronger, which is exactly what --c-primary-darker
      bridges to at line 639 — so this restores the declared intent rather than
      choosing a new colour: #162e51 on white (11.9:1) in light, #cbe5fd on
      #141a21 in dark. The hover is restated too, because `.btn:hover` is in the
      list above as well; --c-primary-lighter (its hover background) bridges to
      --t-accent-surface, which is light in light and dark in dark, so the same
      role clears AA against both. */
.btn--secondary,
.btn--secondary:hover {
  color: var(--t-accent-stronger);
}


/* -- CONTROL BOUNDARIES. `.inp` hard-codes `border:1px solid #565c65`, which is
      5.9:1 on white and 2.6:1 on a dark surface — so in dark mode every text
      field, select and textarea in the portal would lose its outline. `.tab` and
      `.stepper__btn` take their border from --c-disabled, which is 1.66:1 even
      in LIGHT: a step button whose boundary is invisible.

      Both are re-pointed at --t-control-line, which is #565c65 in light (so the
      fields are unchanged) and asserted at >= 3:1 on every surface in every
      theme. NOTHING IS REMOVED: the step buttons, their states and their labels
      are untouched, and the more specific rules that give the CURRENT step its
      accent border and the DONE step its green one still win on specificity —
      which is why they are not restated here. Same for `.inp[aria-invalid]`
      (the 3px error border) and `.inp:disabled` / `.inp[readonly]`. --------- */
.inp,
select.inp,
textarea.inp {
  border-color: var(--t-control-line);
  background: var(--t-surface);
  color: var(--t-text);
}

.tab,
.stepper__btn {
  border-color: var(--t-control-line);
}


/* ============================================================================
   6. FORM CONTROLS AND SCROLLBARS
   ----------------------------------------------------------------------------
   `color-scheme` in section 3 already hands the browser's own widgets — the
   scrollbars, the date picker, the select drop-down list, the spin buttons —
   over to the active theme, which no amount of custom property work can do.
   What it does NOT cover is a control whose background this codebase sets
   explicitly to a token, so those follow the bridge automatically.

   PLACEHOLDER TEXT IS SET, NOT REMOVED. Placeholders are the one piece of form
   text where the browser default (a mid grey) fails on a dark surface, and no
   existing rule declares it. This ADDS the missing colour and changes no
   placeholder wording anywhere.
   ============================================================================ */
::placeholder {
  color: var(--t-text-subtle);
  opacity: 1; /* Firefox dims placeholders again on top of the colour. */
}


/* ============================================================================
   7. PRINT — paper is always light.
   ----------------------------------------------------------------------------
   `:root[class]` is (0,1,1), matching :root.theme-dark, and this block is last,
   so it wins for a person who chose the dark theme and then pressed print. The
   bare `:root` covers everyone else. Nothing here is a colour: it re-points at
   the light theme, so a future theme prints correctly without being named.
   ============================================================================ */
@media print {
  :root,
  :root[class] {
    color-scheme: light;
    --t-page:             var(--th-light-page);
    --t-surface:          var(--th-light-surface);
    --t-surface-alt:      var(--th-light-surface-alt);
    --t-surface-sunken:   var(--th-light-surface-sunken);
    --t-overlay:          var(--th-light-overlay);
    --t-text:             var(--th-light-text);
    --t-text-muted:       var(--th-light-text-muted);
    --t-text-subtle:      var(--th-light-text-subtle);
    --t-text-inverse:     var(--th-light-text-inverse);
    --t-text-disabled:    var(--th-light-text-disabled);
    --t-line:             var(--th-light-line);
    --t-line-strong:      var(--th-light-line-strong);
    --t-line-subtle:      var(--th-light-line-subtle);
    --t-control-line:     var(--th-light-control-line);
    --t-accent:           var(--th-light-accent);
    --t-accent-strong:    var(--th-light-accent-strong);
    --t-accent-stronger:  var(--th-light-accent-stronger);
    --t-accent-soft:      var(--th-light-accent-soft);
    --t-accent-vivid:     var(--th-light-accent-vivid);
    --t-accent-surface:   var(--th-light-accent-surface);
    --t-on-accent:        var(--th-light-on-accent);
    --t-success-text:     var(--th-light-success-text);
    --t-success-strong:   var(--th-light-success-strong);
    --t-success-line:     var(--th-light-success-line);
    --t-success-solid:    var(--th-light-success-solid);
    --t-success-surface:  var(--th-light-success-surface);
    --t-on-success:       var(--th-light-on-success);
    --t-warning-text:     var(--th-light-warning-text);
    --t-warning-strong:   var(--th-light-warning-strong);
    --t-warning-line:     var(--th-light-warning-line);
    --t-warning-solid:    var(--th-light-warning-solid);
    --t-warning-surface:  var(--th-light-warning-surface);
    --t-on-warning:       var(--th-light-on-warning);
    --t-danger-text:      var(--th-light-danger-text);
    --t-danger-strong:    var(--th-light-danger-strong);
    --t-danger-line:      var(--th-light-danger-line);
    --t-danger-solid:     var(--th-light-danger-solid);
    --t-danger-surface:   var(--th-light-danger-surface);
    --t-on-danger:        var(--th-light-on-danger);
    --t-info-text:        var(--th-light-info-text);
    --t-info-strong:      var(--th-light-info-strong);
    --t-info-line:        var(--th-light-info-line);
    --t-info-solid:       var(--th-light-info-solid);
    --t-info-surface:     var(--th-light-info-surface);
    --t-on-info:          var(--th-light-on-info);
    --t-disabled-surface: var(--th-light-disabled-surface);
    --t-disabled-line:    var(--th-light-disabled-line);
    --t-disabled-text:    var(--th-light-disabled-text);
    --t-focus-inner:      var(--th-light-focus-inner);
    --t-focus-outer:      var(--th-light-focus-outer);
    --t-form-green:           var(--th-light-form-green);
    --t-form-green-surface:   var(--th-light-form-green-surface);
    --t-form-yellow:          var(--th-light-form-yellow);
    --t-form-yellow-surface:  var(--th-light-form-yellow-surface);
    --t-form-white:           var(--th-light-form-white);
    --t-form-white-surface:   var(--th-light-form-white-surface);
    --t-form-blue:            var(--th-light-form-blue);
    --t-form-blue-surface:    var(--th-light-form-blue-surface);
    --t-form-purple:          var(--th-light-form-purple);
    --t-form-purple-surface:  var(--th-light-form-purple-surface);
    --t-form-teal:            var(--th-light-form-teal);
    --t-form-teal-surface:    var(--th-light-form-teal-surface);
    --t-on-form-purple:       var(--th-light-on-form-purple);
  }
}


/* ============================================================================
   8. THE TOGGLE — a plain form, styled to match the font switcher beside it.
   ----------------------------------------------------------------------------
   Deliberately NOT a checkbox-and-CSS-sibling trick: that kind of toggle cannot
   survive a page navigation, so the choice would be lost on every click. This
   one posts, the server sets a cookie and re-renders the class, and the choice
   holds for the whole session with no script involved at any point.
   ============================================================================ */
.theme-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1, .5rem);
  margin: 0;
}

.theme-switch__label {
  font-size: var(--fs-3xs, .75rem);
  font-weight: var(--fw-medium, 500);
  color: var(--t-text-muted);
}

.theme-switch__group {
  display: inline-flex;
  border: 1px solid var(--t-line-strong);
  border-radius: var(--radius-pill, 999px);
  overflow: hidden;
}

.theme-switch__btn {
  appearance: none;
  border: 0;
  background: var(--t-surface);
  color: var(--t-text-muted);
  font: inherit;
  font-size: var(--fs-3xs, .75rem);
  padding: .25rem .625rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
}

.theme-switch__btn + .theme-switch__btn {
  border-left: 1px solid var(--t-line-strong);
}

.theme-switch__btn:hover {
  background: var(--t-surface-alt);
  color: var(--t-text);
}

/* aria-pressed is the source of truth for which theme is on, exactly as the
   font switcher does it — so the visual state and the announced state cannot
   drift apart. */
.theme-switch__btn[aria-pressed="true"] {
  background: var(--t-accent);
  color: var(--t-on-accent);
}

.theme-switch__btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

@media print {
  .theme-switch { display: none !important; }
}
