/*
  Design tokens.

  Every colour, space and duration in the site resolves to something declared here.
  The point is not tidiness: it is that a theme change, a contrast fix or a density
  change happens in one file instead of in four hundred rules, and that dark mode is
  a different set of values rather than a second stylesheet that drifts from the first.

  Colour is authored in oklch. Unlike hex or hsl, equal steps in its lightness channel
  look equal to the eye across hues, so a "same weight, different hue" pair actually
  reads that way instead of the yellow looking washed out beside the blue.
*/

:root {
  /* ── Brand ──────────────────────────────────────────────────────────────────
     Deep indigo carrying a violet undertone, not the saturated red-and-yellow
     that every site in this niche reaches for. The niche convention reads as
     fan-made because it borrows the toy palette; this one is meant to read as a
     product that is maintained. */
  --brand-50:  oklch(0.97 0.02 285);
  --brand-100: oklch(0.93 0.05 285);
  --brand-200: oklch(0.87 0.09 285);
  --brand-300: oklch(0.78 0.14 285);
  --brand-400: oklch(0.68 0.18 285);
  --brand-500: oklch(0.58 0.21 285);
  --brand-600: oklch(0.50 0.20 285);
  --brand-700: oklch(0.42 0.17 285);
  --brand-800: oklch(0.33 0.13 285);
  --brand-900: oklch(0.25 0.09 285);

  /* Warm counterweight, used sparingly. Isolation is what makes a call to action
     read as one — an accent applied to six things is no longer an accent. */
  --accent-300: oklch(0.85 0.13 68);
  --accent-400: oklch(0.78 0.16 68);
  --accent-500: oklch(0.72 0.18 62);
  --accent-600: oklch(0.63 0.17 58);

  /* ── Status ─────────────────────────────────────────────────────────────────
     Never carried by hue alone: every status in the UI pairs its colour with an
     icon or a word, because roughly one man in twelve cannot separate the green
     from the red. */
  --ok-500:      oklch(0.72 0.17 152);
  --ok-600:      oklch(0.62 0.16 152);
  --warn-500:    oklch(0.79 0.16 82);
  --warn-600:    oklch(0.68 0.15 76);
  --danger-500:  oklch(0.63 0.21 27);
  --danger-600:  oklch(0.55 0.20 27);
  --info-500:    oklch(0.70 0.13 235);

  /* ── Neutrals (dark-first) ──────────────────────────────────────────────────
     The site is dark by default: it is a companion to a game people play at
     night, and a white page beside a dark client is a flashbang. Light theme is
     a full, deliberate override further down — not an afterthought. */
  --bg:          oklch(0.16 0.015 285);
  --bg-raised:   oklch(0.20 0.018 285);
  --bg-overlay:  oklch(0.24 0.020 285);
  --bg-inset:    oklch(0.13 0.014 285);

  --line:        oklch(0.30 0.018 285);
  --line-strong: oklch(0.40 0.022 285);

  --text:        oklch(0.96 0.005 285);
  --text-muted:  oklch(0.75 0.012 285);
  --text-subtle: oklch(0.60 0.012 285);
  --text-on-brand: oklch(0.99 0 0);

  /* ── Type ───────────────────────────────────────────────────────────────────
     System stack: no webfont request, no layout shift when it lands, no third
     party watching who reads the page. The CSP forbids remote fonts anyway. */
  --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  /* A modular scale (1.25) rather than arbitrary sizes — the relationships between
     headings stay consistent at every breakpoint. Fluid between the two ends so a
     phone is not reading desktop-sized headings. */
  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
  --text-2xl:  clamp(1.5rem, 1.25rem + 1.1vw, 2rem);
  --text-3xl:  clamp(1.875rem, 1.4rem + 2.2vw, 2.75rem);
  --text-4xl:  clamp(2.25rem, 1.5rem + 3.4vw, 4rem);

  --leading-tight: 1.15;
  --leading-snug:  1.35;
  --leading-body:  1.65;

  /* ── Space ──────────────────────────────────────────────────────────────────
     A 4px base. Every gap in the site is one of these, which is what makes the
     rhythm hold together without anyone measuring. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;

  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-full: 999px;

  /* Layered rather than a single blur: near shadows read as elevation, far ones as
     depth, and one shadow trying to do both looks like neither. */
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.28);
  --shadow:    0 2px 4px oklch(0 0 0 / 0.24), 0 8px 16px oklch(0 0 0 / 0.20);
  --shadow-lg: 0 4px 8px oklch(0 0 0 / 0.26), 0 16px 40px oklch(0 0 0 / 0.28);
  --shadow-glow: 0 0 0 1px oklch(0.58 0.21 285 / 0.5), 0 0 32px oklch(0.58 0.21 285 / 0.28);

  /* ── Motion ─────────────────────────────────────────────────────────────────
     Short, and eased out. Motion here exists to explain where something came
     from; anything over ~250ms stops explaining and starts delaying. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 120ms;
  --dur:      200ms;
  --dur-slow: 320ms;

  --container: 1200px;
  --container-wide: 1440px;
  --container-text: 68ch;  /* measure: past ~75 characters the eye loses the line */

  --header-height: 64px;
  --z-header: 100;
  --z-dropdown: 200;
  --z-overlay: 300;
  --z-toast: 400;
}

