/* ============================================================================
   tokens.css — the design system, defined before anything is styled.
   Copy this, change the VALUES, keep the STRUCTURE.

   Three tiers:
     1. primitive  --blue-500        raw values, never used directly in components
     2. semantic   --surface, --ink  what a thing IS; components use these
     3. component  --btn-bg          only when a component needs its own knob

   Change the brand by editing tier 1 and the two hue constants. Nothing else.
   ========================================================================= */

:root {
  /* ---- 1. PRIMITIVES -----------------------------------------------------
     Ramps are built in OKLCH so steps are perceptually even. Chroma follows a
     CURVE, not a constant: peak chroma sits mid-ramp and falls off at both
     ends, because near-white and near-black cannot hold saturation without
     going out of gamut. A constant-chroma ramp is the reason naive HSL
     palettes look muddy at the light end and neon at the dark end. */

  --hue-brand: 27;       /* <- change these two numbers to rebrand */
  --hue-accent: 85;

  --brand-50:  oklch(97.5% 0.014 var(--hue-brand));
  --brand-100: oklch(94.5% 0.030 var(--hue-brand));
  --brand-200: oklch(89.0% 0.058 var(--hue-brand));
  --brand-300: oklch(81.5% 0.094 var(--hue-brand));
  --brand-400: oklch(72.0% 0.132 var(--hue-brand));
  --brand-500: oklch(63.0% 0.158 var(--hue-brand));
  --brand-600: oklch(55.0% 0.152 var(--hue-brand));
  --brand-700: oklch(46.5% 0.130 var(--hue-brand));
  --brand-800: oklch(38.5% 0.104 var(--hue-brand));
  --brand-900: oklch(31.0% 0.076 var(--hue-brand));
  --brand-950: oklch(22.0% 0.050 var(--hue-brand));

  --accent-400: oklch(76.0% 0.148 var(--hue-accent));
  --accent-500: oklch(67.0% 0.170 var(--hue-accent));
  --accent-600: oklch(58.0% 0.160 var(--hue-accent));

  /* Neutrals carry a trace of the brand hue. Pure grey (chroma 0) next to a
     saturated brand colour is a tell — real design systems tint their greys. */
  --n-0:   oklch(100%  0     0);
  --n-25:  oklch(98.8% 0.002 var(--hue-brand));
  --n-50:  oklch(97.2% 0.004 var(--hue-brand));
  --n-100: oklch(94.5% 0.006 var(--hue-brand));
  --n-200: oklch(89.5% 0.008 var(--hue-brand));
  --n-300: oklch(82.0% 0.010 var(--hue-brand));
  --n-400: oklch(69.0% 0.012 var(--hue-brand));
  --n-500: oklch(58.0% 0.014 var(--hue-brand));
  --n-600: oklch(48.5% 0.014 var(--hue-brand));
  --n-700: oklch(39.5% 0.013 var(--hue-brand));
  --n-800: oklch(30.0% 0.012 var(--hue-brand));
  --n-900: oklch(22.5% 0.011 var(--hue-brand));
  --n-950: oklch(16.0% 0.010 var(--hue-brand));
  --n-1000: oklch(10.5% 0.008 var(--hue-brand));

  --ok-500:   oklch(62% 0.150 150);
  --warn-500: oklch(75% 0.155  75);
  --err-500:  oklch(58% 0.195  25);

  /* ---- 2. SEMANTIC (light) ---------------------------------------------- */
  --surface-sunken:  var(--n-100);
  --surface:         var(--n-0);
  --surface-raised:  var(--n-0);
  --surface-overlay: var(--n-0);
  --surface-inverse: var(--n-950);

  --ink:         var(--n-900);   /* body text            — AA on --surface */
  --ink-strong:  var(--n-1000);  /* headings             */
  --ink-muted:   var(--n-600);   /* secondary text       — verify AA, n-500 usually fails */
  --ink-subtle:  var(--n-500);   /* large/decorative only */
  --ink-inverse: var(--n-25);
  --ink-brand:   var(--brand-700);

  --line:        var(--n-200);   /* hairlines, dividers  */
  --line-strong: var(--n-300);
  --field:       var(--n-0);
  --field-line:  var(--n-300);

  --focus: var(--brand-500);

  /* ---- 3. ELEVATION -----------------------------------------------------
     Every level is a COMPOUND shadow: a tight contact shadow plus a wider
     ambient one, because real light produces both. A single flat shadow reused
     at every level is the most common depth mistake.
     The 1px hairline is carried IN the shadow stack so it never affects layout. */

  --shadow-color: 27 15% 12%;

  --e0: none;
  --e1:
    0 0 0 1px hsl(var(--shadow-color) / 0.05),
    0 1px 2px -1px hsl(var(--shadow-color) / 0.10);
  --e2:
    0 0 0 1px hsl(var(--shadow-color) / 0.05),
    0 2px 4px -2px hsl(var(--shadow-color) / 0.10),
    0 4px 10px -3px hsl(var(--shadow-color) / 0.08);
  --e3:
    0 0 0 1px hsl(var(--shadow-color) / 0.06),
    0 4px 8px -3px hsl(var(--shadow-color) / 0.11),
    0 12px 24px -6px hsl(var(--shadow-color) / 0.10);
  --e4:
    0 0 0 1px hsl(var(--shadow-color) / 0.07),
    0 8px 16px -6px hsl(var(--shadow-color) / 0.13),
    0 24px 48px -12px hsl(var(--shadow-color) / 0.13);

  /* Inset treatments — carved surfaces. Their absence is why flat UIs read
     as unfinished: everything lifts, nothing recedes. */
  --e-inset:
    inset 0 1px 2px hsl(var(--shadow-color) / 0.10),
    inset 0 0 0 1px hsl(var(--shadow-color) / 0.05);
  --e-bevel:                      /* top highlight + bottom shade = a physical edge */
    inset 0 1px 0 hsl(0 0% 100% / 0.14),
    inset 0 -1px 0 hsl(var(--shadow-color) / 0.16);

  /* ---- 4. TYPE ----------------------------------------------------------
     Fluid sizes interpolate between viewport bounds. The clamp SLOPE is
     expressed with a rem term alongside the vw term: a pure-vw slope does not
     respond to browser zoom and breaks WCAG 1.4.4 (200% zoom). Keep the rem
     part. */

  --font-display: 'IBM Plex Sans', system-ui, sans-serif;
  --font-text:    'IBM Plex Sans', system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;

  /* 1.250 major-third scale, fluid 390px -> 1440px */
  --t-xs:   clamp(0.750rem, 0.729rem + 0.086vw, 0.800rem);
  --t-sm:   clamp(0.875rem, 0.850rem + 0.102vw, 0.935rem);
  --t-base: clamp(1.000rem, 0.957rem + 0.171vw, 1.100rem);
  --t-md:   clamp(1.125rem, 1.057rem + 0.274vw, 1.285rem);
  --t-lg:   clamp(1.375rem, 1.247rem + 0.514vw, 1.675rem);
  --t-xl:   clamp(1.700rem, 1.460rem + 0.960vw, 2.260rem);
  --t-2xl:  clamp(2.100rem, 1.680rem + 1.680vw, 3.080rem);
  --t-3xl:  clamp(2.600rem, 1.900rem + 2.800vw, 4.235rem);

  --lh-tight: 1.05;   /* display */
  --lh-snug:  1.25;   /* headings */
  --lh-base:  1.6;    /* body */
  --lh-loose: 1.75;   /* long-form */

  --track-display: -0.022em;  /* large type needs negative tracking */
  --track-tight:   -0.012em;
  --track-normal:  0;
  --track-wide:    0.06em;    /* small caps / eyebrow labels */

  --measure: 68ch;            /* 45-75ch is the readable range */

  /* ---- 5. SPACE — one scale. Never invent a value outside it. ------------ */
  --s-3xs: 0.125rem;  --s-2xs: 0.25rem;  --s-xs: 0.5rem;
  --s-sm:  0.75rem;   --s-md:  1rem;     --s-lg: 1.5rem;
  --s-xl:  2rem;      --s-2xl: 3rem;     --s-3xl: 4rem;
  --s-4xl: 6rem;      --s-5xl: 8rem;

  --gutter: clamp(1rem, 0.5rem + 2vw, 2rem);
  --container: 72rem;
  --container-narrow: 44rem;

  /* ---- 6. RADII — a small vocabulary, used consistently ----------------- */
  --r-xs: 0.25rem;  --r-sm: 0.375rem;  --r-md: 0.5rem;
  --r-lg: 0.75rem;  --r-xl: 1rem;      --r-2xl: 1.5rem;
  --r-full: 9999px;

  /* ---- 7. MOTION — duration scales with distance travelled -------------- */
  --d-instant: 80ms;    /* colour/opacity state change */
  --d-fast:    140ms;   /* small element, short distance */
  --d-base:    220ms;   /* standard transition */
  --d-slow:    340ms;   /* large surface, panel, modal */
  --d-slower:  520ms;   /* page-level */

  --ease-out:   cubic-bezier(0.22, 1, 0.36, 1);      /* entering — decelerate */
  --ease-in:    cubic-bezier(0.55, 0, 1, 0.45);      /* exiting  — accelerate */
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);      /* moving within view */
  --ease-spring: linear(                              /* overshoot without a JS lib */
    0, 0.006, 0.025, 0.101, 0.539, 0.795, 0.909, 0.963,
    0.991, 1.001, 1.006, 1.004, 1.002, 1);

  color-scheme: light;
}

