/* ============================================================
   VENDORED FILE — do not hand-edit.
   Source: chimerical-design-system/tokens/tokens.css
   Synced: 2026-09-03  (design-system commit 61c99b3)
   Re-sync: chimerical-design-system/integrations/sync-vendored.sh tokens/tokens.css public/css/chimerical-tokens.css
   ============================================================ */
/* ============================================================
   CHIMERICAL DESIGN SYSTEM — tokens
   Package: @chimerical/design-system — see package.json for version.
   Direction "Structured Technical" — chosen 2026-08-28 after a 3-way
   review (see /showcase for the other two explored directions, archived
   for reference, not for reuse).

   THIS IS THE SINGLE SOURCE OF TRUTH. Consuming apps (Forge, Muster,
   chimerical-ventures-website, and any future app) must import or vendor
   this file mechanically (npm dependency for Vite/Node apps; a version-
   stamped copy via integrations/sync-vendored.sh for static/Blade
   consumers with no build step) — never hand-retype these values. A
   2026-08-28 incident (Muster's marketing/login pages rebuilt from
   memory instead of this file) shipped visibly wrong font-weights and
   button metrics despite using the same token *names* — see
   integrations/README.md for the fix and the vendoring convention.

   Usage: link this file, then optionally the Google Fonts stylesheet
   below, before any component CSS.

   Theme resolution (changed 2026-08-28 — was dark-default; Josh: "Default
   to light mode, and follow the system mode if available"):
     1. No explicit choice -> follow prefers-color-scheme (light if the
        system has no preference or prefers light; dark if it prefers dark).
     2. Explicit choice -> documentElement.dataset.theme = "light" | "dark"
        always wins over system preference, in either direction.
   The bare :root below carries the LIGHT values (the fallback when there
   is no system dark preference and no explicit choice) — do not add a
   third copy of the palette anywhere; every other state derives from the
   two blocks below via :root[data-theme] and the dark media query.
   ============================================================ */

/* wght@400..800 (a range, not a semicolon list) requests Google Fonts'
   actual variable-weight file — required for any non-static weight used
   in this system (e.g. font-weight: 650 on headings). A semicolon list
   of static cuts only serves those exact weights; the browser then
   snaps an in-between request like 650 to the nearest static face
   instead of truly interpolating it — this was the exact bug behind the
   2026-08-28 Muster incident referenced above. */
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@400..800&family=IBM+Plex+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&display=swap');

:root {
  /* ── Surfaces — light (default) ── */
  --bg: #f4f5f6;
  --surface: #ffffff;
  --card: #ffffff;
  --border: rgba(10,10,11,0.10);
  --hair: rgba(10,10,11,0.06);

  /* Persistently-dark app-shell chrome (e.g. DomainNav's icon rail) —
     NOT a themed surface; deliberately darker than --surface in both
     themes, matching nav-concept-c-dual-side-nav.html. */
  --rail-dark: #17181a;

  --text: #111214;
  --text-2: #53565c;
  --text-3: #666a70;

  --accent: #12a668;
  --accent-bright: #0b7a4a;
  --accent-tint: rgba(18,166,104,0.08);
  --on-accent: #111214;

  /* --success intentionally uses a value deeper than --accent-bright, not
     --accent, as TEXT on light backgrounds: raw --accent (#12a668) is only
     2.88:1 on --bg here. All three semantic text colours below are darkened
     one step further than the bare-bg contrast strictly requires, because
     the real usage (a status badge) sits on a low-opacity tint of the same
     colour, not pure --bg — verified >=4.5:1 against that tinted
     background specifically, not just against --bg. */
  --success: #096b40;
  --warning: #a34019;
  --danger: #b02a32;
  --danger-fill: #c32f38;
  --info: #265c94; /* darkened from #2f6fb0 — 3.98:1 against a tinted (not pure) background is
                       under AA; matches the same darken-for-tinted-use fix already applied to
                       success/warning/danger. */
  --success-tint: rgba(9,107,64,0.08);
  --warning-tint: rgba(163,64,25,0.08);
  --danger-tint: rgba(176,42,50,0.08);
  --info-tint: rgba(38,92,148,0.08);

  /* ── Type ── */
  --font-display: "Sora", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;

  /* ── Shape ── */
  --radius-sm: 3px;
  --radius: 4px;
  --radius-lg: 6px;
  --radius-pill: 999px;

  /* ── Layout ── */
  --maxw: 1152px; /* page content max-width — matches Forge's existing convention */

  /* ── Spacing scale (4px base) — prefer these over ad-hoc px values ── */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* ── Breakpoints (px) — reference values; media queries can't read
       custom properties, so treat these as the source of truth to copy
       into @media rules, not something to var()-reference directly ── */
  --bp-sm: 640;
  --bp-md: 900;
  --bp-lg: 1240;

  color-scheme: light;
}

