/* ============================================================================
   panchos — design tokens. Single source of truth for palette, type, spacing
   and motion. Landing, dashboard and the Keycloak theme all read from here, so
   the login screen cannot drift away from the rest of the site.

   CHOSEN 2026-07-28: Acid accent, Clash Display + JetBrains Mono. The rejected
   options and their font files were deleted rather than left switchable — a
   token file full of dormant alternatives stops being a source of truth.
   ============================================================================ */

/* ── faces ───────────────────────────────────────────────────────────────
   All self-hosted, all free: Clash Display is Fontshare's licence (commercial
   use permitted); Space Grotesk and JetBrains Mono are SIL OFL 1.1. No CDN —
   the front door should not wait on a third party, and the entry sequence is
   the first thing anyone sees. 90KB for all three, latin subsets. */
@font-face{font-family:'Clash Display';src:url('/fonts/clash-display.woff2') format('woff2-variations');
  font-weight:200 700;font-display:block}
@font-face{font-family:'Space Grotesk';src:url('/fonts/space-grotesk.woff2') format('woff2-variations');
  font-weight:300 700;font-display:block}
@font-face{font-family:'JetBrains Mono';src:url('/fonts/jetbrains-mono.woff2') format('woff2-variations');
  font-weight:100 800;font-display:swap}

:root{
  /* ── base ──────────────────────────────────────────────────────────────
     NOTE: --bg is TRUE BLACK, not #0a0a0a, and that is a deliberate
     departure from the brief, agreed 2026-07-28. The
     portrait on the landing page is composed on true black; lifting the page
     to #0a0a0a makes its surround read as a darker rectangle. The near-black
     values live on the elevated surfaces instead, where they do the same job. */
  --bg:#000000;
  --s1:#0a0a0b;  --s2:#121213;  --s3:#1b1b1d;

  /* warm neutral text ramp — these lean brown, not blue, and that warmth is
     what keeps a black page from feeling clinical */
  --text:#f4f1ea;  --dim:#b3ada2;  --muted:#7d766b;  --faint:#4a4540;
  --line:rgba(255,255,255,.07);  --line-hi:rgba(255,255,255,.16);

  /* ── accent ────────────────────────────────────────────────────────────
     ACID — exactly one electric accent, used sparingly: the primary action,
     the liveness dot, the hairline a tile draws on hover, focus rings. It is
     never body text. --on-accent is the colour that sits ON it; lime needs
     near-black, and getting that pair wrong is the usual way accents go ugly. */
  --accent:#c6f24e;  --accent-dim:#9ab93b;  --on-accent:#0a0a0b;
  --accent-glow:rgba(198,242,78,.16);
}

:root{
  /* ── type ──────────────────────────────────────────────────────────────
     Clash for display, the existing Space Grotesk for UI, JetBrains Mono for
     anything that reads as an instrument: clock, stats, status, tile numbers. */
  --display:'Clash Display', ui-sans-serif, system-ui, sans-serif;  /* headings only */
  --ui:'Space Grotesk', ui-sans-serif, system-ui, sans-serif;       /* interface */
  --mono:'JetBrains Mono', ui-monospace, SFMono-Regular, monospace; /* readouts */
  --display-weight:600;
  --display-track:-.045em;
  /* Clash's word space is narrow to begin with (11px at 60px, where Space
     Grotesk gives ~15) and the negative tracking shaves it to 8.3 — at heading
     sizes "Sign in to your account" closed up into one word. This buys the
     gaps back without loosening the letterforms, which are the point. */
  --display-word:.1em;

  /* fluid scale. Display tops out near 12vw; the clamp floor keeps it legible
     on a 360px phone and the ceiling stops it exploding on an ultrawide. */
  --t-display:clamp(42px, 11.5vw, 168px);
  --t-h1:clamp(30px, 5.2vw, 64px);
  --t-h2:clamp(20px, 2.4vw, 30px);
  --t-body:clamp(14px, 1.05vw, 16px);
  --t-ui:13.5px;
  --t-mono:11.5px;
  --t-micro:10.5px;

  /* ── spacing ───────────────────────────────────────────────────────────
     One 4px-derived ramp. Everything laid out on the page picks from here so
     rhythm stays consistent between landing and dashboard. */
  --sp-1:4px;  --sp-2:8px;   --sp-3:12px;  --sp-4:16px;  --sp-5:24px;
  --sp-6:32px; --sp-7:48px;  --sp-8:64px;  --sp-9:96px;  --sp-10:144px;
  --radius-pill:9999px;   /* actions */
  --radius-field:10px;    /* inputs */
  --radius-card:16px;     /* containers */
  --measure:46ch;
  --shell:1120px;

  /* ── motion vocabulary ─────────────────────────────────────────────────
     Defined once, reused everywhere. One signature curve for everything that
     moves; the only exception is --ease-out-fast for things leaving, because
     an exit that lingers reads as lag. */
  --ease:cubic-bezier(.22,1,.36,1);        /* signature: soft landing, no bounce */
  --ease-out-fast:cubic-bezier(.4,0,.2,1);
  --t-tap:120ms;      /* press feedback */
  --t-ui-dur:200ms;   /* hovers, colour, borders */
  --t-reveal:700ms;   /* entrances */
  --t-slow:900ms;     /* hero and scroll-driven pieces */
  --stagger:60ms;     /* per line of a split heading */
  --stagger-grid:40ms;/* per card; capped at 8 so a big grid never crawls */
  --lift:-2px;        /* the single hover displacement used site-wide */
}


/* ── reduced motion ────────────────────────────────────────────────────────
   Full respect, not a token gesture: durations collapse, transforms are
   cancelled, and anything that loops is stopped. Reveal states must be applied
   by script so that a stopped animation still leaves content VISIBLE — the
   classic failure here is content that animates in and therefore never
   appears at all. */
@media (prefers-reduced-motion: reduce){
  :root{
    --t-tap:0ms; --t-ui-dur:0ms; --t-reveal:0ms; --t-slow:0ms;
    --stagger:0ms; --stagger-grid:0ms; --lift:0px;
  }
  *, *::before, *::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
}
