/* ===========================================================================
   Recess design system — the subset Karts uses.
   ===========================================================================

   SOURCE OF TRUTH. Everything here is lifted from the monolith, not
   reconstructed from the rendered /design page:

     tokens   tryrecess/monolith  apps/web/src/styles/tailwind.css:309-560
     recipes  tryrecess/monolith  apps/web/src/lib/styles/recess-ds.css
     page     tryrecess/monolith  apps/web/src/routes/design/+page.svelte

   Read from the worktree at C:\Users\thebu\worktrees\starweaver-b89e05f0
   (the PRODUCTION commit). The staging clone on the Desktop does NOT contain
   the design system — `recess-ds` matches nothing there. If these values ever
   need re-syncing, check out production, not staging.

   TWO DELIBERATE DIVERGENCES from the monolith, both because this is a game
   rather than an app surface:

   1. Only the DARK layer is here. Upstream ships a light token block plus a
      `.dark .recess-ds` override; the game is always on a dark backdrop and
      has no theme toggle, so carrying the light layer would be dead weight and
      an invitation to accidentally render half-light. The values below are
      verbatim from the upstream dark layer.

   2. Tokens are declared on `:root` AS WELL AS `.recess-ds`. Upstream scopes
      everything to `.recess-ds` because adoption there is opt-in per surface
      during a migration. Here the entire document is the ds surface, so
      scoping every selector would be pure ceremony. The wrapper class is still
      applied to <body> so recipes pasted from the monolith keep working
      unchanged, and so the house pattern is recognisable.

   The glass treatment is deliberately NOT ported: upstream restricts it to
   surfaces over colour or imagery, and these panels sit on flat ink.
   =========================================================================== */

