/* ══════════════════════════════════════════════════════════════════════════
   THE WORLD BELOW — hero scene: "Storm Above, Life Below".

   The stack, back to front, all inside .hero (which already clips):

     .twbh-sky      css gradient — the storm sky, no repaint cost
     canvas.twbh-back    clouds, far ridges, mid cliffs, waterfalls, valley glow
     canvas.twbh-birds   the pterosaurs (webgl, or the baked-sprite fallback)
     canvas.twbh-front   near canyon walls, crack glow, near mist, rain, flash
     .twbh-scrim    the calm, dark reading side on the left
     .twbh-vig      the frame vignette

   Everything is aria-hidden and pointer-events:none; the hero's own content
   sits at z-index 2 and is never touched. If the script never runs, the page
   is exactly what it was before — the whole stack is injected, not authored
   into the markup.
   ══════════════════════════════════════════════════════════════════════════ */

/* ★★The scene is FIXED and page-wide (his 2026-08-03 ask: "have the whole
   homepage have it, not at the top only"), so it sits behind every section,
   not inside the hero box. It mounts on the body at z-index -2 — the same
   place the site's world engine already proves works — just above that
   engine and below all in-flow content. */
.twbh-root {
  position: fixed;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  pointer-events: none;
  /* the scene paints its own black; a page-level background must not show
     through the moment before the first frame lands */
  background: var(--twbh-void, #04070c);
  contain: strict;
}
/* ★★★THE PAGE FLOOR HAS TO GET OUT OF THE WAY, AND IT FIGHTS BACK.
   twb-theme.css carries `html, body { background: ... !important }` — an
   OPAQUE page floor. body is an in-flow block, so its background paints in
   step 3 of the painting order, ABOVE every negative-z-index layer in step
   2. The scene was mounted, sized, painting 26,809 of 28,000 pixels, and
   completely invisible; even a solid red test fill never reached the screen,
   at z-index -1 or -2. Only `!important` beats it. (The site's own world
   engine sets `body.twb-world-on { background: transparent }` WITHOUT
   !important, so it loses the same fight — its cavern has been walled off
   behind this floor too.) */
body.twbh-page { background: transparent !important; }
/* ...and the landing hero's own wash was an opaque gradient down to the page
   floor, which is the one band that matters most */
body.twbh-page .hero.sw-hero-wash {
  background:
    radial-gradient(120% 90% at 50% 116%, rgba(var(--sw-accent-rgb), .10), transparent 58%),
    linear-gradient(180deg, rgba(var(--twb-scrim-rgb), .30) 0%, rgba(var(--twb-scrim-rgb), .10) 74%);
}
body.twbh-page .hero.sw-hero-wash::after {
  background: linear-gradient(180deg, transparent, rgba(var(--twb-scrim-rgb), .34) 90%);
}
/* the old static key-art plate is what this scene replaces — stop fetching it */
.hero.twbh-on::before { display: none !important; }

/* One storm per page. The site-wide cavern stays MOUNTED so every contract it
   owns still holds (the Motion attribute, the weather push, the atmosphere
   drawer, the ribbon) — it is only hidden, and a hidden canvas measures zero,
   so its own draw calls fall away on their existing size guards. */
body.twbh-page #twbWorld,
body.twbh-page #twbWx,
body.twbh-page #twbFlash { display: none !important; }

/* the hero still wants room for a canyon to be a canyon */
.hero.twbh-on {
  min-height: min(78vh, 780px);
  display: flex;
  align-items: center;
}
.hero.twbh-on > .sw-wrap { width: 100%; }
@media (max-width: 720px) {
  .hero.twbh-on { min-height: min(72vh, 620px); }
}

.twbh-root > * {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* The sky has to be LIGHTEST where the ridges meet it, or every silhouette
   below has nothing to be a silhouette against. */
.twbh-sky {
  z-index: 0;
  background:
    radial-gradient(78% 44% at 62% 50%, var(--twbh-sky-hi) 0%, transparent 72%),
    radial-gradient(80% 54% at 24% 100%, var(--twbh-sky-lo) 0%, transparent 74%),
    linear-gradient(180deg, var(--twbh-sky-a) 0%, var(--twbh-sky-b) 34%, var(--twbh-sky-c) 56%, var(--twbh-sky-d) 100%);
}
.twbh-back  { z-index: 1; }
.twbh-birds { z-index: 2; }
.twbh-front { z-index: 3; }

/* ── the reading side ──────────────────────────────────────────────────────
   Requirement: the left is darker and calmer. The gradient does the heavy
   lifting; the engine also thins rain and mist toward the left so the calm
   is real motion-wise, not just a wash on top of a busy picture. */
.twbh-scrim {
  z-index: 4;
  background:
    linear-gradient(90deg,
      var(--twbh-scrim-1) 0%,
      var(--twbh-scrim-2) 26%,
      var(--twbh-scrim-3) 50%,
      transparent 74%),
    linear-gradient(180deg, var(--twbh-top) 0%, transparent 26%),
    /* the page keeps scrolling past this scene, so the foot of the frame has
       to stay quiet under the sections and the footer */
    linear-gradient(0deg, var(--twbh-top) 0%, transparent 22%);
}
/* On a phone the copy runs the full width, so a left-to-right wash cannot do
   the job — the reading side becomes the whole screen. */
@media (max-width: 760px) {
  .twbh-scrim {
    background:
      linear-gradient(90deg, var(--twbh-scrim-1) 0%, var(--twbh-scrim-2) 62%, var(--twbh-scrim-3) 100%),
      linear-gradient(180deg, var(--twbh-top) 0%, transparent 34%);
  }
}
.twbh-vig {
  z-index: 5;
  background:
    radial-gradient(130% 100% at 50% 50%, transparent 46%, var(--twbh-vig) 100%),
    linear-gradient(0deg, var(--twbh-foot) 0%, transparent 30%);
}

/* ── palettes ─────────────────────────────────────────────────────────────
   Dark is the design. Light theme keeps the same storm but lit from a pale
   overcast, because the hero copy turns to dark ink there and a black wash
   under it would be unreadable. */
:root {
  --twbh-void:    #04070c;
  --twbh-sky-hi:  rgba(122, 160, 184, .34);
  --twbh-sky-lo:  rgba(24, 88, 96, .22);
  --twbh-sky-a:   #030509;
  --twbh-sky-b:   #070d15;
  --twbh-sky-c:   #12202b;
  --twbh-sky-d:   #060c12;
  /* The near-left wall is already near-black, so the scrim only has to
     finish the job — pile more on and the cliff that frames the shot
     disappears into it. */
  --twbh-scrim-1: rgba(3, 6, 10, .90);
  --twbh-scrim-2: rgba(3, 6, 10, .60);
  --twbh-scrim-3: rgba(3, 6, 10, .20);
  --twbh-top:     rgba(3, 6, 10, .50);
  --twbh-vig:     rgba(2, 4, 7, .80);
  --twbh-foot:    rgba(2, 4, 7, .74);
}
:root[data-theme="light"] {
  --twbh-void:    #b6c2cc;
  --twbh-sky-hi:  rgba(255, 255, 255, .70);
  --twbh-sky-lo:  rgba(120, 168, 176, .30);
  --twbh-sky-a:   #aebbc7;
  --twbh-sky-b:   #c2cdd7;
  --twbh-sky-c:   #dfe7ed;
  --twbh-sky-d:   #a9b8c4;
  --twbh-scrim-1: rgba(233, 239, 243, .93);
  --twbh-scrim-2: rgba(233, 239, 243, .80);
  --twbh-scrim-3: rgba(233, 239, 243, .32);
  --twbh-top:     rgba(233, 239, 243, .40);
  --twbh-vig:     rgba(120, 137, 152, .48);
  --twbh-foot:    rgba(120, 137, 152, .40);
}

/* ── the hero's own furniture, over a moving picture ──────────────────────
   The landing page's brand mark and terminal strip were designed against a
   flat wash. Over a canyon they need their own footing. */
.hero.twbh-on .hero-art {
  opacity: .88;
  filter: drop-shadow(0 0 54px rgba(79, 216, 216, .30)) drop-shadow(0 18px 40px rgba(0, 0, 0, .6));
}
:root[data-theme="light"] .hero.twbh-on .hero-art { opacity: .92; }
.hero.twbh-on h1,
.hero.twbh-on .sw-lede { text-shadow: 0 2px 26px rgba(2, 5, 9, .55); }
:root[data-theme="light"] .hero.twbh-on h1,
:root[data-theme="light"] .hero.twbh-on .sw-lede { text-shadow: 0 2px 22px rgba(255, 255, 255, .7); }

/* ── reduced motion / shed ────────────────────────────────────────────────
   Nothing is hidden when motion is off: the scene still paints one full
   still frame, it simply stops moving. A blank hero would read as broken. */
@media (prefers-reduced-motion: reduce) {
  .twbh-root { transition: none; }
}