/*
  Light theme.

  Not an inversion. Inverting a dark palette gives muddy mid-tones and shadows that
  read as dirt, so the neutrals are re-picked and the brand is darkened to hold its
  contrast against a light surface.
*/
:root[data-theme="light"] {
  --bg:          oklch(0.99 0.003 285);
  --bg-raised:   oklch(1 0 0);
  --bg-overlay:  oklch(0.97 0.005 285);
  --bg-inset:    oklch(0.96 0.006 285);

  --line:        oklch(0.90 0.008 285);
  --line-strong: oklch(0.82 0.012 285);

  --text:        oklch(0.22 0.015 285);
  --text-muted:  oklch(0.44 0.014 285);
  --text-subtle: oklch(0.56 0.012 285);

  --brand-400: oklch(0.58 0.21 285);
  --brand-500: oklch(0.50 0.20 285);
  --brand-600: oklch(0.44 0.18 285);

  --shadow-sm: 0 1px 2px oklch(0.3 0.02 285 / 0.08);
  --shadow:    0 2px 4px oklch(0.3 0.02 285 / 0.06), 0 8px 16px oklch(0.3 0.02 285 / 0.08);
  --shadow-lg: 0 4px 8px oklch(0.3 0.02 285 / 0.08), 0 16px 40px oklch(0.3 0.02 285 / 0.12);
}

/*
  Respect the OS preference until the visitor states one of their own.
  data-theme on the root always wins, so a click beats the system setting.
*/
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg:          oklch(0.99 0.003 285);
    --bg-raised:   oklch(1 0 0);
    --bg-overlay:  oklch(0.97 0.005 285);
    --bg-inset:    oklch(0.96 0.006 285);
    --line:        oklch(0.90 0.008 285);
    --line-strong: oklch(0.82 0.012 285);
    --text:        oklch(0.22 0.015 285);
    --text-muted:  oklch(0.44 0.014 285);
    --text-subtle: oklch(0.56 0.012 285);
    --brand-400: oklch(0.58 0.21 285);
    --brand-500: oklch(0.50 0.20 285);
    --brand-600: oklch(0.44 0.18 285);
    --shadow-sm: 0 1px 2px oklch(0.3 0.02 285 / 0.08);
    --shadow:    0 2px 4px oklch(0.3 0.02 285 / 0.06), 0 8px 16px oklch(0.3 0.02 285 / 0.08);
    --shadow-lg: 0 4px 8px oklch(0.3 0.02 285 / 0.08), 0 16px 40px oklch(0.3 0.02 285 / 0.12);
  }
}
