/* ============================================================
   BACK9OPS BRAND TOKENS
   Centralised CSS custom properties for the entire application.
   All color, shadow, radius, and spacing decisions live here.
   Never hardcode these values in component or page CSS files.

   THEME STRATEGY: Dark is the default. The admin shell is always
   dark. Use [data-theme="light"] if a light surface is ever needed
   for a specific section (e.g. public-facing pages).
   ============================================================ */

:root {

  /* ── Design-system spec tokens ───────────────────────────── */
  /* These are the canonical values. All semantic aliases below  */
  /* map onto these. Use --brand-* / --bg-* in new components.  */
  --bg-app:         #020617;
  --bg-surface:     #0F172A;
  --bg-elevated:    #111827;
  --bg-raised:      #1E293B;      /* inputs, inline panels */

  --text-primary:   #F3F6FB;
  --text-secondary: #C2CFDF;
  --text-muted:     #9FB0C4;
  --text-helper:    #B3C0D2;

  --border-subtle:  rgba(255,255,255,0.08);
  --border-default: rgba(255,255,255,0.12);
  --border-strong:  rgba(255,255,255,0.20);

  --brand:          #1D4ED8;
  --brand-hover:    #2563EB;
  --brand-active:   #1E40AF;
  --brand-soft:     rgba(29,78,216,0.15);
  --brand-ring:     rgba(29,78,216,0.30);

  /* ── Primary (Blue) ─────────────────────────────────────── */
  --b9-primary:        #1D4ED8;
  --b9-primary-hover:  #2563EB;
  --b9-primary-active: #1E40AF;
  --b9-primary-soft:   rgba(29,78,216,0.15);
  --b9-primary-text:   #93C5FD;   /* readable blue on dark */
  /* Ink that sits ON the blue fill — the same split --b9-status-fill-ink draws for the
     status colours. --b9-primary-text answers "what can this blue BE as writing"; this one
     answers "what can be written ON it". White on #1D4ED8 measures 6.70:1, and --b9-primary
     is the same value in both themes, so this never needs a light-theme twin. */
  --b9-primary-ink:    #FFFFFF;

  /* ── Accent Green (golf-inspired) ───────────────────────── */
  --b9-accent-green:       #22C55E;
  --b9-accent-green-hover: #16A34A;
  --b9-accent-green-soft:  rgba(34,197,94,0.14);
  --b9-accent-green-text:  #86EFAC;

  /* ── Surfaces (dark-first) ───────────────────────────────── */
  --b9-surface:        var(--bg-app);
  --b9-surface-alt:    var(--bg-surface);
  --b9-surface-muted:  var(--bg-elevated);

  /* ── Borders ────────────────────────────────────────────── */
  --b9-border:         var(--border-subtle);
  --b9-border-strong:  var(--border-default);

  /* ── Typography ─────────────────────────────────────────── */
  --b9-text:           var(--text-primary);
  --b9-text-muted:     var(--text-secondary);
  --b9-text-soft:      var(--text-muted);
  --b9-text-helper:    var(--text-helper);
  /* "Text ON dark" — the ink for a band that is dark in BOTH themes (a brand hero,
     .b9-bg-primary). It used to alias --text-primary, so in light theme it flipped to
     #1A1A1A: measured 2.60:1 as .b9-bg-primary's ink on its own #1D4ED8 fill, against the
     4.5:1 it needs. It names a FIXED surface, so it must not follow the theme. #F3F6FB on
     that same fill measures 6.19:1. Use --b9-text instead when the surface DOES flip. */
  --b9-text-on-dark:   #F3F6FB;

  /* ── Player readability aliases ─────────────────────────── */
  --player-text-primary:   var(--b9-text);
  --player-text-secondary: var(--b9-text-muted);
  --player-text-muted:     var(--b9-text-soft);
  --player-text-inverse:   #ffffff;
  --player-surface-card:   var(--b9-surface-alt);
  --player-surface-elev:   var(--b9-surface-muted);
  --player-border:         var(--b9-border);
  --player-focus-ring:     var(--b9-focus-ring);
  --player-link:           var(--b9-link);
  --player-link-hover:     var(--b9-link-hover);
  --player-table-head-text: var(--b9-text-muted);
  --player-disabled-text:   color-mix(in srgb, var(--b9-text-muted) 72%, transparent);
  --player-success-text:    var(--b9-success-text);
  --player-warning-text:    var(--b9-warning-text);
  --player-danger-text:     var(--b9-danger-text);

  /* Ink that sits ON a bright status fill. The -text tokens answer "what can this colour
     BE as writing"; this answers the opposite question, "what can be written ON it" — the
     same split the club page draws between --ol-accent-text and --ol-accent-ink. White on
     #22C55E measures 2.28:1; this reads 8.31:1 on the same pill, in either theme. */
  --b9-status-fill-ink: #04140A;

  /* Inline <code>. Bootstrap ships #d63384 and this app never re-pointed it, so it failed AA
     in both themes (4.48:1 on the dark page, 4.27:1 on the light one). Same magenta, moved to
     where it can be read: 11.03:1 on #020617 here, 7.00:1 on #F8F9FA in the light block. */
  --b9-code-ink:       #F8A8CE;

  /* ── Status: Success ────────────────────────────────────── */
  --b9-success:        #22C55E;
  --b9-success-soft:   rgba(34,197,94,0.14);
  --b9-success-text:   #86EFAC;

  /* ── Status: Warning ────────────────────────────────────── */
  --b9-warning:        #F59E0B;
  --b9-warning-soft:   rgba(245,158,11,0.14);
  --b9-warning-text:   #FCD34D;

  /* ── Status: Danger ─────────────────────────────────────── */
  --b9-danger:         #EF4444;
  --b9-danger-soft:    rgba(239,68,68,0.14);
  --b9-danger-text:    #FCA5A5;

  /* ── Accent Indigo (identity chips: the B9 ID) ──────────── */
  /* The B9-ID chip already painted itself rgba(99,102,241,…) inline and inked it #818CF8,
     which measured 2.50:1 on its own tint in light. Indigo is part of how that chip reads
     as an identity badge rather than a status, so it becomes a real pair instead of being
     flattened to grey. */
  --b9-indigo:         #6366F1;
  --b9-indigo-soft:    rgba(99,102,241,0.10);
  --b9-indigo-border:  rgba(99,102,241,0.25);
  --b9-indigo-text:    #A5B4FC;

  /* ── Status: Info ───────────────────────────────────────── */
  --b9-info:           #38BDF8;
  --b9-info-soft:      rgba(56,189,248,0.12);
  --b9-info-text:      #7DD3FC;

  /* ── Non-status hues (identity palettes: the player-initial chips) ────────
     The public event page paints a player's initials in one of eight colours so that two
     Toms in a tee-sheet group are told apart at a glance. Five of the eight already drew
     from theme-aware pairs (--success-*, --brand-*, --warning-*, --danger-*); three were
     hand-typed dark-only values and measured 1.01–1.17:1 on the light page — mint on
     mint, lilac on lilac, invisible. They are IDENTITY, not status, so — like the B9-ID
     chip's indigo above — each becomes a real pair rather than being flattened to grey.
     The FILLS are the exact rgba() the page already used and do not move in either
     theme; only the ink written in them gets a light twin. */
  --b9-violet:         #6D28D9;
  --b9-violet-soft:    rgba(109,40,217,0.16);
  --b9-violet-text:    #C4B5FD;
  --b9-teal:           #0D9488;
  --b9-teal-soft:      rgba(13,148,136,0.16);
  --b9-teal-text:      #5EEAD4;
  --b9-cyan:           #0891B2;
  --b9-cyan-soft:      rgba(8,145,178,0.16);
  --b9-cyan-text:      #67E8F9;
  /* Orange joins them for the same reason: components.css draws the LEAGUE type badge in a
     raw #fb923c, which is 1.77:1 on its own tint over a light page. The fill is unchanged;
     only the lettering gets a twin. */
  --b9-orange:         #EA580C;
  --b9-orange-soft:    rgba(234,88,12,0.16);
  --b9-orange-text:    #FB923C;

  /* ── Compatibility aliases ──────────────────────────────── */
  /* Some components (e.g. the league Command Center confirm    */
  /* dialogs) were authored against token names that never      */
  /* existed in this file. An undefined var() with no fallback  */
  /* collapses background to transparent and color to inherited */
  /* — which made those dialogs render as a see-through card    */
  /* with an invisible action button. Map the mistaken names    */
  /* onto the canonical tokens. Additive: nothing above changes */
  /* and light-theme overrides flow through automatically.      */
  /* Prefer --bg-* / --text-* / --b9-warning|danger|success in  */
  /* new code rather than these aliases.                        */
  --b9-surface-raised:    var(--bg-raised);
  --b9-text-secondary:    var(--text-secondary);
  --b9-accent:            var(--brand);
  --color-success:        var(--b9-success);
  --color-success-subtle: var(--b9-success-soft);
  --color-warn:           var(--b9-warning);
  --color-warn-subtle:    var(--b9-warning-soft);
  --color-danger:         var(--b9-danger);
  --color-danger-subtle:  var(--b9-danger-soft);

  /* ── Dark Palette (static — sidebar always uses these) ─── */
  --b9-dark-bg:            #020617;
  --b9-dark-surface:       #0F172A;
  --b9-dark-surface-alt:   #111827;
  --b9-dark-surface-raise: #1E293B;
  --b9-dark-border:        rgba(255,255,255,0.08);
  --b9-dark-border-subtle: rgba(255,255,255,0.06);
  --b9-dark-text:          #F3F6FB;
  --b9-dark-text-muted:    #C2CFDF;
  --b9-dark-text-soft:     #9FB0C4;
  /* Brand blue that can BE writing on the always-dark bands (sidebar, bottom tab bar).
     --b9-primary-text flips to #1E40AF in light theme, which on the still-dark sidebar
     measures 1.9:1; this one never flips. Same value as the dark --b9-primary-text. */
  --b9-dark-primary-text:  #93C5FD;

  /* ── Semantic Aliases ───────────────────────────────────── */

  /* Cards */
  --b9-card-bg:         var(--bg-surface);
  --b9-card-border:     var(--border-subtle);
  --b9-card-shadow:     0 1px 2px rgba(0,0,0,0.40), 0 0 0 1px rgba(255,255,255,0.05);
  --b9-card-shadow-md:  0 4px 20px rgba(0,0,0,0.50), 0 0 0 1px rgba(255,255,255,0.07);
  --b9-card-shadow-hover: 0 8px 32px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.12);
  --b9-card-shadow-xl:  0 25px 50px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.12);
  --b9-card-radius:     12px;

  /* ── Sidebar (always dark, independent of theme) ─────────── */
  /* These never change — the sidebar is always dark.          */
  --bg-sidebar:             #0B1220;
  --bg-sidebar-elevated:    #0F172A;
  --bg-sidebar-active:      rgba(29,78,216,0.18);

  --b9-sidebar-bg:          #0B1220;
  --b9-sidebar-text:        #94A3B8;
  /* Measured 3.93:1 on --b9-sidebar-bg (#0B1220) at 14px/700 — below AA's 4.5:1, and the
     ONE rule that consumes it already carried #94A3B8 as its fallback, so the token had
     drifted from its own default. #94A3B8 measures 7.30:1. Same hue family, no new colour. */
  --b9-sidebar-text-muted:  #94A3B8;
  --b9-sidebar-border:      rgba(255,255,255,0.06);
  --b9-sidebar-active-bg:   rgba(29,78,216,0.18);
  --b9-sidebar-active-text: #E5E7EB;
  --b9-sidebar-hover-bg:    #0F172A;

  /* Top bar */
  --b9-topbar-bg:      var(--bg-surface);
  --b9-topbar-border:  var(--border-subtle);
  --b9-topbar-height:  3.5rem;

  /* Focus ring */
  --b9-focus-ring: 0 0 0 3px var(--brand-ring);

  /* Links */
  --b9-link:       #60A5FA;
  --b9-link-hover: #93C5FD;

  /* Forms */
  --b9-input-bg:           var(--bg-elevated);
  --b9-input-border:       var(--border-default);
  --b9-input-border-focus: var(--brand);
  --b9-input-placeholder:  var(--text-muted);
  --b9-input-radius:       8px;

  /* Tables */
  --b9-table-header-bg:   var(--bg-elevated);
  --b9-table-row-hover:   rgba(255,255,255,0.04);
  --b9-table-border:      var(--border-subtle);

  /* Badges */
  --b9-badge-neutral-bg:   rgba(255,255,255,0.08);
  --b9-badge-neutral-text: var(--text-secondary);
  --b9-badge-radius:       20px;

  /* Spacing */
  --b9-page-padding-x: 1.5rem;
  --b9-page-padding-y: 1.5rem;

  /* Typography */
  --b9-font-sans: Inter, "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
  --b9-font-mono: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace;
  --font-size-base: 1rem;
  --font-size-sm: 14px;
  --touch-target-min: 48px;
  /* Score keys get their OWN floor, distinct from the app-wide touch target.
     48px is a general-population minimum, not an older-adult target: Android's
     own guidance says "larger being even better", and the most-tapped control in
     the product is a score key. The web mirror of the MAUI ScoreKeyMin token,
     and the value every one of the eight reference designs in
     Reports/ScoringDesign/ is drawn against. A floor, never a budget line —
     three of those mockups shrank an overflow key by treating it as one. */
  --score-key-min: 64px;
  --radius-score-key: 10px;
  --color-gray-400: #94A3B8;

  /* ── fo-* spec aliases ───────────────────────────────────── */
  --fo-primary:          var(--brand);
  --fo-primary-hover:    var(--brand-hover);
  --fo-bg:               var(--bg-app);
  --fo-surface:          var(--bg-surface);
  --fo-surface-alt:      var(--bg-elevated);
  --fo-border:           var(--border-default);
  --fo-text:             var(--text-primary);
  --fo-text-muted:       var(--text-secondary);
  --fo-dark-bg:          var(--bg-app);
  --fo-dark-surface:     var(--bg-surface);
  --fo-dark-surface-alt: var(--bg-elevated);
  --fo-dark-border:      var(--border-default);
  --fo-dark-text:        var(--text-primary);
  --fo-dark-text-muted:  var(--text-secondary);

  /* ── Spacing scale (4-based) ─────────────────────────────── */
  /* Use these tokens instead of arbitrary rem/px values.      */
  /* 4px increments: xs=4, sm=8, md=12, base=16, lg=20, xl=24 */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* ── Border radius scale ─────────────────────────────────── */
  --radius-sm:  6px;
  --radius-md:  8px;
  --radius-lg:  12px;
  --radius-xl:  16px;
  --radius-2xl: 20px;
  --radius-full: 9999px;

  /* ── Transition timing ───────────────────────────────────── */
  --t-fast:   100ms;
  --t-base:   160ms;
  --t-slow:   240ms;
  --t-ease:   ease;
  --t-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* ── Z-index scale ───────────────────────────────────────── */
  --z-base:     0;
  --z-raised:   10;
  --z-dropdown: 200;
  --z-sticky:   400;
  --z-fixed:    600;
  --z-overlay:  800;
  --z-modal:    1000;
  --z-toast:    1200;
  --z-tooltip:  1400;

  /* ── Component sizes ─────────────────────────────────────── */
  --hdr-height:     56px;
  --sidebar-width:  250px;
  --content-max-w:  1280px;
  --form-max-w:     640px;
  --modal-max-w:    560px;
}

