/* ==========================================================================
   The black hole stage.

   The object itself is drawn on a <canvas> by blackhole.js — CSS can round a
   box and glow it, but it cannot make an accretion disk pass *behind* the
   shadow at the top and *in front* of it at the bottom, and that occlusion is
   the whole difference between a black hole and a donut. Everything here is
   the room it hangs in: backdrop, stars, and the darkness it leaves behind.

   Scroll drives three custom properties (blackhole.js): --bh-top, --bh-scale,
   --bh-dark. Transform and opacity only — the compositor does the work, the
   main thread stays free for the page.
   ========================================================================== */

body.has-bh { background: #04050A; }

/* Lift the page off the stage. The header is deliberately NOT in this list: it
   is already sticky with z-index 100, and re-declaring `position: relative`
   here would silently un-stick it — and drop it to the same layer as <main>,
   where DOM order wins and the open mobile menu ends up *behind* the hero. */
body.has-bh > main,
body.has-bh > .site-footer { position: relative; z-index: 1; }

.bh-stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: layout paint style;
}

/* Deep-space backdrop. Two very wide, very low-contrast gradients — enough to
   keep the black from reading as "unstyled", not enough to compete with a
   screenshot. */
.bh-sky {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(1300px 700px at 66% -14%, rgba(124, 58, 237, 0.16), transparent 68%),
    radial-gradient(1000px 620px at 6% 30%, rgba(37, 99, 235, 0.09), transparent 70%),
    radial-gradient(900px 900px at 50% 120%, rgba(232, 121, 249, 0.05), transparent 70%),
    #05060B;
}

/* Two star layers: one steady, one breathing. Both drift a little with the
   scroll (--bh-star-y) so the field has depth against the incoming hole. */
.bh-stars {
  position: absolute;
  inset: -6%;
  transform: translate3d(0, var(--bh-star-y, 0px), 0);
  background-image:
    radial-gradient(1.5px 1.5px at 12% 22%, rgba(255,255,255,0.6), transparent 100%),
    radial-gradient(1.1px 1.1px at 28% 64%, rgba(255,255,255,0.38), transparent 100%),
    radial-gradient(1.7px 1.7px at 41% 12%, rgba(203,211,225,0.52), transparent 100%),
    radial-gradient(1.1px 1.1px at 55% 43%, rgba(255,255,255,0.32), transparent 100%),
    radial-gradient(1.4px 1.4px at 67% 79%, rgba(255,255,255,0.42), transparent 100%),
    radial-gradient(1.1px 1.1px at 74% 18%, rgba(167,139,250,0.48), transparent 100%),
    radial-gradient(1.6px 1.6px at 86% 55%, rgba(255,255,255,0.46), transparent 100%),
    radial-gradient(1.1px 1.1px at 93% 30%, rgba(203,211,225,0.36), transparent 100%),
    radial-gradient(1.3px 1.3px at 18% 88%, rgba(255,255,255,0.36), transparent 100%),
    radial-gradient(1.1px 1.1px at 48% 92%, rgba(167,139,250,0.36), transparent 100%),
    radial-gradient(1.2px 1.2px at 81% 90%, rgba(255,255,255,0.32), transparent 100%),
    radial-gradient(1.1px 1.1px at 6% 52%, rgba(255,255,255,0.3), transparent 100%),
    radial-gradient(1.3px 1.3px at 34% 36%, rgba(255,255,255,0.28), transparent 100%),
    radial-gradient(1.1px 1.1px at 62% 8%, rgba(103,232,249,0.34), transparent 100%);
}
.bh-stars--near {
  animation: bh-twinkle 7s ease-in-out infinite alternate;
  background-image:
    radial-gradient(2px 2px at 22% 44%, rgba(255,255,255,0.5), transparent 100%),
    radial-gradient(1.8px 1.8px at 58% 68%, rgba(196,181,253,0.5), transparent 100%),
    radial-gradient(1.9px 1.9px at 88% 14%, rgba(255,255,255,0.44), transparent 100%),
    radial-gradient(1.7px 1.7px at 8% 74%, rgba(103,232,249,0.4), transparent 100%),
    radial-gradient(2px 2px at 44% 84%, rgba(255,255,255,0.34), transparent 100%);
}
@keyframes bh-twinkle {
  from { opacity: 0.45; }
  to   { opacity: 1; }
}

/* The object. Fixed pixel size; the fly-in is a compositor-only scale, which
   is why it stays smooth while the whole page scrolls underneath. */
.bh-hole {
  position: absolute;
  left: 50%;
  top: var(--bh-top, 23vh);
  width: min(660px, 118vw);
  height: min(660px, 118vw);
  transform: translate3d(-50%, -50%, 0) scale(var(--bh-scale, 1));
  transform-origin: 50% 50%;
  will-change: transform;
}
.bh-hole canvas { width: 100%; height: 100%; display: block; }

/* What the hole leaves behind: everything the page sits on turns black. */
.bh-dark {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: var(--bh-dark, 0);
}

/* Readability while the hole hangs directly behind the headline. Two shadows:
   a tight one that keeps the letterforms off the bright photon ring, and a wide
   one that darkens the field behind a whole line. */
body.has-bh .hero h1,
body.has-bh .hero .sub,
body.has-bh .hero .trust-row,
body.has-bh .error-page h1,
body.has-bh .error-page p {
  text-shadow:
    0 0 14px rgba(3, 4, 9, 0.95),
    0 2px 40px rgba(3, 4, 9, 0.9);
}

/* The 404 has no hero to hide behind: push its copy clear of the object. */
body.has-bh .error-page { padding-top: min(46vh, 440px); }

/* Reduced motion: one static frame, parked lower and smaller so it decorates
   the hero instead of blocking it. Nothing moves, nothing gets swallowed. */
@media (prefers-reduced-motion: reduce) {
  .bh-stars--near { animation: none; opacity: 0.7; }
  .bh-hole { top: 30vh; }
}
