/* ============================================================
   SHARED HERO — the homepage hero, used by every page.
   Markup: new/inc/hero.php (snl_hero()). Script: new/js/hero.js.
   Sliced out of index.css so one small stylesheet carries the whole
   look instead of each page re-declaring its own hero.

   LOAD ORDER: last stylesheet in <head> (after global.css and the
   page's own CSS), so a page rule with the same specificity can never
   drift a hero away from the homepage's. Page CSS may still add
   narrower rules (e.g. `.legal-hero .hero-content`, 2 classes).

   TWO SIZES, one look:
     .hero               tall — 128vh, room for the device mockup
                         (.hero-device-wrap) that floats over the wave
     .hero.hero--compact text-only pages — content height + the wave
   and one colour variant that works with either size:
     .hero.hero--light   white hero with the particle web (Studio Setup,
                         Investor Relations)
============================================================ */

.hero {
  position: relative;
  width: 100%;
  min-height: 128vh;
  padding: 110px var(--site-pad-x) 160px;
  text-align: center;
  color: #fff;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* The hero background — one definition, also worn by any other section that carries .hero-bg (the homepage
   Support section: .dark-particles, a .section-blur-overlay child and the particle web from hero-web.js).
   Extra uniform dark layer above var(--grad-hero-bg) — darkens only the
   hero without touching the shared token other sections reuse.
   Radial layer on top adds a soft black vignette at the edges/corners
   for depth — center stays bright so the heading/CTA keep contrast. */
.hero, .hero-bg {
  background:
    radial-gradient(ellipse 90% 70% at 50% 50%, transparent 45%, rgba(0,0,0,0.46) 100%),
    linear-gradient(rgba(0,0,0,0.48), rgba(0,0,0,0.48)),
    var(--grad-hero-bg);
}

/* A .hero-bg section needs no .dark-particles: it brings its own positioning, clipping and glow layer, and its
   direct children (the section's inner wrapper) sit above the web (z 4) and the tint (z 3), as .hero-content does.
   Decorative aria-hidden children are left alone. */
.hero-bg { position: relative; overflow: hidden; }
.hero-bg > :not(.section-blur-overlay, .hero-web, [aria-hidden="true"]) { position: relative; z-index: 10; }

/* No dot grid (global.css's .dark-particles::after) — the particle network
   is the hero's texture. Text and buttons always float above the canvas. */
.hero.dark-particles::after, .hero-bg::after { display: none; }
.hero-content { z-index: 10 !important; }
.hero-btn-group { z-index: 10 !important; }

/* Override dark-particles glow — soft deep-blue/teal from the SNL gradient. Static:
   `animation: none` also cancels the breathing animation the shared
   .hero.dark-particles::before rule in global.css applies, and opacity .75
   is that animation's resting (0%/100%) frame, so the glow keeps the
   brightness it had when the page first painted. */
.hero-bg::before { content: ""; position: absolute; pointer-events: none; z-index: 2; }
.hero.dark-particles::before, .hero-bg::before {
  background: radial-gradient(ellipse at center,
    rgba(var(--accent-deep-rgb), 0.22) 0%,
    rgba(var(--accent-rgb), 0.11) 44%,
    transparent 70%);
  top: 34%; left: 50%;
  transform: translate(-50%, -50%);
  width: clamp(320px, 80vw, 960px); height: clamp(240px, 60vw, 620px);
  filter: blur(38px);
  opacity: 0.75;
  animation: none;
}

/* Hero darkening — .section-blur-overlay is the hero's full-cover tint layer
   (above the background and the glow, below the text at z-index 10 and the
   white wave at z-index 5), so its alpha darkens the whole hero evenly.
   global.css has it at rgba(0,8,24,.08); plain black here because a blue
   tint would cancel the darkening in the blue channel, the brightest one. */
.hero .section-blur-overlay, .hero-bg .section-blur-overlay { background: rgba(0, 0, 0, 0.3); }

/* Particle-network canvas (new/js/hero.js). z-index 4 puts it above the
   darkening tint (3) so the white nodes stay crisp rather than being dimmed
   30%, and below the hero text (10) and the white wave (5). The scroll
   overlay (.hero-scroll-overlay in global.css, also z-index 4) comes after
   it in the markup, so it paints over the particles and they fade out with
   the rest of the hero as it scrolls away. */