:root,
.recess-ds {
  /* ── Surfaces — deep charcoal canvas, raised cards ────────────────────── */
  --ds-bg: #151414;
  --ds-bg-2: #2b2828; /* surface-muted: wells, tracks, subtle buttons */
  --ds-card: #211f1f;

  /* ── Ink — near-white on an opacity ramp ──────────────────────────────── */
  --ds-ink: #f8fafc;
  --ds-ink-2: rgba(248, 250, 252, 0.76);
  --ds-ink-3: rgba(248, 250, 252, 0.7);
  --ds-ink-4: rgba(248, 250, 252, 0.45);
  --ds-ink-5: rgba(248, 250, 252, 0.12);

  /* ── Lines — white alpha hairlines. Structure comes from these plus the
        shadows below, never from a hard border. ─────────────────────────── */
  --ds-rule: rgba(255, 255, 255, 0.12);
  --ds-rule-strong: rgba(255, 255, 255, 0.24);

  /* Text painted on fills built from --ds-ink. --ds-ink is light here, so its
     text must go dark — this is what makes active controls read as
     light-fill / dark-text. */
  --ds-bg-fixed: #171717;
  --ds-ink-fixed: #050505;

  /* ── Accent — brighter violet gradient for a dark canvas ──────────────────
     RESERVED FOR MOMENTS. Never a background, never across a whole surface.
     In this game its only chrome use is the primary CTA.

     The bright stops matter on the playfield: the arena floor (#1c1630) is
     only 8 degrees from the accent hue, so hue does NOT separate them —
     luminance does. Measured on the floor: #a78bfa 6.39:1, #c084fc 6.59:1,
     against the LIGHT stops' 3.05:1 (#7c3aed) and 4.40:1 (#a855f7). Anything
     accent-coloured drawn over the arena must use these dark stops. */
  --ds-accent-grad: linear-gradient(90deg, #a78bfa, #c084fc);
  --ds-accent-1: #a78bfa;
  --ds-accent-2: #c084fc;
  --ds-accent-3: #e5c07b; /* antique gold, lifted */
  --ds-signal: #e5c07b;

  /* ── Label palette — lifted hues that read on dark; softs are low-alpha
        tints of each hue so fills glow instead of washing out. ──────────── */
  --ds-blue: #818cf8;
  --ds-blue-soft: rgba(129, 140, 248, 0.16);
  --ds-purple: #a78bfa;
  --ds-purple-soft: rgba(167, 139, 250, 0.16);
  --ds-red: #f87171;
  --ds-red-soft: rgba(248, 113, 113, 0.16);
  --ds-amber: #fbbf24;
  --ds-amber-soft: rgba(251, 191, 36, 0.16);
  --ds-green: #86efac;
  --ds-green-soft: rgba(134, 239, 172, 0.16);

  /* ── Semantic status — aliases onto the label palette, kept soft ──────── */
  --ds-info: var(--ds-blue);
  --ds-info-soft: var(--ds-blue-soft);
  --ds-success: var(--ds-green);
  --ds-success-soft: var(--ds-green-soft);
  --ds-warning: #fbbf24;
  --ds-warning-solid: var(--ds-amber);
  --ds-warning-soft: var(--ds-amber-soft);
  --ds-danger: var(--ds-red);
  --ds-danger-soft: var(--ds-red-soft);
  /* On dark the softs are low-alpha tints, so the LIFTED hue is what reads
     (green 7.8:1 on the tinted card, red 5.9:1) — the light layer's deepened
     tones would sink into the surface. */
  --ds-success-text: var(--ds-green);
  --ds-danger-text: var(--ds-red);

  /* ── Focus. A near-black ring is invisible on charcoal, so both are a light
        glow. Upstream note: the recipes that draw these also `outline: none`,
        so this is the ONLY keyboard indicator those controls have. ──────── */
  --ds-focus-ring: rgba(248, 250, 252, 0.4);
  --ds-focus-ring-soft: rgba(248, 250, 252, 0.24);

  /* ── Type — Satoshi is the whole system ───────────────────────────────────
     Loaded from the Fontshare CDN in index.html, the same source the monolith
     uses (apps/web/src/styles/tailwind.css:11). `satoshi@1` is the VARIABLE
     build, not weight 1 — upstream switched to it because the old static
     400/500/700/900 request silently snapped the intermediate weights the
     system actually writes (450, 550, 650, 800) to the nearest of four. */
  --ds-font-display: "Satoshi", "Inter", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --ds-font-body: "Satoshi", "Inter", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

  --ds-track-display: -0.04em; /* Satoshi Black headlines, tight */
  --ds-track-head: -0.03em;
  --ds-track-label: 0.04em; /* uppercase labels */
  --ds-lead-display: 0.92;
  --ds-lead-body: 1.5;

  /* ── Radius ───────────────────────────────────────────────────────────── */
  --ds-radius: 14px; /* cards */
  --ds-radius-sm: 10px; /* inputs */
  --ds-radius-pill: 999px; /* buttons, tabs, chips */

  /* ── Elevation — soft and low. Deepened for dark so cards separate from the
        canvas instead of vanishing. ────────────────────────────────────── */
  --ds-shadow-card: 0 18px 44px rgba(0, 0, 0, 0.55);
  --ds-shadow-soft: 0 10px 30px rgba(0, 0, 0, 0.45);
  /* A DOUBLE shadow, not a deeper single one: the 1px contact layer draws the
     card's edge (which a borderless card no longer gets from a rule) while the
     32px ambient layer does the lifting. One soft blur alone reads as a smudge
     with no edge once the border goes. */
  --ds-shadow-card-2: 0 1px 2px rgba(0, 0, 0, 0.35), 0 12px 32px rgba(0, 0, 0, 0.5);
}

/* ═══ Type ═══════════════════════════════════════════════════════════════ */
.ds-display {
  font-family: var(--ds-font-display);
  font-weight: 900;
  letter-spacing: var(--ds-track-display);
  line-height: var(--ds-lead-display);
}
.ds-head {
  font-family: var(--ds-font-display);
  font-weight: 650;
  letter-spacing: var(--ds-track-head);
}
/* Uppercase micro-label. Weight 900 + open tracking is the system's signature
   for these — they are structural landmarks, not body text. */
.ds-label {
  font-family: var(--ds-font-display);
  font-weight: 900;
  font-size: 11px;
  letter-spacing: var(--ds-track-label);
  text-transform: uppercase;
  color: var(--ds-ink-3);
}
/* Accent as TEXT, which is the legitimate small-highlight use of the gradient
   — as opposed to painting it across a surface. */
.ds-grad-text {
  background: var(--ds-accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ═══ Buttons — pills ════════════════════════════════════════════════════ */
.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 24px;
  font-family: var(--ds-font-body);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--ds-radius-pill);
  background: transparent;
  color: var(--ds-ink);
  white-space: nowrap;
  transition:
    background 160ms ease,
    color 160ms ease,
    border-color 160ms ease,
    box-shadow 160ms ease,
    transform 160ms ease;
}
.ds-btn:hover:not(:disabled) {
  transform: translateY(-1px);
}
.ds-btn:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: none;
}
/* The doubled class is load-bearing, not a typo. `.ds-btn:focus-visible` is
   (0,2,0) and LOSES to `.ds-btn-accent` / `.ds-btn-ink`, which are equal
   specificity but declared later and set box-shadow for their resting
   elevation — so the primary CTA would have NO keyboard indicator at all, the
   ring silently overwritten. Doubling outranks both regardless of order, and
   the resting shadow rides along so the button keeps its elevation. */
