/* ==========================================================================
   ORWIN WORLD PRIVATE LIMITED
   Deep Cyber-Aviation Neural Network — brutalist dark mode with AI light leaks
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   The page alternates dark → light → dark. :root holds the dark (default)
   palette; .zone-light re-points the same tokens at light surfaces so every
   token-driven component inverts automatically instead of being restyled.
   -------------------------------------------------------------------------- */
:root {
  --deep-space:  #030611;
  --midnight:    #000f26;
  --surface:     #0d1424;
  --surface-2:   #131c30;

  --cyan:        #00f2ff;
  --blue:        #0a84ff;
  --amber:       #ff8c00;
  --emerald:     #00e676;

  /* Link/label variants that survive on light surfaces (all ≥4.5:1 on white). */
  --cyan-ink:    #0369a1;
  --amber-ink:   #b45309;
  --emerald-ink: #047857;

  --ink:         #f8fafc;
  --ink-2:       #94a3b8;
  --ink-3:       #7a879b;

  --line:        rgba(255, 255, 255, 0.09);
  --line-strong: rgba(0, 242, 255, 0.28);

  --card:        rgba(19, 28, 48, 0.66);
  --card-solid:  #0d1424;

  --shadow:      0 24px 60px rgba(0, 0, 0, 0.45);
  --glow-cyan:   0 0 40px rgba(0, 242, 255, 0.22);
  --glow-amber:  0 0 40px rgba(255, 140, 0, 0.22);

  --font-body: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --font-tech: 'Space Grotesk', system-ui, sans-serif;

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 26px;
  --r-full: 9999px;

  --shell: 1240px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 0.2s var(--ease);
  --t: 0.4s var(--ease);
}

/* Light rhythm sections. `color` inherits as a *resolved* value, so the token
   swap alone would not reach elements that never declare a colour — the
   explicit `color` here re-roots the whole subtree on the light palette. */
.zone-light {
  --deep-space: #ffffff;
  --midnight:   #ffffff;
  --surface:    #ffffff;
  --surface-2:  #f4f6fb;

  --ink:   #0b1220;
  --ink-2: #475569;
  --ink-3: #64748b;

  --line:        rgba(11, 18, 32, 0.10);
  --line-strong: rgba(3, 105, 161, 0.34);

  --card:       #ffffff;
  --card-solid: #ffffff;

  --shadow:     0 14px 40px rgba(11, 18, 32, 0.08);
  --glow-cyan:  0 14px 40px rgba(3, 105, 161, 0.14);
  --glow-amber: 0 14px 40px rgba(180, 83, 9, 0.14);

  --cyan:  var(--cyan-ink);
  --amber: var(--amber-ink);

  background: #ffffff;
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   1b. EXECUTIVE LIGHT THEME (toggle)
   An alternate global skin, opt-in via [data-theme="light"] on <html> (set
   and persisted by the toggle in the masthead — see initTheme() in app.js).
   The dark cinematic look above stays the default; this block re-points the
   same tokens so every component already built on them (.pipeline, .command,
   .solutions, .why, .contact, .footer, .node, .isopanel, .journey, etc.)
   converts for free. Only the handful of rules below that hardcode colours
   instead of reading a token — the hero, its atmosphere, and the journey/car
   scene — need explicit overrides further down this file, each grouped next
   to the dark rule it answers to.

   --cyan/--amber remap to the ink-safe variants for the same reason
   .zone-light does above: most var(--cyan) usage is TEXT/borders, and the
   neon on white fails contrast. The two places that genuinely need to stay a
   glowing neon cyan — the flight-path route lines and the circuit wire — are
   overridden back to literal #00f2ff further down, so they keep reading as
   glowing lines rather than going dull along with the UI chrome. */
html[data-theme="light"] {
  --deep-space: #f8fafc;
  --midnight:   #eef2f7;
  --surface:    #ffffff;
  --surface-2:  #f1f5f9;

  --ink:   #0b1220;
  --ink-2: #475569;
  --ink-3: #64748b;

  --line:        rgba(11, 18, 32, 0.10);
  --line-strong: rgba(3, 105, 161, 0.30);

  --card:       #ffffff;
  --card-solid: #ffffff;

  /* Soft, sophisticated — replaces the dark theme's heavy black/neon shadows
     sitewide for every component that already reads --shadow/--glow-*. */
  --shadow:     0 20px 50px rgba(15, 23, 42, 0.10);
  --glow-cyan:  0 14px 40px rgba(3, 105, 161, 0.14);
  --glow-amber: 0 14px 40px rgba(180, 83, 9, 0.14);

  --cyan:  var(--cyan-ink);
  --amber: var(--amber-ink);
}

/* --------------------------------------------------------------------------
   2. RESET & BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Measured, not assumed: body's overflow-x:hidden alone did not stop the
     page from actually scrolling sideways once .hero's own clip was relaxed
     (window.scrollTo(300,0) moved it) — CSS's spec-level propagation of
     overflow from body to the viewport did not hold up in practice here.
     Setting it on html directly is what genuinely blocks it; confirmed by
     re-running the same scrollTo probe afterward. */
  overflow-x: hidden;
}

body {
  font-family: var(--font-body);
  background: var(--deep-space);
  color: var(--ink);
  line-height: 1.6;
  overflow-x: hidden;
  min-height: 100vh;
}

/* Custom cursor via native `cursor:url()` — a static image with zero runtime
   cost, unlike the removed JS version that fought the WebGL canvas for the
   main thread on every mousemove. The browser draws and positions it itself. */
body {
  cursor: url('../assets/arrowhead.svg') 0 0, auto !important;
}
a, button, .btn {
  cursor: url('../assets/arrowhead.svg') 0 0, pointer !important;
}

img, svg, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
ul, ol { list-style: none; }

