/* ==========================================================================
   baddie — design tokens (single source of truth)
   --------------------------------------------------------------------------
   Ink and warm white carry every screen. Pink and purple are precise accents:
   one signature moment per view.

   LIGHT  = "day"   rose-white surfaces, ink text, pink signature, purple agent
   DARK   = "night" aubergine-black surfaces, warm-white text, purple signature,
                    pink agent

   Theme switching
     System : <html>                      (follows prefers-color-scheme)
     Light  : <html data-theme="light">
     Dark   : <html data-theme="dark">
     Stage  : <section data-theme="dark">  a dark plate inside a light page.
              Any element can carry data-theme="dark"; everything inside it
              reads the dark tokens. (There is no light plate inside dark.)

   Fonts — three families, all open source (SIL OFL 1.1), all self-hosted.
   Nothing is fetched from a font CDN: the Content Security Policy forbids it.
     Display : Bodoni Moda   (variable: opsz 6–96, wght 400–900)   the brand speaking
     Text    : Hanken Grotesk (variable: wght 100–900, italics)    the work
     Mono    : Geist Mono    (variable: wght 100–900)              the facts

       pnpm add @fontsource-variable/bodoni-moda @fontsource-variable/hanken-grotesk @fontsource-variable/geist-mono

       import "@fontsource-variable/bodoni-moda/opsz.css";             // opsz + wght axes. NOT the default
                                                                       // entry: that one is locked to the
                                                                       // 11pt text cut and loses the hairlines.
       import "@fontsource-variable/hanken-grotesk/wght.css";          // wght axis
       import "@fontsource-variable/hanken-grotesk/wght-italic.css";   // italics
       import "@fontsource-variable/geist-mono/wght.css";              // wght axis

     Those packages register "Bodoni Moda Variable", "Hanken Grotesk Variable"
     and "Geist Mono Variable"; the stacks below already name them.

   Contrast: every pairing listed in check-contrast.mjs meets WCAG 2.1 AA in
   both themes. Run `node brand/check-contrast.mjs` after ANY colour edit.

   The dark block appears twice (system + explicit) because CSS has no way to
   share it; check-contrast.mjs fails if the two copies ever drift apart.
   Tokens marked DEPRECATED still resolve, so nothing breaks; do not use them
   in new work.
   ========================================================================== */

