/* shared/site/background.css — background layer for the landing pages that had none.
 *
 * The engine paints a full-viewport scene, so the page's own opaque body colour is cleared and the
 * layer sits behind ALL content (negative z-index) instead of fighting the page's stacking. That is
 * deliberate: these landing pages are independent, self-contained documents with their own fixed
 * headers and overlays, and a negative-z layer cannot cover or break any of them.
 */
html,
body { background: transparent !important; }

#site-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
#site-bg canvas,
#site-bg svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* 2026-10-22 — the mirror pages are app-style: their panels are opaque, so a layer behind them
   is never seen. Make the layer a LIGHT OVERLAY above the panels: screen blend keeps it out of the
   reading path (black is neutral), pointer-events keeps it out of the way. */
#site-bg {
  z-index: 2147482000;
  opacity: .5;
  mix-blend-mode: screen;
}

/* ---------------------------------------------------------------------------
   2026-10-26 — hand-composed scenes (shared/site/scenes.js).
   A scene is a picture, not an abstraction: screen blend would wash it out, so a
   scene layer is drawn normally at slightly reduced opacity, with a vignette that
   keeps the header and the edges out of the way of the drawing. The quote in the
   attribute selector is the engine name in the layer's own data-spec JSON.
   --------------------------------------------------------------------------- */
#site-bg[data-spec*='"engine":"scene"'] {
  /* 2026-10-26 — the scene is a BACKGROUND, not an overlay. It used to inherit the mirror-page
     z-index (2147482000), so the picture was painted over every panel and every line of text at
     86% opacity: measured text-area contrast on orbit-plugin-kit was 25.5/255. Behind the content
     at full strength, the same text measures 92.5/255 and the scene reads as a place the page sits
     in. The mirror pages that need an overlay keep their own rule; this only touches scenes. */
  z-index: -1;
  opacity: 1;
  mix-blend-mode: normal;
}
/* 2026-11-02 — the product is the highlight; the background is the entertainment. A scene that is
   beautiful at full strength competes with the copy that sells the thing, so the picture is pushed
   back: less brightness, less saturation, and a heavier scrim. The scene stays legible as a scene;
   it just never wins a fight with a heading. */
#site-bg[data-spec*='"engine":"scene"'] svg,
#site-bg[data-spec*='"engine":"scene"'] canvas {
  filter: brightness(.8) saturate(.9);
}
#site-bg[data-spec*='"engine":"scene"']::before {
  /* Text protection. With the scene behind the content, any copy that sits directly on the
     picture (app pages keep a transparent body) was still competing with bright neon: a 50-element
     sample measured a median of 65/255. This scrim darkens the picture behind the content without
     touching panels or text (it lives inside the layer, which is behind both). */
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(5, 7, 11, .74), rgba(5, 7, 11, .6) 45%, rgba(5, 7, 11, .78));
}
#site-bg[data-spec*='"engine":"scene"']::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(130% 100% at 50% 42%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .24) 58%, rgba(0, 0, 0, .62) 100%);
}

/* Scene motion. Each class is attached to authored SVG elements by scenes.js; the
   drawing itself never moves, only the weather and the dream. */
@keyframes sc-steam {
  0%, 100% { transform: translateY(0); opacity: .14; }
  50% { transform: translateY(-22px); opacity: .3; }
}
@keyframes sc-snow {
  0% { transform: translateY(-12vh); }
  100% { transform: translateY(106vh); }
}
@keyframes sc-contrail {
  0% { stroke-dashoffset: 0; opacity: .25; }
  50% { opacity: .75; }
  100% { stroke-dashoffset: -680; opacity: .25; }
}
@keyframes sc-flicker {
  0%, 100% { opacity: 1; }
  42% { opacity: .72; }
  56% { opacity: .88; }
  70% { opacity: .78; }
}
@keyframes sc-drift {
  0%, 100% { transform: translateX(-16px); }
  50% { transform: translateX(16px); }
}
@keyframes sc-mote {
  0%, 100% { transform: translateY(0); opacity: .2; }
  50% { transform: translateY(-26px); opacity: .68; }
}
@keyframes sc-soft {
  0%, 100% { opacity: .55; }
  50% { opacity: .8; }
}
@keyframes sc-rain {
  0% { transform: translateY(-30px); }
  100% { transform: translateY(48px); }
}
/* 2026-10-26 — lighting in the rain. Nothing shows a bolt: the sky's own wash brightens and
   dims slowly, the practical lights breathe, and one rain layer brightens so the drops catch
   the light. All of it is slow and low-amplitude, and all of it stops under reduced motion. */
@keyframes sc-sky-light {
  0%, 100% { opacity: .04; }
  41% { opacity: .04; }
  44% { opacity: .14; }
  48% { opacity: .06; }
  67% { opacity: .11; }
  71% { opacity: .04; }
}
@keyframes sc-glow-pulse {
  0%, 100% { opacity: .07; }
  50% { opacity: .18; }
}
@keyframes sc-rain-light {
  0%, 100% { opacity: .2; }
  45% { opacity: .3; }
  55% { opacity: .25; }
  100% { opacity: .2; }
}
/* 2026-10-26 — the Skull Island vector's own slow motion: Kong breathes, the flyer hovers on its
   dive line. Small amplitudes on purpose: this is a background, not a clip. */
