/* ============================================================
   SideQuest User Platform — prototype slice 0.1/0.2
   One brand, two lights. Dark is "the property at night",
   inherited from sidequest-website-voice/static/css/main.css.
   Light is the same violet-and-ice brand at noon — same hues,
   inverted ground. Not a second brand.
   ============================================================ */

/* ---------- theme-independent tokens: not part of either palette ---------- */
:root {
  --radius: 5px;
  --radius-sm: 3px;
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body: "Instrument Sans", -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
  --rail: 13.5rem;
  --bar: 3.75rem;

  /* Font-size scale, named after their own rem value rather than a semantic
     rung (xs/sm/md...) -- the existing sizes are sixteen distinct values a
     handful of hundredths apart, with no natural five- or six-step ladder
     hiding in them, and inventing one here would mean silently nudging sizes
     to fit it, which is exactly the kind of change this step must not make.
     Every value below is copied verbatim from where it already lived, so
     applying a token changes no computed style. Only values already reused
     two or more times got a token; a size used exactly once stays a literal
     where it is. */
  --fs-62: 0.62rem; --fs-66: 0.66rem; --fs-68: 0.68rem; --fs-70: 0.7rem;
  --fs-72: 0.72rem; --fs-74: 0.74rem; --fs-76: 0.76rem; --fs-78: 0.78rem;
  --fs-80: 0.8rem;  --fs-82: 0.82rem; --fs-84: 0.84rem; --fs-85: 0.85rem;
  --fs-86: 0.86rem; --fs-90: 0.9rem;  --fs-100: 1rem;   --fs-120: 1.2rem;

  /* Spacing scale, same naming rule and same "only if reused" cutoff, and
     scoped to the single-value margin/padding/gap declarations -- a
     shorthand pair like `padding: 0.36rem 0.78rem` is left as a literal
     rather than partially tokenized, since only one of its two values
     repeats elsewhere and a half-tokenized shorthand would read as an
     inconsistency, not a consolidation. */
  --sp-10: 0.1rem;  --sp-15: 0.15rem; --sp-20: 0.2rem;  --sp-25: 0.25rem;
  --sp-30: 0.3rem;  --sp-35: 0.35rem; --sp-40: 0.4rem;  --sp-45: 0.45rem;
  --sp-50: 0.5rem;  --sp-55: 0.55rem; --sp-60: 0.6rem;  --sp-70: 0.7rem;
  --sp-75: 0.75rem; --sp-80: 0.8rem;  --sp-85: 0.85rem; --sp-90: 0.9rem;
  --sp-100: 1rem;   --sp-120: 1.2rem; --sp-125: 1.25rem; --sp-150: 1.5rem;
  --sp-2px: 2px;
}

/* ---------- Palette: two declaration lists, light and dark ----------
   Five copies used to exist here (base :root, a prefers-color-scheme media
   rule, :root[data-theme="dark"], :root[data-ui="light"], :root[data-ui="dark"])
   and had drifted apart in formatting (never in actual colour). Now there are
   two: the dark tokens below, and the light tokens after them. Each is typed
   once and reused via a selector list.

   The dark list still has to appear twice in the SOURCE, because @media
   cannot be folded into a comma-separated selector list -- the system-
   preference path (no explicit override, follow the OS) has to live inside
   its own @media block, while the two explicit-override attributes
   (data-theme, the host's; data-ui, the in-page toggle's) do not want the
   @media guard at all: they must win even when the OS disagrees. Both copies
   below are byte-identical on purpose; if they ever drift again, that is the
   bug this comment exists to catch. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg-0: #0a0714; --bg-1: #110b20;
    --panel: rgba(126, 96, 255, 0.055); --panel-2: rgba(126, 96, 255, 0.12);
    --line: rgba(178, 152, 255, 0.14); --line-soft: rgba(178, 152, 255, 0.08);
    --text: #f1ecfc; --text-dim: #b3a6d6; --text-faint: #8577ab;
    --violet: #7a5cff; --violet-deep: #432ea8;
    --lilac: #b9a3ff; --lilac-bright: #ddd0ff; --lilac-dim: rgba(185, 163, 255, 0.5);
    --wordmark: #f1ecfc;
    --ok: #9a8dc4;   --ok-bg: rgba(154, 141, 196, 0.14);
    --crit: #ff7a8c; --crit-bg: rgba(255, 122, 140, 0.16);
    --lead: #a88cff; --lead-bg: rgba(168, 140, 255, 0.16);
    --wave-played: rgba(185, 163, 255, 0.95); --wave-rest: rgba(178, 152, 255, 0.22);
    --head-bg: rgba(10, 7, 20, 0.8); --grain-op: 0.045;
    --sky:
      radial-gradient(120% 80% at 82% -12%, rgba(122, 92, 255, 0.22) 0%, transparent 58%),
      radial-gradient(90% 90% at 6% 4%, rgba(67, 46, 168, 0.34) 0%, transparent 62%),
      linear-gradient(180deg, #0d0919 0%, #100b1e 46%, #0a0714 100%);
  }
}
:root[data-theme="dark"],
:root[data-ui="dark"] {
  --bg-0: #0a0714; --bg-1: #110b20;
  --panel: rgba(126, 96, 255, 0.055); --panel-2: rgba(126, 96, 255, 0.12);
  --line: rgba(178, 152, 255, 0.14); --line-soft: rgba(178, 152, 255, 0.08);
  --text: #f1ecfc; --text-dim: #b3a6d6; --text-faint: #8577ab;
  --violet: #7a5cff; --violet-deep: #432ea8;
  --lilac: #b9a3ff; --lilac-bright: #ddd0ff; --lilac-dim: rgba(185, 163, 255, 0.5);
  --wordmark: #f1ecfc;
  --ok: #9a8dc4;   --ok-bg: rgba(154, 141, 196, 0.14);
  --crit: #ff7a8c; --crit-bg: rgba(255, 122, 140, 0.16);
  --lead: #a88cff; --lead-bg: rgba(168, 140, 255, 0.16);
  --wave-played: rgba(185, 163, 255, 0.95); --wave-rest: rgba(178, 152, 255, 0.22);
  --head-bg: rgba(10, 7, 20, 0.8); --grain-op: 0.045;
  --sky:
    radial-gradient(120% 80% at 82% -12%, rgba(122, 92, 255, 0.22) 0%, transparent 58%),
    radial-gradient(90% 90% at 6% 4%, rgba(67, 46, 168, 0.34) 0%, transparent 62%),
    linear-gradient(180deg, #0d0919 0%, #100b1e 46%, #0a0714 100%);
}
/* Light tokens: the base default AND the in-page toggle's explicit choice,
   one declaration list covering both. Declared last so :root[data-ui="light"]
   wins at equal specificity over :root[data-theme="dark"] above, when a host
   sets data-theme="dark" but the visitor has toggled data-ui="light" -- the
   in-page choice must outrank the host's, matching isDark()'s own precedence
   (ui, then host, then system) further down in the script. */