/* ============================================================
   LIGHT THEME OVERRIDE
   Only applied to specific sections that need a light surface
   (e.g. public-facing embeds). The admin shell is always dark.
   ============================================================ */
[data-theme="light"] {
  --bg-app:         #F8F9FA;
  --bg-surface:     #FFFFFF;
  --bg-elevated:    #F1F5F9;
  --bg-raised:      #E2E8F0;
  --text-primary:   #1A1A1A;
  --text-secondary: #475569;
  /* tokens.css declares these too, as html[data-theme="light"] (0,1,1) against this block's
     (0,1,0), so ITS values are the ones that render and these three lines never have. Kept in
     step with it rather than left stating a different answer to the same question. */
  --border-subtle:  rgba(0,0,0,0.06);
  --border-default: rgba(0,0,0,0.12);
  --border-strong:  rgba(0,0,0,0.20);
  --b9-surface:        #F8F9FA;
  --b9-surface-alt:    #FFFFFF;
  --b9-surface-muted:  #F1F5F9;
  --b9-border:         #E5E7EB;
  --b9-border-strong:  #CBD5E1;
  --b9-text:           #1A1A1A;
  --b9-text-muted:     #475569;
  --b9-card-bg:        #FFFFFF;
  --b9-card-border:    #E5E7EB;
  --b9-card-shadow:    0 1px 3px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
  --b9-card-shadow-md: 0 4px 12px rgba(15,23,42,0.10);
  --b9-primary-soft:   #DBEAFE;
  --b9-primary-text:   #1E40AF;
  --b9-input-bg:       #FFFFFF;
  --b9-input-border:   #CBD5E1;
  --b9-table-header-bg:  #F1F5F9;
  --b9-table-row-hover:  #F0F7FF;
  --b9-badge-neutral-bg:   #F1F5F9;
  --b9-badge-neutral-text: #475569;
  --b9-success-soft:   #DCFCE7;
  --b9-success-text:   #14532D;
  --b9-warning-soft:   #FEF3C7;
  --b9-warning-text:   #78350F;
  --b9-danger-soft:    #FEE2E2;
  --b9-danger-text:    #991B1B;
  --b9-info-soft:      #E0F2FE;
  --b9-info-text:      #0C4A6E;
  --b9-accent-green-soft: #DCFCE7;
  /* #15803D measured 4.07:1 on --bg-raised and 4.57:1 on its own #DCFCE7 pill — under AA on
     the surface it is most often written on. #166534 measures 5.78:1 and 6.49:1 there. */
  --b9-accent-green-text: #166534;
  --b9-link:       #1D4ED8;
  --b9-link-hover: #1E40AF;

  /* ── What the light half used to FORGET ──────────────────────────────────────────────
     Everything below was defined for dark on :root and never restated here, so light mode
     inherited a value picked for a near-black page. Each line is the light twin of a token
     that is genuinely theme-dependent. Fills (--b9-success, --b9-warning, --b9-primary …)
     are deliberately NOT here: the product keeps its colours, and a fill written as ink is
     a bug in the consuming rule, not in the palette — reach for the -text twin there. */

  /* The identity hues' light ink. Fills unchanged (see :root) — only the lettering moves:
     #C4B5FD measured 1.17:1 on its own chip over the light page, #5EEAD4 1.01:1, #67E8F9
     1.01:1. Worst pairing for each new value, over its own fill on every light surface,
     is 6.32:1 / 5.78:1 / 5.54:1. */
  --b9-violet-text:    #5B21B6;
  --b9-teal-text:      #115E59;
  --b9-cyan-text:      #155E75;
  /* #FB923C measured 1.77:1 on its own 16% orange tint over the light page; this is 7.33:1
     on the same chip and 8.89:1 on the plain light surface. */
  --b9-orange-text:    #7C2D12;

  /* Inherited #64748B, which measures 3.86:1 on --bg-raised and 3.90:1 on the blue tint the
     inbox rows use — it was the whole of the inbox's 44 failures. Matches --text-muted. */
  --b9-text-soft:      #4F5D6E;
  --b9-text-helper:    #4B5563;
  /* #818CF8 measured 2.50:1 on its own tint over the light page. */
  --b9-indigo-text:    #4338CA;
  /* Inherited the dark #9FB0C4: 2.43:1 on a white input. Placeholders are text. */
  --b9-input-placeholder: #4F5D6E;
  /* The same magenta as dark's #F8A8CE, taken the other way: 7.00:1 on the light page. */
  --b9-code-ink:       #A3195B;
  /* Keep this block's shared tokens in step with the html[data-theme="light"] block in
     tokens.css. That selector is (0,1,1) and this one is (0,1,0), so tokens.css WINS every
     name both files declare, regardless of load order. Same values here means the winner is
     the right value either way — and the guard asserts the two blocks never disagree. */
  --text-muted:      #4F5D6E;
  --text-helper:     #4B5563;

  --player-text-primary:   var(--b9-text);
  --player-text-secondary: var(--b9-text-muted);
  --player-text-muted:     var(--b9-text-soft);
  --player-surface-card:   var(--b9-surface-alt);
  --player-surface-elev:   var(--b9-surface-muted);
  --player-border:         var(--b9-border);
  --player-link:           var(--b9-link);
  --player-link-hover:     var(--b9-link-hover);
  --player-table-head-text: var(--b9-text-muted);
  --player-success-text:    var(--b9-success-text);
  --player-warning-text:    var(--b9-warning-text);
  --player-danger-text:     var(--b9-danger-text);
}


