/* ============================================================
   Blue Tees Usage — design tokens
   Hand-written CSS. No build step. Native custom properties only.
   Ship at /assets/tokens.css (imported first by every page).

   Naming: semantic, never literal. --surface-raised, not --gray-50.

   THEMING — one declaration per token, no duplicated palettes.
   Every themed token is written light-dark(<light>, <dark>). light-dark()
   resolves against the `color-scheme` in effect ON THE ELEMENT THAT USES
   THE TOKEN, so:
     • :root { color-scheme: light dark } auto-follows the OS;
     • [data-theme="light"] / [data-theme="dark"] pin a scheme, on <html>
       for the whole document or on any container for a scoped region;
     • there is no second copy of the palette to drift out of sync.

   TWO RULES THAT MUST SURVIVE ANY EDIT
   1. Never write a themed token as a var() alias of another token
      (`--focus-ring-offset: var(--surface-raised)`). var() inside a custom
      property is substituted where the property is DECLARED, so an alias on
      :root freezes whatever the referent resolved to there and inherits that
      frozen value into every subtree — including a scoped light region under
      a dark OS. light-dark() does not have this problem; var()-of-a-token
      does. That is why light-dark() pairs are repeated inline below instead
      of being composed from shared tint tokens.
   2. Chart.js reads colors in JS: getComputedStyle at init and again on
      theme change.

   Browser floor: Chrome 123+, Safari 17.5+, Firefox 120+ — already assumed
   by the no-build-step constraint.
   ============================================================ */

/* ============================================================
   Manrope — self-hosted, variable, same-origin.

   WHY NOT GOOGLE FONTS
   The css2 endpoint cannot carry an integrity hash: it serves different CSS
   per User-Agent (woff2 to modern browsers, woff to older ones), so one fixed
   hash would block the stylesheet for whoever it was not generated against.
   Self-hosting is the only way to actually pin the bytes, and it also drops
   two preconnects and a render-blocking third-party request from every page.

   ONE VARIABLE FILE PER SUBSET, NOT ONE PER WEIGHT
   The pages use five weights (400/500/600/700/800). As static instances that
   is ten files; as a variable font with a 200-800 axis it is two, totalling
   ~39 KB. Any weight in the range is now free — including ones the design
   system does not currently name.

   PROVENANCE
   Google Fonts Manrope v20, latin and latin-ext subsets, fetched from
   fonts.gstatic.com. Licensed OFL-1.1 (assets/fonts/OFL.txt), which permits
   redistribution. sha256:
     latin      e310b55a7fd9677f5e3555e6c6c4d064fa1f1d24393f0ddbe217cea12a8c432f
     latin-ext  ce093b341d9c10658ee1eaa85c5f8042ff3307bc6ccfc5f405616eb437f0009e
   Cyrillic, Greek and Vietnamese subsets are deliberately not shipped — this
   is an internal English dashboard. Add them here if that ever changes.

   These live in tokens.css rather than a file of their own because tokens.css
   is already loaded first by all four pages, so no page can forget the fonts
   and then silently fall back to system sans.

   Paths are relative to this file, i.e. /assets/fonts/. That prefix is already
   allowlisted in _worker.js.
   ============================================================ */

