/*!
 * SpeedGoat Design System — speedgoat.css
 * v2.0.0 · 2026-07-16
 * Single distributable stylesheet. Drop this file, the fonts/ folder, and
 * the speedgoat-bg.* images into your app (e.g. Shiny www/) and load with
 * one line:
 *   <link rel="stylesheet" href="speedgoat.css">
 * Ships: @font-face (Inter + IBM Plex Mono), color tokens (canonical,
 * count-web HSL scales + aliases), typography, spacing/radius, effects,
 * the shared background image (--bg-image + .sg-canvas), and the
 * [data-theme="dark"] scope.
 * BREAKING (v2.0.0): the count-web/shadcn names --primary and --border are
 * now HSL component triples (consume as hsl(var(--primary)) or the resolved
 * var(--color-primary) / var(--color-border)); they are no longer resolved
 * colors. This aligns with count-web so hsl(var(--primary)) resolves the same
 * in an adopting app regardless of stylesheet load order.
 * Source of truth: this design system repo. Do not hand-edit — regenerate.
 */

/* ===== Fonts ===== */
/* ============================================================
   SpeedGoat — Self-hosted webfonts (SIL OFL)
   Inter (UI) + IBM Plex Mono (numerals). Latin + latin-ext subsets.
   Binaries in assets/fonts/. No runtime dependency on Google Fonts.
   ============================================================ */
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-400-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;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-400.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;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-500-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;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-500.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;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-600-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;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/ibm-plex-mono-600.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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url("fonts/inter-400-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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url("fonts/inter-400.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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url("fonts/inter-500-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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url("fonts/inter-500.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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/inter-600-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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url("fonts/inter-600.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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url("fonts/inter-700-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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url("fonts/inter-700.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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:800;
  font-display:swap;
  src:url("fonts/inter-800-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;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:800;
  font-display:swap;
  src:url("fonts/inter-800.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;
}


/* ===== Colors (canonical) ===== */
/* ============================================================
   SpeedGoat — Color tokens  (CANONICAL)
   Source of truth: count-web (production shadcn/ui + Tailwind v4).
   Figma was the original starting point; the production app is the
   authority, so these values mirror count-web/src/app/globals.css.

   Structure:
     1. Raw semantic scales as HSL triples  (--action-primary: H,S,L)
     2. Ready-to-use color aliases           (--color-*  → hsl(...))
     3. Legacy compatibility aliases         (--primary, --success, …)
        kept so older DS cards keep working, repointed to canon.
   Prefer the semantic scales for anything new.
   ============================================================ */
:root{
  /* ---------- 1. RAW SEMANTIC SCALES (H,S,L triples) ---------- */

  /* base / neutrals */
  --base-4: 215, 16%, 47%; /* @kind color */
  --base-5: 213, 27%, 84%; /* @kind color */
  --base-invert: 0, 0%, 100%; /* @kind color */
  --primitive-blue-700: 212, 82%, 66%; /* @kind color */

  /* text ramp */
  --text-base-1: 222, 47%, 11%; /* @kind color */ /* primary text */
  --text-base-2: 215, 25%, 27%; /* @kind color */
  --text-base-3: 215, 16%, 47%; /* @kind color */ /* labels / muted */
  --text-base-4: 215, 20%, 65%; /* @kind color */ /* placeholder */
  --text-base-5: 214, 32%, 91%; /* @kind color */
  --text-primary-1: 216, 86%, 30%; /* @kind color */
  --text-primary-2: 217, 67%, 44%; /* @kind color */
  --text-primary-3: 217, 67%, 44%; /* @kind color */
  --text-primary-4: 212, 100%, 81%; /* @kind color */

  /* surface */
  --surface-primary-1: 208, 94%, 7%; /* @kind color */
  --surface-primary-2: 212, 86%, 15%; /* @kind color */
  --surface-primary-3: 214, 54%, 97%; /* @kind color */
  --surface-secondary-1: 210, 40%, 96%; /* @kind color */
  --surface-secondary-2: 210, 40%, 98%; /* @kind color */
  --surface-background-1: 210, 40%, 96%; /* @kind color */
  --surface-background-2: 210, 40%, 98%; /* @kind color */

  /* action */
  --action-primary: 217, 85%, 36%; /* @kind color */ /* #0E4AAA — primary actions */
  --action-primary-hovered: 215, 86%, 25%; /* @kind color */
  --action-primary-focused: 215, 86%, 25%; /* @kind color */
  --action-primary-disabled: 217, 54%, 79%; /* @kind color */
  --action-secondary: 0, 0%, 100%; /* @kind color */
  --action-secondary-hovered: 210, 40%, 96%; /* @kind color */
  --action-secondary-focused: 210, 40%, 96%; /* @kind color */
  --action-secondary-disabled: 210, 40%, 98%; /* @kind color */

  /* line / borders */
  --line-primary-1: 217, 67%, 44%; /* @kind color */
  --line-primary-2: 217, 54%, 67%; /* @kind color */
  --line-primary-3: 217, 55%, 87%; /* @kind color */
  --line-primary-4: 218, 52%, 96%; /* @kind color */
  --line-secondary-1: 217, 33%, 17%; /* @kind color */
  --line-secondary-2: 215, 20%, 65%; /* @kind color */
  --line-secondary-3: 214, 32%, 91%; /* @kind color */
  --line-secondary-4: 210, 40%, 96%; /* @kind color */
  --line-secondary-5: 210, 40%, 98%; /* @kind color */

  /* primary ramp */
  --primary-1: 212, 86%, 15%; /* @kind color */
  --primary-3: 217, 67%, 44%; /* @kind color */
  --primary-4: 212, 100%, 81%; /* @kind color */
  --primary-5: 217, 54%, 92%; /* @kind color */
  --primary-core: 217, 85%, 36%; /* @kind color */
  --primary-hovered: 214, 86%, 20%; /* @kind color */
  --primary-disabled: 217, 54%, 79%; /* @kind color */

  /* feedback — success */
  --success-1: 143, 55%, 22%; /* @kind color */
  --success-2: 143, 55%, 34%; /* @kind color */
  --success-3: 143, 55%, 47%; /* @kind color */ /* #36BA68 */
  --success-4: 143, 55%, 56%; /* @kind color */
  --success-5: 141, 54%, 95%; /* @kind color */

  /* feedback — warning */
  --warning-1: 31, 70%, 20%; /* @kind color */
  --warning-2: 30, 70%, 34%; /* @kind color */
  --warning-3: 31, 90%, 56%; /* @kind color */ /* #F4922A */
  --warning-4: 31, 100%, 62%; /* @kind color */
  --warning-5: 37, 100%, 94%; /* @kind color */

  /* feedback — error */
  --error-1: 8, 73%, 18%; /* @kind color */
  --error-2: 8, 73%, 18%; /* @kind color */
  --error-3: 9, 75%, 50%; /* @kind color */ /* #DF3D20 */
  --error-4: 9, 75%, 58%; /* @kind color */
  --error-5: 6, 76%, 95%; /* @kind color */

  /* shadcn base aliases */
  --background: 0, 0%, 100%; /* @kind color */
  --foreground: 222.2, 84%, 4.9%; /* @kind color */
  --card: 0, 0%, 100%; /* @kind color */
  --muted: 210, 40%, 96.1%; /* @kind color */
  --border-hsl: 214, 32%, 91%; /* @kind color */
  --input-hsl: 214, 32%, 91%; /* @kind color */
  --ring: 222.2, 84%, 4.9%; /* @kind color */
  --destructive: 0, 84.2%, 60.2%; /* @kind color */
  --radius: 0.5rem; /* @kind radius */

  /* ---------- 2. READY-TO-USE COLOR ALIASES ---------- */
  --color-action-primary: hsl(var(--action-primary));
  --color-action-primary-hovered: hsl(var(--action-primary-hovered));
  --color-action-primary-disabled: hsl(var(--action-primary-disabled));
  --color-primary: hsl(var(--primary)); /* count-web alias for the resolved primary */
  --color-action-secondary: hsl(var(--action-secondary));
  --color-action-secondary-hovered: hsl(var(--action-secondary-hovered));

  --color-text-base-1: hsl(var(--text-base-1));
  --color-text-base-2: hsl(var(--text-base-2));
  --color-text-base-3: hsl(var(--text-base-3));
  --color-text-base-4: hsl(var(--text-base-4));
  --color-text-primary-1: hsl(var(--text-primary-1));
  --color-text-primary-2: hsl(var(--text-primary-2));

  --color-success: hsl(var(--success-3));
  --color-warning: hsl(var(--warning-3));
  --color-error: hsl(var(--error-3));

  --color-line-primary-2: hsl(var(--line-primary-2));
  --color-line-primary-3: hsl(var(--line-primary-3));
  --color-line-primary-4: hsl(var(--line-primary-4));
  --color-border: hsl(var(--line-secondary-3));
  --color-surface-secondary-1: hsl(var(--surface-secondary-1));

  /* ---------- 3. LEGACY COMPATIBILITY ALIASES ----------
     Older DS cards + StatCard/Button specimens use these names.
     Repointed to canonical count-web values (primary now #0E4AAA). */
  --primary: 217, 85%, 36%; /* @kind color */ /* HSL component, count-web-aligned (#0E4AAA). Consume via hsl(var(--primary)) or var(--color-primary) — never bare var(--primary). */
  --primary-ink: hsl(var(--action-primary-hovered));
  --primary-soft: hsl(var(--primary-5));

  /* ---------- INK CHROME ----------
     The brand's signature ink-framed workspace: dark chrome (header, sidebar,
     console panels) sitting BESIDE light cards in a light app. This is NOT the
     dark theme — tokens/dark.css is a whole-page scope you opt into with
     data-theme="dark", and it remaps everything. Ink chrome coexists with light
     surfaces and is always dark, in both themes.

     Until now the system shipped three ink surfaces and NOTHING to put on them —
     no text ramp, no divider, no primary. dark.css even says "the ink chrome
     already reads dark and is unchanged" while providing nothing to build it
     with, so every app that needed ink chrome invented its own ramp. The
     ipm-tool ui_kit did exactly that, in 153 hardcoded hex occurrences, and
     independently rediscovered --ink-3 as #233149.

     Contrast on --ink (#0F172A), computed: ink-text-1 14.89:1, -2 12.42:1,
     -3 8.12:1, -4 5.12:1 — all four clear WCAG AA for body text, and the first
     three clear AAA. Reserve -4 for labels and disabled states by HIERARCHY,
     not because it fails contrast. The brand primary cannot be used on ink at
     all (#0E4AAA is 2.19:1 — fails), which is why --ink-primary is brightened
     to #4D9BFF (6.33:1, AA) with --ink-primary-2 at 8.17:1 (AAA).

     CAVEAT on the two structural steps: --ink-line (1.48:1) and --ink-hover
     (1.74:1) are below the 3:1 that WCAG 1.4.11 asks of meaningful UI
     boundaries. They are fine as decorative dividers and hover washes — which
     is all the ink chrome uses them for — but if a boundary is the ONLY thing
     conveying a control's extent or state, do not rely on them alone. */
  --ink:#0F172A;                /* default ink chrome */
  --ink-2:#172033;              /* panel on ink */
  --ink-3:#243049;              /* raised panel on ink */
  --ink-deep:#0C1424;           /* frame behind ink panels — deepest step */
  --ink-raised:#1F2A40;         /* card/well on ink */
  --ink-line:#2A3650;           /* divider / border on ink */
  --ink-hover:#33415A;          /* hover + active on ink */
  --ink-text-1:#E4EBF6;         /* primary text on ink */
  --ink-text-2:#CDD8EA;         /* body text on ink */
  --ink-text-3:#9FB0CC;         /* labels on ink */
  --ink-text-4:#7C8AA3;         /* dimmest — labels/disabled only, not body */
  --ink-primary:#4D9BFF;        /* primary action on ink (brightened for contrast) */
  --ink-primary-2:#7FB3F0;      /* primary hover / secondary accent on ink */

  --success: hsl(var(--success-3));
  --success-ink: hsl(var(--success-2));
  --success-soft: hsl(var(--success-5));
  --warning: hsl(var(--warning-3));             /* was #FBAC12 (Figma) → now #F4922A */
  --warning-ink: hsl(var(--warning-2));
  --warning-soft: hsl(var(--warning-5));
  --danger: hsl(var(--error-3));                /* was #FA3232 → now #DF3D20 */
  --danger-soft: hsl(var(--error-5));

  /* projection/forecast accent — app-specific, not a count-web token.
     Retained as a named data-viz accent only. */
  --projection:#FF671F;
  --projection-ink:#e55a1a;
  --projection-soft:rgba(255,103,31,.12);

  --text-1: hsl(var(--text-base-1));
  --text-2: hsl(var(--text-base-2));
  --text-3: hsl(var(--text-base-3));
  --text-muted: hsl(var(--text-base-4));

  --border: 214.3, 31.8%, 91.4%; /* @kind color */ /* HSL component, count-web-aligned. Consume via hsl(var(--border)) or var(--color-border). */
  --border-2: hsl(var(--line-secondary-2));
  --bg: hsl(var(--surface-background-1));
  --surface:#ffffff;
  --surface-2: hsl(var(--surface-secondary-2));


  /* ---------- BRAND MARK ----------
     The two tones the logo itself is drawn in. These are NOT the UI action
     colour: --action-primary (#0E4AAA) is for buttons, links and active state;
     these are for the mark, the wordmark, and the brand name when it is set in
     type (Speed in --brand-light, Goat in --brand-dark; Goat goes white on ink
     chrome, where the dark tone disappears).
     Source: the brand-kit lockups in design/brand-source/ — three files agree on
     this pair, and it matches the historical favicon.
     The ribbon palette's --vb-high and --vb-medium, and map strata 2 and 5, were
     #004672 and #0D7DC5 — the same two colours carrying export drift. They now
     reference these, so the brand pair has exactly one definition. */
  --brand-dark:#004673;   /* @kind color */
  --brand-light:#0f7dc3;  /* @kind color */

  /* data ribbon palette (value boxes, categorical series) — app data-viz ramp */
  --vb-high: var(--brand-dark);
  --vb-medium: var(--brand-light);
  --vb-dark:#0A5A9C;
  --vb-grey:#64748b;
  --vb-low:#5D6578;
}


/* ===== Typography ===== */
/* ============================================================
   SpeedGoat — Typography tokens
   UI face: Inter. Numerics/code: IBM Plex Mono.
   The scale below reflects sizes used across the IPM tool.
   ============================================================ */
:root{
  /* --- families --- */
  --ui:"Inter", system-ui, -apple-system, sans-serif; /* @kind font */
  --mono:"IBM Plex Mono", ui-monospace, "SF Mono", monospace; /* @kind font */

  /* --- weights --- */
  --w-regular:400; /* @kind font */
  --w-medium:500; /* @kind font */
  --w-semibold:600; /* @kind font */
  --w-bold:700; /* @kind font */
  --w-heavy:800; /* @kind font */ /* metric values, key figures */

  /* --- type scale (px) --- */
  --fs-display:23px;  /* headline metric values */
  --fs-h1:21px;       /* section / placeholder titles */
  --fs-h2:17px;       /* card titles */
  --fs-lg:15px;       /* brand name, emphasized body */
  --fs-base:14.5px;   /* body default */
  --fs-body:13.5px;   /* dense body, buttons */
  --fs-sm:12.5px;     /* controls, pills, secondary */
  --fs-xs:11.5px;     /* captions, links */
  --fs-2xs:11px;      /* stat labels */
  --fs-micro:9.5px;   /* uppercase eyebrow labels */

  /* --- tracking --- */
  --track-tight:-.02em;  /* large / heavy figures */
  --track-snug:-.01em;
  --track-wide:.04em;    /* uppercase labels */
  --track-caps:.08em;    /* small caps eyebrows */

  /* --- line height --- */
  --lh-tight:1.1; /* @kind font */
  --lh-snug:1.3; /* @kind font */
  --lh-body:1.55; /* @kind font */
}


/* ===== Spacing & radius ===== */
/* ============================================================
   SpeedGoat — Spacing, radius & density tokens

   RADIUS IS NAMESPACED, ON PURPOSE. shadcn/ui — which both count-web
   and telemetry-web are built on — defines --radius (0.5rem = 8px),
   --radius-sm (calc(--radius - 4px) = 4px) and --radius-md
   (calc(--radius - 2px) = 6px). This system's brand radii are 13/9/6,
   so the same three names carried different values in the two places.
   An app linking dist/speedgoat.css would have had every shadcn
   component silently reshaped by stylesheet load order — cards 8→13px,
   anything rounded-sm 4→9px — with nothing in the app changed to cause
   it. That is the --primary/--border collision fixed at v2.0.0, in a
   different guise.

   --sg-* cannot collide, so adopting the stylesheet no longer changes
   an app's geometry. A consuming app opts in by referencing --sg-radius*
   explicitly, or by mapping its own --radius onto ours.
   ============================================================ */
:root{
  --pad:20px;        /* card interior padding */
  --gap:18px;        /* grid / stack gap */
  --fs:14.5px;       /* base font-size hook (density-linked) */

  --sg-radius:13px;     /* cards, panels */
  --sg-radius-sm:9px;   /* controls, buttons, small cards */
  --sg-radius-md:6px;   /* shadcn rounded-md — buttons, inputs, selects */
  --sg-radius-xs:6px;   /* chips, inline tags */

  /* discrete step values used across layouts */
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:14px;
  --space-5:18px;
  --space-6:22px;
  --space-7:28px;
}

/* Density modes — set data-density on a container to rescale. */
[data-density="compact"]{ --pad:14px; --gap:12px; --fs:13.5px; --sg-radius:10px; }
[data-density="comfy"]{ --pad:28px; --gap:24px; --fs:15.5px; --sg-radius:15px; }


/* ===== Effects ===== */
/* ============================================================
   SpeedGoat — Elevation & effect tokens
   Shadows are soft, low-spread, slate-tinted. Cards lean on
   a hairline border + faint shadow rather than heavy elevation.
   ============================================================ */
:root{
  --shadow:0 1px 2px rgba(15,23,42,.05), 0 2px 6px rgba(15,23,42,.04);   /* resting card */
  --shadow-pop:0 8px 28px rgba(15,23,42,.16);                            /* popovers, menus, modals */

  /* accent shadows for filled buttons */
  --shadow-primary:0 1px 2px rgba(0,0,0,.20);
  --shadow-success:0 1px 3px rgba(54,186,104,.40);

  --focus-ring:0 0 0 3px rgba(14,74,170,.28);   /* keyboard focus */
  --hairline:1px solid var(--color-border);
}

/* ============================================================
   Motion

   README documents the motion rule — "fast and functional: 0.13–0.22s ease …
   no bounce, no spring, no entrance animation on content" — but shipped no
   token for it, so every surface hardcoded its own duration and none of them
   honoured a reduced-motion preference. Flagged by the ipm-tool regeneration,
   whose loading state honoured the query the system itself did not.

   --motion-fast   micro-feedback: color, background, border on hover/press
   --motion-base   the default for transform and layout-affecting changes
   --motion-slow   the top of the documented range — rail collapse, drawers

   prefers-reduced-motion is a stated accessibility need, not a preference to
   weigh: vestibular disorders make large transform animation genuinely
   unpleasant. Durations collapse to ~0 rather than to `none` so that
   transitionend / animationend listeners still fire and no state machine that
   waits on them can hang.
   ============================================================ */
:root{
  --motion-fast:.13s;   /* @kind other */
  --motion-base:.18s;   /* @kind other */
  --motion-slow:.22s;   /* @kind other */
  --motion-ease:ease;   /* @kind other */
}

@media (prefers-reduced-motion: reduce){
  :root{
    --motion-fast:.01ms;   /* @kind other */
    --motion-base:.01ms;   /* @kind other */
    --motion-slow:.01ms;   /* @kind other */
  }
  /* Catch-all for anything not yet routed through the tokens above. */
  *, *::before, *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}


/* ===== Prose (rendered markdown) ===== */
/* ============================================================
   SpeedGoat — Prose (`.sg-prose`)
   Long-form rendered output: markdown, Rmd/Quarto reports, vignettes.

   WHY THIS EXISTS. Markdown is one of the estate's larger surfaces and none of
   it was branded:
     * 17 pkgdown sites, every one on plain `template: bootstrap: 5`;
     * `includeMarkdown()` About/contact pages in 8+ Shiny apps;
     * `spdgt.assist`'s chat gadget, which renders md → HTML and already takes a
       `css` argument with nothing to give it;
     * six copies of the IPM Analysis Report, all `theme: spacelab` with their
       stylesheet fetched from a **Google Drive URL**.
   The token layer had a type SCALE but nothing that applied it to a document.

   HOW TO USE IT. Wrap the rendered HTML, don't restyle it:
     Shiny:   div(class = "sg-prose", includeMarkdown("www/About.md"))
     Rmd:     <div class="sg-prose"> … </div>, or set it on <body>
     gadget:  pass `css` pointing at speedgoat.css and wrap the message body

   SCOPED ON PURPOSE. Every rule is under `.sg-prose`, so linking
   speedgoat.css cannot restyle an app's own headings and tables — the mistake
   that made the radius namespacing necessary. Nothing here is an element
   selector at top level.

   Uses only semantic tokens, so `[data-theme="dark"]` inverts it for free —
   there is deliberately no dark block in this file. Verified by gate 12, which
   now also scans this file for var() references that do not resolve.
   ============================================================ */

.sg-prose{
  font-family:var(--ui);
  font-size:var(--fs-base);
  line-height:var(--lh-body);
  color:var(--text-1);
  /* A measure, not a full-bleed column. Long-form text past ~78 characters is
     measurably harder to track back to the next line, and these reports are
     read on wide dashboards. Override with `max-width` where a table needs it. */
  max-width:78ch;
}
.sg-prose > :first-child{ margin-top:0; }
.sg-prose > :last-child{ margin-bottom:0; }

/* --- headings: the existing scale, not new sizes --------------------------- */
.sg-prose h1,
.sg-prose h2,
.sg-prose h3,
.sg-prose h4,
.sg-prose h5,
.sg-prose h6{
  font-family:var(--ui);
  color:var(--text-1);
  line-height:var(--lh-snug);
  letter-spacing:var(--track-snug);
  margin:1.9em 0 .6em;
}
.sg-prose h1{ font-size:var(--fs-h1); font-weight:var(--w-bold); letter-spacing:var(--track-tight); }
.sg-prose h2{ font-size:var(--fs-h2); font-weight:var(--w-semibold); }
.sg-prose h3{ font-size:var(--fs-lg); font-weight:var(--w-semibold); }
.sg-prose h4{ font-size:var(--fs-base); font-weight:var(--w-semibold); }
/* h5/h6 become eyebrow labels rather than shrinking below body size — the IPM
   report nests four levels deep (## Abundance → #### Preseason Abundance). */
.sg-prose h5,
.sg-prose h6{
  font-size:var(--fs-micro);
  font-weight:var(--w-bold);
  text-transform:uppercase;
  letter-spacing:var(--track-caps);
  color:var(--text-3);
}
/* A rule under the top two levels, the way the report's sections read. */
.sg-prose h1,
.sg-prose h2{
  padding-bottom:.3em;
  border-bottom:1px solid hsl(var(--line-secondary-3));
}

/* --- body ----------------------------------------------------------------- */
.sg-prose p{ margin:0 0 1.05em; }
.sg-prose strong{ font-weight:var(--w-semibold); color:var(--text-1); }
.sg-prose small{ font-size:var(--fs-sm); color:var(--text-2); }
.sg-prose hr{
  border:0;
  border-top:1px solid hsl(var(--line-secondary-3));
  margin:2em 0;
}

/* --- links: brand blue, underlined. Underline is not decoration here — these
       documents get printed and read at a glance, and colour alone is not an
       accessible affordance. ------------------------------------------------ */
.sg-prose a{
  color:var(--color-action-primary);
  text-decoration:underline;
  text-underline-offset:2px;
  text-decoration-thickness:1px;
}
.sg-prose a:hover{ color:hsl(var(--action-primary-hovered)); }

/* --- lists ---------------------------------------------------------------- */
.sg-prose ul,
.sg-prose ol{ margin:0 0 1.05em; padding-left:1.4em; }
.sg-prose li{ margin:.3em 0; }
.sg-prose li > ul,
.sg-prose li > ol{ margin:.3em 0; }
.sg-prose li::marker{ color:var(--text-3); }
.sg-prose dt{ font-weight:var(--w-semibold); margin-top:.8em; }
.sg-prose dd{ margin:.2em 0 0 1.4em; color:var(--text-2); }

/* --- numbers are monospaced and tabular ----------------------------------
   The brand's most-lost rule: every number, metric and code value uses
   var(--mono). In a report that means inline code AND table cells, because a
   column of proportional digits does not align and cannot be scanned. */
.sg-prose code,
.sg-prose kbd,
.sg-prose samp{
  font-family:var(--mono);
  font-size:.92em;
  font-variant-numeric:tabular-nums;
}
.sg-prose :not(pre) > code{
  background:hsl(var(--surface-secondary-1));
  color:var(--text-1);
  padding:.1em .38em;
  border-radius:var(--sg-radius-xs);
}
.sg-prose pre{
  font-family:var(--mono);
  font-size:var(--fs-sm);
  line-height:var(--lh-snug);
  background:hsl(var(--surface-secondary-1));
  border:1px solid hsl(var(--line-secondary-3));
  border-radius:var(--sg-radius-md);
  padding:12px 14px;
  overflow-x:auto;
  margin:0 0 1.05em;
}
.sg-prose pre > code{ background:none; padding:0; border-radius:0; }

/* --- tables: the report is mostly tables ---------------------------------- */
.sg-prose table{
  border-collapse:collapse;
  width:100%;
  font-size:var(--fs-sm);
  margin:0 0 1.3em;
  /* Numeric columns must align, so the whole table is tabular. */
  font-variant-numeric:tabular-nums;
}
.sg-prose thead th{
  text-align:left;
  font-size:var(--fs-micro);
  font-weight:var(--w-bold);
  text-transform:uppercase;
  letter-spacing:var(--track-wide);
  color:var(--text-3);
  padding:0 10px 7px;
  border-bottom:1px solid hsl(var(--line-secondary-3));
  white-space:nowrap;
}
.sg-prose tbody td,
.sg-prose tbody th{
  padding:7px 10px;
  border-bottom:1px solid hsl(var(--line-secondary-4));
  vertical-align:top;
}
.sg-prose tbody tr:last-child td{ border-bottom:0; }
.sg-prose caption{
  caption-side:bottom;
  text-align:left;
  font-size:var(--fs-xs);
  color:var(--text-3);
  padding-top:8px;
}

/* --- blockquote: used for the report's "Using this report" guidance -------- */
.sg-prose blockquote{
  margin:0 0 1.05em;
  padding:2px 0 2px 14px;
  border-left:3px solid hsl(var(--line-secondary-2));
  color:var(--text-2);
}
.sg-prose blockquote > :last-child{ margin-bottom:0; }

/* --- figures -------------------------------------------------------------- */
.sg-prose img{ max-width:100%; height:auto; border-radius:var(--sg-radius-md); }
.sg-prose figure{ margin:0 0 1.3em; }
.sg-prose figcaption{
  font-size:var(--fs-xs);
  color:var(--text-3);
  padding-top:6px;
}

/* --- a wide variant, for a report that is mostly tables ------------------
   `.sg-prose.sg-prose-wide` drops the measure. Separate rather than an
   override so a consumer opts in per document instead of fighting max-width. */
.sg-prose-wide{ max-width:none; }


/* ===== Background image ===== */
/* ============================================================
   SpeedGoat — Background image
   The shared brand backdrop (soft layered mountains) used across the
   SpeedGoat apps. Optimized to webp/avif (~15 KB, was ~1.6 MB PNG).
   Binaries live in assets/ (source) and dist/ (distributable); the
   url()s below are relative, so they resolve from either location —
   exactly like assets/fonts.css.
     • light backdrop in :root
     • dusk variant in the [data-theme="dark"] scope
   ============================================================ */
:root{
  --bg-image: image-set(
    url("speedgoat-bg.avif") type("image/avif"),
    url("speedgoat-bg.webp") type("image/webp")); /* @kind other */
}
[data-theme="dark"], .dark{
  --bg-image: image-set(
    url("speedgoat-bg-dark.avif") type("image/avif"),
    url("speedgoat-bg-dark.webp") type("image/webp")); /* @kind other */
}

/* Full-bleed brand canvas. Put .sg-canvas on <body> (or a full-height
   wrapper). Mirrors what the apps set by hand: cover / center / fixed.
   The first background-image is a plain fallback for engines without
   image-set(); var(--bg-image) wins everywhere else and follows the
   dark scope automatically. */
.sg-canvas{
  background-image: url("speedgoat-bg.webp");
  background-image: var(--bg-image);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center center;
  background-attachment: fixed;
}


/* ===== Map tokens (Leaflet) ===== */
/* ============================================================
   SpeedGoat — Map tokens  (Leaflet)
   Canonicalizes the hardcoded literals in count-web's map layers
   (map/, map-as-lines/, canvas-pin-marker) so every map draws from
   one place instead of inline hex.

   Colour rule holds on maps too: ONE brand hue. The stratum ramp is
   a blue→neutral progression, not a rainbow — green/amber/red stay
   status-only, and --projection stays forecast-only.
   ============================================================ */
:root{
  /* ---------- polygons: management units & subunits ---------- */
  --map-boundary-stroke: hsl(var(--text-base-1)); /* @kind color */ /* outer management-unit outline (was "black") */
  --map-unit-stroke: hsl(var(--line-secondary-2)); /* @kind color */ /* resting subunit edge (was #b1b1b1) */
  --map-unit-stroke-selected: hsl(var(--base-invert)); /* @kind color */ /* selected subunit edge */
  --map-unit-fill-selected: hsl(var(--text-base-1)); /* @kind color */ /* selected subunit body (was #000000) */

  /* ---------- lines & transects ---------- */
  --map-line: hsl(var(--action-primary)); /* @kind color */ /* default transect (was #2560BC — stale Figma primary) */
  --map-line-hovered: hsl(var(--warning-3)); /* @kind color */ /* hovered transect (was #F0953C) */

  /* ---------- point markers ---------- */
  --map-marker-dot: hsl(var(--base-invert)); /* @kind color */ /* centre dot of a radius marker */
  --map-marker-ring: hsl(var(--action-primary)); /* @kind color */ /* fallback when no stratum colour applies */

  /* ---------- stratum ramp ----------
     Strata normally carry a data-driven `mapColor`. This is the
     fallback ramp when they don't — 9 steps to match the nine
     stratified variants the design library defines. */
  --map-stratum-1: hsl(var(--primary-1)); /* @kind color */
  --map-stratum-2: var(--brand-dark); /* @kind color */
  --map-stratum-3:#0A5A9C; /* @kind color */
  --map-stratum-4: hsl(var(--action-primary)); /* @kind color */
  --map-stratum-5: var(--brand-light); /* @kind color */
  --map-stratum-6: hsl(var(--primary-3)); /* @kind color */
  --map-stratum-7: hsl(var(--primary-4)); /* @kind color */
  --map-stratum-8: hsl(var(--primary-5)); /* @kind color */
  --map-stratum-9:#5D6578; /* @kind color */

  /* ---------- geometry ----------
     Unitless so they can be read straight into Leaflet pathOptions. */
  --map-weight:2;                  /* resting stroke */
  --map-weight-selected:4;         /* selected stroke */
  --map-weight-hit:10;             /* invisible hit area on lines */
  --map-dash:6 6;                  /* @kind other */ /* design/planned geometry */
  --map-fill-opacity:.6;           /* resting fill */
  --map-fill-opacity-selected:.7;  /* selected fill */
  --map-marker-radius:10;          /* default marker radius, px */
  --map-point-radius:50;           /* default point radius, metres */
}


/* ===== Dark theme scope ===== */
/* ============================================================
   SpeedGoat — Dark theme scope
   Opt-in: set data-theme="dark" (or class="dark") on <html> or any
   container. Remaps the HSL semantic scales + the few hard-coded
   aliases so every token-driven component follows. The ink chrome
   (header/sidebar) already reads dark and is unchanged.
   ============================================================ */
[data-theme="dark"], .dark{
  /* surfaces & background */
  --background: 208, 80%, 8%;      /* @kind color */
  --foreground: 210, 40%, 96%;     /* @kind color */
  --card: 212, 45%, 12%;           /* @kind color */
  --muted: 214, 30%, 18%;          /* @kind color */
  --surface:#0f1a2e;
  --surface-secondary-1: 214, 30%, 16%;  /* @kind color */
  --surface-secondary-2: 213, 35%, 14%;  /* @kind color */
  --surface-background-1: 208, 62%, 9%;  /* @kind color */
  --surface-background-2: 213, 35%, 12%; /* @kind color */

  /* text ramp */
  --text-base-1: 210, 40%, 96%;    /* @kind color */
  --text-base-2: 214, 25%, 82%;    /* @kind color */
  --text-base-3: 215, 18%, 66%;    /* @kind color */
  --text-base-4: 215, 16%, 52%;    /* @kind color */
  --text-primary-2: 212, 90%, 74%; /* links / primary text on dark @kind color */
  --text-primary-3: 212, 90%, 74%; /* @kind color */

  /* lines / borders */
  --line-primary-3: 213, 45%, 42%; /* @kind color */
  --line-primary-4: 214, 28%, 22%; /* @kind color */
  --line-secondary-2: 215, 18%, 42%; /* @kind color */
  --line-secondary-3: 215, 24%, 22%; /* @kind color */
  --line-secondary-4: 215, 26%, 18%; /* @kind color */
  --border: 215, 24%, 22%;           /* @kind color */ /* count-web --border component, dark-aware */

  /* primary wash / focus tint */
  --primary-5: 214, 50%, 22%;      /* @kind color */

  /* feedback soft fills (tinted for dark) */
  --success-5: 143, 42%, 15%;      /* @kind color */
  --warning-5: 33, 48%, 16%;       /* @kind color */
  --error-5: 8, 48%, 17%;          /* @kind color */

  /* elevation reads via borders on dark; keep a soft ambient shadow */
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 2px 8px rgba(0,0,0,.35);
  --shadow-pop:0 10px 32px rgba(0,0,0,.55);
}