/* ============================================================
   A SURFACE THE THEME DOES NOT REACH
   ============================================================
   Some surfaces are dark in BOTH themes on purpose: the public top bar and footer, the
   event hero, the results banner, the scoreboard, the registration page. The theme still
   flips every token UNDERNEATH them, so the ink written on such a surface turns dark in
   light mode and disappears. Measured on the public pages, 2026-09-09:

       .pub-footer-copy       #4F5D6E on #1E293B   2.18:1   (on all ten public pages)
       .ereg-status-heading   #1A1A1A on #111827   1.02:1   ("Registration is open")
       .lb-wd-badge           #1A1A1A on #242A38   1.21:1
       .lb-share-btn          #475569 on #071428   2.43:1

   Chunk A fixed the player nav drawer one case at a time by re-pointing each rule at the
   invariant --b9-dark-* family. That works, but only for the rules somebody remembered:
   the scoreboard alone reads thirty theme tokens, and the next line of markup added inside
   one of these surfaces would be broken again. So the surface declares itself instead, and
   every token inside it — including ones no rule reads yet, and ones belonging to child
   components whose scoped CSS cannot reach in — comes back to its dark value.

   Usage:  <footer class="pub-footer b9-always-dark">

   🔴 The selector is deliberately gated on the LIGHT theme. In dark this block does not
   apply at all, so dark cannot regress — not "should not", cannot. Every value below is
   the value the dark theme already resolves to; the guard
   (PublicLightThemeContrastGuardTests) asserts both halves of that: that each declaration
   equals the dark theme's own value, and that the ink then clears AA on the real bands.

   --bg-sidebar is deliberately ABSENT. tokens.css sets it to #1E293B in light on purpose
   ("intentionally dark"), the bar and footer are painted with it, and both inks below
   clear AA on #1E293B and on the dark theme's #0B1220 alike. Restating it here would
   quietly undo somebody else's design decision.
   ============================================================ */