@keyframes sc-hover {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
.sc-steam { animation: sc-steam 11s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.sc-snow { animation: sc-snow linear infinite; transform-box: fill-box; }
.sc-contrail { animation: sc-contrail 14s linear infinite; }
.sc-flicker { animation: sc-flicker 5.5s ease-in-out infinite; }
.sc-drift { animation: sc-drift 16s ease-in-out infinite; transform-box: fill-box; transform-origin: center; will-change: transform; }
.sc-mote { animation: sc-mote 9s ease-in-out infinite; transform-box: fill-box; }
.sc-soft { animation: sc-soft 6s ease-in-out infinite; }
.sc-rain { animation: sc-rain .9s linear infinite; }
.sc-sky-light { animation: sc-sky-light 13s ease-in-out infinite; }
.sc-glow-pulse { animation: sc-glow-pulse 9s ease-in-out infinite; }
.sc-rain-light { animation: sc-rain-light 11s ease-in-out infinite; }
.sc-hover { animation: sc-hover 9s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }

@media (prefers-reduced-motion: reduce) {
  .sc-steam, .sc-snow, .sc-contrail, .sc-flicker, .sc-drift, .sc-mote, .sc-soft, .sc-rain,
  .sc-sky-light, .sc-glow-pulse, .sc-rain-light, .sc-hover {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   LOOP MODE (?loop) — for recording a seamless clip of the animated scene.
   Every duration below divides the twelve-second capture cycle (12s, 6s, or
   one of its tenths), so the pose at t=12s is identical to the pose at t=0s and
   the GIF loops without a visible jump. This is capture infrastructure only;
   a normal visitor never receives the class.
   --------------------------------------------------------------------------- */
html.scene-loop .sc-sky-light,
html.scene-loop .sc-glow-pulse,
html.scene-loop .sc-rain-light,
html.scene-loop .sc-drift,
html.scene-loop .sc-hover,
html.scene-loop .sc-steam,
html.scene-loop .sc-soft,
html.scene-loop .sc-flicker,
html.scene-loop .sc-snow,
html.scene-loop .sc-contrail {
  animation-duration: 12s !important;
}
html.scene-loop .sc-mote {
  animation-duration: 6s !important;
}
html.scene-loop .sc-rain {
  animation-duration: 1.2s !important;
}


/* ---------------------------------------------------------------------------
   2026-10-26 — THE POINTER LIGHT FIELD. The scene is a night street, so the
   cursor becomes a practical light: a warm lamp with a cool trailing halo that
   follows the pointer, a slow parallax on the drawing underneath, and a pulse
   of light on click. background.js owns the geometry; this only styles it.
   Loop mode (?loop) and prefers-reduced-motion never create these elements.
   --------------------------------------------------------------------------- */
#site-lights {
  position: fixed;
  inset: 0;
  z-index: 2147482001;
  overflow: hidden;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: .26;
}
#site-bg .bg-light,
#site-bg .bg-trail {
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50%;
  pointer-events: none;
  will-change: transform;
}
#site-bg .bg-light {
  width: 72vmax;
  height: 72vmax;
  background: radial-gradient(circle at 50% 50%,
    rgba(255, 200, 140, .30) 0%,
    rgba(255, 140, 96, .16) 24%,
    rgba(255, 70, 150, .08) 40%,
    rgba(0, 0, 0, 0) 62%);
  mix-blend-mode: screen;
  filter: blur(6px);
  opacity: .95;
}
#site-bg .bg-trail {
  width: 46vmax;
  height: 46vmax;
  background: radial-gradient(circle at 50% 50%,
    rgba(120, 205, 255, .20) 0%,
    rgba(90, 140, 255, .10) 30%,
    rgba(0, 0, 0, 0) 62%);
  mix-blend-mode: screen;
  filter: blur(10px);
  opacity: .85;
}
#site-bg .bg-pulse {
  position: absolute;
  left: 0;
  top: 0;
  width: 12px;
  height: 12px;
  border: 2px solid rgba(255, 214, 166, .95);
  border-radius: 50%;
  box-shadow: 0 0 26px 6px rgba(255, 170, 110, .5);
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: bg-pulse 900ms cubic-bezier(.2, .7, .3, 1) forwards;
}
/* THE PRODUCT IS THE HIGHLIGHT. Every scene-backed page puts its product in .card panels: give
   them a solid, calm surface and real depth, so they read above the picture instead of floating in
   it. Pages that style their own cards keep their colours, borders and layout; this only supplies
   the separation a busy background makes necessary. */
.card {
  background: rgba(9, 13, 17, .9) !important;
  border-color: rgba(255, 255, 255, .12) !important;
  box-shadow: 0 16px 44px rgba(0, 0, 0, .45), 0 1px 0 rgba(255, 255, 255, .04) inset !important;
  backdrop-filter: blur(2px);
}
.card h2, .card h3 {
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}
.card button.primary, .card a.primary {
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}

@keyframes bg-pulse {
  0% { width: 12px; height: 12px; opacity: .95; border-width: 3px; }
  100% { width: 340px; height: 340px; opacity: 0; border-width: 1px; }
}
@media (prefers-reduced-motion: reduce) {
  #site-bg .bg-light, #site-bg .bg-trail, #site-bg .bg-pulse { display: none; }
}
