/* ==========================================================================
   UNOVA — "Nova's Dusk" design tokens
   The single source of truth. Every colour, size, duration and easing in this
   site comes from here; nothing downstream hard-codes a value.

   The 3D layer reads the same numbers from js/scene/palette.js. If you change
   a colour, change it in both — they are deliberately two short files rather
   than one clever one that has to be parsed at runtime.
   ========================================================================== */

:root {
  /* --- Surfaces: dusk stage, lifted navy, never pitch black --------------- */
  --ink: 9 13 26;         /* #090D1A  page base — deep, not quite black      */
  --ink-2: 15 21 38;      /* #0F1526  raised surface / cards                 */
  --ink-3: 26 34 58;      /* #1A223A  hairline / divider                     */
  --ink-deep: 4 6 13;     /* #04060D  vignette floor, scene fog far          */

  /* --- Nova's own palette, with strict UI roles -------------------------- */
  --vinyl: 243 235 220;   /* #F3EBDC  cream casing → body + heading text     */
  --nova: 79 227 196;    /* #4FE3C4  mint eye → THE interactive colour      */
  --signal: 255 139 110;  /* #FF8B6E  coral cheeks → decorative accent only  */
  --pulse: 124 245 176;   /* #7CF5B0  antenna green → status / success only  */

  /* --- Text ramp. Contrast on --ink: 13.8:1 / 7.2:1 / 5.2:1 (AAA/AA) ------ */
  --text-1: var(--vinyl);
  --text-2: 168 176 200;  /* #A8B0C8 */
  --text-3: 138 149 180;  /* #8A95B4 */

  --focus-ring: var(--nova);

  /* --- Typography --------------------------------------------------------- */
  --font-display: 'Bricolage Grotesque', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;

  /* Fluid display scale. Never below the 16px body floor. */
  --size-display-xl: clamp(2.75rem, 7.2vw, 6.75rem);
  --size-display-lg: clamp(2.25rem, 5.6vw, 4.75rem);
  --size-display-md: clamp(2rem, 4.5vw, 3.5rem);
  --size-display-sm: clamp(1.5rem, 2.6vw, 2.25rem);
  --size-lede: clamp(1.0625rem, 1.4vw, 1.375rem);
  --size-body: 1rem;
  --size-sm: 0.875rem;
  --size-xs: 0.75rem;

  /* --- Spacing: 4/8 rhythm, plus two fluid steps for section gaps --------- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-14: 3.5rem;
  --space-16: 4rem;
  --space-section: clamp(5rem, 12vh, 10rem);
  --gutter: clamp(1.25rem, 4vw, 3.5rem);

  --shell: 84rem;
  /* Measured, not guessed: 68ch resolved to 100+ characters per line on the
     larger display sizes, because a `ch` (the width of "0") is much wider than
     the average lowercase glyph. `em` keeps the character count constant across
     font sizes — 27em lands at ~70 characters everywhere for this typeface. */
  --measure: 27em;
  --radius: 14px;
  --radius-pill: 999px;

  /* --- Motion: one easing pair and three durations, used everywhere ------- */
  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-exit: cubic-bezier(0.7, 0, 0.84, 0);
  --dur-micro: 180ms;
  --dur-base: 280ms;
  --dur-scene: 420ms;

  /* --- Layering. Written down so nothing invents its own z-index. --------- */
  --z-canvas: 0;          /* raised to --z-canvas-loading while loading      */
  --z-content: 10;
  --z-nav: 50;
  --z-transition: 80;
  --z-curtain: 90;        /* loader backdrop — BELOW the canvas, on purpose  */
  --z-canvas-loading: 95;
  --z-loader: 100;
  --z-dock: 70;           /* Nova — above content, below nav and the loader   */

  color-scheme: dark;
}