.ds-btn.ds-btn:focus-visible {
  outline: none;
  box-shadow:
    var(--ds-shadow-soft),
    0 0 0 3px var(--ds-focus-ring);
}
.ds-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
.ds-btn-ink {
  background: var(--ds-ink);
  color: var(--ds-bg-fixed);
  border-color: var(--ds-ink);
  box-shadow: var(--ds-shadow-soft);
}
.ds-btn-ink:hover:not(:disabled) {
  background: #ffffff;
  border-color: #ffffff;
}
.ds-btn-out {
  background: var(--ds-card);
  color: var(--ds-ink);
  border-color: var(--ds-rule-strong);
}
.ds-btn-out:hover:not(:disabled) {
  background: var(--ds-ink);
  color: var(--ds-bg-fixed);
  border-color: var(--ds-ink);
}
.ds-btn-subtle {
  background: var(--ds-bg-2);
  color: var(--ds-ink-2);
}
.ds-btn-subtle:hover:not(:disabled) {
  background: var(--ds-ink-5);
  color: var(--ds-ink);
}
.ds-btn-ghost {
  color: var(--ds-ink-2);
}
.ds-btn-ghost:hover:not(:disabled) {
  background: var(--ds-bg-2);
  color: var(--ds-ink);
}
/* THE accent moment in the chrome. One button, not a surface. */
.ds-btn-accent {
  background: var(--ds-accent-grad);
  color: #170f27;
  border-color: transparent;
  box-shadow: var(--ds-shadow-soft);
  font-weight: 700;
}
.ds-btn-accent:hover:not(:disabled) {
  filter: brightness(1.08);
}
.ds-btn-danger {
  background: var(--ds-red-soft);
  color: var(--ds-danger-text);
  border-color: rgba(248, 113, 113, 0.32);
}
.ds-btn-danger:hover:not(:disabled) {
  background: rgba(248, 113, 113, 0.26);
}
.ds-btn-sm {
  padding: 8px 14px;
  font-size: 12.5px;
}
.ds-btn-xs {
  padding: 5px 11px;
  font-size: 11.5px;
  font-weight: 700;
}
.ds-btn-lg {
  padding: 17px 30px;
  font-size: 15px;
}
.ds-btn-block {
  display: flex;
  width: 100%;
}

/* ═══ Fields ═════════════════════════════════════════════════════════════ */
.ds-field-label {
  font-family: var(--ds-font-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--ds-ink);
}
.ds-input {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  background: var(--ds-bg-2);
  border: 1px solid var(--ds-rule-strong);
  border-radius: var(--ds-radius-sm);
  padding: 13px 16px;
  font-family: var(--ds-font-body);
  font-size: 15px;
  color: var(--ds-ink);
  transition:
    border-color 140ms ease,
    box-shadow 140ms ease;
}
.ds-input::placeholder {
  color: var(--ds-ink-4);
}
/* `:focus-within` rides alongside `:focus` because the recipe gets worn two
   ways upstream — directly on an <input>, and on a wrapper holding an icon
   plus a bare input. On a wrapper `:focus` can never match, so those fields
   would have no focus indicator at all. */
.ds-input:focus,
.ds-input:focus-within {
  outline: none;
  border-color: var(--ds-ink);
  box-shadow: 0 0 0 3px var(--ds-focus-ring-soft);
}

/* ═══ Chips / tabs — pills ═══════════════════════════════════════════════ */
.ds-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  font-family: var(--ds-font-body);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ds-ink-2);
  background: var(--ds-card);
  border: 1px solid var(--ds-rule-strong);
  border-radius: var(--ds-radius-pill);
  cursor: pointer;
  transition:
    background 140ms ease,
    color 140ms ease,
    border-color 140ms ease,
    transform 140ms ease;
}
.ds-chip:hover:not(:disabled) {
  border-color: var(--ds-ink);
  transform: translateY(-1px);
}
.ds-chip:active:not(:disabled) {
  transform: translateY(0);
}
.ds-chip.ds-chip:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ds-focus-ring);
}
.ds-chip-on {
  background: var(--ds-ink);
  color: var(--ds-bg-fixed);
  border-color: var(--ds-ink);
}

/* ═══ Cards ══════════════════════════════════════════════════════════════ */
.ds-card {
  background: var(--ds-card);
  border-radius: var(--ds-radius);
  box-shadow: var(--ds-shadow-card);
}
/* Structure from a hairline, never a hard border. */
.ds-rule {
  border: 0;
  border-top: 1px solid var(--ds-rule);
  margin: 0;
}

/* ═══ Status / alerts — semantic colour kept soft ════════════════════════ */
.ds-alert {
  border-radius: var(--ds-radius-sm);
  padding: 11px 13px;
  font-size: 13px;
  line-height: 1.5;
  text-align: left;
}
.ds-alert-warning {
  background: var(--ds-warning-soft);
  color: var(--ds-warning);
  border: 1px solid rgba(251, 191, 36, 0.32);
}
.ds-alert-info {
  background: var(--ds-info-soft);
  color: var(--ds-info);
  border: 1px solid rgba(129, 140, 248, 0.32);
}

/* ═══ Meters ═════════════════════════════════════════════════════════════ */
.ds-progress {
  height: 8px;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-ink-5);
  overflow: hidden;
}
.ds-progress-fill {
  display: block;
  height: 100%;
  border-radius: var(--ds-radius-pill);
  transition: width 150ms linear, background 150ms linear;
}