.hero-particles {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 4;
  display: block;
  pointer-events: none;
}

.hero-content {
  position: relative;
  z-index: 3;
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
  padding: 0;
  will-change: transform; /* the headline parallax (hero.js) moves this */
}
.hero-static-text { color: #ffffff; display: block; }

.hero p {
  color: #ffffff;
  margin-bottom: 0;
  font-size: var(--text-body-lg, 18px);
  font-family: var(--p-font, 'Inter', sans-serif);
  font-weight: 400;
  line-height: var(--lh-body-lg, 1.70);
  padding: 0 10px;
  max-width: 820px;
  margin-left: auto;
  margin-right: auto;
}
/* A lede of several paragraphs: a gap between them (unclassed only, so .legal-updated etc. are untouched) */
.hero-content > p:not([class]) + p:not([class]) { margin-top: 16px; }
.hero-btn-group {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: var(--gap-desc-content, 40px);
  margin-bottom: 52px;
  position: relative;
  z-index: 4;
}

/* Hero badge uses the global .badge-pill — only hero-specific overrides needed */
.hero-content .badge-pill {
  position: relative;
  z-index: 4;
  white-space: normal;
}

/* Calm hero — nothing in the hero plays on its own except the particle-network
   background (the headline parallax and the scroll darkening only move while
   the page scrolls), so the CTA's bell-ringing icon (global.css
   .cta-btn [data-lucide], iconRing every 3s) is switched off here. Button
   hover/press effects are untouched and every CTA outside the hero keeps the
   icon animation. */
.hero[data-calm-hero] .cta-btn [data-lucide] { animation: none; }

/* Device mockup that floats over the wave (.hero-device-wrap base + 900/599/480
   media live in global.css). */
.hero-device {
  width: 100%;
  position: relative;
  padding-bottom: 32px;
}
@media (max-width: 599px) { .hero-device-wrap { padding: 0 8px 6px; margin-top: -100px; } }
/* Phones: the card is a bigger frame — nearly edge to edge and 4:3 instead of 16:9 (the videos / photos are cover-cropped, their subject sits centred). The carousel pages keep their own sizing. */
@media (max-width: 599px) { .hero-device-wrap:not(.studio-hero-wrap) .tf-screen { aspect-ratio: 4 / 3; } }

/* Media above the headline (snl_hero 'media' option, factory.php): a video / image
   card inside the hero, in normal flow before the copy — no floating, no wave. Sits
   above the copy (z 10) like .hero-content. */
.hero-media {
  position: relative;
  z-index: 10;
  width: 100%;
  max-width: 720px;
  margin: 0 auto 40px;
}
/* No shadow behind the card here: the hero is white, so the shared --hero-media-shadow would read as a grey halo. */
.hero-media .tf-screen { box-shadow: none; }
@media (max-width: 599px) { .hero-media { margin-bottom: 28px; } }

/* Compact — text-only pages (legal, contact, demo): same background, particles,
   overlay, parallax and wave, but sized to its copy instead of leaving 128vh
   for a device mockup. Padding-bottom = the wave (an SVG with a fixed 182px
   height at every width) + the parallax drift (up to 90px, see hero.js) + a
   little air, so the copy never runs into the wave and gets the full drift;
   under 900px the drift room is trimmed to keep phones from a huge banner. */
.hero.hero--compact { min-height: 0; padding: 118px var(--site-pad-x) 290px; }

/* Light — the white hero (snl_hero(['light' => true]): Studio Setup, Investor
   Relations): white background, dark text, the particle web (hero-web.js) in
   place of the constellation, and none of the dark hero's glow / tint /
   scroll-darkening layers. It combines with either size, and this block is
   the one place that defines it. */
.hero.hero--light { background: var(--bg); color: var(--fg-primary); }
.hero.hero--light::before { display: none; }
.hero.hero--light .section-blur-overlay,
.hero.hero--light .hero-scroll-overlay { display: none; }
.hero.hero--light h1,
.hero.hero--light p { color: var(--fg-primary); }
/* Tall light hero: centre the copy between the top of the hero and the carousel
   (.hero-device-wrap, pulled up over the wave by its own negative margin-top —
   see global.css). The .hero padding split above is tuned for a normal
   device-card page; here padding-top just adds dead air above the copy (the
   huge min-height/flex slack already gives it room), so it is zeroed, and
   padding-bottom is set to match the carousel's margin-top at each breakpoint
   so the flex-centred copy lands equidistant from the hero top and the
   carousel's top edge instead of drifting toward the top. Compact keeps its own
   padding: it has no carousel. */
.hero.hero--light:not(.hero--compact) {
  padding-top: 0;
  padding-bottom: 240px; /* matches .hero-device-wrap's default margin-top: -240px */
}
/* Tall light hero with a button row (class hero--centre-clear, ops.php): the rule above centres the copy between the
   very top of the hero and the carousel, but the top 65px is the fixed header pill and the button row carries the dark
   hero's 52px bottom margin, so the visible copy sat ~90px too high (127px under the pill, 312px above the carousel at
   1886 x 863). 132px of padding-top = the pill's bottom edge (65) + the carousel card's offset from its wrapper (67), which
   is what it takes at every breakpoint because padding-bottom already equals the wrapper's negative margin; dropping the
   last element's margin makes the visible copy the thing that is centred. */
.hero.hero--light.hero--centre-clear:not(.hero--compact) { padding-top: 132px; }
.hero.hero--light.hero--centre-clear:not(.hero--compact) .hero-content > :last-child { margin-bottom: 0; }

/* Compact light hero: no carousel floats over its wave, and a white wave on a
   white hero only hides the bottom of the web behind a hard edge, so the wave is
   dropped together with the 182px of padding it needed. The copy is centred
   in the hero: the bottom padding equals the top padding at each breakpoint
   (118 / 104 / 100px, see the .hero--compact rules), and the copy's last
   element (the CTA row, which carries a 52px bottom margin for the dark hero's
   wave) loses that margin so the visible space under it matches the space
   above. The parallax caps its own drift to the room left (hero.js measure()).
   Wins over every .hero--compact padding rule below on specificity. */
.hero.hero--light.hero--compact { padding-bottom: 118px; }
.hero.hero--light.hero--compact .hero-content > :last-child { margin-bottom: 0; }
.hero.hero--light.hero--compact .hero-curve { display: none; }

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 899px) {
  .hero { padding: 90px 16px 200px; min-height: 680px; }
  .hero.hero--compact { padding: 104px 16px 260px; min-height: 0; }
  .hero.hero--light:not(.hero--compact) { padding-bottom: 160px; } /* matches margin-top: -160px */
  .hero.hero--light.hero--compact { padding-bottom: 104px; } /* = the compact padding-top above */
  .hero-btn-group { gap: 14px; }
}
@media (max-width: 767px) {
  .hero { padding: 80px 16px 220px; min-height: 750px; }
  /* Phones get a plain static background: no constellation canvas and no
     scroll-darkening overlay (hero.js also skips both below 768px, so neither
     draws nor listens for scroll). The glow and tint layers are static. */
  .hero-particles,
  .hero-scroll-overlay { display: none; }
}
@media (max-width: 599px) {
  .hero { padding: 76px 16px 220px; min-height: 720px; }
  .hero.hero--light:not(.hero--compact) { padding-bottom: 220px; } /* matches margin-top: -220px */
  /* Mobile: the glow is cheaper (GPU) and the tint stays on for contrast */
  .hero.dark-particles::before { filter: blur(20px); width: 100%; height: 40vh; }
  .hero .section-blur-overlay { display: block; }
}
@media (max-width: 480px) {
  .hero { padding: 70px 14px 200px; min-height: 740px; }
  .hero.hero--compact { padding: 100px 14px 260px; min-height: 0; }
  .hero.hero--light:not(.hero--compact) { padding-bottom: 200px; } /* matches margin-top: -200px */
  .hero.hero--light.hero--compact { padding-bottom: 100px; } /* = the compact padding-top above */
  .hero p { font-size: 13px; margin-bottom: 20px; }
  .hero-btn-group {
    flex-direction: column;
    width: 100%;
    max-width: 280px;
    margin-left: auto;
    margin-right: auto;
    gap: 12px;
    margin-bottom: 14px;
  }
  .hero-btn-group .cta-btn,
  .hero-btn-group .cta-secondary {
    width: 100%;
    justify-content: center;
    padding: 14px 28px;
    font-size: 14px;
  }
}