/* ==========================================================================
   LIGHT SURFACES — the other half of the mixture.

   The page alternates: dark sections let the 3D scene show through, light
   sections are opaque and carry the long reading copy. Both are the SAME
   stylesheet — a light section just redefines the tokens inside its own
   subtree, so every component below inherits the new palette without a single
   component-level override. That is the whole reason everything was routed
   through variables in the first place.

   Two things had to change beyond "swap the greys":

   1. --vinyl is the TEXT role, not "cream". On a light surface it becomes deep
      ink, which is why headings, body, buttons and borders all flip together.
   2. Mint (#4FE3C4) on stone is 1.5:1 — invisible. Interactive colour on light
      surfaces is a deep teal at 4.8:1, so it stays recognisably the same hue
      and still passes AA as text. Never reuse a dark-mode accent on light.
   ========================================================================== */

[data-surface='light'] {
  /* Stone, not paper. The first version was #F0ECE4 — L* 93, four points off
     white — sitting directly against an L* 5 navy. Two surfaces that far apart
     don't read as one design with two moods, they read as two different sites
     spliced together, and the light half is genuinely uncomfortable at night.
     Dropping to L* 85 and warming it toward the Nova cream closes most of
     that gap while still being unmistakably the light half. */
  --ink: 218 213 201;     /* #DAD5C9  warm stone — the band itself             */
  --ink-2: 234 230 220;   /* #EAE6DC  raised card, lifts off the band          */
  --ink-3: 194 186 168;   /* #C2BAA8  hairline                                 */
  --ink-deep: 205 199 185;

  --vinyl: 20 26 44;      /* #141A2C  the TEXT role flips to deep ink          */

  /* Every accent is re-darkened for the new, deeper ground. Mint #4FE3C4 on
     stone is 1.5:1 — invisible. These are the same hues at 4.5:1 or better,
     measured against #DAD5C9 rather than assumed. */
  --nova: 0 102 80;      /* #006650  4.8:1                                    */
  --signal: 156 52 25;    /* #9C3419  4.9:1                                    */
  --pulse: 20 96 62;

  --text-1: var(--vinyl);
  --text-2: 74 81 100;    /* #4A5164  5.4:1                                    */
  --text-3: 86 93 110;    /* #565D6E  4.5:1 — the floor, not a rounding error  */

  /* Opaque, and above the canvas — a translucent light band over a dark 3D
     scene is mud. The dark sections are where the scene is meant to show. */
  position: relative;
  z-index: var(--z-content);
  background: rgb(var(--ink));
  color: rgb(var(--text-1));
  color-scheme: light;
}

/* Glass was tuned for a dark room: a white film over dark navy. Invert the
   film on paper or the cards vanish. */
[data-surface='light'] .glass {
  background: linear-gradient(
    160deg,
    rgb(var(--ink-2)) 0%,
    rgb(var(--ink-2)) 55%,
    rgb(var(--vinyl) / 0.04) 100%
  );
  border-color: rgb(var(--vinyl) / 0.12);
  box-shadow: 0 1px 2px rgb(var(--vinyl) / 0.04), 0 12px 32px rgb(var(--vinyl) / 0.05);
}

/* The scrim exists to hold contrast over the live canvas. On an opaque light
   section there is no canvas to fight, so it would only add a cream halo. */
[data-surface='light'] .scrim::before { display: none; }

[data-surface='light'] .btn--ghost { border-color: rgb(var(--vinyl) / 0.24); }

/* The seam is a hard edge, deliberately.
   The first version faded the light surface out over 5rem of the dark section
   above and below it. But a gradient between near-black and near-white is a
   ramp through grey, and painted semi-transparently over a live 3D scene that
   grey reads as a smudge on the screen — it looked like a rendering fault
   rather than a transition. A clean edge with a hairline reads as a decision.
   The accent line is what tells the eye it was drawn on purpose. */
[data-surface='light'] {
  border-top: 1px solid rgb(var(--nova) / 0.5);
  border-bottom: 1px solid rgb(var(--nova) / 0.5);
}

/* On phones, --size-sm carries real body copy (card bodies, summaries, form
   help), so it has to clear the 16px floor — below that iOS auto-zooms on
   focus and small text stops being comfortable one-handed. */
@media (max-width: 640px) {
  :root {
    --size-sm: 1rem;
    --size-xs: 0.8125rem;
  }
}