:root {
  color-scheme: light;

  /* ---- Brand hues (theme-independent) ---------------------------------- */
  /* pink */
  --pink-50: #fff1f7;
  --pink-100: #ffe1ee;
  --pink-200: #ffc4df;
  --pink-300: #ff96c8;
  --pink-400: #ff5fad;
  --pink-500: #ff2e93; /* the signature hot pink — the mark and art, never text */
  --pink-600: #de0a75;
  --pink-700: #b60661;
  --pink-800: #92084f;
  --pink-900: #6f0a3f;
  --pink-950: #450524;

  /* purple */
  --purple-50: #f7f2ff;
  --purple-100: #eee5ff;
  --purple-200: #ddccff;
  --purple-300: #c4a8ff;
  --purple-400: #a77dff;
  --purple-500: #8b4dff; /* the signature electric purple */
  --purple-600: #742ef0;
  --purple-700: #5e1fcc;
  --purple-800: #4c1aa3;
  --purple-900: #3d187f;
  --purple-950: #250b57;

  /* ---- Surfaces --------------------------------------------------------- */
  --bg: #faf7f8; /* page: warm white with a trace of rose */
  --bg-elevated: #ffffff; /* popovers, menus, modals, toasts */
  --surface: #ffffff; /* cards, panels, sidebar */
  --surface-2: #f3eef0; /* wells, hover fill, quiet controls */
  --surface-3: #e9e2e5; /* pressed / selected neutral fill */
  --field-bg: #ffffff; /* inputs */
  --bg-inverse: #170d16; /* tooltips */
  --text-inverse: #ffffff;
  --scrim: rgb(23 13 22 / 0.5); /* behind modals */

  /* ---- Lines ------------------------------------------------------------ */
  --border: #e7dfe3; /* hairlines, card edges (decorative) */
  --border-strong: #8c7c86; /* control outlines — ≥3:1 on every surface */

  /* ---- Text ------------------------------------------------------------- */
  --text: #170d16; /* ink: aubergine-black */
  --text-muted: #5a4a56;
  --text-faint: #756570; /* timestamps, placeholders — still AA on bg/surface/surface-2 */

  /* ---- Ink: the solid, high-contrast fill. The default primary button,
          the checked switch, the selected segment. Ink in light, warm white
          in dark. ---------------------------------------------------------- */
  --ink: #170d16;
  --ink-hover: #3a2b38;
  --ink-active: #4d3d4a;
  --ink-contrast: #ffffff; /* text/icons on --ink */

  /* ---- Primary (YOU): pink in light. The signature. One moment per view. - */
  --primary: var(--pink-600);
  --primary-hover: var(--pink-700);
  --primary-active: var(--pink-800);
  --primary-contrast: #ffffff; /* text/icons on --primary and on --gradient-brand */
  --primary-text: var(--pink-700); /* primary-coloured text/icons on bg, surface, soft */
  --primary-soft: #fdebf3;
  --primary-soft-hover: #fbdcea;
  --primary-border: var(--pink-300);

  /* ---- Accent (YOUR AGENT): purple in light ------------------------------ */
  --accent: var(--purple-600);
  --accent-hover: var(--purple-700);
  --accent-contrast: #ffffff;
  --accent-text: var(--purple-700);
  --accent-soft: #f1ebfe;
  --accent-border: var(--purple-300);

  /* ---- Status. Each colour works as text on bg/surface/its -soft, and as a
          solid fill under its -contrast. Danger is orange-red on purpose so it
          can never be mistaken for brand pink: check-contrast.mjs fails if its
          hue comes within 40 degrees of --primary or --accent. --------------- */
  --success: #0b7a48;
  --success-contrast: #ffffff;
  --success-soft: #e3f5ec;
  --success-border: #9fdcbd;

  --warning: #8f4e00;
  --warning-contrast: #ffffff;
  --warning-soft: #fdf1d6;
  --warning-border: #f0cd85;

  --danger: #c2280a;
  --danger-hover: #a01f06;
  --danger-contrast: #ffffff;
  --danger-soft: #fdeae4;
  --danger-border: #f5b5a3;

  --info: #0b63c4;
  --info-contrast: #ffffff;
  --info-soft: #e6f0fd;
  --info-border: #a9cbf5;

  /* ---- Focus ------------------------------------------------------------ */
  --focus-ring: var(--purple-600); /* always the *other* brand hue from the signature */
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;

  /* ---- Gradients -------------------------------------------------------- */
  /* The mark's gradient: the one place pink and purple meet. Graphic only —
     the mark, and at most one hero object per page. Never under text. */
  --gradient-mark-from: var(--pink-500);
  --gradient-mark-via: #c53ecb;
  --gradient-mark-to: var(--purple-500);
  --gradient-mark: linear-gradient(
    135deg,
    var(--gradient-mark-from) 0%,
    var(--gradient-mark-via) 50%,
    var(--gradient-mark-to) 100%
  );
  /* A text-safe version of the same idea, per theme. --gradient-brand-contrast
     is AA on every point of it. No component uses it; it exists for one
     marketing moment at most. */
  --gradient-brand-from: var(--pink-600);
  --gradient-brand-via: #b414b4;
  --gradient-brand-to: var(--purple-600);
  --gradient-brand-contrast: #ffffff;
  --gradient-brand: linear-gradient(
    135deg,
    var(--gradient-brand-from) 0%,
    var(--gradient-brand-via) 52%,
    var(--gradient-brand-to) 100%
  );
  /* DEPRECATED — gradient text is retired; .b-gradient-text now sets a solid colour. */
  --gradient-text-from: var(--pink-600);
  --gradient-text-to: var(--purple-600);
  --gradient-text: linear-gradient(100deg, var(--gradient-text-from) 0%, var(--gradient-text-to) 100%);
  /* DEPRECATED — tinted washes are retired; both stops are --surface-2, so this is a flat fill. */
  --gradient-surface-from: var(--surface-2);
  --gradient-surface-to: var(--surface-2);
  --gradient-surface: linear-gradient(135deg, var(--gradient-surface-from) 0%, var(--gradient-surface-to) 100%);
  /* DEPRECATED — the page wash is retired. Pages sit on plain --bg. */
  --gradient-glow: none;

  /* ---- Platform identity (text/icon-safe on bg, surface and surface-2) --- */
  --platform-facebook: #0b5fe0;
  --platform-instagram: #c2247c;
  --platform-youtube: #c70000;
  --platform-tiktok: #101014;
  --platform-bluesky: #0a62c7;
  --platform-mastodon: #5052e6;
  --platform-telegram: #0a6a9c;
  --platform-whatsapp: #0d7a43;
  --platform-x: #14171a;
  --platform-threads: #1f1f1f;
  --platform-linkedin: #0a5fb4;
  /* how much platform colour is mixed into --surface for a tinted pill */
  --platform-tint: 8%;

  /* ---- Shadows -----------------------------------------------------------
     Surfaces are flat: depth is a hairline. Only things that float over the
     page (menus, toasts, modals) cast a shadow, tight and low. The other
     shadow tokens are a transparent zero shadow, written that way (not
     `none`) so they stay valid inside a comma-separated list. */
  --shadow-xs: 0 0 0 0 transparent; /* DEPRECATED — flat */
  --shadow-sm: 0 0 0 0 transparent; /* DEPRECATED — flat */
  --shadow-md: 0 0 0 0 transparent; /* DEPRECATED — flat */
  --shadow-lg: 0 4px 12px -4px rgb(23 13 22 / 0.14); /* menus, toasts */
  --shadow-xl: 0 12px 24px -8px rgb(23 13 22 / 0.2); /* modals */
  --shadow-glow: 0 0 0 0 transparent; /* DEPRECATED — no glows */
  --shadow-glow-strong: 0 0 0 0 transparent; /* DEPRECATED — no glows */
  --shadow-glow-accent: 0 0 0 0 transparent; /* DEPRECATED — no glows */
  --shadow-gloss: 0 0 0 0 transparent; /* DEPRECATED — no gloss */

  /* ---- Typography ------------------------------------------------------- */
  --font-display:
    "Bodoni Moda Variable", "Bodoni Moda", "Bodoni 72", Didot, "Bodoni MT", "Times New Roman", Times, serif;
  --font-sans:
    "Hanken Grotesk Variable", "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
  --font-mono:
    "Geist Mono Variable", "Geist Mono", ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Code", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* type scale (rem; 1rem = 16px) */
  --fs-2xs: 0.6875rem; /* 11 — counters, and the labels under the phone tab bar's icons */
  --fs-xs: 0.75rem; /* 12 — mono labels, badges */
  --fs-sm: 0.875rem; /* 14 — controls, secondary UI */
  --fs-md: 0.9375rem; /* 15 — nav items, list rows */
  --fs-base: 1rem; /* 16 — body */
  --fs-lg: 1.125rem; /* 18 */
  --fs-xl: 1.25rem; /* 20 */
  --fs-2xl: 1.5rem; /* 24 */
  --fs-3xl: 1.875rem; /* 30 */
  --fs-4xl: 2.375rem; /* 38 */
  --fs-5xl: 3rem; /* 48 */
  --fs-6xl: 4rem; /* 64 */
  --fs-display: clamp(2.75rem, 1.55rem + 5.4vw, 5.5rem); /* marketing hero */

  --lh-tight: 1.04; /* display */
  --lh-snug: 1.25; /* headings, controls */
  --lh-normal: 1.5; /* body */
  --lh-relaxed: 1.65; /* long-form */

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-black: 800; /* DEPRECATED for display type: the serif is set at --fw-display */
  --fw-display: 500; /* Bodoni Moda, everywhere it appears */
  /* Bodoni Moda's optical size, pinned for type of 24px and up. Left to follow
     the font size, the hairlines thin out until they break on a 1x screen.
     The smaller the type, the sturdier the cut. */
  --opsz-display: 24; /* 44px and up: .b-display */
  --opsz-headline: 18; /* 30 to 48px: h1, .b-h1 */
  --opsz-title: 14; /* 24 to 30px: h2, .b-h2, empty-state titles */

  --ls-tighter: -0.03em; /* display ≥ 38px */
  --ls-tight: -0.015em; /* headings */
  --ls-normal: 0;
  --ls-wide: 0.04em;
  --ls-caps: 0.06em; /* DEPRECATED — all-caps is retired; mono labels are lowercase and untracked */

  /* ---- Spacing (4px base) ------------------------------------------------ */
  --space-0: 0;
  --space-px: 1px;
  --space-0-5: 0.125rem; /* 2 */
  --space-1: 0.25rem; /* 4 */
  --space-1-5: 0.375rem; /* 6 */
  --space-2: 0.5rem; /* 8 */
  --space-3: 0.75rem; /* 12 */
  --space-4: 1rem; /* 16 */
  --space-5: 1.25rem; /* 20 */
  --space-6: 1.5rem; /* 24 */
  --space-8: 2rem; /* 32 */
  --space-10: 2.5rem; /* 40 */
  --space-12: 3rem; /* 48 */
  --space-16: 4rem; /* 64 */
  --space-20: 5rem; /* 80 */
  --space-24: 6rem; /* 96 */

  /* ---- Radii: small and exact. Pills are for buttons and chips only. ------ */
  --radius-xs: 4px; /* kbd, inline code, checkboxes */
  --radius-sm: 6px; /* tooltips, skeletons */
  --radius-md: 8px; /* inputs, nav items, alerts, list rows */
  --radius-lg: 10px; /* cards, toasts */
  --radius-xl: 14px; /* modals, panels */
  --radius-2xl: 20px; /* marketing plates */
  --radius-full: 999px; /* buttons, chips, badges, avatars */

  /* ---- Sizing ------------------------------------------------------------- */
  --control-sm: 2rem; /* 32 */
  --control-md: 2.5rem; /* 40 */
  --control-lg: 3rem; /* 48 */
  --tap-min: 2.75rem; /* 44 — minimum hit area on touch */
  --sidebar-w: 16.5rem; /* 264 */
  --content-max: 45rem; /* 720 — feed / reading column */
  --page-max: 75rem; /* 1200 */
  /* breakpoints (media queries cannot read variables): 480 · 768 · 1024 · 1280 */

  /* ---- Motion: short and quiet. Nothing overshoots. ------------------------ */
  --duration-instant: 80ms;
  --duration-fast: 120ms;
  --duration-base: 180ms;
  --duration-slow: 260ms;
  --duration-slower: 400ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.9, 0.3);
  --ease-bounce: cubic-bezier(0.16, 1, 0.3, 1); /* DEPRECATED — same curve as --ease-out; nothing bounces */
  --motion-scale: 1; /* multiply transforms by this; becomes 0 under reduced motion */

  /* ---- Layers --------------------------------------------------------------- */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 100;
  --z-nav: 200;
  --z-dropdown: 300;
  --z-overlay: 400;
  --z-modal: 500;
  --z-toast: 600;
  --z-tooltip: 700;
}

