/* ============================================================
   GREENVILLE TRIUMPH - DASHBOARD DESIGN TOKENS
   design.greenvilletriumph.club/tokens.css
   2026 rebrand. Brand palette byte-verified against the .aco swatch.
   Brandpad source of truth: https://brandpad.io/greenville-triumph/
   Rev 2026-06-05: + text-alpha ladder, shadow-float overlays, motion
   primitives (instant duration, ease-in, linear() spring upgrade).
   Structural ports from the design.seantippen.com overhaul; identity
   (palette, fonts) unchanged - brand-safe additions only.
   Rev 2026-06-09: QUIET LABELS. .eyebrow demoted to muted/600;
   accent on labels is now opt-in via .eyebrow-accent (one featured
   kicker per page). Law: labels never wear the accent; green means
   interactive or live, nothing else.
   Rev 2026-06-09 v2: LABEL SCALE. Labels were chronically too small
   and inconsistently tracked, the longest-running complaint in the
   system. Fixes baked in:
     • --text-label is the ONE size for every uppercase mono label
       (eyebrows, section numbers, KPI/stat labels, table headers,
       nav links). It renders ~15px at desk distance and never dips
       below the old desktop size on mobile.
     • --text-xs is the absolute floor for ANY text. No font-size
       below it, ever, anywhere. Raw rem/px font-sizes are banned;
       size only via --text-* tokens.
     • Tracking is tokenized: --track-label (working labels) and
       --track-kicker (the one featured kicker). Still exactly two
       label tracking values; both sit lower than the old 0.10/0.14
       because the labels got bigger (bump size, cut tracking).
     • Working labels are weight 600 across the board. 700 belongs
       to the featured kicker and status hardware (badges, deltas).
   JetBrains Mono is now self-hosted here like the brand faces, so
   the mono never silently falls back to Consolas.

   What this is: the design system that builds Triumph dashboards and
   staff-facing tools. On-brand (the seven brand colors, the brand fonts)
   but tuned for dense data at desk distance, not poster viewing.

   How to consume in any Triumph dashboard:
     <link rel="stylesheet" href="https://design.greenvilletriumph.club/tokens.css">
     <link rel="stylesheet" href="https://design.greenvilletriumph.club/components.css">
   Then use var(--token-name) in CSS, never hex/RGBA/OKLCH.

   Chart.js exception: the canvas API can't resolve CSS vars, so dataset
   colors must be hex literals. Use the --brand-* / --series-* hex values.
   ============================================================ */

/* ============================================================
   BRAND FONTS  (self-hosted, served from this domain, CORS open)
   ------------------------------------------------------------
   Two families, per Brandpad:
     • Fabiola Capitals - display / hero ONLY (single-weight 400 OTF)
     • Inter            - every working heading + body + UI (variable 100–900)

   Fabiola is a SINGLE-WEIGHT OTF. Requesting weight > 400 makes the
   browser SYNTHETICALLY bold it - fattening strokes, crushing spacing
   into the "smashed serif" look. `font-synthesis: none` in the base
   reset is the guardrail: any stray heavy weight on a Fabiola element
   falls back to the real 400. Never override it. Use 400 only.

   Inter, by contrast, is a real variable font - its 700/800/900 weights
   are genuine cut weights, not synthesized. That is why all working
   headings are Inter heavy: brand-correct AND structurally sound.
   ============================================================ */