html[data-theme="light"] .b9-always-dark {
  /* surfaces */
  --bg-app:         #020617;
  --bg-surface:     #0F172A;
  --bg-elevated:    #111827;
  --bg-raised:      #1E293B;
  --b9-surface:     #020617;
  --b9-surface-alt: #0F172A;
  --b9-surface-muted: #111827;
  --b9-surface-raised: #1E293B;
  --b9-card-bg:     #0F172A;
  --b9-input-bg:    #111827;
  --b9-table-header-bg: #111827;
  --b9-table-row-hover: rgba(255,255,255,0.04);

  /* ink */
  --text-primary:   #F3F6FB;
  --text-secondary: #C2CFDF;
  --text-muted:     #9FB0C4;
  --text-helper:    #B3C0D2;
  --b9-text:        #F3F6FB;
  --b9-text-muted:  #C2CFDF;
  --b9-text-secondary: #C2CFDF;
  --b9-text-soft:   #9FB0C4;
  --b9-text-helper: #B3C0D2;
  --b9-input-placeholder: #9FB0C4;
  --b9-badge-neutral-bg:   rgba(255,255,255,0.08);
  --b9-badge-neutral-text: #C2CFDF;

  /* edges */
  --border-subtle:  rgba(255,255,255,0.06);
  --border-default: rgba(255,255,255,0.10);
  --border-strong:  rgba(255,255,255,0.18);
  /* Written through the two names above, exactly as :root writes them, rather than as fresh
     rgba() literals. Same resolved value either way (the guard on this block proves it), but a
     literal here would make these four names newly visible to
     BackgroundTintTokensAreNotUsedAsTextGuardTests, whose token reader does not follow var()
     chains — and it would then report three PRE-EXISTING misuses on surfaces this package does
     not own as though they were caused here. They are real and they are reported; they are not
     this block's to fix. */
  --b9-border:      var(--border-subtle);
  --b9-border-strong: var(--border-default);
  --b9-card-border: var(--border-subtle);
  --b9-input-border: var(--border-default);

  /* brand + links */
  --brand-hover:    #2563EB;
  --brand-active:   #1E40AF;
  --brand-soft:     rgba(29,78,216,0.15);
  --brand-ring:     rgba(29,78,216,0.30);
  --brand-text:     #93C5FD;
  --b9-primary-soft: rgba(29,78,216,0.15);
  --b9-primary-text: #93C5FD;
  --b9-link:        #60A5FA;
  --b9-link-hover:  #93C5FD;

  /* status — the tint moves with the ink, because a soft fill composited over a dark band
     is a different colour from the same fill over cream, and the pair has to match. */
  --success:        #22C55E;
  --success-soft:   rgba(34,197,94,0.14);
  --success-text:   #86EFAC;
  --warning:        #F59E0B;
  --warning-soft:   rgba(245,158,11,0.14);
  --warning-text:   #FCD34D;
  --danger:         #EF4444;
  --danger-soft:    rgba(239,68,68,0.14);
  --danger-text:    #FCA5A5;
  --info:           #38BDF8;
  --info-soft:      rgba(56,189,248,0.12);
  --info-text:      #7DD3FC;
  --green:          #22C55E;
  --green-soft:     rgba(34,197,94,0.14);
  --green-text:     #86EFAC;
  --b9-success-soft: rgba(34,197,94,0.14);
  --b9-success-text: #86EFAC;
  --b9-warning-soft: rgba(245,158,11,0.14);
  --b9-warning-text: #FCD34D;
  --b9-danger-soft:  rgba(239,68,68,0.14);
  --b9-danger-text:  #FCA5A5;
  --b9-info-soft:    rgba(56,189,248,0.12);
  --b9-info-text:    #7DD3FC;
  --b9-accent-green-soft: rgba(34,197,94,0.14);
  --b9-accent-green-text: #86EFAC;
  --b9-indigo-text:  #A5B4FC;
  --b9-violet-text:  #C4B5FD;
  --b9-teal-text:    #5EEAD4;
  --b9-cyan-text:    #67E8F9;
  --b9-orange-text:  #FB923C;
  --b9-code-ink:     #F8A8CE;
}