/* ==========================================================================
   DARK — system preference (unless the user forced light)
   ========================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #0e0a10;
    --bg-elevated: #1c161f;
    --surface: #151017;
    --surface-2: #1e1821;
    --surface-3: #2a222e;
    --field-bg: #100c12;
    --bg-inverse: #f6f1f4;
    --text-inverse: #170d16;
    --scrim: rgb(0 0 0 / 0.72);

    --border: #2b232f;
    --border-strong: #7b6e7f;

    --text: #f6f1f4;
    --text-muted: #b9adb8;
    --text-faint: #9a8d99;

    --ink: #f6f1f4;
    --ink-hover: #ffffff;
    --ink-active: #ddd5da;
    --ink-contrast: #170d16;

    --primary: var(--purple-400);
    --primary-hover: var(--purple-300);
    --primary-active: var(--purple-200);
    --primary-contrast: #150a2b;
    --primary-text: var(--purple-300);
    --primary-soft: #241a3a;
    --primary-soft-hover: #2e2149;
    --primary-border: #4d3a80;

    --accent: var(--pink-400);
    --accent-hover: var(--pink-300);
    --accent-contrast: #2e0419;
    --accent-text: var(--pink-300);
    --accent-soft: #36142f;
    --accent-border: #84296f;

    --success: #4ade94;
    --success-contrast: #052814;
    --success-soft: #0f2a1e;
    --success-border: #1f5a3d;

    --warning: #ffc14d;
    --warning-contrast: #2e1c00;
    --warning-soft: #33250a;
    --warning-border: #6e5115;

    --danger: #ff7d4d;
    --danger-hover: #ff9a73;
    --danger-contrast: #2b0d02;
    --danger-soft: #3b1a0b;
    --danger-border: #86391b;

    --info: #6cb4ff;
    --info-contrast: #041c3a;
    --info-soft: #102540;
    --info-border: #1f4b82;

    --focus-ring: var(--pink-400);

    --gradient-brand-from: var(--purple-400);
    --gradient-brand-via: #d46ee0;
    --gradient-brand-to: var(--pink-400);
    --gradient-brand-contrast: #150a2b;
    --gradient-brand: linear-gradient(
      135deg,
      var(--gradient-brand-from) 0%,
      var(--gradient-brand-via) 52%,
      var(--gradient-brand-to) 100%
    );
    --gradient-text-from: var(--purple-300);
    --gradient-text-to: var(--pink-300);
    --gradient-text: linear-gradient(100deg, var(--gradient-text-from) 0%, var(--gradient-text-to) 100%);
    --gradient-surface-from: var(--surface-2);
    --gradient-surface-to: var(--surface-2);
    --gradient-surface: linear-gradient(135deg, var(--gradient-surface-from) 0%, var(--gradient-surface-to) 100%);

    --platform-facebook: #6ba4ff;
    --platform-instagram: #f777c4;
    --platform-youtube: #ff6b6b;
    --platform-tiktok: #25f4ee;
    --platform-bluesky: #4fb0ff;
    --platform-mastodon: #a3a4ff;
    --platform-telegram: #4cc3f7;
    --platform-whatsapp: #3ddc84;
    --platform-x: #f2f4f5;
    --platform-threads: #ffffff;
    --platform-linkedin: #70b5f9;
    --platform-tint: 14%;

    --shadow-lg: 0 4px 12px -4px rgb(0 0 0 / 0.5);
    --shadow-xl: 0 12px 24px -8px rgb(0 0 0 / 0.6);
  }
}

/* ==========================================================================
   DARK — explicit, on <html> or on any element (a "stage").
   Must stay identical to the block above.
   ========================================================================== */