@font-face {
  font-family: 'Fabiola Capitals';
  src: url('https://design.greenvilletriumph.club/fonts/Fabiola-Capitals.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('https://design.greenvilletriumph.club/fonts/Inter-VariableFont.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('https://design.greenvilletriumph.club/fonts/Inter-Italic-VariableFont.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
/* JetBrains Mono: a dashboard utility face (numbers, labels, code),
   not a Brandpad face. Self-hosted variable woff2 so consumers get
   the real 600/800 weights with zero extra <link> tags. Before this,
   pages had to load it themselves and a missing link silently fell
   back to Consolas; pages also requested 400/500/700 only, so 600
   and 800 silently rendered as 700 (font-synthesis: none refuses to
   fake weights). The variable file covers 100-800 in one request. */
@font-face {
  font-family: 'JetBrains Mono';
  src: url('https://design.greenvilletriumph.club/fonts/JetBrainsMono-Variable.woff2') format('woff2-variations');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: only dark;

  /* ============================================================
     BRAND PALETTE  (canonical 7, never extend)
     ------------------------------------------------------------
     The seven approved colors. Every other token is derived from
     one of these. Never introduce an 8th brand color. The surface
     ladder below is NOT a new color - it is Deep Night lifted toward
     Upstate Fog, the same way a tint card already worked.
     ============================================================ */
  --brand-greenville-blue: #002855;  /* PMS 295 C    - formal navy, deep emphasis bands */
  --brand-triumph-green:   #61a631;  /* PMS 369 C    - primary brand accent */
  --brand-upstate-fog:     #f2fafa;  /* PMS 7541 C   - primary text on dark */
  --brand-morning-mist:    #d2e6e5;  /* PMS 5455 C   - soft text on dark */
  --brand-deep-night:      #020022;  /* PMS Black 6 C - page canvas */
  --brand-electric-lime:   #69b3e7;  /* PMS 292 C    - sky-blue accent (Brandpad name is misleading) */
  --brand-light-green:     #97d700;  /* PMS 375 C    - lime accent (never paired with electric-lime) */

  /* ============================================================
     SURFACE ELEVATION LADDER  (derived from Deep Night)
     ------------------------------------------------------------
     A calm slate ladder, each step a little lighter, carrying the
     brand's blue-violet undertone. This replaces the old "every card
     is saturated navy #002855" approach that made dashboards read as
     a heavy wall. Reserve true Greenville Blue for ONE deep band
     (hero base, footer) via --color-band-navy.

       --color-bg          page canvas
       --color-surface-1   faint band  (alternating sections)
       --color-surface-2   card / panel default
       --color-surface-3   hover / raised card
       --color-surface-4   overlay / popover / drawer
     ============================================================ */
  --color-bg:        #14181f;   /* calm cool slate, low chroma. NOT the saturated Deep Night,
                                   which is a near-black blurple that reads harsh as a full canvas. */
  --color-surface-1: #191e27;   /* faint band (alternating sections) */
  --color-surface-2: #22262e;   /* card / panel default */
  --color-surface-3: #2d3039;   /* hover / raised card */
  --color-surface-4: #383b45;   /* overlay / popover / drawer */
  --color-band-navy: var(--brand-greenville-blue);   /* deep emphasis band, used sparingly */
  --brand-deep-night-bg: #14181f;   /* alias for the dark-mode lock literal */

  /* Aliases - keep older code working; new code uses the ladder above */
  --color-surface:     var(--color-surface-2);
  --color-surface-alt: var(--color-surface-1);

  /* ============================================================
     TEXT HIERARCHY
     ============================================================ */
  --color-text:        var(--brand-upstate-fog);            /* primary body + headings */
  --color-text-soft:   var(--brand-morning-mist);           /* secondary / supporting */
  --color-text-muted:  rgba(242, 250, 250, 0.58);           /* captions, labels, meta */
  --color-text-faint:  rgba(242, 250, 250, 0.38);           /* disabled, placeholder */

  /* ------------------------------------------------------------
     OPACITY-BASED TEXT  (Upstate Fog at fixed opacities)
     ------------------------------------------------------------
     The named steps above (text / soft / muted / faint) are tuned
     for the dark page canvas. These five composite the SAME ink
     over ANY surface - a navy band, an accent-subtle row, a
     colored callout - and stay legible where a canvas-tuned step
     would muddy. Rule of thumb: named steps on the canvas; reach
     for alpha steps when text sits on a colored / variable bg. */
  --text-alpha-90: rgba(242, 250, 250, 0.90);
  --text-alpha-70: rgba(242, 250, 250, 0.70);
  --text-alpha-50: rgba(242, 250, 250, 0.50);
  --text-alpha-30: rgba(242, 250, 250, 0.30);
  --text-alpha-15: rgba(242, 250, 250, 0.15);

  /* ============================================================
     BORDERS
     ============================================================ */
  --color-border:          rgba(242, 250, 250, 0.10);       /* default hairline */
  --color-border-emphasis: rgba(242, 250, 250, 0.20);       /* table headers, input underline */
  --color-border-strong:   rgba(242, 250, 250, 0.32);       /* active / hovered edges */

  /* ============================================================
     ACCENT ROLES
     ------------------------------------------------------------
     One accent per layout. Pick --color-blue OR --color-pop, not
     both. A dashboard-system rule (Brandpad does not mandate it).
     Exception: KPI tiles and chart series may key through the full
     accent set to tell metrics apart (like the data-series block).
     ============================================================ */
  --color-accent:        var(--brand-triumph-green);   /* primary CTA, active nav, KPI 1st */
  --color-accent-hover:  var(--brand-light-green);     /* CTA hover pop */
  --color-blue:          var(--brand-electric-lime);   /* secondary accent, KPI 2nd */
  --color-pop:           var(--brand-light-green);     /* third accent, KPI 3rd */
  --accent-subtle:       rgba(97, 166, 49, 0.10);      /* row tint, chip fill */
  --accent-muted:        rgba(97, 166, 49, 0.18);      /* active chip, focus glow */

  /* ============================================================
     STATUS COLORS  (system signals only, NEVER decorative)
     ------------------------------------------------------------
     Reserve for state: success / warning / danger / info. Do not
     use --color-warning as a 4th accent. Yellow means warning; using
     it decoratively means a real warning gets missed.
     ============================================================ */
  --color-success:        var(--brand-triumph-green);
  --color-success-subtle: rgba(97, 166, 49, 0.16);
  --color-warning:        #d4a14b;
  --color-warning-subtle: rgba(212, 161, 75, 0.16);
  --color-danger:         #ef4444;
  --color-danger-subtle:  rgba(239, 68, 68, 0.16);
  --color-info:           var(--brand-electric-lime);
  --color-info-subtle:    rgba(105, 179, 231, 0.16);

  /* ============================================================
     DATA SERIES  (hex literals - Chart.js can't read CSS vars)
     ------------------------------------------------------------
     Stays inside the seven brand colors (never an 8th). These are the
     four that read cleanly as lines/bars on the dark canvas, in
     rotation order. Status colors (success/warning/danger) are for
     state, not series. Need a 5th series? Tint one of these, don't
     invent a colour.
     Order: green → sky → lime → mist.
     ============================================================ */
  --series-green: #61a631;   /* Triumph Green */
  --series-sky:   #69b3e7;   /* Electric Lime (sky blue) */
  --series-lime:  #97d700;   /* Light Green (lime) */
  --series-mist:  #d2e6e5;   /* Morning Mist - neutral series */

  /* ============================================================
     TYPOGRAPHY FAMILIES
     ------------------------------------------------------------
     Fabiola = display / hero ONLY (opt in with .h-display).
     Inter   = every working heading (h1–h6) + body + UI.
     JetBrains Mono = numbers, eyebrows, code (a dashboard utility,
     not a brand face; self-hosted via @font-face above, so pages
     get it for free - no Google Fonts <link> needed).
     ============================================================ */
  --font-display: 'Fabiola Capitals', Georgia, 'Times New Roman', serif;
  --font-sans:    'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'JetBrains Mono', 'Fira Code', Consolas, monospace;

  /* ============================================================
     TYPE SCALE  (fluid, dashboard-dense)
     ------------------------------------------------------------
     Tight clamp ranges so a component looks the same at 1280px and
     1920px instead of ballooning. The old poster scale (h1 → 139px,
     h2 → 67px) is gone; --text-display is the one big moment and it
     is Fabiola-only.

       --text-xs       0.78–0.88rem  fine print: deltas, footnotes,
                                     badges, dense-table cells. THE
                                     ABSOLUTE FLOOR - nothing on any
                                     page renders smaller than this.
       --text-sm       0.81–0.90rem  dense body, meta
       --text-label    0.84–0.95rem  EVERY uppercase mono label:
                                     eyebrows, section numbers, KPI
                                     and stat labels, table headers,
                                     nav links. A role token, not a
                                     scale step; pairs with
                                     --track-label / --track-kicker.
       --text-base     0.94–1.00rem  body default
       --text-lg       1.06–1.20rem  lead body, card titles,
                                     subsection headers (minimum)
       --text-xl       1.25–1.60rem  h3 / large value
       --text-2xl      1.50–2.10rem  h2 / section titles
       --text-3xl      1.90–2.90rem  h1 / page titles
       --text-4xl      2.30–3.60rem  oversized stat / scoreboard numerals
       --text-display  2.6–5.25rem   Fabiola hero ONLY (.h-display)

     SIZE LAW: font-size only ever takes a --text-* token. Never a
     raw rem/px value. The floor is --text-xs; the label tier is
     --text-label. Shrinking a registry component's type in page CSS
     is drift, full stop. (Labels too small, everywhere, for months:
     this scale is the fix. Do not undo it one 0.65rem at a time.)
     ============================================================ */
  --text-xs:      clamp(0.78rem,  0.75rem + 0.18vw, 0.88rem);
  --text-sm:      clamp(0.81rem,  0.78rem + 0.16vw, 0.90rem);
  --text-label:   clamp(0.84rem,  0.80rem + 0.20vw, 0.95rem);   /* ~15px at 1440; old tier maxed at 13.4px */
  --text-base:    clamp(0.94rem,  0.91rem + 0.18vw, 1.00rem);
  --text-lg:      clamp(1.06rem,  1.00rem + 0.30vw, 1.20rem);
  --text-xl:      clamp(1.25rem,  1.10rem + 0.55vw, 1.60rem);
  --text-2xl:     clamp(1.50rem,  1.30rem + 0.90vw, 2.10rem);
  --text-3xl:     clamp(1.90rem,  1.60rem + 1.35vw, 2.90rem);
  --text-4xl:     clamp(2.30rem,  1.85rem + 1.95vw, 3.60rem);   /* oversized stat / scoreboard numeral: fills the gap between --text-3xl (page titles) and --text-display (Fabiola hero). Mono/Inter only, never Fabiola. */
  --text-display: clamp(2.40rem,  2.70rem + 3.10vw, 6.25rem);   /* dashboard hero, visually calibrated: ~88px @1440. Sweet spot between too-small (~73px, reads as H2) and too-big (Brandpad poster 8.7rem/117px). Keep the rendered hero ~85-100px; do not drift either way. */

  /* ============================================================
     TRACKING  (letter-spacing as tokens - the anti-sprawl law)
     ------------------------------------------------------------
     Consumers had drifted to eight distinct letter-spacing values;
     that sprawl is the disease. Exactly three exist, and they are
     tokens so a fourth cannot appear without editing this file:
       --track-label    every working uppercase label
       --track-kicker   the ONE featured kicker per page
       --track-subhead  .subsection-label (uppercase at heading size)
     Values sit lower than the old 0.10/0.14em because the labels
     got bigger (standing rule: bump a label's size, cut tracking).
     Headings keep their own negative tracking; this block governs
     uppercase label type only.
     ============================================================ */
  --track-label:   0.08em;
  --track-kicker:  0.12em;
  --track-subhead: 0.05em;

  /* ============================================================
     WEIGHT SCALE
     ------------------------------------------------------------
     Body default is 400 (Regular) for dashboard legibility. Brandpad
     ships marketing body at 300 (Light); 300 is reserved here for
     large lede / hero subtitle where thin reads as elegant, not weak.
     Working headings are Inter 700–900 (real variable cut weights).
     ============================================================ */
  --weight-light:    300;
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-extra:    800;
  --weight-black:    900;

  /* ============================================================
     LEADING + MEASURE
     ============================================================ */
  --leading-tight:   1.15;
  --leading-snug:    1.35;
  --leading-normal:  1.5;
  --leading-relaxed: 1.65;
  --measure:         64ch;   /* readable line length cap */

  /* ============================================================
     SPACING - FLUID  (rhythm between blocks)
     ============================================================ */
  --space-xs:  clamp(0.3rem,  0.25rem + 0.15vw, 0.45rem);
  --space-sm:  clamp(0.55rem, 0.45rem + 0.3vw,  0.85rem);
  --space-md:  clamp(0.9rem,  0.75rem + 0.5vw,  1.35rem);
  --space-lg:  clamp(1.35rem, 1.1rem + 0.85vw,  2rem);
  --space-xl:  clamp(2rem,    1.5rem + 1.4vw,   3rem);
  --space-section: clamp(2.75rem, 2rem + 3vw,   5rem);   /* top/bottom of every <section> */

  /* ============================================================
     SPACING - FIXED  (4px base, for precise component work)
     ============================================================ */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;

  /* ============================================================
     LAYOUT SHELLS  (page utilization)
     ------------------------------------------------------------
     Three container widths so dashboards use the screen instead of
     stranding a skinny column in the middle of a wide monitor:
       --content-max   1200px  reading / prose / single column
       --content-wide  1440px  KPI grids, charts, multi-column data
       --content-full  none    full-bleed dense tables (padding only)
     ============================================================ */
  --content-max:  1200px;
  --content-wide: 1440px;
  --gutter:       clamp(1.25rem, 1rem + 2vw, 2.5rem);
  --sidebar-w:    248px;
  --nav-h:        60px;
  --card-pad:     var(--space-md);

  /* ============================================================
     RADIUS  (Triumph is sharp by default)
     ============================================================ */
  --radius:      0px;     /* everything that isn't a pill or thumb */
  --radius-full: 999px;   /* badges, pills, toggle thumb, accent dots */

  /* ============================================================
     SHADOW ELEVATION  (hierarchy, not decoration - use sparingly)
     ============================================================ */
  --shadow-ring: 0 0 0 1px rgba(2, 0, 34, 0.40);
  --shadow-sm:   0 1px  2px rgba(2, 0, 34, 0.45);
  --shadow-md:   0 6px  18px rgba(2, 0, 34, 0.50);
  --shadow-lg:   0 18px 44px rgba(2, 0, 34, 0.62);
  /* Float = drop + hairline ring, for surfaces that detach from the
     canvas (dropdowns, popovers, toasts, command surfaces). The ring
     reads as a crisp edge so the overlay separates cleanly instead of
     just smudging a shadow under itself. */
  --shadow-float:    0 4px  20px rgba(2, 0, 34, 0.45), var(--shadow-ring);
  --shadow-float-lg: 0 12px 40px rgba(2, 0, 34, 0.55), var(--shadow-ring);

  /* ============================================================
     MOTION
     ============================================================ */
  --duration-instant: 0.08s;   /* hover/focus micro-states, tighter than fast */
  --duration-fast: 0.15s;
  --duration:      0.25s;
  --duration-slow: 0.45s;
  --ease-out:      cubic-bezier(0.2, 0, 0.1, 1);     /* decelerate - default for entrances */
  --ease-in:       cubic-bezier(0.4, 0, 1, 1);       /* accelerate - exits, dismissals */
  --ease-in-out:   cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring:   cubic-bezier(0.34, 1.4, 0.64, 1); /* fallback; real overshoot via linear() below */
}

/* Spring overshoot, where supported. cubic-bezier can't cleanly
   overshoot past 1; linear() can. Non-supporting browsers keep the
   cubic-bezier fallback above, so nothing regresses. Gentle peak
   (~1.05) so toggles/toasts settle without a cartoon bounce. */
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --ease-spring: linear(0, 0.05, 0.2, 0.45, 0.7, 0.88, 0.98, 1.04, 1.05, 1.03, 1.01, 1);
  }
}

