/* ==========================================================================
   Sphinx Labs — hero section
   Depends on the tokens defined in css/styles.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero
   Previously a rounded blue card inset from the page. Now full-bleed: the
   card border dissolves and #0A0A0A runs edge to edge, so the page opens with
   no seam and the transparent header floats over it rather than sitting on a
   panel. This is the single change that most changes the page's first
   impression, and it costs no markup — the section keeps its .shell wrapper
   for the content column while the background escapes it.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  /* Break out to the viewport edge without leaving the flow. Cancelling only
     the gutter is not enough — .shell is capped at 1440px, so past that width
     the background stopped short and left a seam down both sides. `50% - 50vw`
     resolves to the shell's own offset at any width; html/body carry
     overflow-x: clip, so the vw units cannot open a horizontal scrollbar.
     The padding then rebuilds the 1210px column, so nothing inside moves. */
  margin-inline: calc(50% - 50vw);
  padding-inline: max(var(--gutter), calc(50vw - var(--content) / 2));
  /* Pull up under the transparent header so the bloom starts behind the logo. */
  margin-top: -108px;
  padding-top: 108px;
  border-radius: 0;
  /* Lands on --page, not --hero-to: the two differ by 5 per channel, which read
     as a ruled line across the bottom edge once the hero went full width. */
  background: linear-gradient(
    180deg,
    var(--hero-from) 0%,
    var(--hero-to) 62%,
    var(--page) 100%
  );
  isolation: isolate;
}

/* --------------------------------------------------------------------------
   Corner blooms
   Both light sources in one pseudo-element, as stacked radial-gradients.
   Lime sits top-left where the eye lands first and the CTAs live; the blue
   fills the opposite corner so the composition has weight on both diagonals.
   No blur filter — see the note at the top of css/effects.css.
   -------------------------------------------------------------------------- */

