/* The homepage stage: one full-bleed dark field, the terminal and the account
 * pane floating on it as glass, and everything utilitarian below the fold.
 *
 * `home-split.css` owns the split grid. This file owns the field itself, the
 * header's disappearing act, and the band under the hero. They are separate
 * because the grid is a layout and this is a look — and only this one is
 * scoped, wholesale, to `body.home-split-body`.
 *
 * Brand orange appears here as *light*, never as paint: two soft off-screen
 * glows. That keeps the field neutral enough for the chain rail's green/red
 * pips and the amber approval card to stay the loudest things on the page. */

:root:has(body.home-split-body),
.home-split-body {
  --sp-stage-ink: oklch(0.16 0.012 55);
  --sp-stage-glow: oklch(0.62 0.19 47);
  --sp-stage-glass: oklch(0.24 0.012 55 / 0.58);
  --sp-stage-glass-border: oklch(1 0 0 / 0.09);
  --sp-stage-blur: 24px;

  /* What separates glass from a translucent rectangle is the edge: real glass
     catches light along its top rim and loses it toward the bottom. One
     gradient, painted on a 1px inset ring, does the whole job — and it is a
     token rather than a rule because both panes need the identical edge or
     they read as two different materials. */
  --sp-stage-specular:
    linear-gradient(160deg,
      oklch(1 0 0 / 0.34) 0%,
      oklch(1 0 0 / 0.06) 26%,
      oklch(1 0 0 / 0) 52%,
      oklch(1 0 0 / 0.05) 100%);
  --sp-stage-rim: oklch(0.62 0.19 47 / 0.28);
  --sp-stage-text: oklch(0.96 0.004 60);
  --sp-stage-text-dim: oklch(0.82 0.008 60);
  --sp-stage-text-muted: oklch(0.68 0.01 60);

  /* Brand orange as light, not paint. Declared once and used twice — on the
     root, and again over the video in `.stage-video-layer::after`. */
  --sp-stage-glows:
    radial-gradient(60rem 40rem at 12% -10%, oklch(0.62 0.19 47 / 0.22), transparent 60%),
    radial-gradient(50rem 35rem at 88% 60%, oklch(0.62 0.19 47 / 0.13), transparent 60%);
}

/* The field lives on the root, not on the body, so the band below the fold
   shares it with no seam — and, critically, so it cannot paint *over* the video.
   `head-assets.html` sets `html { background-color }` for anti-FOUC, and a root
   that has a background is exactly the condition under which the body's own
   background stops propagating to the canvas: it would paint on the body box
   instead, above `.stage-video-layer`'s `z-index: -1`, hiding the footage
   completely. Putting it here keeps it behind the layer by construction.
   This is also the fallback the page falls back to if the video never arrives. */
:root:has(body.home-split-body) {
  background: var(--sp-stage-glows), var(--sp-stage-ink);
  background-attachment: fixed;
}

.home-split-body {
  background: transparent;
  /* Native form controls and scrollbars follow, without claiming the global
     theme — the footer's theme toggle still owns that. */
  color-scheme: dark;
  color: var(--sp-stage-text);
  /* The page scrolls now; only the horizontal overflow is unwanted. */
  overflow-x: hidden;
}

/* ── the video field ────────────────────────────────────────────────────── */

/* Fixed and behind everything, so the hero and the band below it share one
   continuous field with no seam at the fold and nothing to keep in sync while
   scrolling. `z-index: -1` puts it under the page's own content without taking
   it out of the body's stacking context, so the orange glows above composite
   over it rather than being hidden by it. */
/* The poster is set here as well as on the <video> so that first paint has an
   image whichever one the browser gets to first. Needs core >= 0.25.0, which is
   where `resolve_mime_type` learned image/webp — these responses carry
   `nosniff`, so an unmapped extension does not degrade, it fails to decode. */
.stage-video-layer {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  background: var(--sp-stage-ink) url("/files/video/hero/hero-poster.webp") center / cover no-repeat;
}

.stage-video-layer .hero-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Starts invisible over its own poster and crossfades once it can play, so a
     half-buffered first frame never pops. hero-header.js adds `.is-ready`. */
  opacity: 0;
  transition: opacity 900ms ease;
}

.stage-video-layer .hero-video.is-ready {
  opacity: 1;
}

/* The scrim is the reason any of this is readable.
   Adapted from the hero implementation this replaces, where it was tuned for
   exactly this problem: light text over an image that will not hold still. The
   blur takes the detail out of the footage so the eye stops trying to resolve
   it, and the gradients weight the darkening toward the top, where the header
   sits, and the bottom, where the band arrives. */
/* The glows again, this time above the footage. `background-attachment: fixed`
   on the body cannot reach here, but the layer is itself fixed, so they hold
   the same position on screen either way. */
.stage-video-layer::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--sp-stage-glows);
  z-index: 2;
  pointer-events: none;
}