:root,
:root[data-ui="light"] {
  --bg-0: #faf8ff; --bg-1: #f2eefc;
  --panel: rgba(122, 92, 255, 0.05); --panel-2: rgba(122, 92, 255, 0.11);
  --line: rgba(67, 46, 168, 0.17); --line-soft: rgba(67, 46, 168, 0.09);
  --text: #150f28; --text-dim: #574c78; --text-faint: #756a96;
  --violet: #5b3fd6; --violet-deep: #3f2a9e;
  --lilac: #7c5ce8; --lilac-bright: #a68bf5; --lilac-dim: rgba(124, 92, 232, 0.4);
  --wordmark: #3f2a9e;
  --ok: #6f6392;   --ok-bg: rgba(111, 99, 146, 0.1);
  --crit: #cc3344; --crit-bg: rgba(204, 51, 68, 0.1);
  --lead: #5b3fd6; --lead-bg: rgba(91, 63, 214, 0.11);
  --wave-played: rgba(91, 63, 214, 0.85); --wave-rest: rgba(91, 63, 214, 0.19);
  --head-bg: rgba(250, 248, 255, 0.86); --grain-op: 0.025;
  --sky:
    radial-gradient(120% 80% at 82% -12%, rgba(122, 92, 255, 0.15) 0%, transparent 58%),
    radial-gradient(90% 90% at 6% 4%, rgba(91, 63, 214, 0.09) 0%, transparent 62%),
    linear-gradient(180deg, #fbf9ff 0%, #f6f2fd 46%, #f1ecfa 100%);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg-0); color: var(--text);
  font-family: var(--font-body); font-size: 0.9375rem; line-height: 1.6;
  -webkit-font-smoothing: antialiased; overflow-x: clip; min-height: 100vh;
  transition: background 0.35s ease, color 0.35s ease;
}
::selection { background: var(--panel-2); color: var(--text); }
a { color: inherit; text-decoration: none; }
button, select, input, textarea { font: inherit; color: inherit; background: none; border: none; }
button, select { cursor: pointer; }
:focus-visible { outline: 2px solid var(--lilac); outline-offset: 2px; border-radius: 3px; }

/* ---------- uppercase micro-labels: one shared rule for twelve selectors ----------
   Every "small caps heading" on the page (stat headers, table headers, form
   labels, pills, tags...) agreed on exactly two things: bold weight and
   uppercase. Font-size, letter-spacing and colour never agreed across all
   twelve, so those stay on each selector's own rule below, unchanged, rather
   than being forced to a single value that would move real pixels. `.label`
   itself is not yet written onto any element -- it exists so a new label
   added later can just use the class instead of retyping these two lines --
   while `.stat-k`, `.card-title` and `.calls thead th` keep their names
   exactly as they were; suites select on them. `.back` is 600 here, not 700,
   so it restates its own font-weight below, after this rule, where it wins. */
.label,
.stat-k,
.calls thead th,
.fig-k,
.people thead th,
.field label,
.pill,
.back,
.card-title,
.turn-who,
.picker-title,
details.meta > summary,
.fact dt {
  font-weight: 700;
  text-transform: uppercase;
}

[hidden] { display: none !important; }

@media (max-width: 52rem) {

  /* Every text control, not an enumerated list — slice 0.4 added selects and
     inputs that the old per-selector list silently missed, which is the iOS
     focus-zoom defect all over again. `!important` because any component class
     (`.p-sel select`) outranks a bare element selector, and this is a floor that
     must never lose a specificity argument. Buttons are excluded: they do not
     trigger the zoom and forcing them to 16px would wreck the chip rows. This
     used to be a second, separate `@media (max-width: 52rem)` block below the
     iOS media query further down; merged in here, in the same relative order
     it already had (last), since it shares no selector with anything above it. */
  input, select, textarea { font-size: 16px !important; }
}

/* iOS zooms the whole page when it focuses a control smaller than 16px, which
   throws the layout out. Fix the cause — the font size — rather than locking
   the viewport, which would take pinch-zoom away from everyone. */
@media (hover: none) and (pointer: coarse) {
  input, select, textarea { font-size: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: 0.01ms !important; }
}