::selection { background: rgba(0, 242, 255, 0.28); color: #ffffff; }

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

.shell {
  width: min(100% - 48px, var(--shell));
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY PRIMITIVES
   -------------------------------------------------------------------------- */
.eyebrow {
  display: inline-block;
  font-family: var(--font-tech);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 18px;
}
.eyebrow-amber { color: var(--amber); }

.display {
  font-family: var(--font-tech);
  font-size: clamp(2rem, 4.4vw, 3.5rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--ink);
}
.display em {
  font-style: normal;
  background: linear-gradient(115deg, var(--cyan) 0%, var(--blue) 60%, var(--cyan) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.zone-light .display em {
  background: linear-gradient(115deg, #0369a1 0%, #00b8d9 55%, #0a84ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.lede {
  color: var(--ink-2);
  font-size: 1.06rem;
  max-width: 62ch;
  margin-top: 20px;
}

.lede-block { margin-bottom: 64px; }
.lede-center { text-align: center; }
.lede-center .lede { margin-inline: auto; }

.footnote {
  margin-top: 40px;
  font-size: 0.82rem;
  color: var(--ink-3);
  font-style: italic;
  max-width: 70ch;
}

/* --------------------------------------------------------------------------
   4. BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 26px;
  border: 1px solid transparent;
  border-radius: var(--r-full);
  background: var(--btn-bg);
  font-family: var(--font-tech);
  font-size: 0.94rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform var(--t), box-shadow var(--t), background var(--t), border-color var(--t), color var(--t);
  white-space: nowrap;
}
.btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.btn-lg { padding: 16px 32px; font-size: 1rem; }
.btn-block { width: 100%; }

/* Dark ink on a bright cyan fill — the strongest contrast pairing available
   for the primary action, and it holds up on both dark and light sections. */
.btn-primary {
  --btn-bg: linear-gradient(120deg, #00f2ff 0%, #38bdf8 55%, #0a84ff 100%);
  color: #041018;
  box-shadow: 0 10px 30px rgba(0, 242, 255, 0.24);
}
.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 42px rgba(0, 242, 255, 0.36);
}

/* Solid orange fill, opaque on both dark and light zones so — unlike the
   translucent ghost style it replaced — it needs no per-zone override. Dark
   ink for text: white on #f96f05 is ~2.9:1 (fails WCAG AA), dark ink clears
   ~7:1, so this matches .btn-primary's dark-on-bright pattern instead. */
.btn-accent {
  --btn-bg: #f96f05;
  color: #041018;
  border-color: #f96f05;
  box-shadow: 0 10px 30px rgba(249, 111, 5, 0.28);
}
.btn-accent:hover {
  --btn-bg: #e56400;
  border-color: #e56400;
  transform: translateY(-2px);
  box-shadow: 0 16px 42px rgba(249, 111, 5, 0.4);
}

/* Hero-only variant: 90° orange-to-maroon gradient per exact request. White
   text, since dark ink (the base .btn-accent choice) clears AA at the orange
   stop but fails badly against the maroon one (~2.65:1) — white does the
   reverse, so it gets a text-shadow to hold up better at the orange end too. */
.hero-cta .btn-accent {
  --btn-bg: linear-gradient(90deg, #fb6f05, #ac0029);
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
  border-color: transparent;
}
.hero-cta .btn-accent:hover {
  --btn-bg: linear-gradient(90deg, #e56400, #8f0021);
}

/* --------------------------------------------------------------------------
   5. IGNITION LOADER
   -------------------------------------------------------------------------- */
html.ignition-open,
html.ignition-open body { overflow: hidden; }

.ignition {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 34px;
  background: var(--deep-space);
  clip-path: circle(150% at 50% 50%);
}
.ignition[hidden] { display: none; }

.ignition-stage {
  position: relative;
  width: min(60vw, 340px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}
.ignition-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* Shown only if the video cannot play at all. */
.ignition-fallback {
  position: absolute;
  width: 58%;
  opacity: 0;
  filter: drop-shadow(0 0 30px rgba(0, 242, 255, 0.5));
}
.ignition.no-video .ignition-video { display: none; }
.ignition.no-video .ignition-fallback { opacity: 1; animation: pulse 1.6s var(--ease) infinite; }

@keyframes pulse {
  0%, 100% { transform: scale(1);    opacity: 0.85; }
  50%      { transform: scale(1.05); opacity: 1; }
}

.ignition-readout { text-align: center; }
.ignition-wordmark {
  display: block;
  font-family: var(--font-tech);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  color: var(--ink);
}
.ignition-status {
  display: block;
  margin-top: 12px;
  font-family: var(--font-tech);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  color: var(--cyan);
}
.ignition-bar {
  width: 220px;
  height: 2px;
  margin: 22px auto 0;
  background: rgba(255, 255, 255, 0.12);
  border-radius: var(--r-full);
  overflow: hidden;
}
.ignition-bar-fill {
  display: block;
  width: 0%;
  height: 100%;
  background: linear-gradient(90deg, var(--cyan), var(--blue));
  box-shadow: 0 0 14px rgba(0, 242, 255, 0.8);
}

/* --------------------------------------------------------------------------
   6. (removed — cursor is now the native `cursor:url()` rule set near the
      top of this file, alongside body/html. See there.)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   7. MASTHEAD
   -------------------------------------------------------------------------- */
.masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 700;
  padding: 18px 0;
  background: #e2e8f0;
  transition: background var(--t), backdrop-filter var(--t), border-color var(--t), padding var(--t);
  border-bottom: 1px solid transparent;
}
.masthead.is-stuck {
  padding: 11px 0;
  background: #e2e8f0;
  border-bottom-color: var(--line);
}

.masthead-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
}

/* One knob scales the whole lockup; the masthead runs it at 1.5x. */
.brandmark {
  --brand-scale: 1;
  display: inline-flex;
  align-items: center;
  gap: calc(12px * var(--brand-scale));
}
.masthead .brandmark { --brand-scale: 1.5; }

.brandmark-glyph {
  width: calc(42px * var(--brand-scale));
  height: calc(42px * var(--brand-scale));
  object-fit: contain;
}

.brandmark-type {
  display: flex;
  flex-direction: column;
  /* Without this the default `stretch` sizes both lines to the wider of the
     two, which hides any mismatch behind equal boxes containing unequal text. */
  align-items: flex-start;
  line-height: 1.08;
}

/* The two lines are tuned to render at the same width so the wordmark reads as
   one flush block beside the mark: ORWIN is 5 characters set large and open,
   WORLD PVT. LTD. is 15 set small and tracked out to match. The negative
   margin cancels the trailing letter-space, which would otherwise leave the
   longer line hanging a fraction wider on the right. */
.brandmark-name {
  font-family: var(--font-tech);
  font-size: calc(1.16rem * var(--brand-scale));
  font-weight: 700;
  letter-spacing: 0.132em;
  margin-right: -0.132em;
  color: #ffffff;
}
.masthead .brandmark-name { color: #0f172a; }
/* The footer's own brandmark-name instance is unscoped and still hardcoded
   white for the dark footer — invisible once the Executive Light Theme
   turns .footer's background pale via the --midnight token override. */
html[data-theme="light"] .footer .brandmark-name { color: #0f172a; }
.brandmark-sub {
  font-family: var(--font-tech);
  font-size: calc(0.453rem * var(--brand-scale));
  font-weight: 600;
  /* Swept against ORWIN's *visible* extent — advance width minus the trailing
     letter-space each line carries, which differs between them because the two
     are set at different sizes. At this tracking the inked runs finish within
     0.002px of each other. Being an em value, the match holds at every
     --brand-scale, so the footer lockup stays flush too. */
  letter-spacing: 0.111em;
  margin-right: -0.111em;
  color: var(--cyan);
}
.masthead .brandmark-sub { color: #0f172a; }

/* Glassmorphism pill: houses the nav links and the action buttons together,
   floating free of the logo so the two can sit apart in the header per the
   space-between layout above. */
.floating-nav {
  display: flex;
  align-items: center;
  gap: 34px;
  padding: 10px 14px 10px 26px;
  background: rgba(3, 6, 17, 0.55);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid rgba(0, 242, 255, 0.28);
  border-radius: 50px;
  box-shadow: 0 0 24px rgba(0, 242, 255, 0.10), inset 0 0 0 1px rgba(255, 255, 255, 0.03);
}
.floating-nav ul { display: flex; gap: 30px; }
.floating-nav a {
  position: relative;
  font-size: 0.94rem;
  color: #cbd5e1;
  transition: color var(--t-fast);
}
.floating-nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -6px;
  width: 0; height: 1.5px;
  background: var(--cyan);
  transition: width var(--t);
}
.floating-nav a:hover { color: #ffffff; }
.floating-nav a:hover::after { width: 100%; }

.masthead-actions { display: flex; gap: 12px; }
.masthead-actions .btn { padding: 10px 20px; font-size: 0.86rem; }

/* Executive Light Theme toggle — lives in the footer, beside the brandmark
   (see .footer-brand-row). Shows a sun while dark (click to go light) and a
   moon once light (click to go back) — the icon always previews the theme a
   click would land on, not the current one. Unlike the masthead (a fixed
   #e2e8f0 regardless of theme), the footer itself is token-driven
   (var(--midnight)), so var(--ink) correctly flips light/dark right along
   with it instead of needing a fixed colour. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  padding: 0;
  flex-shrink: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  background: rgba(0, 242, 255, 0.05);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast), transform var(--t-fast);
}
.theme-toggle:hover { border-color: var(--cyan); transform: translateY(-1px); }
.theme-toggle-icon { width: 18px; height: 18px; }
.theme-toggle .icon-moon { display: none; }
html[data-theme="light"] .theme-toggle { background: rgba(3, 105, 161, 0.06); }
html[data-theme="light"] .theme-toggle .icon-sun { display: none; }
html[data-theme="light"] .theme-toggle .icon-moon { display: block; }

.footer-brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.masthead-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  width: 42px; height: 42px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.masthead-toggle span {
  display: block;
  width: 18px; height: 1.8px;
  background: #0f172a;
  transition: transform var(--t), opacity var(--t-fast);
}
.masthead-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.8px) rotate(45deg); }
.masthead-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.masthead-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.8px) rotate(-45deg); }

/* Never rendered on desktop, and `hidden` must still win once it is — a bare
   `display: flex` here would override the UA stylesheet's [hidden] rule. */
.mobile-nav {
  display: none;
  flex-direction: column;
  gap: 4px;
  padding: 18px 24px 26px;
  background: rgba(3, 6, 17, 0.97);
  backdrop-filter: blur(18px);
  border-top: 1px solid var(--line);
}
/* Same dark-on-dark bug as .modal-panel/.field/.ticker above: its `a`
   children inherit body's var(--ink), which is correctly dark in this
   theme, but this panel's own background never was. */
html[data-theme="light"] .mobile-nav { background: rgba(255, 255, 255, 0.98); }
.mobile-nav a {
  padding: 13px 4px;
  font-family: var(--font-tech);
  font-size: 1rem;
  border-bottom: 1px solid var(--line);
}
.mobile-nav-actions { display: flex; gap: 12px; margin-top: 18px; }
.mobile-nav-actions .btn { flex: 1; }

/* --------------------------------------------------------------------------
   8. HERO + WEBGL GLOBE
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  /* Explicit stacking level, not just isolation: isolate. .lightbleed follows
     immediately after in the DOM with z-index:auto, so without this hero's
     overflow content would paint UNDER it in their shared boundary region —
     the same visual result as clipping, just caused by paint order instead of
     overflow. Raising hero above it lets the globe's glow show through. */
  z-index: 2;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding: 140px 0 90px;
  background: #010e21;
  /* Was `hidden`. The globe-wrapper's stage is 120vh tall centred in a 100svh
     hero, so roughly 10vh of the sphere (and its halo) always extended past
     the hero's own box top and bottom — hidden sliced that off in a flat line
     exactly at the boundary. Horizontal safety does not depend on this:
     body already carries overflow-x:hidden as the real guard against the
     globe's 30% right-edge overhang. */
  overflow: visible;
  isolation: isolate;
}
html[data-theme="light"] .hero { background: #f8fafc; }

/* Faint technical grid, the "brutalist" substrate under the glow. */
.hero-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.028) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 45%, #000 20%, transparent 78%);
}
/* Same grid, inked dark instead of white so it stays a faint substrate
   rather than vanishing against the light hero background. */
html[data-theme="light"] .hero-grid {
  background-image:
    linear-gradient(rgba(11,18,32,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11,18,32,0.05) 1px, transparent 1px);
}

/* The globe owns the right half of the hero outright. Nothing else is layered
   over this region, so a press here can only ever land on the canvas — the
   previous failure was the copy column's box reaching across the sphere. The
   canvas itself is far wider than this wrapper and starts at its left edge,
   so the planet still reads as enormous and bleeds off the right, while its
   hitbox begins exactly on the 50% line and never crosses it. */
.globe-wrapper {
  --globe-size: max(1000px, 120vh);
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 50%;
  z-index: 50;
}

/* The only element in the hero meant to receive pointer input. touch-action:
   none stops the browser claiming vertical swipes for scrolling before the
   drag handler ever sees them. */
.hero-globe {
  position: absolute;
  left: 0;
  top: 50%;
  translate: 0 -50%;
  z-index: 1;
  width: var(--globe-size);
  height: var(--globe-size);
  /* The base reset caps every canvas at max-width:100%, which would clamp the
     sphere to the wrapper's 50% and shrink it back to a contained illustration.
     The planet is meant to overflow this box to the right. */
  max-width: none;
  pointer-events: auto;
  touch-action: none;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}
.hero-globe.is-live { opacity: 1; }

/* Dual-temperature atmosphere. Both gradient cores sit just inside the
   sphere's silhouette, so the opaque globe occludes them and only the outer
   falloff escapes past the limb — that occlusion is what makes it read as a
   fresnel rim rather than a lit disc behind glass. Blue banks along the
   lower-left, amber along the upper-right. */
/* Opaque sphere body, carrying the glow directly.

   The size is not a guess: COBE's fragment shader draws the planet only where
   dot(b,b) <= 0.64 — that is |b| <= 0.8 — in a space where b spans ±1 across
   the canvas. So the rendered sphere is exactly 80% of the canvas box, and a
   layer at 100% (as before) overhangs it by 10% a side, which is precisely the
   dark ring that appeared between the planet and its halo. */
.hero-globe-body {
  position: absolute;
  /* Concentric with the canvas: 80% of its size, inset 10% on each side. */
  left: calc(var(--globe-size) * 0.1);
  top: 50%;
  translate: 0 -50%;
  z-index: 0;
  pointer-events: none;
  width: calc(var(--globe-size) * 0.8);
  height: calc(var(--globe-size) * 0.8);
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%,
    #0b1526 0%,
    #070d1c 42%,
    #030713 72%,
    #01030a 100%);
  /* Tight halo hugging the limb. Keeping a hint of the two temperatures —
     cool blue low-left, warm amber high-right — without the wide blurred
     field that previously read as a detached ring. */
  box-shadow:
    0 0 80px 20px rgba(0, 242, 255, 0.40),
    -26px 26px 90px 6px rgba(10, 132, 255, 0.34),
    26px -26px 90px 6px rgba(255, 140, 0, 0.26);
}
/* Executive Light Theme: the sphere body flips from a lit planet to a pale
   enterprise-grey globe, so the dark node dots COBE renders on top of it
   (see initGlobe()'s theme-aware baseColor/markerColor in app.js) become the
   high-contrast element instead of the sphere itself. The halo softens to a
   sophisticated close-in glow rather than the dark theme's three-colour
   neon corona. */
html[data-theme="light"] .hero-globe-body {
  background: radial-gradient(circle at 36% 30%,
    #ffffff 0%,
    #eef2f7 42%,
    #e2e8f0 72%,
    #d7dee7 100%);
  box-shadow:
    0 0 60px 14px rgba(3, 105, 161, 0.16),
    -20px 20px 60px 4px rgba(10, 132, 255, 0.10),
    20px -20px 60px 4px rgba(180, 83, 9, 0.08);
}

.hero-globe-hint {
  position: absolute;
  z-index: 4;
  right: 5%;
  bottom: 84px;
  font-family: var(--font-tech);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  opacity: 0;
  transition: opacity var(--t);
  pointer-events: none;
}
.hero-globe-hint.is-shown { opacity: 1; }

/* With the sphere now reaching across into the copy, the headline needs its own
   ground. This scrim pulls the left side back to the hero's base colour and has
   fully released before the limb, so the atmosphere itself stays untouched. */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(1, 14, 33, 0.97) 0%,
    rgba(1, 14, 33, 0.90) 30%,
    rgba(1, 14, 33, 0.55) 48%,
    rgba(1, 14, 33, 0.12) 62%,
    rgba(1, 14, 33, 0) 74%);
}
html[data-theme="light"] .hero::before {
  background: linear-gradient(100deg,
    rgba(248, 250, 252, 0.97) 0%,
    rgba(248, 250, 252, 0.90) 30%,
    rgba(248, 250, 252, 0.55) 48%,
    rgba(248, 250, 252, 0.12) 62%,
    rgba(248, 250, 252, 0) 74%);
}

/* The shell stays full width so it lines up with the masthead; the copy is
   constrained on the children instead. Putting a max-width on the shell
   itself would let its `margin-inline: auto` centre it inside the hero flex
   row rather than keeping it on the left. */
/* The hero clips its own overflow, so the globe's halo would otherwise be cut
   dead straight across the bottom edge — the exact hard line that made the
   hero and the section below look like two stacked blocks. Fading to the
   hero's own colour first means there is nothing left to clip. */
.hero::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 220px;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(1, 14, 33, 0) 0%,
    rgba(1, 14, 33, 0.55) 46%,
    rgba(1, 14, 33, 0.9) 76%,
    #010e21 100%);
}
html[data-theme="light"] .hero::after {
  background: linear-gradient(180deg,
    rgba(248, 250, 252, 0) 0%,
    rgba(248, 250, 252, 0.55) 46%,
    rgba(248, 250, 252, 0.9) 76%,
    #f8fafc 100%);
}

/* The copy column is a full-width .shell sitting above the globe, so its box
   blanketed the sphere and swallowed every pointer event — the globe was
   unreachable across its whole visible area. The container itself is now
   transparent to the pointer and only the actual content blocks take events
   back, which keeps the text selectable and the buttons clickable while
   leaving the empty space beside them free for dragging the globe. */
/* The copy column is confined to the left half and keeps the shell's gutter,
   so its box stops exactly where the globe wrapper begins. It stays in normal
   flow (not absolute) so the hero still sizes to the copy — taking it out of
   flow would collapse the hero to its min-height and clip the headline.
   pointer-events stays belt-and-braces even though the boxes no longer meet. */
.hero-inner {
  position: relative;
  z-index: 60;
  width: 50%;
  padding-left: max(24px, calc((100% - var(--shell)) / 2));
  padding-right: 28px;
  pointer-events: none;
}
.hero-inner > * {
  max-width: 100%;
  pointer-events: auto;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 9px 20px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  background: rgba(0, 242, 255, 0.05);
  backdrop-filter: blur(10px);
  font-family: var(--font-tech);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #d7e6ee;
}
html[data-theme="light"] .status-pill {
  background: rgba(3, 105, 161, 0.05);
  color: #0b3a52;
}
.status-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--emerald);
  box-shadow: 0 0 10px var(--emerald);
  animation: blink 2.1s ease-in-out infinite;
}
@keyframes blink { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
.status-sep { width: 1px; height: 12px; background: var(--line); }

.hero-title {
  font-family: var(--font-tech);
  /* Scaled against the copy column rather than the viewport — the column is
     now half the width it was, so the old 6.2vw broke the headline into five
     ragged lines. Sized down again (~18%) from clamp(2.2rem,4.3vw,3.9rem): at
     full size the headline was out-competing the globe for attention instead
     of sharing the frame with it. */
  font-size: clamp(1.8rem, 3.5vw, 3.2rem);
  font-weight: 700;
  /* -12% (1.02 -> 0.9). Held back from the full 15-20% asked: this is a bold
     display face wrapping to three lines, and pushing leading toward ~0.85
     starts landing one line's descenders on the next line's cap-height —
     checked by rendering and reading line-box positions, not by eye. 0.9 is
     the tightest value where consecutive line boxes stay clear on this copy. */
  line-height: 0.9;
  letter-spacing: -0.035em;
  margin: 30px 0 24px;
  background: linear-gradient(112deg, #ffffff 0%, #cfefff 42%, #00f2ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
html[data-theme="light"] .hero-title {
  background: linear-gradient(112deg, #0b1220 0%, #14304a 42%, #0369a1 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* Split-reveal wrapper injected by JS. */
.hero-title .word { display: inline-block; }
.hero-title .word-inner { display: inline-block; will-change: transform, opacity; }

.hero-lede {
  color: var(--ink-2);
  font-size: 1rem;
  max-width: 58ch;
}

.hero-cta { display: flex; flex-wrap: wrap; gap: 16px; margin: 36px 0 44px; }

.ticker {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 18px;
  padding: 22px 26px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(13, 20, 36, 0.55);
  backdrop-filter: blur(14px);
  max-width: 660px;
}
/* Hardcoded, not token-driven, like .ticker dt below — both need an
   explicit pairing or the dark glass panel keeps the white stat numbers
   readable while var(--ink-2) on the dd labels (already theme-aware) goes
   dark-on-dark, and vice versa if only one half were fixed. */
html[data-theme="light"] .ticker { background: rgba(255, 255, 255, 0.6); }
.ticker-cell { position: relative; text-align: center; }
.ticker-cell + .ticker-cell::before {
  content: '';
  position: absolute;
  left: -9px; top: 12%;
  width: 1px; height: 76%;
  background: var(--line);
}
.ticker dt {
  font-family: var(--font-tech);
  font-size: clamp(1.1rem, 2vw, 1.5rem);
  font-weight: 700;
  color: #ffffff;
}
html[data-theme="light"] .ticker dt { color: #0b1220; }
.ticker dd {
  margin-top: 3px;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--ink-2);
}

.scroll-cue {
  position: absolute;
  z-index: 3;
  bottom: 30px; left: 50%;
  translate: -50% 0;
}
.scroll-cue-rail {
  display: block;
  width: 24px; height: 40px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  position: relative;
}
.scroll-cue-bead {
  position: absolute;
  top: 7px; left: 50%;
  translate: -50% 0;
  width: 4px; height: 7px;
  border-radius: var(--r-full);
  background: var(--cyan);
  animation: bead 1.9s var(--ease) infinite;
}
@keyframes bead {
  0%        { transform: translateY(0);    opacity: 0; }
  35%       { opacity: 1; }
  75%, 100% { transform: translateY(17px); opacity: 0; }
}

/* --------------------------------------------------------------------------
   9. GEMINI LIGHT-BLEED TRANSITION
   An overflowing container holding a wide flattened oval "horizon", a heavily
   blurred radial core, and a veil that resolves the last of the dark into
   pure white — no flat semicircle edge anywhere.
   -------------------------------------------------------------------------- */
/* The divider is a flat sheet of the hero's own colour, so there is NO seam
   where it begins — the only boundary the eye can find is the curved crown of
   the dome below. A vertical linear-gradient here is what produced the flat
   blue stripe previously, so the colour break is done entirely by geometry. */
.lightbleed {
  --crown: 30%;
  position: relative;
  height: clamp(340px, 38vw, 520px);
  background: #010e21;
  overflow: hidden;
  isolation: isolate;
}
/* Matches .hero's own light-theme override for the same "no seam" reason
   the comment above gives — the hero is #f8fafc now, so this divider has
   to follow it there too, or the dark strip becomes a visible seam of its
   own between the two now-light neighbours. */
html[data-theme="light"] .lightbleed { background: #f8fafc; }

/* Purely decorative — the transition arc must never intercept input. */
.lightbleed,
.lightbleed-glow,
.lightbleed-dome { pointer-events: none; }

/* Atmospheric light source, centred on the crown line: the upper half bleeds
   into the dark, the lower half is occluded by the dome, so the light reads as
   coming from behind the horizon rather than from an element on the page. */
.lightbleed-glow {
  /* Kept exactly to the container so overflow:hidden has nothing to slice —
     an element extending past the top edge is what produced a hard blue line
     there, since the gradient was still bright where it got cut. */
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 64% 82% at 50% var(--crown),
    rgba(255, 255, 255, 0.98) 0%,
    rgba(168, 232, 255, 0.92) 12%,
    rgba(0, 242, 255, 0.62) 26%,
    rgba(10, 132, 255, 0.46) 40%,
    rgba(12, 62, 190, 0.24) 56%,
    rgba(3, 6, 17, 0) 74%);
  filter: blur(130px);
  /* The blurred result is faded out long before the top edge, over a generous
     ramp, so the bleed always terminates in the hero's own black rather than
     against the clip boundary. Masking is applied after filtering, so this
     catches the blur spread too — overflow:hidden never gets to cut anything
     that is still visible. */
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0,0,0,0.06) 14%, rgba(0,0,0,0.35) 26%, #000 46%);
          mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0,0,0,0.06) 14%, rgba(0,0,0,0.35) 26%, #000 46%);
}

/* The dome: an upward-bulging ellipse, far wider than the viewport so its
   flanks exit off-screen and only the gentle central arc is visible. Its lower
   half runs past the container's bottom edge, so the white it lands on is the
   same white as the section below — the two merge with no visible join. */
.lightbleed-dome {
  position: absolute;
  left: 50%;
  bottom: -58%;
  translate: -50% 0;
  width: 168%;
  height: 128%;
  background: #ffffff;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  /* Stacked shadows give the crown a hot white rim fading out through cyan
     into deep blue — the luminous arc itself. Their total reach is kept under
     the crown's distance to the top edge so the halo is never clipped either;
     the long-range bleed is the .lightbleed-glow layer's job. */
  box-shadow:
    0 -8px 26px 2px rgba(214, 245, 255, 0.85),
    0 -18px 60px 12px rgba(0, 242, 255, 0.42),
    0 -34px 110px 26px rgba(10, 132, 255, 0.30);
}

/* --------------------------------------------------------------------------
   10. SECTION RHYTHM
   -------------------------------------------------------------------------- */
.pipeline, .command, .tripizo, .solutions, .why, .contact { padding: clamp(90px, 11vw, 150px) 0; }
.command   { background: var(--deep-space); }
.solutions { background: var(--midnight); }
.contact   { background: var(--deep-space); }

/* --------------------------------------------------------------------------
   11. DATA PIPELINE — CIRCUIT DIAGRAM
   -------------------------------------------------------------------------- */
.circuit {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(20px, 5vw, 70px);
  padding: 20px 0;
}

.circuit-paths {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}
.circuit-track path {
  fill: none;
  stroke: var(--line);
  stroke-width: 1.5;
}
.circuit-live path {
  fill: none;
  stroke: url(#wire);
  stroke-width: 2.4;
  stroke-linecap: round;
  filter: drop-shadow(0 0 6px rgba(0, 242, 255, 0.55));
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}

.circuit-col { display: flex; flex-direction: column; gap: 14px; position: relative; z-index: 1; }
.circuit-outputs { align-items: flex-end; text-align: right; }
.circuit-col-label {
  font-family: var(--font-tech);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 4px;
}

.node {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  padding: 13px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--card-solid);
  box-shadow: var(--shadow);
  font-family: var(--font-tech);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  transition: border-color var(--t), transform var(--t);
}
.node:hover { border-color: var(--line-strong); transform: translateX(4px); }
.circuit-outputs .node:hover { transform: translateX(-4px); }
.node-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 10px currentColor;
  color: var(--cyan);
  flex-shrink: 0;
}
.node-dot-amber { background: var(--amber); color: var(--amber); }

.circuit-core { align-items: center; }
.core {
  position: relative;
  display: grid;
  place-items: center;
  width: clamp(130px, 17vw, 178px);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--card-solid);
  box-shadow: var(--glow-cyan), var(--shadow);
  text-align: center;
}
.core-label {
  font-family: var(--font-tech);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.5;
}
.core-ring {
  position: absolute;
  inset: -12px;
  border-radius: 50%;
  border: 1px dashed var(--line-strong);
  animation: spin 22s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   12. TRAVELOS COMMAND CENTER — ISOMETRIC GLASS PANEL
   -------------------------------------------------------------------------- */
.isostage { perspective: 1800px; }

.isopanel {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background:
    linear-gradient(155deg, rgba(0, 242, 255, 0.07) 0%, rgba(10, 132, 255, 0.03) 40%, transparent 70%),
    var(--card-solid);
  box-shadow: var(--shadow), var(--glow-cyan);
  overflow: hidden;
  transform-style: preserve-3d;
  will-change: transform;
}

.isopanel-chrome {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 15px 22px;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.02);
}
.chrome-dot { width: 11px; height: 11px; border-radius: 50%; }
.chrome-red   { background: #ff5f56; }
.chrome-amber { background: #ffbd2e; }
.chrome-green { background: #27c93f; }
.chrome-title {
  margin-left: 14px;
  font-family: var(--font-tech);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-2);
}
.chrome-sync {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-tech);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--emerald);
}
.sync-pulse {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--emerald);
  box-shadow: 0 0 9px var(--emerald);
  animation: blink 1.7s ease-in-out infinite;
}

.isopanel-body {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 22px;
  padding: 26px;
}

.telemetry {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}
.tile {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(0, 242, 255, 0.04);
}
.tile-label { font-size: 0.76rem; color: var(--ink-2); }
.tile-value {
  font-family: var(--font-tech);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--ink);
}
.tile-trend { font-family: var(--font-tech); font-size: 0.72rem; font-weight: 600; }
.tile-trend.up   { color: var(--emerald); }
.tile-trend.down { color: var(--amber); }

.ledger, .pipeline-analytics {
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.02);
}
.ledger-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  font-family: var(--font-tech);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ink);
}
.ledger-state {
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--emerald);
}
.ledger-rows li {
  display: grid;
  grid-template-columns: 1fr 70px 34px;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  font-size: 0.82rem;
  color: var(--ink-2);
  border-bottom: 1px solid var(--line);
}
.ledger-rows li:last-child { border-bottom: 0; }
.ledger-rows b {
  font-family: var(--font-tech);
  font-size: 0.74rem;
  color: var(--emerald);
  text-align: right;
}
.bar {
  display: block;
  height: 4px;
  border-radius: var(--r-full);
  background: var(--line);
  position: relative;
  overflow: hidden;
}
.bar::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--fill, 0%);
  background: linear-gradient(90deg, var(--cyan), var(--blue));
  border-radius: inherit;
}

