/* ============================================================================
   HENDERBURGH OS — Design Tokens
   ----------------------------------------------------------------------------
   One source of truth for colour, type, radius, spacing, elevation and motion.

   WHY THIS EXISTS
   An audit of the templates found the system had drifted badly: 17 distinct
   border-radius values, ~15 near-identical dark greys drawn from THREE different
   Tailwind palettes (zinc + neutral + slate) mixed inside the same product,
   3 different "accent greens", and ~19 font sizes including 8-9px text that is
   unreadable at arm's length. Individually every page looked fine; together they
   never felt like one crafted product. This file collapses that sprawl.

   HOW TO USE
   - Prefer a token over a raw hex/px value. Always.
   - Prefer a primitive class (.hb-card, .hb-label, .hb-stat) over re-styling.
   - Tailwind utilities still work; tokens are for anything Tailwind can't express
     consistently, and for the component primitives below.
   - Adding a NEW colour/size/radius should feel like a decision, not a reflex.
     If you need one, it probably belongs here rather than in a template.

   ACCESSIBILITY NOTE
   The old `text-zinc-500` (#71717a) on the near-black background measures ~3.0:1,
   which fails WCAG AA (4.5:1) for body text — and it was used 165 times, often at
   10-11px where it matters most. --text-3 below is reserved for >=12px incidental
   text only; --text-2 is the smallest safe default for anything you must read.
   ========================================================================== */

:root {
  /* ── Colour ───────────────────────────────────────────────────────────────
     Neutral charcoal, not navy — no blue hue in the background ramp, kept
     ominous/instrument-panel dark rather than tech-blue. Backgrounds are
     never pure #000: on OLED phones pure black smears during scroll and
     makes "off" states invisible. */
  --navy-0:        #0a0a0b;   /* page */
  --navy-1:        #131316;   /* card / panel */
  --navy-2:        #1a1a1f;   /* raised, hover, input */
  --navy-3:        #232329;   /* pressed / active well */

  --bg:            var(--navy-0);
  --surface:       var(--navy-1);
  --surface-2:     var(--navy-2);
  --surface-3:     var(--navy-3);

  --line:          rgba(255, 255, 255, 0.08);   /* default hairline */
  --line-strong:   rgba(255, 255, 255, 0.14);   /* emphasised border */

  --text:          #e8edf2;   /* primary — headings, numbers */
  --text-2:        #a7b0bd;   /* secondary — passes AA at all sizes */
  --text-3:        #7a8494;   /* tertiary — >=12px incidental text ONLY */

  /* ONE accent: emerald green. Cyan is gone. --accent (brand/link/focus/
     active-nav) and --success (on/live/good state) are the same colour again
     — the split was overthinking it; the original site used one green for
     both and it read fine. Both tokens stay defined so nothing that already
     migrated onto var(--success) needs touching. */
  --accent:        #4ade80;   /* emerald — the only accent */
  --accent-rgb:    74, 222, 128;
  --accent-dim:    rgba(74, 222, 128, 0.14);
  --accent-line:   rgba(74, 222, 128, 0.32);

  --success:       #4ade80;
  --success-rgb:   74, 222, 128;
  --success-dim:   rgba(74, 222, 128, 0.14);
  --success-line:  rgba(74, 222, 128, 0.32);

  --amber:         #FFB454;   /* second accent — highlight, secondary stat */
  --violet:        #8B7FFF;   /* third accent — tertiary stat, rare use */

  --info:          #60a5fa;   /* the one blue: links, secondary state */
  --warn:          #f59e0b;   /* stale data, needs attention */
  --danger:        #f87171;   /* failure, destructive */

  /* ── Type ─────────────────────────────────────────────────────────────────
     Canonical stack (matches /vitals):
       sans    = Inter — body, card titles, UI chrome
       display = Space Grotesk — hero / page identity, big stats
       mono    = system mono — rare code-like bits only
     Labels on vitals are Inter uppercase + tracking, not mono. */
  --font-sans:    'Inter', system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: 'Space Grotesk', 'Inter', system-ui, sans-serif;
  --font-mono:    ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --t-label: 0.625rem;  /* 10px — MONO UPPERCASE LABELS ONLY, never prose */
  --t-xs:    0.75rem;   /* 12px — smallest readable incidental text */
  --t-sm:    0.8438rem; /* 13.5px — dense secondary copy */
  --t-base:  0.9375rem; /* 15px — body */
  --t-lg:    1.125rem;  /* 18px — card titles */
  --t-xl:    1.5rem;    /* 24px — section headings */
  --t-2xl:   clamp(1.75rem, 4vw, 2.25rem);   /* page headings */
  --t-hero:  clamp(2.25rem, 7vw, 3.75rem);   /* the front-door statement */

  --lh-tight: 1.1;
  --lh-snug:  1.35;
  --lh-body:  1.55;

  /* ── Radius ───────────────────────────────────────────────────────────────
     Four values, replacing seventeen. */
  --r-sm:   0.5rem;   /* 8px  — chips, inputs, small controls */
  --r-md:   0.75rem;  /* 12px — buttons, tiles */
  --r-lg:   1rem;     /* 16px — cards, panels */
  --r-full: 999px;    /* pills, dots, avatars */

  /* ── Spacing (4px base) ──────────────────────────────────────────────────*/
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.25rem;  --s-6: 1.5rem;   --s-8: 2rem;     --s-12: 3rem;

  /* ── Elevation ───────────────────────────────────────────────────────────*/
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.30);
  --shadow-md: 0 4px 12px -2px rgba(0,0,0,0.35);
  --shadow-lg: 0 16px 32px -12px rgba(0,0,0,0.45);

  /* ── Motion ──────────────────────────────────────────────────────────────
     Press is deliberately sub-100ms: on a control you tap constantly it must
     read as physical, not as an animation. Anything above ~150ms on an action
     feels like latency. Longer easing is reserved for decoration. */
  --ease-out:   cubic-bezier(0.22, 1, 0.36, 1);
  --ease-press: cubic-bezier(0.2, 0, 0, 1);
  --d-press: 80ms;
  --d-fast:  140ms;
  --d-base:  260ms;
  --d-slow:  400ms;

  /* Minimum comfortable touch target (audit found 26px toggles). */
  --tap-min: 44px;
}