/* ── Phone motion (under 768px, no JS needed) ───────────────────
   Phones get no canvas (no web, no constellation) and no scroll overlay, so the
   hero used to be a still picture. This is its replacement: everything here is
   transform / opacity only, so it runs on the compositor and costs no layout or
   paint per frame.
     1. the copy rises in once, staggered (h1, lede, buttons, the media card);
     2. the glow behind the copy drifts and breathes, and a second, teal one
        (::after; the dark hero's dot grid is switched off on phones anyway)
        drifts the other way; the white hero gets the same two soft glows;
     3. the device card rises in, then floats a few px.
   Off under prefers-reduced-motion, off with Save-Data (hero.js sets data-still)
   and paused while the hero is off screen (hero.js sets data-paused). */
@media (max-width: 767px) and (prefers-reduced-motion: no-preference) {
  @keyframes heroRise  { from { transform: translateY(18px); } to { transform: none; } } /* transform only: a fade from opacity 0 delayed the LCP text by ~0.5s */
  @keyframes heroFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
  @keyframes heroGlowA { 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: .75; } 50% { transform: translate(-30%, -40%) scale(1.3); opacity: 1; } }
  @keyframes heroGlowB { 0%, 100% { transform: translate(0, 0) scale(1); opacity: .55; } 50% { transform: translate(-45%, -22%) scale(1.3); opacity: 1; } }

  .hero-media, .hero-content > h1, .hero-content > p, .hero-content > .hero-btn-group, .hero-content > .legal-updated {
    animation: heroRise .7s cubic-bezier(.22, 1, .36, 1) both;
  }
  .hero-content > h1 { animation-delay: .05s; }
  .hero-content > p { animation-delay: .17s; }
  .hero-content > p ~ p { animation-delay: .24s; }
  .hero-content > .hero-btn-group { animation-delay: .3s; }
  .hero-content > .legal-updated { animation-delay: .34s; }

  .hero.dark-particles::before, .hero-bg::before {
    background: radial-gradient(ellipse at center, rgba(var(--accent-deep-rgb), 0.5) 0%, rgba(var(--accent-rgb), 0.2) 44%, transparent 70%);
    animation: heroGlowA 9s ease-in-out infinite;
    will-change: transform, opacity;
  }
  .hero.dark-particles::after, .hero-bg::after {
    display: block;
    content: "";
    position: absolute;
    right: -20%; bottom: 12%;
    width: 80vw; height: 60vw;
    background: radial-gradient(ellipse at center, rgba(var(--accent-rgb), 0.5) 0%, rgba(var(--accent-rgb), 0.16) 45%, transparent 70%);
    opacity: .6;
    pointer-events: none;
    z-index: 2;
    animation: heroGlowB 11s ease-in-out infinite;
    will-change: transform, opacity;
  }
  /* The white hero hides ::before in the block above; on a phone it shows the same two glows, fainter. */
  .hero.hero--light.dark-particles::before { display: block; }
  .hero.hero--light.dark-particles::before, .hero.hero--light.dark-particles::after { opacity: .5; }

  .hero-device-wrap .tf-screen {
    animation: heroRise .8s .4s cubic-bezier(.22, 1, .36, 1) both, heroFloat 7s 1.3s ease-in-out infinite;
  }

  .hero[data-still] *, .hero[data-still]::before, .hero[data-still]::after, .hero-bg[data-still]::before, .hero-bg[data-still]::after,
  .hero[data-still] ~ .hero-device-wrap .tf-screen { animation: none !important; }
  .hero[data-paused]::before, .hero[data-paused]::after, .hero-bg[data-paused]::before, .hero-bg[data-paused]::after,
  .hero[data-paused] ~ .hero-device-wrap .tf-screen { animation-play-state: paused; }
}