.spark { margin-bottom: 14px; }
.spark svg { width: 100%; height: 84px; }
.spark-line {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 5px rgba(0, 242, 255, 0.5));
}
.spark-fill { fill: url(#wire); opacity: 0.12; }

.chiprow { display: flex; flex-wrap: wrap; gap: 16px; font-size: 0.78rem; color: var(--ink-2); }
.chiprow li { display: inline-flex; align-items: center; gap: 7px; }
.chip-dot { width: 8px; height: 8px; border-radius: 50%; }
.chip-dot.new       { background: var(--cyan); }
.chip-dot.contacted { background: var(--amber); }
.chip-dot.won       { background: var(--emerald); }

.isopanel-note {
  padding: 0 26px 22px;
  font-size: 0.76rem;
  font-style: italic;
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   13. TRIPIZO PROOF OF CONCEPT
   -------------------------------------------------------------------------- */
.proofrail {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 46px;
  font-family: var(--font-tech);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.proofrail-track {
  flex: 1;
  height: 3px;
  border-radius: var(--r-full);
  background: var(--line);
  overflow: hidden;
}
.proofrail-fill {
  display: block;
  width: 0%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--cyan-ink), var(--amber-ink));
}

.servicegrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
}
.service {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 26px 24px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  box-shadow: var(--shadow);
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.service:hover {
  transform: translateY(-5px);
  border-color: var(--line-strong);
  box-shadow: var(--glow-amber);
}
.service-icon {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--amber);
  margin-bottom: 8px;
}
.service h3 { font-family: var(--font-tech); font-size: 1.02rem; font-weight: 600; color: var(--ink); }
.service p  { font-size: 0.88rem; color: var(--ink-2); }

/* --------------------------------------------------------------------------
   13b. THE JOURNEY — pinned scroll sequence
   Every animated element's *resting* state here is its final, sensible one:
   route drawn, cards visible, vehicles hidden. GSAP sets the start states at
   runtime, so if the script never runs — or reduced-motion is on and the scenes
   are skipped — the section still reads as a finished panel instead of a blank.
   -------------------------------------------------------------------------- */

/* Tripizo above is white and the journey is near-black; this is the ramp. */
.journey-approach {
  height: clamp(160px, 20vw, 260px);
  background: linear-gradient(180deg, #ffffff 0%, #aebdd4 30%, #26374f 68%, var(--deep-space) 100%);
}
/* Both neighbours are light in this theme, so the ramp collapses to a
   near-flat hand-off instead of the dark-theme's white-to-black ladder. */
html[data-theme="light"] .journey-approach {
  background: linear-gradient(180deg, #ffffff 0%, #f4f7fa 55%, var(--deep-space) 100%);
}

.journey {
  /* The corner's position. Declared here so the timeline can read the same
     numbers the layout uses instead of duplicating them in JS. */
  --route-x: 33%;
  --route-y: 34%;
  /* One length governs both vehicles so their visual mass always matches. */
  --car-len: clamp(200px, 20vw, 320px);
  position: relative;
  height: 100vh;
  overflow: hidden;
  background: var(--deep-space);
  isolation: isolate;
}

.journey-stage {
  position: absolute;
  inset: 0;
}

/* --- Route -------------------------------------------------------------- */
.route { position: absolute; inset: 0; pointer-events: none; }

.route-h,
.route-v,
.route-corner {
  position: absolute;
  background: linear-gradient(90deg, rgba(0,242,255,0) 0%, var(--cyan) 12%, var(--cyan) 100%);
  box-shadow: 0 0 18px rgba(0, 242, 255, 0.75), 0 0 46px rgba(0, 242, 255, 0.35);
}
/* The flight-route line is the "glowing cyan path" this theme is meant to
   keep — .route-h/.route-v deliberately stay literal #00f2ff-adjacent here
   rather than following --cyan into its ink-safe remap above, or the path
   would dull to navy along with the rest of the light-theme UI chrome. The
   glow itself is trimmed back slightly so it reads as considered rather
   than neon against the pale background. box-shadow is shared for both
   axes; each axis keeps its own gradient override below, next to its
   dark-theme original, since .route-h runs 90deg and .route-v runs 180deg. */
html[data-theme="light"] .route-h,
html[data-theme="light"] .route-v {
  box-shadow: 0 0 14px rgba(0, 200, 240, 0.55), 0 0 32px rgba(0, 200, 240, 0.22);
}
html[data-theme="light"] .route-h {
  background: linear-gradient(90deg, rgba(0,242,255,0) 0%, #00c8f0 12%, #00c8f0 100%);
}

/* Runs from the right edge to the corner. Scaled from the right, so it draws
   toward the corner in the same direction the car travels. */
.route-h {
  top: var(--route-y, 34%);
  left: var(--route-x, 33%);
  right: 0;
  height: 2px;
  transform-origin: right center;
}

/* Drops from the corner to the floor, drawn downward. */
.route-v {
  left: var(--route-x, 33%);
  top: var(--route-y, 34%);
  bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, var(--cyan) 0%, var(--cyan) 78%, rgba(0,242,255,0) 100%);
  transform-origin: center top;
}
html[data-theme="light"] .route-v {
  background: linear-gradient(180deg, #00c8f0 0%, #00c8f0 78%, rgba(0,242,255,0) 100%);
}

/* Hard 90° junction marker. */
.route-corner {
  left: var(--route-x, 33%);
  top: var(--route-y, 34%);
  width: 12px;
  height: 12px;
  translate: -5px -5px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 0 20px rgba(0, 242, 255, 0.95), 0 0 60px rgba(0, 242, 255, 0.55);
}
/* The junction node itself: dark and high-contrast against the light route,
   its glow softened to match the trimmed .route-h/.route-v halo above. A
   white dot here would vanish into the light-theme background entirely. */
html[data-theme="light"] .route-corner {
  background: #0b1220;
  box-shadow: 0 0 16px rgba(0, 200, 240, 0.65), 0 0 40px rgba(0, 200, 240, 0.3);
}

/* --- Vehicles ----------------------------------------------------------- */
.journey-vehicle {
  position: absolute;
  opacity: 0;
  will-change: transform;
  pointer-events: none;
  max-width: none;
}

/* ==========================================================================
   COMPOSITE VEHICLE (side view) — chassis + two independently-rotating wheels
   --------------------------------------------------------------------------
   The root problem across every earlier version of this block was the
   chassis asset itself, not the percentages: car-chassis.png carried 36.6% of
   fully transparent margin below the car body (the body's real content ended
   at 63.4% down the frame, not 100%). That's exactly why translate:-100% kept
   getting "corrected" away in earlier commits — it pins the WRAPPER's raw
   frame edge to the line, and with that much dead space between the frame
   edge and the actual car, the body would float visibly above it. Once
   car-chassis.png was cropped tight to the body (the same fix already applied
   to car-wheel.png), translate:-100% does exactly what it looks like it
   should: the box below is a completely literal implementation, no
   compensating offsets anywhere.

   1. WRAPPER — Sit perfectly on the line */
.car-side-wrapper {
  position: absolute;
  width: clamp(200px, 20vw, 320px);
  /* Align to the horizontal route line */
  top: var(--route-y, 34%);
  left: 0;
  /* Push the absolute bottom of the wrapper to rest exactly on the line.
     This only lands correctly because car-chassis.png is now cropped tight
     to the car body — no leftover transparent margin for the wrapper's own
     edge to diverge from the body's real bottom. */
  translate: 0 -100%;
  z-index: 2;
}

/* 2. CHASSIS — Fill the wrapper.
   Deliberately NOT position:absolute: left in normal flow, this single
   in-flow image is what gives the wrapper its real height (auto-height on a
   div with only absolutely-positioned children collapses to 0 — an in-flow
   image with its own intrinsic ratio is what avoids that here). */
.car-chassis {
  width: 100%;
  height: auto;
  display: block;
  /* +1px/+1px fit nudge. Uses `translate`, not top/left: this element is
     deliberately position:static (see above — normal flow is what lets it
     drive the wrapper's own height), and top/left do nothing on a static
     element. `translate` works regardless of position and doesn't affect
     layout, so the wrapper's height calculation is untouched. */
  translate: 1px 1px;
  /* Adds a natural shadow to the car body */
  filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.65));
}
/* Soft, sophisticated ground shadow in place of the dark theme's heavy
   near-black one — a 0.65-alpha black blur reads as murky rather than
   grounded once the road beneath it is light instead of near-black. */
html[data-theme="light"] .car-chassis {
  filter: drop-shadow(0 14px 22px rgba(15, 23, 42, 0.18));
}

/* 3. WHEELS — Hard scale constraint.
   car-chassis.png keeps the brake rotor/caliper baked in at both wheel wells
   (only the outer rim+tire were removed), so these two images exist purely to
   sit on top and occlude that fixed art with a rotating one. */
.car-wheel {
  position: absolute;
  /* Strictly shrink to fit the wheel wells */
  width: 14%;
  height: auto;
  border-radius: 50%;
  transform-origin: center center;
  /* Base lift so the wheels don't dip below the car's undercarriage. Was
     shared identically by both wheels through the last round of nudges; now
     that front and rear need different total y-offsets, each subclass below
     declares its own full `bottom` value instead (same specificity as this
     rule, so a shared value here would just be dead weight once both
     subclasses override it).

     Fixed pixel offsets throughout this element, not `translate`: GSAP sets
     an inline `translate: none` on these once it starts animating their
     rotation (confirmed by reading the live inline style), which would
     silently override any translate set in this stylesheet. calc() on
     left/bottom is unaffected, since GSAP never touches those properties —
     confirmed this before choosing the mechanism, not assumed. */
  z-index: 1;
}

/* 4. AXLE ALIGNMENT
   Reset to clean absolute values this round, replacing the accumulated
   calc()-based pixel nudges from the last several rounds — these are stated
   as final target percentages, not incremental deltas, so there's nothing to
   carry forward from the prior calc() expressions. */
/* Car faces left: front wheel is on the left side of the image.
   These percentages are not hand-tuned nudges — they're derived directly
   from car-chassis.png's own geometry: a Hough-circle fit against the
   baked-in brake rotor art locates each axle centre at (84, 110) for the
   front and (349, 110) for the rear, out of the asset's native 451x140
   frame. left/bottom then solve for where this wheel's own box must sit
   so its centre (the wheel image is centred in its own square canvas)
   lands exactly on that axle point, accounting for the chassis's own
   `translate: 1px 1px` nudge. Both wheels land on the same rotor height
   (y=110), so they share one `bottom` value — there is no real front/rear
   ride-height difference in the source art. */
.wheel-front {
  left: calc(12.375% + 1px - 1px);
  bottom: calc(0.402% - 1px - 1px);
}
/* Car faces left: rear wheel is on the right side of the image.
   Nudged 2px further back (left) from the geometry-derived baseline above,
   for a more grounded stance. */
.wheel-rear {
  left: calc(72.5% - 2px);
  bottom: 0.5%;
}

/* Nose already points down in the source art, so no rotation is needed.
   Height is derived from the same --car-len rather than set independently:
   the side view's car fills 86.2% of its frame width and the top view's fills
   89.6% of its frame height, so 0.9621 makes the two render the same physical
   length. The translate centres the car — not the frame — over the route: its
   opaque pixels are centred at 48% across and 49.6% down, not 50/50. */
.car-top {
  left: var(--route-x, 33%);
  top: 0;
  height: calc(var(--car-len) * 0.9621);
  width: auto;
  /* Only the horizontal centring lives here. The vertical half is applied in
     JS instead: GSAP folds this CSS `translate` into its own transform, so an
     animated `y` would silently discard a -49.6% written here — which parked
     the car exactly half its length below the corner. */
  translate: -48% 0;
  filter: drop-shadow(0 0 34px rgba(0, 242, 255, 0.3));
}
html[data-theme="light"] .car-top {
  filter: drop-shadow(0 0 22px rgba(0, 200, 240, 0.22));
}

/* Source art noses left, so it is flipped to fly left-to-right. */
.plane-top {
  top: 50%;
  left: 0;
  height: 120vh;
  width: auto;
  translate: 0 -50%;
  transform: scaleX(-1);
  filter: drop-shadow(0 40px 80px rgba(0, 0, 0, 0.7));
  z-index: 3;
}
html[data-theme="light"] .plane-top {
  filter: drop-shadow(0 26px 46px rgba(15, 23, 42, 0.20));
}

/* --- Wipe --------------------------------------------------------------- */
/* Carries the Solutions section's own colour, so when the sequence unpins the
   hand-off lands on an identical field with no visible seam. */
.journey-wipe {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--midnight);
  transform-origin: left center;
  transform: scaleX(0);
  /* Promoted so the scrubbed sweep is composited on the GPU rather than
     repainting a full-viewport panel every frame. */
  will-change: transform;
  pointer-events: none;
}

/* --- Trust panel -------------------------------------------------------- */
.journey-panel {
  position: absolute;
  top: 50%;
  right: clamp(24px, 5vw, 72px);
  translate: 0 -50%;
  width: min(60%, 780px);
  z-index: 1;
}
.journey-panel .eyebrow { margin-bottom: 12px; }
.journey-panel .display { font-size: clamp(1.7rem, 2.9vw, 2.6rem); margin-bottom: 26px; }

.trustgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.trustcard {
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  backdrop-filter: blur(16px);
  box-shadow: var(--shadow);
}
.trustcard-wide { grid-column: span 2; }

.trustcard-index {
  display: block;
  font-family: var(--font-tech);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--cyan);
  margin-bottom: 8px;
}
.trustcard h3 {
  font-family: var(--font-tech);
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--ink);
}
.trustcard p { font-size: 0.86rem; color: var(--ink-2); }

