/* ============================================================
   Base — reset, canvas, ambient aurora background, typography
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: hidden; }
body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---- Ambient aurora: slow-breathing neon glows over near-black ---- */
.aurora {
  position: fixed; inset: 0; z-index: -3; pointer-events: none;
  background:
    radial-gradient(1100px 760px at 82% -12%, rgba(var(--halo-cyan-rgb),.18), transparent 58%),
    radial-gradient(1000px 720px at -8% 16%, rgba(var(--accent-blue-rgb),.20), transparent 56%),
    radial-gradient(820px 620px at 24% 108%, rgba(255,200,0,.06), transparent 58%),
    var(--bg);
  /* Static on purpose: when this fixed layer animated, its transform forced
     every glass panel + the header to re-run backdrop-filter each frame — a
     heavy, Chrome-specific compositing cost. The ambient glow reads fine still. */
}
/* persistent animated starfield behind the whole page */
#mesh { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -2; pointer-events: none; }

/* faint cyber grid */
.grid-overlay {
  position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: .35;
  background-image:
    linear-gradient(rgba(255,255,255,.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.03) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(circle at 50% 30%, #000 0%, transparent 75%);
}

/* ---- Typographic rhythm ---- */
h1, h2, h3 { margin: 0 0 var(--s-4); font-weight: 700; letter-spacing: -.02em; line-height: 1.05; }
h1 { font-size: clamp(40px, 7vw, 88px); font-weight: 900; }
h2 { font-size: clamp(28px, 4vw, 52px); }
h3 { font-size: clamp(20px, 2.4vw, 30px); }
p  { margin: 0 0 var(--s-4); color: var(--ink-70); font-size: clamp(16px, 1.3vw, 18px); }
a  { color: inherit; text-decoration: none; }
strong { color: var(--ink); font-weight: 700; }

/* ---- One focus language: a single cyan ring on every interactive surface
   (keyboard only). <summary> keeps its bespoke neon-edge ring in discover.css. */
:where(a, button, input, select, textarea, [tabindex], summary):focus-visible {
  outline: 2px solid var(--halo-cyan);
  outline-offset: 2px;
  border-radius: 4px;
}

.mono { font-family: var(--font-mono); }
.eyebrow {
  font-family: var(--font-mono); font-size: 12px; text-transform: uppercase;
  letter-spacing: .18em; color: var(--halo-cyan); margin: 0 0 var(--s-4);
  display: inline-flex; align-items: center; gap: var(--s-2);
}
/* Emphasised keyword inside a heading — a single SOLID on-brand colour.
   (Gradient-clipped text was removed: it's a top AI-slop tell and dimmed
   legibility. The spectrum now lives only in the logo + HaloWave.) */
.grad-text { color: var(--accent-ink); }

/* ---- Layout helpers ---- */
.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s-5); }
section { position: relative; padding: clamp(64px, 11vh, 140px) 0; }
.section-head { max-width: 760px; margin: 0 auto var(--s-8); text-align: center; }
.section-head p { font-size: clamp(17px, 1.6vw, 20px); }
/* Restrained "upcoming" label — a quiet mono note, not a badge. */
.section-head .ch-eta { margin: 12px 0 0; font-size: 12px; font-family: var(--font-mono);
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-50); }

/* ---- Scroll reveal ----
   Content is visible by DEFAULT. The hidden/animated start state only applies
   when JS is active (html.js) AND the element hasn't revealed yet. If the
   observer never fires, nothing stays hidden. */
.reveal { transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease), filter var(--t-slow) var(--ease); }
html.js .reveal:not(.in) { opacity: 0; transform: translateY(22px); filter: blur(6px); }
.reveal[data-delay="1"] { transition-delay: .08s; }
.reveal[data-delay="2"] { transition-delay: .16s; }
.reveal[data-delay="3"] { transition-delay: .24s; }

/* The hero is above the fold — its <h1>/stats are the LCP. Never hold them
   hidden behind the reveal JS (on throttled mobile that runs late → slow LCP).
   They paint immediately with a transform-only entrance: opacity stays 1, so
   LCP fires at first paint. The reveal JS still adds .in later (no-op here). */
html.js .hero .reveal { opacity: 1; filter: none; transform: none;
  animation: heroReveal var(--t-slow) var(--ease) both; }
html.js .hero .reveal[data-delay="2"] { animation-delay: .09s; }
html.js .hero .reveal[data-delay="3"] { animation-delay: .18s; }
@keyframes heroReveal { from { transform: translateY(18px); } to { transform: none; } }

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .aurora { animation: none; }
  .reveal { opacity: 1; transform: none; filter: none; transition: none; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}
