/*
 * Kadam — design tokens for the web.
 *
 * Ported verbatim from the app's `src/theme/tokens.ts`. Where the landing-page
 * spec (docs/LANDING.md §4.4) proposed a value the app already decides, the app
 * wins; every one of those reconciliations is listed in docs/IMPLEMENTATION.md
 * and marked `[app wins]` below.
 *
 * One identity in two temperatures. Four palettes total. Geometry, the type
 * ramp, the motion curves and the hairlines are shared — only the palette
 * changes, so the two personas read as the same product in different weather.
 *
 * The active palette is selected by `data-pal` on any element. `<html>` carries
 * the page default; §3.4's persona morph sets it on its own section, which is
 * why these live on an attribute rather than on `:root`.
 */

/* ------------------------------------------------------------------ *
 * Palettes
 * ------------------------------------------------------------------ */

/*
 * The second selector on each palette is for the hero's split panels (§3.1).
 * They pick their palette from their own persona and the page's temperature,
 * both of which are known before first paint — so the split needs no
 * JavaScript and cannot flash the wrong colour on load. Nothing else on the
 * page uses `data-persona-pal`.
 */

/* Indigo — the strength persona, dark. The page default. */
[data-pal='indigo'],
[data-theme='dark'] [data-persona-pal='strength'] {
  --ink: #12102a;
  --card: #1b1840;
  --raised: #252152;
  --sheet: #252152;
  --text: #edebf7;
  --text-dim: rgba(237, 235, 247, 0.58);
  --icon: #8b86bc;
  --pulse: #e0a63c;
  --pulse-text: #e0a63c;
  --pulse-line: #e0a63c;
  --pulse-soft: rgba(224, 166, 60, 0.13);
  --pulse-soft-border: rgba(224, 166, 60, 0.32);
  --on-accent: #20160a;
  --hairline: rgba(255, 255, 255, 0.08);
  --divider: rgba(255, 255, 255, 0.06);
  --track: rgba(255, 255, 255, 0.07);
  --bar-track: rgba(255, 255, 255, 0.08);
  --outline: rgba(255, 255, 255, 0.1);
  --chip-border: rgba(255, 255, 255, 0.12);
  --control-border: rgba(255, 255, 255, 0.18);
  --nav-bg: rgba(18, 16, 42, 0.84);
  --seg-on: #edebf7;
  --seg-on-text: #171340;
  --placeholder: #171340;
  --hatch: rgba(255, 255, 255, 0.035);
  --shadow-card: 0 8px 13px rgba(0, 0, 0, 0.55);
}

/* Ivory — Indigo's light counterpart. */
[data-pal='ivory'],
[data-theme='light'] [data-persona-pal='strength'] {
  --ink: #f7f3ec;
  --card: #ffffff;
  --raised: #efe8dc;
  --sheet: #ffffff;
  --text: #1a1640;
  --text-dim: rgba(26, 22, 64, 0.58);
  --icon: #6f6996;
  --pulse: #e0a63c;
  --pulse-text: #8a5a0e;
  --pulse-line: #a87418;
  --pulse-soft: rgba(224, 166, 60, 0.16);
  --pulse-soft-border: rgba(138, 90, 14, 0.28);
  --on-accent: #20160a;
  --hairline: rgba(26, 22, 64, 0.07);
  --divider: rgba(26, 22, 64, 0.07);
  --track: rgba(26, 22, 64, 0.09);
  --bar-track: rgba(26, 22, 64, 0.07);
  --outline: rgba(26, 22, 64, 0.1);
  --chip-border: rgba(26, 22, 64, 0.12);
  --control-border: rgba(26, 22, 64, 0.18);
  --nav-bg: rgba(247, 243, 236, 0.88);
  --seg-on: #1a1640;
  --seg-on-text: #f7f3ec;
  --placeholder: #efe8dc;
  --hatch: rgba(26, 22, 64, 0.05);
  --shadow-card: 0 6px 14px rgba(11, 20, 64, 0.14);
}