@media (max-width: 1080px) {
  .journey-panel { width: min(72%, 620px); right: 20px; }
  .journey-panel .display { font-size: clamp(1.4rem, 4vw, 2rem); }
  .trustcard { padding: 15px 16px; }
  .trustcard p { font-size: 0.8rem; }
}

@media (max-width: 720px) {
  .journey { height: auto; padding: 80px 0; }
  .journey-stage { position: relative; inset: auto; }
  /* Below this width there is no room for a lane beside the copy, so the
     sequence stands down and the panel simply reads as a normal section. */
  .route, .journey-vehicle, .journey-wipe { display: none; }
  .journey-panel {
    position: relative;
    top: auto; right: auto; translate: none;
    width: calc(100% - 40px);
    margin-inline: auto;
  }
  .trustgrid { grid-template-columns: 1fr; }
  .trustcard-wide { grid-column: span 1; }
}

/* --------------------------------------------------------------------------
   14. BENTO GRID — animated conic border glow
   @property lets the gradient angle animate; browsers without it simply get
   the static border, which is why the glow lives on a ::before overlay.
   -------------------------------------------------------------------------- */
@property --bevel {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.bento {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.bcard {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 30px;
  border-radius: var(--r-lg);
  background: var(--card-solid);
  border: 1px solid var(--line);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--t), box-shadow var(--t);
}
.bcard-wide { grid-column: span 2; }
.bcard-tall { grid-row: span 2; }

/* The rotating conic ring: a full-bleed gradient masked to a 1px frame. */
.bcard::before {
  content: '';
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(from var(--bevel),
    transparent 0deg,
    rgba(0, 242, 255, 0.9) 60deg,
    rgba(10, 132, 255, 0.5) 110deg,
    transparent 190deg,
    transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  opacity: 0;
  transition: opacity var(--t);
}
.bcard:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow), var(--glow-cyan);
}
.bcard:hover::before {
  opacity: 1;
  animation: bevel-spin 4s linear infinite;
}
@keyframes bevel-spin { to { --bevel: 360deg; } }