/* ── Surfaces — dark. Fires when the system prefers dark AND there's no
     explicit data-theme="light" override pinning it to light regardless. ── */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0a0a0b;
    --surface: #111113;
    --card: #151517;
    --border: rgba(255,255,255,0.07);
    --hair: rgba(255,255,255,0.05);
    --rail-dark: #050506;

    /* text-3 is calibrated to clear WCAG AA (4.5:1) against --bg — it is
       used for real small-text labels (mono captions, counts), not purely
       decorative dimming, so it must pass as text, not just "look subtle". */
    --text: #e7e7ea;
    --text-2: #9a9aa3;
    --text-3: #84848f;

    --accent: #3ecf8e;
    --accent-bright: #6fe3ac;
    --accent-tint: rgba(62,207,142,0.10);
    /* Label colour for text/icons placed ON a solid --accent fill (e.g. a
       primary button) — deliberately dark in both themes, since --accent is
       a mid-tone green in both and light text on it fails contrast in
       light mode specifically. Verified >=4.5:1 against --accent in both
       themes. */
    --on-accent: #0a0a0b;

    /* Semantic (status) — separate from the brand accent, never used for
       ordinary UI chrome. Each is calibrated as TEXT on --bg (badges,
       alert copy, links) — verified >=4.5:1 in both themes. --danger-fill
       is a second, darker value for the one case a semantic colour is
       used as a solid button fill with white text; --danger itself is too
       light for that in dark mode even though it's correct as text. */
    --success: #3ecf8e;
    --warning: #e0913f;
    --danger: #e5484d;
    --danger-fill: #c23238;
    --info: #5b9fe0;
    --success-tint: rgba(62,207,142,0.10);
    --warning-tint: rgba(224,145,63,0.10);
    --danger-tint: rgba(229,72,77,0.10);
    --info-tint: rgba(91,159,224,0.10);

    color-scheme: dark;
  }
}

/* ── Explicit override: data-theme="dark" always wins, even if the system
     itself prefers light — same values as the media-query block above,
     just triggered by attribute instead of system preference. ── */
:root[data-theme="dark"] {
  --bg: #0a0a0b;
  --surface: #111113;
  --card: #151517;
  --border: rgba(255,255,255,0.07);
  --hair: rgba(255,255,255,0.05);
  --rail-dark: #050506;
  --text: #e7e7ea;
  --text-2: #9a9aa3;
  --text-3: #84848f;
  --accent: #3ecf8e;
  --accent-bright: #6fe3ac;
  --accent-tint: rgba(62,207,142,0.10);
  --on-accent: #0a0a0b;
  --success: #3ecf8e;
  --warning: #e0913f;
  --danger: #e5484d;
  --danger-fill: #c23238;
  --info: #5b9fe0;
  --success-tint: rgba(62,207,142,0.10);
  --warning-tint: rgba(224,145,63,0.10);
  --danger-tint: rgba(229,72,77,0.10);
  --info-tint: rgba(91,159,224,0.10);
  color-scheme: dark;
}

/* ── Explicit override: data-theme="light" always wins, even if the system
     prefers dark. Redundant with the bare :root values above (already
     light) but kept explicit so the three-state pattern stays symmetric
     and obvious to read — never rely on specificity alone here. ── */
:root[data-theme="light"] {
  --bg: #f4f5f6;
  --surface: #ffffff;
  --card: #ffffff;
  --border: rgba(10,10,11,0.10);
  --hair: rgba(10,10,11,0.06);
  --rail-dark: #17181a;
  --text: #111214;
  --text-2: #53565c;
  --text-3: #666a70;
  --accent: #12a668;
  --accent-bright: #0b7a4a;
  --accent-tint: rgba(18,166,104,0.08);
  --on-accent: #111214;
  --success: #096b40;
  --warning: #a34019;
  --danger: #b02a32;
  --danger-fill: #c32f38;
  --info: #265c94;
  --success-tint: rgba(9,107,64,0.08);
  --warning-tint: rgba(163,64,25,0.08);
  --danger-tint: rgba(176,42,50,0.08);
  --info-tint: rgba(38,92,148,0.08);
  color-scheme: light;
}

* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  transition: background 0.15s ease, color 0.15s ease;
}
a { color: inherit; }

/* ── Focus — every interactive element, everywhere, gets this ring.
     Never rely on a browser default outline or a border-colour-only change
     (too easy to miss, especially for low-vision users) — this is a real
     3px ring in the accent colour with a soft halo, applied via
     :focus-visible so it only shows for keyboard focus, not every mouse
     click. Consuming apps should not override this per-component; if a
     component needs a different focus treatment, change it here so every
     app stays consistent. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  /* accent-bright, not accent — plain --accent is only 2.88:1 against the
     light-mode background, under the 3:1 WCAG 1.4.11 minimum for a
     non-text UI indicator like a focus ring. accent-bright clears >=4.9:1
     in both themes. */
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}

/* ── Scroll-reveal — pair with the useScrollReveal composable (fades in
     once, on first intersection). Reduced-motion is handled above (the
     global transition-duration collapse), not here. ── */
.cds-rise { opacity: 0; transform: translateY(18px); transition: opacity 0.7s ease, transform 0.7s ease; }
.cds-rise.in { opacity: 1; transform: none; }

.tabular { font-variant-numeric: tabular-nums; }
.label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}