/* ============================================================
   BASE RESET
   ============================================================ */
* { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 12px);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  background-color: var(--color-bg);
  color-scheme: only dark;
}

body {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: var(--weight-regular);   /* 400 - dashboard legibility */
  line-height: var(--leading-normal);
  color: var(--color-text);
  background: var(--color-bg);
  overflow-x: hidden;
  /* Brand guardrail: refuse browser-synthesized weights/italics. Fabiola
     is single-weight 400; without this a stray heavy weight would render a
     crushed fake-bold. Inter's real cut weights are unaffected. Never remove. */
  font-synthesis: none;
}

a {
  color: var(--color-accent);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
a:hover { color: var(--color-pop); }

img, svg { display: block; max-width: 100%; }

::selection { background: var(--accent-muted); color: var(--color-text); }

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: rgba(242, 250, 250, 0.08);
  padding: 0.12em 0.4em;
  color: var(--color-accent);
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: var(--color-bg); }
::-webkit-scrollbar-thumb { background: var(--color-surface-3); border: 2px solid var(--color-bg); }
::-webkit-scrollbar-thumb:hover { background: var(--color-accent); }

/* ============================================================
   HEADINGS
   ------------------------------------------------------------
   DEFAULT: every heading is Inter heavy. Fabiola is opt-in for the
   single page hero via .h-display. This is deliberate:

     • Brandpad assigns Fabiola to H1/H2/H3. On a poster that sings.
       On a data-dense dashboard at desk distance it fights the data
       and (at H2/H3) repeatedly synthetic-bolds into mush.
     • So the dashboard system restricts Fabiola to ONE hero moment
       (.h-display, rendered at the real Brandpad spec) and uses Inter
       700–900 for the working hierarchy. Fewer Fabiola lines, each
       one correct, instead of many lines each slightly wrong.

   .h-display is the Brandpad H1: Fabiola, weight 400, line-height 1.0,
   tracking normal, text-transform none. The display size is capped for
   screens (Brandpad's own poster max is ~8.7rem; here ~5.25rem).
   ============================================================ */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-sans);
  color: var(--color-text);
  text-transform: none;
}
h1 { font-size: var(--text-3xl); font-weight: var(--weight-extra); line-height: var(--leading-tight); letter-spacing: -0.02em; }
h2 { font-size: var(--text-2xl); font-weight: var(--weight-extra); line-height: 1.2;  letter-spacing: -0.018em; }
h3 { font-size: var(--text-xl);  font-weight: var(--weight-bold);  line-height: 1.3;  letter-spacing: -0.012em; }
h4 { font-size: var(--text-lg);  font-weight: var(--weight-bold);  line-height: 1.35; letter-spacing: -0.008em; }
h5 { font-size: var(--text-base);font-weight: var(--weight-bold);  line-height: 1.4;  letter-spacing: -0.004em; }
h6 {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  line-height: 1.4;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* The one Fabiola moment. Brandpad H1 spec, screen-capped. */
.h-display {
  font-family: var(--font-display);
  font-weight: var(--weight-regular);   /* 400 - never heavier */
  font-size: var(--text-display);
  line-height: 0.85;                    /* Brandpad ships H1 tight (0.8); 0.85 stays tight + multi-line safe */
  letter-spacing: normal;               /* Brandpad: normal tracking on H1 */
  text-transform: none;
  color: var(--color-text);
}

/* ============================================================
   LAYOUT PRIMITIVES
   ------------------------------------------------------------
   .container       1200px reading column
   .container-wide  1440px dashboard column (KPIs, charts, tables)
   .container-full  full width, gutter padding only
   section          vertical rhythm; .bg-surface alternates a faint band
   .band-navy       the one deep Greenville-Blue emphasis band
   ============================================================ */
.container,
.container-wide,
.container-full {
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
  width: 100%;
}
.container      { max-width: var(--content-max); }
.container-wide { max-width: var(--content-wide); }

section {
  padding: var(--space-section) 0;
  scroll-margin-top: var(--nav-h);
  position: relative;
}
section.bg-surface { background: var(--color-surface-1); }
section.band-navy  { background: var(--color-band-navy); }

.table-scroll { overflow-x: auto; }

/* ============================================================
   GRID HELPERS  (the page-utilization fix)
   ------------------------------------------------------------
   Drop-in responsive grids so a dashboard fills the width instead
   of stacking everything in one column.
     .grid        12-col base (use --col-span utilities or inline)
     .grid-2/3/4  equal columns, collapse to 1 on narrow
     .grid-kpi    auto-fit KPI/stat tiles (min 180px)
     .grid-cards  auto-fit cards (min 260px)
     .grid-auto   auto-fit, min 220px
   Gap defaults to --space-md; override with --grid-gap.
   ============================================================ */
.grid,
.grid-2, .grid-3, .grid-4,
.grid-kpi, .grid-cards, .grid-auto {
  display: grid;
  gap: var(--grid-gap, var(--space-md));
}
.grid    { grid-template-columns: repeat(12, 1fr); }
.grid-2  { grid-template-columns: repeat(2, 1fr); }
.grid-3  { grid-template-columns: repeat(3, 1fr); }
.grid-4  { grid-template-columns: repeat(4, 1fr); }
.grid-kpi   { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid-cards { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-auto  { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

@media (max-width: 900px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* Span utilities for the 12-col .grid */
.col-2 { grid-column: span 2; } .col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; } .col-5 { grid-column: span 5; }
.col-6 { grid-column: span 6; } .col-7 { grid-column: span 7; }
.col-8 { grid-column: span 8; } .col-9 { grid-column: span 9; }
.col-12{ grid-column: span 12; }
@media (max-width: 900px) {
  .col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9 { grid-column: span 12; }
}

/* ============================================================
   TEXT UTILITIES
   ============================================================ */
.text-soft   { color: var(--color-text-soft); }
.text-muted  { color: var(--color-text-muted); }
.text-accent { color: var(--color-accent); }
.text-light  { font-weight: var(--weight-light); }   /* 300 - large lede only */
.measure     { max-width: var(--measure); }
.mono        { font-family: var(--font-mono); }
.tnum        { font-variant-numeric: tabular-nums; }

/* ============================================================
   EYEBROW  (uppercase mono kicker above a heading)
   ------------------------------------------------------------
   QUIET BY DEFAULT (rev 2026-06-09). Labels are wayfinding, not
   signals: they never wear the accent. Green is reserved for
   interactive or live elements (links, active nav, CTAs, live
   counters, NOW states); a green label teaches the eye that green
   sometimes means nothing, which taxes every real green signal.
   ONE featured kicker per page (the hero's) may opt in with
   .eyebrow-accent. Size is --text-label (the label tier - never
   smaller); tracking only via --track-label / --track-kicker.
   ============================================================ */
.eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.eyebrow-accent {
  color: var(--color-accent);
  font-weight: var(--weight-bold);
  letter-spacing: var(--track-kicker);
}

/* ============================================================
   REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