.bcard-index {
  font-family: var(--font-tech);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--cyan);
  opacity: 0.75;
}
.bcard h3 { font-family: var(--font-tech); font-size: 1.24rem; font-weight: 600; color: var(--ink); }
.bcard p  { font-size: 0.92rem; color: var(--ink-2); flex: 1; }

.tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.tags li {
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.74rem;
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   15. WHY US
   -------------------------------------------------------------------------- */
.whygrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
}
.whycard {
  padding: 30px 26px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  box-shadow: var(--shadow);
  transition: transform var(--t), border-color var(--t);
}
.whycard:hover { transform: translateY(-5px); border-color: var(--line-strong); }
.whycard h3 { font-family: var(--font-tech); font-size: 1.04rem; font-weight: 600; margin-bottom: 8px; color: var(--ink); }
.whycard p  { font-size: 0.9rem; color: var(--ink-2); }

/* --------------------------------------------------------------------------
   16. CONTACT
   -------------------------------------------------------------------------- */
.contact-inner { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(30px, 5vw, 70px); align-items: start; }
.contact-inner .lede-block { margin-bottom: 0; }

.contact-cards { display: grid; gap: 14px; }
.ccard {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 22px 24px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card-solid);
  transition: border-color var(--t), transform var(--t);
}
a.ccard:hover { border-color: var(--line-strong); transform: translateX(5px); }
.ccard-label { font-size: 0.78rem; color: var(--ink-2); }
.ccard-value { font-family: var(--font-tech); font-size: 1.06rem; font-weight: 600; color: var(--cyan); }
.ccard-value-plain { color: var(--ink); }