[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0e0a10;
  --bg-elevated: #1c161f;
  --surface: #151017;
  --surface-2: #1e1821;
  --surface-3: #2a222e;
  --field-bg: #100c12;
  --bg-inverse: #f6f1f4;
  --text-inverse: #170d16;
  --scrim: rgb(0 0 0 / 0.72);

  --border: #2b232f;
  --border-strong: #7b6e7f;

  --text: #f6f1f4;
  --text-muted: #b9adb8;
  --text-faint: #9a8d99;

  --ink: #f6f1f4;
  --ink-hover: #ffffff;
  --ink-active: #ddd5da;
  --ink-contrast: #170d16;

  --primary: var(--purple-400);
  --primary-hover: var(--purple-300);
  --primary-active: var(--purple-200);
  --primary-contrast: #150a2b;
  --primary-text: var(--purple-300);
  --primary-soft: #241a3a;
  --primary-soft-hover: #2e2149;
  --primary-border: #4d3a80;

  --accent: var(--pink-400);
  --accent-hover: var(--pink-300);
  --accent-contrast: #2e0419;
  --accent-text: var(--pink-300);
  --accent-soft: #36142f;
  --accent-border: #84296f;

  --success: #4ade94;
  --success-contrast: #052814;
  --success-soft: #0f2a1e;
  --success-border: #1f5a3d;

  --warning: #ffc14d;
  --warning-contrast: #2e1c00;
  --warning-soft: #33250a;
  --warning-border: #6e5115;

  --danger: #ff7d4d;
  --danger-hover: #ff9a73;
  --danger-contrast: #2b0d02;
  --danger-soft: #3b1a0b;
  --danger-border: #86391b;

  --info: #6cb4ff;
  --info-contrast: #041c3a;
  --info-soft: #102540;
  --info-border: #1f4b82;

  --focus-ring: var(--pink-400);

  --gradient-brand-from: var(--purple-400);
  --gradient-brand-via: #d46ee0;
  --gradient-brand-to: var(--pink-400);
  --gradient-brand-contrast: #150a2b;
  --gradient-brand: linear-gradient(
    135deg,
    var(--gradient-brand-from) 0%,
    var(--gradient-brand-via) 52%,
    var(--gradient-brand-to) 100%
  );
  --gradient-text-from: var(--purple-300);
  --gradient-text-to: var(--pink-300);
  --gradient-text: linear-gradient(100deg, var(--gradient-text-from) 0%, var(--gradient-text-to) 100%);
  --gradient-surface-from: var(--surface-2);
  --gradient-surface-to: var(--surface-2);
  --gradient-surface: linear-gradient(135deg, var(--gradient-surface-from) 0%, var(--gradient-surface-to) 100%);

  --platform-facebook: #6ba4ff;
  --platform-instagram: #f777c4;
  --platform-youtube: #ff6b6b;
  --platform-tiktok: #25f4ee;
  --platform-bluesky: #4fb0ff;
  --platform-mastodon: #a3a4ff;
  --platform-telegram: #4cc3f7;
  --platform-whatsapp: #3ddc84;
  --platform-x: #f2f4f5;
  --platform-threads: #ffffff;
  --platform-linkedin: #70b5f9;
  --platform-tint: 14%;

  --shadow-lg: 0 4px 12px -4px rgb(0 0 0 / 0.5);
  --shadow-xl: 0 12px 24px -8px rgb(0 0 0 / 0.6);
}

/* ==========================================================================
   Reduced motion — the tokens themselves go still, so anything built on them
   complies without extra work.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 0.01ms;
    --duration-fast: 0.01ms;
    --duration-base: 0.01ms;
    --duration-slow: 0.01ms;
    --duration-slower: 0.01ms;
    --motion-scale: 0;
  }
}