/* ============================================================================
   PRIMITIVES — the small set of component classes pages should reach for.
   Prefixed `hb-` so they can be adopted incrementally without colliding with
   the existing .card / .live-card rules still in the templates.
   ========================================================================== */

/* ── Pointer-tracked spotlight glow ───────────────────────────────────────────
   The homepage's signature card hover: a soft wash that follows the cursor
   plus a gradient hairline that lights up under it. Lives here (not in one
   page's <style>) so every card on every page gets the identical effect.

   Apply by adding `.hb-spot` to a card. --mx/--my are set by the delegated
   pointermove listener in static/motion.js; they default to the card centre
   so a card still looks right before the first pointer event and on touch
   devices, where the effect never activates at all.

   Compositor-only (opacity), hover-devices only, off under reduced motion.
   Requires the element to establish a stacking context + non-static position;
   .hb-spot sets both so it works on a bare <div>. */
.hb-spot { position: relative; isolation: isolate; --mx: 50%; --my: 50%; }
.hb-spot::before,
.hb-spot::after {
  content: ''; position: absolute; inset: 0;
  opacity: 0; transition: opacity var(--d-slow) ease;
  pointer-events: none; border-radius: inherit;
}
/* the wash */
.hb-spot::before {
  z-index: -1;
  background: radial-gradient(300px circle at var(--mx) var(--my),
              rgba(var(--accent-rgb), 0.10), transparent 62%);
}
/* the lit hairline — masked to just the 1px border ring */
.hb-spot::after {
  padding: 1px;
  background: radial-gradient(220px circle at var(--mx) var(--my),
              rgba(var(--accent-rgb), 0.55), rgba(var(--accent-rgb), 0.16) 40%, transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
@media (hover: hover) {
  .hb-spot:hover::before, .hb-spot:hover::after { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hb-spot::before, .hb-spot::after { display: none; }
}

/* Surface -------------------------------------------------------------------*/
.hb-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--d-fast) ease,
              box-shadow var(--d-fast) ease,
              transform var(--d-base) var(--ease-out);
}
@media (hover: hover) {
  .hb-card:hover {
    border-color: var(--line-strong);
    box-shadow: var(--shadow-md);
  }
}

/* Instrument label — mono, uppercase, tracked. The single most effective
   "this is a control panel" signal, borrowed from the reference research. */
.hb-label {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 600;
}

/* Numbers. tabular-nums stops digits jittering as live values update — on a
   dashboard that refreshes constantly this is the difference between "calm"
   and "twitchy". */
.hb-stat {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: var(--lh-tight);
  color: var(--text);
}
.hb-stat-unit { color: var(--text-3); font-weight: 400; }

/* Interactive: press feedback that fires on the element, fast. */
.hb-press { transition: transform var(--d-base) var(--ease-out); }
.hb-press:active { transform: scale(0.985); transition: transform var(--d-press) var(--ease-press); }

/* Live/state dots -----------------------------------------------------------*/
.hb-dot { width: 6px; height: 6px; border-radius: var(--r-full); flex-shrink: 0; display: inline-block; }
.hb-dot-live   { background: var(--success); animation: hb-pulse 2.4s ease-in-out infinite; }
.hb-dot-stale  { background: var(--warn); }
.hb-dot-off    { background: var(--text-3); }
@keyframes hb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--success-rgb), 0.45); }
  50%      { box-shadow: 0 0 0 4px rgba(var(--success-rgb), 0); }
}