.ccard-cta { gap: 12px; padding: 28px 26px; background: var(--surface-2); }
.ccard-cta h3 { font-family: var(--font-tech); font-size: 1.2rem; font-weight: 600; color: var(--ink); }
.ccard-cta p  { font-size: 0.92rem; color: var(--ink-2); }
.ccard-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 6px; }

/* --------------------------------------------------------------------------
   17. FOOTER
   -------------------------------------------------------------------------- */
.footer { background: var(--midnight); border-top: 1px solid var(--line); padding: 70px 0 0; }
.footer-inner { display: grid; grid-template-columns: 1.4fr 2fr; gap: 50px; padding-bottom: 50px; }
.footer-brand p { margin-top: 18px; font-size: 0.9rem; color: var(--ink-2); max-width: 42ch; }
.footer-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.footer-cols h4 {
  font-family: var(--font-tech);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 16px;
}
.footer-cols a, .footer-plain {
  display: block;
  padding: 6px 0;
  font-size: 0.9rem;
  color: var(--ink-2);
  transition: color var(--t-fast);
}
.footer-cols a:hover { color: var(--cyan); }

.footer-base {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 22px 0;
  border-top: 1px solid var(--line);
  font-size: 0.82rem;
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   18. MODALS
   -------------------------------------------------------------------------- */
.modal {
  width: min(100% - 32px, 720px);
  max-height: 88vh;
  /* The universal reset zeroes margins, which kills the `margin: auto` the UA
     stylesheet relies on to centre a dialog in the top layer. */
  margin: auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: visible;
}
.modal::backdrop {
  background: rgba(2, 5, 12, 0.72);
  backdrop-filter: blur(8px);
}

.modal-panel {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: rgba(13, 20, 36, 0.94);
  backdrop-filter: blur(26px) saturate(150%);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.6), var(--glow-cyan);
  max-height: 88vh;
  overflow-y: auto;
  padding: 30px;
}
/* Hardcoded dark glass, like .field input/select/textarea below — .modal's
   own text already reads var(--ink) (correctly dark in this theme), which
   is exactly why leaving this panel dark was invisible rather than just
   dim: dark-on-dark, not a missing colour. */