.hero::before {
  content: "";
  position: absolute;
  inset: -10% -5% 0;
  z-index: -2;
  pointer-events: none;
  /* --par-y is published by js/motion.js during scroll. It defaults to 0, so
     the bloom is correctly placed with JS disabled. */
  transform: translate3d(0, var(--par-y, 0px), 0);
  will-change: transform;
  background:
    radial-gradient(46% 42% at 14% 6%, rgba(198, 255, 0, 0.16), transparent 62%),
    radial-gradient(52% 48% at 88% 78%, rgba(7, 78, 135, 0.62), transparent 64%),
    radial-gradient(70% 50% at 50% 110%, rgba(7, 78, 135, 0.3), transparent 70%);
  /* The bottom bloom is centred at 110% — below the hero — so `overflow: hidden`
     used to cut it at full strength and leave a hard line. This pseudo-element
     is inset to the hero, so fading it here retires the bloom before the edge
     instead of clipping it, and it stays aimed where it was designed to be. */
  -webkit-mask-image: linear-gradient(180deg, #000 68%, transparent 99%);
  mask-image: linear-gradient(180deg, #000 68%, transparent 99%);
}

/* --------------------------------------------------------------------------
   Floating specks
   Twelve dots painted as twelve radial-gradient layers on ONE element, drifting
   as a single transform. Twelve separate animated divs would mean twelve
   composited layers and twelve markup additions; this is one layer, no markup,
   and identical on screen.
   -------------------------------------------------------------------------- */

.hero::after {
  content: "";
  position: absolute;
  inset: -6%;
  z-index: -1;
  pointer-events: none;
  background-repeat: no-repeat;
  background-image:
    radial-gradient(2px 2px at 12% 22%, rgba(198, 255, 0, 0.55), transparent),
    radial-gradient(1.5px 1.5px at 26% 68%, rgba(255, 255, 255, 0.35), transparent),
    radial-gradient(2.5px 2.5px at 41% 14%, rgba(198, 255, 0, 0.3), transparent),
    radial-gradient(1.5px 1.5px at 55% 82%, rgba(255, 255, 255, 0.4), transparent),
    radial-gradient(2px 2px at 68% 36%, rgba(198, 255, 0, 0.4), transparent),
    radial-gradient(1.5px 1.5px at 79% 72%, rgba(255, 255, 255, 0.3), transparent),
    radial-gradient(2px 2px at 88% 24%, rgba(198, 255, 0, 0.35), transparent),
    radial-gradient(1.5px 1.5px at 33% 44%, rgba(255, 255, 255, 0.25), transparent),
    radial-gradient(2px 2px at 62% 58%, rgba(198, 255, 0, 0.25), transparent),
    radial-gradient(1.5px 1.5px at 18% 88%, rgba(255, 255, 255, 0.3), transparent),
    radial-gradient(2px 2px at 92% 56%, rgba(255, 255, 255, 0.22), transparent),
    radial-gradient(1.5px 1.5px at 48% 30%, rgba(198, 255, 0, 0.3), transparent);
  animation: hero-specks 24s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes hero-specks {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(0, -26px, 0);
  }
}

/* --------------------------------------------------------------------------
   Hero lede
   -------------------------------------------------------------------------- */

.hero__lede {
  font-size: clamp(1rem, 1.4vw, 1.25rem);
  font-weight: 300;
  line-height: 1.7;
}

/* --------------------------------------------------------------------------
   Rotating dot field
   The Figma decoration (52:22219) is a radial lattice of ~2,800 dots, so
   spinning it about its own centre reads as continuous circular drift with no
   seam — a tiling background could not do this.

   On the dark canvas the asset's own ink is too heavy, so it is dimmed rather
   than replaced: same file, no extra request.
   -------------------------------------------------------------------------- */

.hero__dots {
  position: absolute;
  top: 93px;
  left: 50%;
  width: 1408px;
  height: 1411px;
  /* Pre-rasterized to WebP (was a 122KB SVG of ~2,800 vector paths). This div is
     the LCP element; rasterizing 2,800 paths on a throttled mobile CPU was the LCP
     bottleneck. It renders at a fixed 1408px so the vector gained us nothing, and at
     0.28 opacity the raster is visually identical. See docs/image-optimization-report.md. */
  background: url("../images/doted-bg.webp") center / contain no-repeat;
  transform-origin: 50% 50%;
  /* One turn every 2 minutes — present but never distracting. */
  animation: hero-dots-spin 120s linear infinite;
  pointer-events: none;
  user-select: none;
  opacity: 0.28;
  z-index: -1;
  /* Promote to its own layer so the spin doesn't repaint the hero text. */
  will-change: transform;
}

/* translateX is kept inside the keyframes: `transform` is one property, so an
   animation on it would otherwise overwrite the centring. */
@keyframes hero-dots-spin {
  from {
    transform: translateX(-50%) rotate(0deg);
  }
  to {
    transform: translateX(-50%) rotate(360deg);
  }
}

/* --------------------------------------------------------------------------
   Trusted-by strip
   -------------------------------------------------------------------------- */

/* The partner logos ship white-on-transparent (they were drawn for the old
   blue hero), so they need no recolouring — only restraint. Holding them at
   65% keeps them as supporting evidence rather than competing with the CTAs,
   and full opacity on hover rewards a look without demanding one. */
.logo-strip img {
  opacity: 0.65;
  transition: opacity 0.3s ease;
}

.logo-strip img:hover {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1023px) {
  .hero {
    margin-top: -96px;
    padding-top: 96px;
  }

  /* Hold the lattice larger than the card so no corner is ever left bare. */
  .hero__dots {
    top: 40px;
    width: 1100px;
    height: 1102px;
  }
}

@media (max-width: 767px) {
  .hero__dots {
    top: 20px;
    width: 820px;
    height: 822px;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — keep the decoration, drop the movement.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .hero__dots,
  .hero::after {
    animation: none;
  }
}