/* ============================================================================
   SHARED CHROME — sticky top bar used by templates/partials/chrome.html.
   Ported from the homepage's ticker bar so every page opens on the same
   instrument-panel language. See that partial for markup/usage.
   ========================================================================== */
.hb-chrome {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  display: flex; align-items: center; gap: 22px;
  padding: 14px 24px;
  background: rgba(10, 10, 11, 0.82);   /* --bg at 82%, neutral (not navy-tinted) */
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12.5px;
  overflow-x: auto; white-space: nowrap;
}
.hb-chrome-brand {
  font-family: var(--font-display); font-weight: 600;
  font-size: 14px; letter-spacing: 0.04em; color: var(--text);
  text-decoration: none; flex-shrink: 0;
}
.hb-chrome-nav { display: flex; align-items: center; gap: 4px; margin-left: 8px; }
.hb-chrome-nav a {
  color: var(--text-3); text-decoration: none; font-size: 12px;
  padding: 6px 10px; border-radius: var(--r-sm);
  transition: color var(--d-fast) ease, background var(--d-fast) ease;
}
.hb-chrome-nav a:hover { color: var(--text); background: var(--surface-2); }
.hb-chrome-nav a.active { color: var(--accent); background: var(--accent-dim); }
.hb-chrome-spacer { flex: 1; }
/* Body offset so fixed chrome never overlaps page content — pages that used
   their own hero padding-top should drop it in favour of this one class. */
.hb-chrome-offset { padding-top: 56px; }

/* Touch target guarantee ----------------------------------------------------*/
.hb-tap { min-height: var(--tap-min); min-width: var(--tap-min); }

/* ============================================================================
   GLOBAL SAFETY
   ========================================================================== */

/* Visible focus for keyboard users. Tailwind's reset removes the default
   outline and the templates never replaced it. */
:where(a, button, [role="button"], input, select, textarea):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Honour reduced motion globally — decoration stops, content never hides. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