/* latin-ext — 15,240 bytes */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("fonts/manrope-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin — 24,576 bytes */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("fonts/manrope-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light dark;

  /* ---------- Surfaces ---------- */
  --surface-page:        light-dark(#F6F7F9, #0C0E12);  /* app background behind everything */
  --surface-raised:      light-dark(#FFFFFF, #14171D);  /* cards, tiles, sidebar, header */
  --surface-sunken:      light-dark(#F1F3F7, #1A1E25);  /* segmented-control trough, bar tracks */
  --surface-inset:       light-dark(#FBFCFD, #171B21);  /* note blocks, table header zebra */
  --surface-overlay:     light-dark(#12161C, #232830);  /* tooltips, popovers — dark in both themes */
  --surface-hover:       light-dark(#FAFBFC, #1A1E25);  /* row + nav hover */
  --surface-active:      light-dark(#F1F4F9, #1F242C);  /* pressed */
  --surface-scrim:       light-dark(rgba(14,17,22,.45), rgba(0,0,0,.62));

  /* ---------- Borders ---------- */
  --border-subtle:       light-dark(#F2F4F7, #1E222A);  /* table row rules, internal dividers */
  --border-default:      light-dark(#E7EAF0, #262C35);  /* card + input outlines */
  --border-strong:       light-dark(#D3D9E2, #39404B);  /* hover on interactive outlines */
  --border-dashed:       light-dark(#C9D0DB, #414956);  /* withheld-state pill */

  /* ---------- Text ---------- */
  --text-primary:        light-dark(#0E1116, #F2F4F7);
  --text-secondary:      light-dark(#59616F, #A3ACBA);
  --text-muted:          light-dark(#68707E, #7B8492);  /* AA on --surface-page (4.60:1)
                                                           and --surface-raised, but NOT on
                                                           --surface-sunken: 4.49 light / 4.42
                                                           dark. Use --text-secondary on a
                                                           sunken trough, badge or code chip. */
  --text-faint:          light-dark(#6B7280, #8A929F);  /* column headers, disabled */
  --text-inverse:        light-dark(#FFFFFF, #0C0E12);
  --text-on-overlay:     light-dark(#C3CAD6, #C3CAD6);  /* overlay is dark in both themes */
  --text-link:           light-dark(#2B5FE3, #7FA9FF);
  --text-link-hover:     light-dark(#004DF5, #A9C6FF);

  /* ---------- Brand ----------
     #004DF5 is the Blue Tees brand blue. Reserved for the primary button and
     the active-nav indicator — the logo mark itself carries no blue, it is a
     white glyph on a near-black plate. It is NOT the UI accent, and it fails
     AA on a near-black surface — in dark theme the token lightens. */
  --brand:               light-dark(#004DF5, #4C86FF);
  --brand-hover:         light-dark(#0043D6, #6B9CFF);
  --brand-active:        light-dark(#0039B8, #3D77F0);
  --brand-contrast:      light-dark(#FFFFFF, #071026);

  /* No --mark-bg / --mark-fg. The mark is the supplied logo raster
     (assets/blue-tees-mark.png, drawn by .brand-mark in chrome.css and
     .gate-mark in auth-gate.css), so its plate and glyph are baked into the
     file and there is nothing here to theme. Don't reintroduce a plate token
     to sit behind it — the artwork is opaque and would hide it. */

  /* ---------- Accent (does the interface + chart work) ---------- */
  --accent:              light-dark(#2B5FE3, #6B9CFF);
  --accent-hover:        light-dark(#1F4FCC, #8AB2FF);
  --accent-soft:         light-dark(#ECF1FE, rgba(76,134,255,.14));  /* selected nav, soft fills */
  --accent-soft-border:  light-dark(#D7E3FC, rgba(76,134,255,.26));
  --accent-text:         light-dark(#1B45B8, #A9C6FF);  /* accent text on accent-soft, AA */

  /* ---------- Status ----------
     Text-bearing status colors are darkened past the point where they look
     "right" as a hue, because they are read as words at 11px. AA or nothing. */
  --positive:            light-dark(#0F7A52, #3ECF8E);
  --positive-soft:       light-dark(#E7F4EE, rgba(62,207,142,.14));
  --positive-border:     light-dark(#C6E5D6, rgba(62,207,142,.28));
  --negative:            light-dark(#C0384A, #FF7A8A);
  --negative-soft:       light-dark(#FCECEE, rgba(255,122,138,.13));
  --negative-border:     light-dark(#F0CDD3, rgba(255,122,138,.28));
  --caution:             light-dark(#8A5A0A, #E5A54B);
  --caution-soft:        light-dark(#FDF3E2, rgba(229,165,75,.14));
  --caution-border:      light-dark(#F0DCB4, rgba(229,165,75,.28));
  --info:                light-dark(#1F6F8B, #5EC5E0);
  --info-soft:           light-dark(#E6F2F6, rgba(94,197,224,.13));

  /* ---------- Withheld / not-comparable ----------
     A first-class state, not an absence. The product refuses to show a
     misleading comparison. Dashed, muted, never empty. */
  --withheld:            light-dark(#646C7B, #8A929F);
  --withheld-soft:       light-dark(#F4F6F9, rgba(255,255,255,.05));
  --withheld-border:     light-dark(#C9D0DB, #414956);

  /* ---------- Snapshot marker ----------
     Point-in-time metrics that do not react to the date picker. */
  --snapshot:            light-dark(#68707E, #8A929F);
  --snapshot-soft:       light-dark(#F1F3F7, rgba(255,255,255,.05));

  /* ---------- Confidence tiers ----------
     methodology.html's real vocabulary. Literal pairs, never var() aliases of
     the status tokens — see rule 1 above. methodology.html and this block
     change together. */
  --tier-exact:         light-dark(#0F7A52, #3ECF8E);
  --tier-exact-soft:    light-dark(#E7F4EE, rgba(62,207,142,.14));
  --tier-derived:       light-dark(#1B45B8, #8AB2FF);
  --tier-derived-soft:  light-dark(#ECF1FE, rgba(76,134,255,.14));
  --tier-point:         light-dark(#646C7B, #8A929F);
  --tier-point-soft:    light-dark(#F1F3F7, rgba(255,255,255,.05));
  --tier-sampled:       light-dark(#8A5A0A, #E5A54B);
  --tier-sampled-soft:  light-dark(#FDF3E2, rgba(229,165,75,.14));
  --tier-estimate:      light-dark(#8E3F52, #F294A8);
  --tier-estimate-soft: light-dark(#FBECEF, rgba(242,148,168,.13));

  /* ---------- Focus (already implemented — must survive) ---------- */
  --focus-ring:          light-dark(#2B5FE3, #7FA9FF);
  --focus-ring-offset:   light-dark(#FFFFFF, #14171D);
  --focus-ring-width:    2px;
  --focus-ring-offset-width: 2px;

  /* ---------- Elevation ----------
     Soft and low-spread. Borders carry structure; shadow carries lift only.
     In dark theme elevation is carried by surface lightness, so the tints go
     near-opaque-black and tighten rather than smear. */
  --shadow-xs:  0 1px 1px light-dark(rgba(16,24,40,.03), rgba(0,0,0,.25));
  --shadow-sm:  0 1px 2px light-dark(rgba(16,24,40,.04), rgba(0,0,0,.30));
  --shadow-md:  0 1px 2px light-dark(rgba(16,24,40,.05), rgba(0,0,0,.35)),
                0 10px 24px -16px light-dark(rgba(16,24,40,.22), rgba(0,0,0,.60));
  --shadow-lg:  0 2px 4px light-dark(rgba(16,24,40,.05), rgba(0,0,0,.35)),
                0 30px 70px -34px light-dark(rgba(16,24,40,.42), rgba(0,0,0,.75));
  --shadow-overlay: 0 12px 28px -10px light-dark(rgba(16,24,40,.45), rgba(0,0,0,.70));
  --shadow-brand:   0 1px 2px light-dark(rgba(0,77,245,.30), rgba(76,134,255,.28));
  --shadow-inset-control: 0 1px 2px light-dark(rgba(16,24,40,.10), rgba(0,0,0,.40));

  /* ---------- Radius ---------- */
  --radius-xs:   4px;   /* segmented-control thumb */
  --radius-sm:   6px;
  --radius-md:   8px;   /* buttons, inputs */
  --radius-lg:   11px;  /* nav items, note blocks */
  --radius-xl:   14px;  /* cards, tiles — the signature radius */
  --radius-2xl:  18px;  /* page-level containers, auth card */
  --radius-pill: 999px;

  /* ---------- Spacing (4px base) ---------- */
  --space-0:  0;
  --space-1:  2px;
  --space-2:  4px;
  --space-3:  6px;
  --space-4:  8px;
  --space-5:  10px;
  --space-6:  12px;
  --space-7:  14px;
  --space-8:  16px;
  --space-9:  18px;
  --space-10: 20px;
  --space-12: 24px;
  --space-14: 28px;
  --space-16: 32px;
  --space-20: 40px;
  --space-24: 48px;
  --space-32: 64px;

  /* ---------- Layout ---------- */
  --rail-width:          248px;
  --page-gutter:         32px;
  --page-gutter-tight:   20px;
  --section-gap:         24px;
  --card-gap:            16px;
  --tile-gap:            14px;
  --content-max:         1440px;
  --prose-max:           68ch;
  --topbar-height:       64px;

  /* ---------- Typography ----------
     Manrope, self-hosted — see the @font-face block at the top of this file.
     Weight does the hierarchy work, not size, so sizes stay in a tight band and
     density survives. Any weight from 200 to 800 is available, because what
     ships is one variable font rather than a set of static instances.

     The per-role --type-*-weight tokens below ARE var() aliases, which rule 1
     at the top of this file forbids — for COLOUR. The reason rule 1 exists is
     that a var() alias freezes at its declaration site and so cannot re-resolve
     per colour-scheme. A weight has no per-scheme value to re-resolve: 800 is
     800 in both themes. Aliasing a scheme-invariant token is safe; aliasing a
     themed one is the bug. */
  --font-sans: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "JetBrains Mono", Menlo, monospace;

  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-black:    800;

  --type-display-size:      29px;  /* KPI value */
  --type-display-line:      1;
  --type-display-weight:    var(--weight-black);
  --type-display-track:     -.035em;

  --type-display-lg-size:   38px;  /* auth gate headline, hero figure */
  --type-display-lg-line:   1.05;
  --type-display-lg-track:  -.035em;

  --type-page-title-size:   20px;
  --type-page-title-line:   1.2;
  --type-page-title-weight: var(--weight-black);
  --type-page-title-track:  -.02em;

  --type-section-size:      13px;  /* section heading above a card group */
  --type-section-line:      1.3;
  --type-section-weight:    var(--weight-black);
  --type-section-track:     -.01em;

  --type-card-title-size:   14px;
  --type-card-title-line:   1.3;
  --type-card-title-weight: var(--weight-bold);
  --type-card-title-track:  -.012em;

  --type-body-size:         13.5px;
  --type-body-line:         1.65;
  --type-body-weight:       var(--weight-medium);

  --type-ui-size:           12.5px; /* buttons, chips, nav, readouts */
  --type-ui-line:           1.35;
  --type-ui-weight:         var(--weight-semibold);

  --type-kpi-label-size:    12px;
  --type-kpi-label-line:    1.35;
  --type-kpi-label-weight:  var(--weight-semibold);

  --type-table-size:        12.5px;
  --type-table-line:        1.4;
  --type-table-weight:      var(--weight-medium);
  --type-table-num-weight:  var(--weight-semibold);

  --type-caption-size:      11.5px;
  --type-caption-line:      1.5;
  --type-caption-weight:    var(--weight-medium);

  --type-overline-size:     10.5px; /* column headers, sidebar group labels */
  --type-overline-line:     1.2;
  --type-overline-weight:   var(--weight-bold);
  --type-overline-track:    .08em;

  --type-wordmark-track:    .06em;
  --type-wordmark-sub-track: .14em;

  /* Every numeric surface uses tabular figures. Non-negotiable — the daily
     table and KPI row jitter without it. */
  --numeric: tabular-nums;

  /* ---------- Motion ----------
     Motion clarifies causation and nothing else. Duration is short, easing is
     decelerating, and anything the user did not initiate does not move. */
  --ease-out:      cubic-bezier(.2, .8, .2, 1);    /* default: entries, state changes */
  --ease-in-out:   cubic-bezier(.4, 0, .2, 1);     /* two-way: theme toggle, thumb slide */
  --ease-spring:   cubic-bezier(.34, 1.4, .64, 1); /* segmented thumb only, sparingly */

  --duration-instant: 80ms;   /* hover color, focus ring */
  --duration-fast:    140ms;  /* tooltip, chip, pill, dropdown entry */
  --duration-base:    200ms;  /* tab + segment thumb, theme cross-fade */
  --duration-slow:    320ms;  /* number roll on range change */
  --duration-chart:   520ms;  /* Chart.js first draw-in, once per load */

  --transition-color: color var(--duration-instant) var(--ease-out),
                      background-color var(--duration-instant) var(--ease-out),
                      border-color var(--duration-instant) var(--ease-out);
  --transition-lift:  box-shadow var(--duration-fast) var(--ease-out),
                      border-color var(--duration-fast) var(--ease-out);
  --transition-pop:   opacity var(--duration-fast) var(--ease-out),
                      transform var(--duration-fast) var(--ease-out);

  /* ---------- Chart palette ----------
     Chart.js sets colors in JS, so these are read once at init and again on
     theme change. Six categorical hues, distinguishable at 8px bar width and
     AA against --surface-raised. Grey is not a seventh hue: --chart-neutral
     is reserved for "unclassified"/"other" so an absence never reads as a
     category. */
  --chart-1: light-dark(#2B5FE3, #6B9CFF);
  --chart-2: light-dark(#16A5B8, #3ECFDF);
  --chart-3: light-dark(#7A5AF0, #A78BFA);
  --chart-4: light-dark(#E0913A, #F0A85C);
  --chart-5: light-dark(#0F9A6A, #3ECF8E);
  --chart-6: light-dark(#D2607C, #F2789A);
  --chart-neutral: light-dark(#C4CBD6, #4A525E);

  --chart-grid:        light-dark(#EDF0F4, #232830);
  --chart-axis-text:   light-dark(#A2AAB8, #7B8492);
  --chart-tooltip-bg:  light-dark(#12161C, #262C35);
  --chart-tooltip-text: #FFFFFF;
  --chart-tooltip-sub: light-dark(#C3CAD6, #A3ACBA);
  --chart-fill-from:   light-dark(rgba(43,95,227,.20), rgba(107,156,255,.24));
  --chart-fill-to:     light-dark(rgba(43,95,227,0), rgba(107,156,255,0));
  --chart-line-width:  2.25;
  --chart-bar-radius:  5;
  --chart-tension:     .42;

  /* ---------- Heatmap ----------
     One hue at varying alpha, normalised PER COLUMN, never across columns.
     Consumed with color-mix at the use site so the base resolves in the
     scheme of the cell, not of :root:

       background: color-mix(in srgb,
         var(--heat-base-neutral) calc(var(--heat-alpha-max) * 100% * var(--t)),
         transparent);

     (--t is the 0–1 normalised value, set inline per cell.) */
  --heat-base-neutral:  light-dark(#2B5FE3, #6B9CFF);
  --heat-base-positive: light-dark(#0F9A6A, #3ECF8E);
  --heat-alpha-min:    .06;
  --heat-alpha-max:    .36;

  /* ---------- Permanently-dark surfaces ----------
     The hero plates: LAUNCH's .snapshot, GAME's .product-band and the
     methodology doc band. They multiply a photograph against a dark plate,
     so they must NOT invert — --surface-overlay lifts in dark theme (which
     is correct for a tooltip, wrong here: it washes the blend out) and
     --text-primary would go near-white on near-white.

     These are BARE values, not light-dark() pairs, on purpose: the
     constancy is the point, and writing it in the source stops the next
     reader "fixing" a pair that looks un-differentiated. They also sit
     outside the @media print override block below so the plate survives
     printing — see the print block for the companion rule pages need.

     THE INVARIANT, stated so it can be checked: each of the five is
     declared exactly once, here, with a bare value. None may gain a
     light-dark() pair, and none may be re-declared inside an @media or
     [data-theme] block. Break either and a hero plate starts tracking the
     theme, which is the one thing it must never do. Naming the case is
     what makes that checkable — as six literals scattered across three
     files it was only a convention, and the third page to be written
     would have reached for --surface-raised. */
  --surface-fixed-dark:   #0B0D10;  /* the plate the photograph multiplies against */
  --surface-fixed-dark-2: #14181D;  /* a raised block sitting ON the plate */
  --text-on-fixed-dark:   #FFFFFF;  /* headings and primary copy — 19.46:1 */
  --accent-on-fixed-dark: #8EB0FF;  /* eyebrow, links, small caps — 9.08:1 */
  --border-on-fixed-dark: rgba(255, 255, 255, .14);  /* rules and hairlines on the plate */
  /* Secondary copy on these plates is --text-on-overlay; it needs no second name. */
}

/* ---------- Explicit theme pins ----------
   The manual toggle writes data-theme on <html> and wins over the OS
   preference; absence of the localStorage key means "follow the OS".
   Because these only set color-scheme, they also work on any container —
   a scoped light card inside a dark page costs one attribute.

   NO PAGE IS PINNED ANY MORE. All four follow the OS by default and carry the
   toggle. The last pin came off the dashboards when Chart.js stopped holding
   light-theme hex literals and started reading these tokens on
   btg:themechange (assets/theme.js owns that event; the dashboards' own
   scripts do the repaint). A pin was only ever right while something on the
   page could not theme itself. */
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"]  { color-scheme: dark; }

/* ---------- Print ----------
   Every page has a working print path. Force the light token set regardless
   of theme so nothing depends on a dark background for legibility, then
   flatten the paper-facing surfaces and drop elevation.

   The --surface-fixed-dark family is deliberately NOT overridden here: those
   plates carry white headings, so flattening them to white prints
   white-on-white. They keep their values, and each page that uses one also
   sets print-color-adjust: exact on it so the plate actually renders — a
   background colour is dropped by default when printing. */
@media print {
  :root, [data-theme="dark"], [data-theme="light"] {
    color-scheme: light;

    --surface-page:     #FFFFFF;
    --surface-raised:   #FFFFFF;
    --surface-sunken:   #F4F6F9;
    --surface-inset:    #FAFBFC;
    --border-subtle:    #E7EAF0;
    --border-default:   #D3D9E2;
    --text-primary:     #0E1116;
    --text-secondary:   #3D4552;
    --text-muted:       #59616F;
    --shadow-xs: none;
    --shadow-sm: none;
    --shadow-md: none;
    --shadow-lg: none;
    --shadow-inset-control: none;
    --shadow-brand: none;
  }
}

/* ---------- Reduced motion ----------
   Everything in the motion spec is decorative reinforcement of a state
   change that is already visible. All of it can go. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 0ms;
    --duration-fast:    0ms;
    --duration-base:    0ms;
    --duration-slow:    0ms;
    --duration-chart:   0ms;
  }
}
