/* ============================================================================
   BOB HQ — DESIGN TOKENS
   Every colour, size, duration and easing in the product resolves to something
   in this file. Nothing downstream is allowed to hardcode a hex value.

   THE TWO-ACCENT RULE (the single most important decision in here)
   Bob's brand carries gold AND cyan. Two saturated accents on one dark surface
   normally fight — everything becomes "important" and the eye has nowhere to
   rest. So they are split by MEANING, not by taste, and the split never bends:

     GOLD  = Bob himself, and value.  His face, his voice, prices, rewards,
             XP, the single primary action on a screen.
     CYAN  = the software.  Navigation, links, focus rings, active states,
             selection, anything that responds to a pointer.

   Read a screen and you can tell what is Bob and what is interface without
   reading a word. It also caps gold at roughly one element per viewport, which
   is what keeps it feeling like currency instead of decoration.
   ========================================================================= */

:root {
  /* --- brand ------------------------------------------------------------ */
  --gold: #ffce3a;
  --gold-d: #c9971a;        /* pressed / gradient foot */
  --gold-l: #ffe08a;        /* hover lift */
  --gold-t: #17140a;        /* text ON gold — near-black, not pure, so it reads warm */
  --cyan: #2cd4e8;
  --cyan-d: #1a9fb0;
  --cyan-l: #7fe9f5;
  --cyan-t: #04181c;

  /* --- surfaces ---------------------------------------------------------
     A five-step ramp, not two. Depth in a dark UI comes from stacked planes;
     with only "background" and "card" every panel sits at the same altitude
     and the whole thing reads flat no matter how many shadows you add. */
  --bg: #07080d;            /* the void behind everything */
  --bg-1: #0a0c13;          /* app chrome: sidebar, topbar */
  --surface: #0f121b;       /* cards, panels */
  --surface-2: #151926;     /* raised: hover, inputs, popovers */
  --surface-3: #1c2132;     /* highest: modals, active rows */

  /* --- lines ------------------------------------------------------------ */
  --line: #1e2331;          /* default hairline */
  --line-2: #2a3145;        /* emphasised / hover */
  --line-glow: rgba(44, 212, 232, .35);

  /* --- text ------------------------------------------------------------- */
  --text: #eef1f7;          /* headings, primary copy */
  --text-2: #a8b1c4;        /* secondary copy, descriptions */
  --text-3: #6b748a;        /* meta, timestamps, counts */
  --text-4: #454c5e;        /* disabled, dividers-as-text */

  /* --- semantic --------------------------------------------------------- */
  --ok: #4ade80;
  --warn: #fbbf24;
  --danger: #f87171;
  --verified: #2cd4e8;

  /* --- rarity ------------------------------------------------------------
     Achievements need a difficulty signal that is readable BEFORE the text.
     The ramp is borrowed from the games this audience already plays (grey →
     blue → purple → gold) because inventing a private rarity language would
     mean teaching it, and nobody reads a legend.

     Legendary is deliberately the SAME gold as Bob and as prices. That is not
     a violation of the two-accent rule, it is the rule working: gold means
     value, and a legendary achievement is the most valuable thing on the page
     it appears on. It also caps legendary at a handful of items overall, which
     is what stops the ramp from inflating. */
  --rar-common: #7c869c;
  --rar-rare: #4aa3f0;
  --rar-epic: #b06cf5;
  --rar-legendary: #ffce3a;

  /* --- creator tiers -----------------------------------------------------
     Four steps, and the last one reuses gold for the same reason legendary
     does. Green reads as "growing", cyan as "part of the platform" (it is the
     same cyan as the verified check, deliberately), purple as scarce, gold as
     the top. */
  --tier-builder: #6fcf97;
  --tier-verified: #2cd4e8;
  --tier-featured: #b06cf5;
  --tier-elite: #ffce3a;

  /* --- typography -------------------------------------------------------
     System stack only. No webfont, no CDN — HQ has to boot instantly offline
     and never flash unstyled text, and a font request is the one thing that
     reliably breaks both. The display face is the same stack at a tighter
     tracking; the weight and spacing do the work a second family would. */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --t-display: 700 clamp(28px, 3.2vw, 42px)/1.08 var(--font);
  --t-h1: 700 clamp(22px, 2.1vw, 28px)/1.15 var(--font);
  --t-h2: 650 19px/1.25 var(--font);
  --t-h3: 600 15px/1.35 var(--font);
  --t-body: 400 14.5px/1.6 var(--font);
  --t-sm: 400 13px/1.5 var(--font);
  --t-xs: 500 11.5px/1.4 var(--font);
  --track-tight: -.02em;
  --track-caps: .08em;

  /* --- geometry ---------------------------------------------------------- */
  --r-sm: 8px;
  --r: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-pill: 999px;

  /* Space scale. Added in the polish pass: the first version picked padding
     per-component by eye, which is why 13px, 14px, 15px and 16px all appear in
     places doing the same job. A geometric-ish ladder means two panels built by
     different code paths land on the same rhythm without coordination. New work
     uses these; existing values were only changed where the mismatch showed. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 22px;
  --s-6: 30px;
  --s-7: 40px;
  --s-8: 56px;

  --sidebar-w: 244px;
  --sidebar-w-rail: 76px;   /* icon-only collapse */
  --topbar-h: 64px;
  --gutter: clamp(20px, 2.4vw, 38px);
  --page-max: 1440px;

  /* --- elevation --------------------------------------------------------
     Dark UIs cannot use shadow alone to lift a surface — black on near-black
     is invisible. Each level pairs a shadow with a 1px top highlight, which is
     what actually sells the edge. */
  --e-1: 0 1px 2px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.03);
  --e-2: 0 6px 20px -6px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.045);
  --e-3: 0 18px 50px -12px rgba(0,0,0,.75), inset 0 1px 0 rgba(255,255,255,.06);
  --e-gold: 0 8px 30px -8px rgba(255,206,58,.4);
  --e-cyan: 0 8px 30px -8px rgba(44,212,232,.35);

  /* --- motion -----------------------------------------------------------
     Three durations, one curve. The curve is a soft overshoot-free ease-out:
     things arrive quickly and settle, which reads as "responsive software"
     rather than "animated website". Anything slower than --d-3 gets noticed
     as waiting, so nothing in the product is allowed past it. */
  --ease: cubic-bezier(.22, .9, .28, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --d-1: 130ms;             /* micro: hover, colour, press */
  --d-2: 240ms;             /* element: cards, popovers */
  --d-3: 380ms;             /* view: route change, modal */

  --z-content: 1;
  --z-sticky: 50;
  --z-sidebar: 100;
  --z-pop: 200;
  --z-modal: 300;
  --z-toast: 400;
}

/* Reduced motion is honoured globally rather than per-component. Durations go
   to ~0 instead of animations being disabled, so anything that reads a token to
   time a JS step still gets a real number and never divides by zero. */
@media (prefers-reduced-motion: reduce) {
  :root { --d-1: 1ms; --d-2: 1ms; --d-3: 1ms; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