/* Dusk — the cycle persona, dark. */
[data-pal='dusk'],
[data-theme='dark'] [data-persona-pal='cycle'] {
  --ink: #17101e;
  --card: #241826;
  --raised: #2f2032;
  --sheet: #2f2032;
  --text: #f6ede8;
  --text-dim: rgba(246, 237, 232, 0.58);
  --icon: #a98ca0;
  --pulse: #ffb59b;
  --pulse-text: #ffb59b;
  --pulse-line: #ffb59b;
  --pulse-soft: rgba(255, 181, 155, 0.13);
  --pulse-soft-border: rgba(255, 181, 155, 0.32);
  --on-accent: #2e1b24;
  --hairline: rgba(255, 255, 255, 0.08);
  --divider: rgba(255, 255, 255, 0.06);
  --track: rgba(255, 255, 255, 0.07);
  --bar-track: rgba(255, 255, 255, 0.08);
  --outline: rgba(255, 255, 255, 0.1);
  --chip-border: rgba(255, 255, 255, 0.12);
  --control-border: rgba(255, 255, 255, 0.18);
  --nav-bg: rgba(23, 16, 30, 0.84);
  --seg-on: #f6ede8;
  --seg-on-text: #2e1b24;
  --placeholder: #1e1524;
  --hatch: rgba(255, 255, 255, 0.035);
  --shadow-card: 0 8px 13px rgba(0, 0, 0, 0.55);
}

/* Dawn — the cycle persona, light. */
[data-pal='dawn'],
[data-theme='light'] [data-persona-pal='cycle'] {
  --ink: #fbf5f0;
  --card: #ffffff;
  --raised: #f2e7e0;
  --sheet: #ffffff;
  --text: #2e1b24;
  --text-dim: rgba(46, 27, 36, 0.6);
  --icon: #9c7f92;
  --pulse: #ffb59b;
  --pulse-text: #a6432a;
  --pulse-line: #c25e3e;
  --pulse-soft: rgba(255, 181, 155, 0.22);
  --pulse-soft-border: rgba(166, 67, 42, 0.26);
  --on-accent: #2e1b24;
  --hairline: rgba(46, 27, 36, 0.08);
  --divider: rgba(46, 27, 36, 0.08);
  --track: rgba(46, 27, 36, 0.09);
  --bar-track: rgba(46, 27, 36, 0.08);
  --outline: rgba(46, 27, 36, 0.11);
  --chip-border: rgba(46, 27, 36, 0.13);
  --control-border: rgba(46, 27, 36, 0.19);
  --nav-bg: rgba(251, 245, 240, 0.88);
  --seg-on: #2e1b24;
  --seg-on-text: #fbf5f0;
  --placeholder: #f2e7e0;
  --hatch: rgba(46, 27, 36, 0.05);
  --shadow-card: 0 6px 14px rgba(11, 20, 64, 0.14);
}

/*
 * Cycle phase family — four moments in one day, not a traffic light. The only
 * multi-hue family Kadam owns, and the only palette the constellation's
 * particles are allowed to draw from (§4.2).
 */
:root {
  --phase-menstrual: #c25e7a;
  --phase-follicular: #f2a65a;
  --phase-ovulation: #e8c468;
  --phase-luteal: #a67b9a;
}

/* ------------------------------------------------------------------ *
 * Geometry
 * ------------------------------------------------------------------ */

:root {
  --r-hero: 22px;
  --r-sheet: 26px;
  --r-card: 18px;
  --r-card-sm: 16px;
  --r-control: 15px;
  --r-control-16: 16px;
  --r-chip: 9px;
  --r-chip-lg: 11px;
  --r-pill: 24px;

  /* 0.5pt hairlines everywhere — never 1pt, and never thickened on focus. */
  --hair: 0.5px;

  /* The app's screen gutter is 18. The page widens it with viewport, floored at 18. */
  --gutter: clamp(18px, 5vw, 40px);
  --card-gap: 13px;

  /* Measures. The prose column is capped where a 17px line hits ~68 characters. */
  --measure: 34rem;
  --page: 74rem;
  --page-narrow: 58rem;
}

/* ------------------------------------------------------------------ *
 * Type
 * ------------------------------------------------------------------ */

/*
 * IBM Plex Mono, self-hosted. No font CDN: a page whose strongest section is
 * "nothing leaves your phone" should not open a connection to Google to render
 * its own labels.
 *
 * All three of the app's weights ship — 400 for body mono, 500 for kickers and
 * labels, 600 for values — subset to Latin and converted to WOFF2 by
 * `npm run build:fonts`. That is 47 KB for the set, against 398 KB for the raw
 * TTFs, which is what makes carrying the third weight affordable.
 */
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/IBMPlexMono-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/IBMPlexMono-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/IBMPlexMono-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/*
 * Metric-matched fallback. Plex Mono is wider than the system mono, so an
 * unadjusted swap reflows every kicker on the page. These adjustments hold the
 * advance width close enough that the swap is invisible at label sizes, which
 * is what keeps CLS at zero (§4.7).
 */