/* ---- DARK ----------------------------------------------------------------
   Dark mode is a re-mapping of SEMANTIC tokens, not an inversion.
   Elevation is expressed as LIGHTNESS (higher surface = lighter), because
   shadows barely read on a dark ground. Chroma is pulled back slightly:
   saturated colour on dark appears more intense than the same colour on light.

   Order matters. The media query comes first so an explicit [data-theme]
   choice can override it; without this order a manual toggle loses to the OS.
   ------------------------------------------------------------------------ */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --surface-sunken:  var(--n-1000);
    --surface:         var(--n-950);
    --surface-raised:  var(--n-900);
    --surface-overlay: var(--n-800);
    --surface-inverse: var(--n-50);

    --ink:         var(--n-100);
    --ink-strong:  var(--n-25);
    --ink-muted:   var(--n-400);
    --ink-subtle:  var(--n-500);
    --ink-inverse: var(--n-950);
    --ink-brand:   var(--brand-300);

    --line:        oklch(100% 0 0 / 0.09);
    --line-strong: oklch(100% 0 0 / 0.16);
    --field:       oklch(100% 0 0 / 0.04);
    --field-line:  oklch(100% 0 0 / 0.14);

    --focus: var(--brand-400);

    --shadow-color: 27 40% 2%;
    --e1: 0 0 0 1px oklch(100% 0 0 / 0.06), 0 1px 2px -1px hsl(var(--shadow-color) / 0.6);
    --e2: 0 0 0 1px oklch(100% 0 0 / 0.07), 0 2px 6px -2px hsl(var(--shadow-color) / 0.6);
    --e3: 0 0 0 1px oklch(100% 0 0 / 0.08), 0 8px 20px -6px hsl(var(--shadow-color) / 0.7);
    --e4: 0 0 0 1px oklch(100% 0 0 / 0.09), 0 20px 44px -12px hsl(var(--shadow-color) / 0.8);
    --e-bevel: inset 0 1px 0 oklch(100% 0 0 / 0.07), inset 0 -1px 0 oklch(0% 0 0 / 0.30);

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --surface-sunken:  var(--n-1000);
  --surface:         var(--n-950);
  --surface-raised:  var(--n-900);
  --surface-overlay: var(--n-800);
  --surface-inverse: var(--n-50);
  --ink:         var(--n-100);
  --ink-strong:  var(--n-25);
  --ink-muted:   var(--n-400);
  --ink-subtle:  var(--n-500);
  --ink-inverse: var(--n-950);
  --ink-brand:   var(--brand-300);
  --line:        oklch(100% 0 0 / 0.09);
  --line-strong: oklch(100% 0 0 / 0.16);
  --field:       oklch(100% 0 0 / 0.04);
  --field-line:  oklch(100% 0 0 / 0.14);
  --focus: var(--brand-400);
  --shadow-color: 27 40% 2%;
  --e1: 0 0 0 1px oklch(100% 0 0 / 0.06), 0 1px 2px -1px hsl(var(--shadow-color) / 0.6);
  --e2: 0 0 0 1px oklch(100% 0 0 / 0.07), 0 2px 6px -2px hsl(var(--shadow-color) / 0.6);
  --e3: 0 0 0 1px oklch(100% 0 0 / 0.08), 0 8px 20px -6px hsl(var(--shadow-color) / 0.7);
  --e4: 0 0 0 1px oklch(100% 0 0 / 0.09), 0 20px 44px -12px hsl(var(--shadow-color) / 0.8);
  --e-bevel: inset 0 1px 0 oklch(100% 0 0 / 0.07), inset 0 -1px 0 oklch(0% 0 0 / 0.30);
  color-scheme: dark;
}