html[data-theme="light"] .modal-panel {
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 40px 90px rgba(15, 23, 42, 0.18), var(--glow-cyan);
}

.modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 26px;
}
.modal-head .eyebrow { margin-bottom: 8px; }
.modal-head h2 { font-family: var(--font-tech); font-size: 1.6rem; font-weight: 700; }
.modal-close {
  width: 38px; height: 38px;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--ink-2);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast);
}
.modal-close:hover { color: var(--cyan); border-color: var(--line-strong); }

.tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.tab {
  padding: 9px 18px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: none;
  font-family: var(--font-tech);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  transition: all var(--t-fast);
}
.tab.is-active {
  background: rgba(0, 242, 255, 0.12);
  border-color: var(--line-strong);
  color: var(--cyan);
}

.tabpane[hidden] { display: none; }
.telemetry-modal { grid-template-columns: repeat(2, 1fr); }

.rowlist li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  margin-bottom: 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.02);
  font-size: 0.9rem;
  color: var(--ink-2);
}
.pill {
  flex-shrink: 0;
  padding: 4px 13px;
  border-radius: var(--r-full);
  font-family: var(--font-tech);
  font-size: 0.72rem;
  font-weight: 700;
}
.pill.new       { background: rgba(0, 242, 255, 0.16); color: var(--cyan); }
.pill.contacted { background: rgba(255, 140, 0, 0.16); color: var(--amber); }
.pill.won       { background: rgba(0, 230, 118, 0.16); color: var(--emerald); }