.stage-video-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* The top and bottom stay heavy, because that is where the header and the
     band land; the middle lifts, because that is the only part of the frame
     anyone sees move. */
  backdrop-filter: blur(6px) saturate(1.08);
  -webkit-backdrop-filter: blur(6px) saturate(1.08);
  background:
    linear-gradient(180deg,
      oklch(0.12 0.012 55 / 0.80) 0%,
      oklch(0.12 0.012 55 / 0.42) 32%,
      oklch(0.12 0.012 55 / 0.42) 68%,
      oklch(0.12 0.012 55 / 0.86) 100%),
    linear-gradient(90deg,
      oklch(0.12 0.012 55 / 0.42) 0%,
      transparent 55%);
}

/* ── the glass edge ─────────────────────────────────────────────────────── */

/* Both panes get the same rim from here rather than each from its own file,
   because the thing that makes two floating surfaces read as one sheet of
   glass is that the light hits them identically. `mask-composite` paints the
   gradient only in the 1px ring, so this is an edge and not a wash over the
   content — and it sits on ::before at z-index 0 so the terminal's own
   children, which set their own stacking, stay above it. */
.home-split-body .pi-terminal .terminal,
.home-split-body .auth-pane .pane {
  position: relative;
}

.home-split-body .pi-terminal .terminal::before,
.home-split-body .auth-pane .pane::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  padding: 1px;
  background: var(--sp-stage-specular);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

/* On a dark field the white wordmark is the right asset, and it is already in
   the header markup — see the `.logo-video` rule in header-core.css. */
.home-split-body .logo-light,
.home-split-body .logo-dark { display: none; }
.home-split-body .logo-video { display: block; }

/* The muted grey the tagline uses elsewhere is unreadable on the dark field. */
.home-split-body .logo-tagline { color: var(--sp-stage-text-muted); }

/* ── header ─────────────────────────────────────────────────────────────── */

/* Over the stage the header is a logo and nothing else: it dissolves into the
   field rather than sitting on it as a white bar. */
.home-split-body .site-header {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
  box-shadow: none;
}

/* Once the hero has scrolled past, the header needs its own surface again or
   the logo lands on top of the band's content. `hero-header.js` sets the
   attribute on <html>. */
[data-scrolled] .home-split-body .site-header {
  background: oklch(0.16 0.012 55 / 0.72);
  backdrop-filter: blur(var(--sp-stage-blur)) saturate(160%);
  -webkit-backdrop-filter: blur(var(--sp-stage-blur)) saturate(160%);
  border-bottom-color: var(--sp-stage-glass-border);
}

/* `display: none` rather than visual hiding: the nav is genuinely gone here,
   so it leaves the tab order and the a11y tree with it. The same links live in
   the band below, built from the same config. */
.home-split-body .nav-links,
.home-split-body .mobile-menu-toggle,
.home-split-body .mobile-menu-overlay { display: none; }

/* ── the scroll cue ─────────────────────────────────────────────────────── */

/* A 100dvh hero reads as the whole page unless something says otherwise, and
   then nobody finds the band. */
.home-split-body .home-split {
  position: relative;
}

.home-split-scroll-cue {
  position: absolute;
  left: 50%;
  bottom: var(--sp-space-3);
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-space-2);
  color: var(--sp-stage-text-muted);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transition: opacity 0.3s ease;
}

.home-split-scroll-cue:hover {
  color: var(--sp-stage-text-dim);
}

/* Once you have scrolled, the cue has done its job — and it must stop taking
   clicks as well as fading, or it sits invisible over the band. */
[data-scrolled] .home-split-scroll-cue {
  opacity: 0;
  pointer-events: none;
}

/* ── below the fold ─────────────────────────────────────────────────────── */

/* The band itself is `components/home-scene.css` — it needs the stage tokens
   declared above, and nothing else here needs it. */

/* ── footer ─────────────────────────────────────────────────────────────── */

/* The homepage emits a footer for the first time here — it had nowhere to
   scroll to before. It carries the legal links and the theme toggle for free;
   it just has to stop being a light slab. */
.home-split-body .site-footer {
  background: transparent;
  border-top: 1px solid var(--sp-stage-glass-border);
  color: var(--sp-stage-text-dim);
}

.home-split-body .site-footer a,
.home-split-body .site-footer h3,
.home-split-body .site-footer p {
  color: var(--sp-stage-text-dim);
}

.home-split-body .site-footer a:hover {
  color: var(--sp-stage-text);
}

/* The footer markup carries only the two themed logos and neither has the ink
   for this field — the white wordmark the header uses over the video is not in
   the partial, and the partial is compiled into the binary. So the logo comes
   in as a background image on the ::after: the real asset, at the real aspect
   ratio, without a rebuild to add a third <img> the rest of the site would
   never show. */
.home-split-body .site-footer .logo-light,
.home-split-body .site-footer .logo-dark { display: none; }

.home-split-body .site-footer .footer-logo::after {
  content: '';
  display: block;
  width: 140px;
  height: 32px;
  background: url("/files/images/logo-white.svg") left center / contain no-repeat;
}

.home-split-body .theme-toggle-btn {
  color: var(--sp-stage-text-dim);
  border-color: var(--sp-stage-glass-border);
}

/* ── narrow ─────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  /* With the hero stacked there is no fold to cue past. */
  .home-split-scroll-cue { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .home-split-scroll-cue { transition: none; }
}