/* ============================================================
   BOOTSTRAP 5 TOKEN OVERRIDES
   Override Bootstrap custom properties to align with the
   Back9Ops palette — avoids fighting the framework.
   ============================================================ */
:root {
  --bs-primary:          var(--brand);
  --bs-primary-rgb:      29,78,216;
  --bs-success:          var(--b9-success);
  --bs-success-rgb:      34,197,94;
  --bs-warning:          var(--b9-warning);
  --bs-warning-rgb:      245,158,11;
  --bs-danger:           var(--b9-danger);
  --bs-danger-rgb:       239,68,68;
  --bs-info:             var(--b9-info);
  --bs-info-rgb:         56,189,248;
  --bs-body-bg:          var(--bg-app);
  --bs-body-color:       var(--text-primary);
  --bs-secondary-color:  var(--text-secondary);
  --bs-tertiary-color:   var(--text-muted);
  /* RGB triplets + emphasis color for Bootstrap utilities that resolve through
     rgba(var(--bs-*-rgb), …) — e.g. .text-body, .bg-body, .text-body-emphasis.
     Bootstrap only defines these under `:root,[data-bs-theme=light]` (near-black
     #212529 = 33,37,41), and this app themes via [data-theme], not [data-bs-theme],
     so they were never re-pointed for dark. That made .text-body render near-black
     on dark surfaces (e.g. the Settings → Public club page URL). Pin them to the
     dark palette here; html[data-theme="light"] overrides below. Triplets must be
     literals — var(--text-primary) cannot feed an rgba() channel list. */
  --bs-body-color-rgb:      243, 246, 251;   /* --text-primary   #F3F6FB */
  --bs-body-bg-rgb:         2, 6, 23;        /* --bg-app         #020617 */
  --bs-emphasis-color:      var(--text-primary);
  --bs-emphasis-color-rgb:  243, 246, 251;   /* --text-primary   #F3F6FB */
  --bs-secondary-color-rgb: 194, 207, 223;   /* --text-secondary #C2CFDF */
  --bs-tertiary-color-rgb:  159, 176, 196;   /* --text-muted     #9FB0C4 */
  --bs-border-color:     var(--border-subtle);
  --bs-link-color:       var(--b9-link);
  --bs-link-hover-color: var(--b9-link-hover);
  --bs-font-sans-serif:  var(--b9-font-sans);
  --bs-body-font-family: var(--b9-font-sans);
  --bs-border-radius:    8px;
  --bs-border-radius-lg: 12px;
  --bs-border-radius-sm: 6px;
  --bs-card-bg:              var(--bg-surface);
  --bs-card-border-color:    var(--border-subtle);
  --bs-card-box-shadow:      var(--b9-card-shadow);
  /* Form controls */
  --bs-form-control-bg:       var(--bg-elevated);
  --bs-form-control-color:    var(--text-primary);
  --bs-form-control-border:   var(--border-default);
  --bs-input-bg:              var(--bg-elevated);
  --bs-input-color:           var(--text-primary);
  --bs-input-border-color:    var(--border-default);
  --bs-input-focus-border-color: var(--brand);
  --bs-input-placeholder-color:  var(--text-muted);
}

/* Light-theme triplets for the same Bootstrap utilities. Uses html[data-theme]
   (specificity 0,1,1) so it always wins over the :root block above regardless of
   source order. Non-rgb --bs-* vars adapt automatically (they reference tokens). */
html[data-theme="light"] {
  --bs-body-color-rgb:      26, 26, 26;     /* --text-primary   #1A1A1A */
  --bs-body-bg-rgb:         248, 249, 250;  /* --bg-app         #F8F9FA */
  --bs-emphasis-color-rgb:  26, 26, 26;     /* --text-primary   #1A1A1A */
  --bs-secondary-color-rgb: 71, 85, 105;    /* --text-secondary #475569 */
  /* Was 100,116,139 (#64748B) — the value --text-muted held before chunk A darkened it.
     A triplet cannot reference a token, so it does not follow along on its own and this
     line was left stating the old answer: .text-body-tertiary measured 4.31:1 on --bg-app
     in light, under AA. #4F5D6E is what --text-muted actually resolves to (5.45:1 worst). */
  --bs-tertiary-color-rgb:  79, 93, 110;    /* --text-muted     #4F5D6E */
}