.modal-note { margin-top: 20px; font-size: 0.78rem; font-style: italic; color: var(--ink-3); }

/* Form */
.form { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
/* Honeypot for the Web3Forms botcheck field — off-screen rather than
   display:none, since some bots skip hidden/display:none inputs but still
   blind-fill absolutely-positioned ones. */
.botcheck {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.field { display: flex; flex-direction: column; gap: 7px; }
.field-full, .form .btn, .form-status { grid-column: 1 / -1; }
.field label { font-size: 0.84rem; font-weight: 600; color: var(--ink-2); }
.field input, .field select, .field textarea {
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(3, 6, 17, 0.6);
  color: var(--ink);
  transition: border-color var(--t-fast);
  width: 100%;
  resize: vertical;
}
html[data-theme="light"] .field input,
html[data-theme="light"] .field select,
html[data-theme="light"] .field textarea {
  background: rgba(15, 23, 42, 0.04);
}
.field input::placeholder, .field textarea::placeholder { color: #64748b; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--cyan); outline: none; }
.field input[aria-invalid="true"], .field select[aria-invalid="true"] { border-color: #f87171; }

.form-status { font-size: 0.88rem; min-height: 1.2em; }
.form-status.ok   { color: var(--emerald); }
.form-status.fail { color: #fca5a5; }
/* Both are tuned for the dark modal panel — #00e676 and #fca5a5 each land
   under 2:1 against the light theme's now-white .modal-panel, which matters
   here since, unlike the decorative status dots elsewhere that also use
   these colours, this is a full sentence of real feedback text. */
html[data-theme="light"] .form-status.ok   { color: var(--emerald-ink); }
html[data-theme="light"] .form-status.fail { color: #b91c1c; }

/* --------------------------------------------------------------------------
   19. SCROLL REVEAL BASELINE
   Elements start hidden only once JS confirms it can animate them, so a
   script failure can never leave the page blank.
   -------------------------------------------------------------------------- */
html.gsap-ready [data-stagger],
html.gsap-ready [data-node],
html.gsap-ready [data-tile] {
  opacity: 0;
  transform: translateY(26px);
}

/* --------------------------------------------------------------------------
   20. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .floating-nav { display: none; }
  .masthead-toggle { display: flex; }
  .mobile-nav:not([hidden]) { display: flex; }

  .hero { padding-top: 120px; }
  /* Narrow screens cannot afford a 50/50 split, so the copy takes the full
     width and the globe drops behind it as a dimmed backdrop. The two do
     overlap here, which is why the copy column keeps pointer-events:none on
     the container — only the text and buttons take presses, and the rest of
     the sphere stays draggable. */
  .globe-wrapper {
    --globe-size: max(680px, 92vh);
    width: 62%;
    opacity: 0.55;
    z-index: 1;
  }
  .hero-inner {
    width: 100%;
    padding-right: 24px;
    z-index: 3;
  }
  .hero::before {
    background: linear-gradient(122deg,
      rgba(1, 14, 33, 0.97) 0%,
      rgba(1, 14, 33, 0.9) 38%,
      rgba(1, 14, 33, 0.5) 58%,
      rgba(1, 14, 33, 0) 80%);
  }

  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bcard-tall { grid-row: span 1; }

  .contact-inner { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr; gap: 36px; }
}

@media (max-width: 820px) {
  .circuit { grid-template-columns: 1fr; gap: 26px; }
  .circuit-paths { display: none; }
  .circuit-outputs { align-items: stretch; text-align: left; }
  .circuit-core { order: -1; }
  .isopanel-body { grid-template-columns: 1fr; }
  .telemetry { grid-template-columns: repeat(2, 1fr); }
  .ticker { grid-template-columns: repeat(3, 1fr); row-gap: 20px; }
  .ticker-cell + .ticker-cell::before { display: none; }
}

@media (max-width: 560px) {
  .shell { width: calc(100% - 32px); }
  .bento { grid-template-columns: 1fr; }
  .bcard-wide { grid-column: span 1; }
  .form { grid-template-columns: 1fr; }
  .modal-panel { padding: 22px; }
  .hero-cta .btn { flex: 1; }
  .footer-cols { grid-template-columns: 1fr 1fr; }
}

/* --------------------------------------------------------------------------
   21. REDUCED MOTION
   Strip decorative motion, but never hide content — the reveal baseline is
   cleared so everything is visible immediately.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html.gsap-ready [data-stagger],
  html.gsap-ready [data-node],
  html.gsap-ready [data-tile] { opacity: 1; transform: none; }
  .circuit-live path { stroke-dashoffset: 0; }
}