@font-face {
  font-family: 'Plex Fallback';
  src: local('SFMono-Regular'), local('Menlo'), local('Consolas'), local('monospace');
  size-adjust: 104%;
  ascent-override: 92%;
  descent-override: 26%;
  line-gap-override: 0%;
}

:root {
  /* Display and UI: the system face — SF Pro on Apple, matching the app. */
  --font-ui:
    -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'IBM Plex Mono', 'Plex Fallback', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Ramp. Fluid between a 360px phone and a 1280px desktop. */
  --fs-display: clamp(2.25rem, 1.35rem + 4vw, 4rem);
  --fs-h2: clamp(1.75rem, 1.25rem + 2.2vw, 2.75rem);
  --fs-h3: clamp(1.25rem, 1.05rem + 0.9vw, 1.625rem);
  --fs-lead: clamp(1.0625rem, 1rem + 0.5vw, 1.3125rem);
  --fs-body: 1.0625rem;
  --fs-small: 0.9375rem;
  --fs-fine: 0.8125rem;

  /* Kickers: mono, uppercase, wide-tracked — the app's own label treatment.
     `Kicker` in src/components/Type.tsx is font.mono (500) at 11px with 1.5
     letter-spacing, so that is the weight, not 600. */
  --fs-kicker: 0.6875rem;
  --ls-kicker: 0.13em;
  --fw-kicker: 500;
}

/* ------------------------------------------------------------------ *
 * Motion
 * ------------------------------------------------------------------ */

:root {
  --dur-micro: 120ms; /* hover, focus, hairline colour change */
  --dur-control: 180ms; /* buttons, tabs, toggles, crossfades — app duration.press */
  --dur-colour: 240ms; /* [app wins] app duration.colour — palette swaps */
  --dur-reveal: 420ms; /* section and block entrances — app duration.enter */
  --dur-morph: 640ms; /* the persona morph, and only that */
  --dur-draw: 700ms; /* [app wins] a ring sweeping — app Ring.tsx pace='ease' */

  /* [app wins] entrances use the app's own enter curve, easing.enter. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* Anything reversible: toggles, morphs. No app equivalent; spec value kept. */
  --ease-inout: cubic-bezier(0.6, 0, 0.2, 1);
  /* [app wins] the ring sweep uses the same enter curve the app draws with. */
  --ease-draw: cubic-bezier(0.22, 1, 0.36, 1);
  /* [app wins] app easing.press — the one curve allowed to overshoot. */
  --ease-press: cubic-bezier(0.32, 1.5, 0.6, 1);

  --stagger: 60ms; /* between siblings, capped at five steps */
  --travel-block: 16px;
  --travel-inline: 8px;
  --press-scale: 0.955; /* [app wins] app pressScale.button */

  /* Whether the page's two continuous animations are allowed to run. */
  --loop: running;
}

/*
 * Under reduced motion every duration collapses to zero. Doing it at the token
 * level means a transition added later cannot forget to honour it; §4.6 is a
 * rendering path, not a set of opt-in exceptions.
 *
 * `[data-motion='off']` is the same switch, thrown by the reader rather than by
 * the operating system — the footer control. It exists because the page now has
 * continuous motion (the constellation's ambient drift, the hero's float), and
 * WCAG 2.2.2 asks for a way to stop anything that moves for more than five
 * seconds. Honouring only `prefers-reduced-motion` would leave the reader who
 * simply finds it distracting with nothing to press.
 */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-micro: 0ms;
    --dur-control: 0ms;
    --dur-colour: 0ms;
    --dur-reveal: 0ms;
    --dur-morph: 0ms;
    --dur-draw: 0ms;
    --stagger: 0ms;
    --travel-block: 0px;
    --travel-inline: 0px;
    --press-scale: 1;
    --loop: paused;
  }
}

[data-motion='off'] {
  --dur-micro: 0ms;
  --dur-control: 0ms;
  --dur-colour: 0ms;
  --dur-reveal: 0ms;
  --dur-morph: 0ms;
  --dur-draw: 0ms;
  --stagger: 0ms;
  --travel-block: 0px;
  --travel-inline: 0px;
  --press-scale: 1;
  --loop: paused;
}
