/* ==========================================================================
   Ambient page backgrounds. Component styles for js/ambient-bg.js.
   Source of truth for motion, timing, and opacity: the two demos in
   design-refs/ (ping_link_concepts.html, bespoke_gap_backgrounds.html).
   Values here are ported, not invented, with one deliberate
   substitution forced by the sitewide transform/opacity motion rule:
   the demo ping ring is a box-shadow spread; here it is a scaled
   ::after ring (same size, same timing, compositor-only). The demos’
   coordinate-grid background is deliberately not shipped here (removed
   2026-07-11, Raven).
   Colors ride two RGB triplets set inline on the layer by the JS:
   --ambient-rgb (from --color-accent) and --ambient-bg-rgb (from
   --color-bg), refreshed on theme flips. All alpha values match the
   demos exactly; nothing renders brighter than the reference.
   ========================================================================== */

[data-ambient] {
  position: relative;
  /* New stacking context without touching z-index, so the layer can sit
     at z -1: above the background of this wrapper, below the background
     and text of every in-flow descendant. Sections with opaque
     backgrounds cover it; the effects read through the gaps. isolation
     scopes that z-index locally even though the layer itself is
     position:fixed (fixed escapes ancestors for POSITIONING, not for
     the stacking context an isolated ancestor establishes). */
  isolation: isolate;
}

.ambient-layer {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: -1;
  pointer-events: none;
  contain: layout paint;
}

.ambient-layer svg.ambient-fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ---- Reduced-motion fallback for the field variants (ping,
   triangulation, waypoint): a handful of static field marks scattered
   across the full container height, so the layer is never empty now
   that those variants have no persistent grid to fall back on. ---- */

.ambient-static-mark {
  position: absolute;
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: rgba(var(--ambient-rgb), 0.32);
}

/* ---- Shared: ping (3.2s pulse, dot + expanding ring) ---- */

.ambient-ping {
  position: absolute;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: rgba(var(--ambient-rgb), 1);
  animation: ambientPingDot var(--ap-dur, 3.2s) ease-out forwards;
}

.ambient-ping::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid rgba(var(--ambient-rgb), 0.5);
  animation: ambientPingRing var(--ap-dur, 3.2s) ease-out forwards;
}

@keyframes ambientPingDot {
  0%   { opacity: 0.9; transform: scale(0.6); }
  70%  { opacity: 0.35; }
  100% { opacity: 0; transform: scale(1); }
}

/* Demo end state: shadow spread 26px around a 6px dot, faded to zero.
   Ring scale 9.5 lands the same outer diameter. */
@keyframes ambientPingRing {
  0%   { opacity: 0.5; transform: scale(1); }
  100% { opacity: 0; transform: scale(9.5); }
}

/* ---- Orbit (UAS): dashed rings, two counter-rotating arms ---- */

.ambient-orbit {
  position: absolute;
  width: 0;
  height: 0;
}

.ambient-orbit__ring {
  position: absolute;
  border: 1px dashed rgba(var(--ambient-rgb), 0.10);
  border-radius: 50%;
}

.ambient-orbit__ring--r1 {
  width: 180px;
  height: 180px;
  margin: -90px 0 0 -90px;
}

.ambient-orbit__ring--r2 {
  width: 300px;
  height: 300px;
  margin: -150px 0 0 -150px;
  border-color: rgba(var(--ambient-rgb), 0.055);
}

.ambient-orbit__arm {
  position: absolute;
  width: 0;
  height: 0;
  animation: ambientSpin var(--ao-d1, 34s) linear infinite;
}

.ambient-orbit__arm--a2 {
  animation-duration: var(--ao-d2, 76s);
  animation-direction: reverse;
}

.ambient-orbit__dot {
  position: absolute;
  left: 90px;
  top: 0;
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: rgba(var(--ambient-rgb), 0.65);
}

.ambient-orbit__arm--a2 .ambient-orbit__dot {
  left: 150px;
  background: rgba(var(--ambient-rgb), 0.30);
}

@keyframes ambientSpin {
  to { transform: rotate(360deg); }
}

/* ---- Shared point of interest (orbit and arc hubs) ---- */

.ambient-poi {
  position: absolute;
  width: 5px;
  height: 5px;
  margin: -2.5px 0 0 -2.5px;
  border-radius: 50%;
  background: rgba(var(--ambient-rgb), 0.55);
}

.ambient-poi::after {
  content: "";
  position: absolute;
  inset: -6px;
  border: 1px solid rgba(var(--ambient-rgb), 0.18);
  border-radius: 50%;
}

/* ---- Coverage arc (close protection): two rotating sweep arcs ---- */

.ambient-arc {
  position: absolute;
  width: 0;
  height: 0;
}

.ambient-arc__spin {
  position: absolute;
  animation: ambientSpin var(--aa-d, 42s) linear infinite;
}

.ambient-arc__spin--rev {
  animation-direction: reverse;
}

.ambient-arc__svg {
  position: absolute;
  left: -130px;
  top: -130px;
  width: 260px;
  height: 260px;
  overflow: visible;
}

/* ---- Subject profile: canvas fills the fixed layer exactly ---- */

.ambient-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ---- Optional contrast scrim (off by default; data-ambient-scrim) ---- */

.ambient-scrim {
  position: absolute;
  inset: 0;
  background: rgba(var(--ambient-bg-rgb), 0.45);
}

/* ---- Pause hook (document hidden, or the page scrolled far enough
   that this section’s wrapper is entirely out of view) ---- */

.ambient-layer.is-paused *,
.ambient-layer .is-paused * {
  animation-play-state: paused !important;
}

/* ---- Reduced motion: each variant holds its meaningful static frame.
   Ping, triangulation, and waypoint fall back to the static field marks
   above; constellation keeps the city map; probe keeps the boundary;
   transit keeps the channel and endpoints; orbit and arc hold their
   geometry still. Transient spawns and traveling marks never appear;
   the JS renders recovery assembled and draws one settled canvas
   frame. ---- */

@media (prefers-reduced-motion: reduce) {
  .ambient-ping {
    display: none;
  }
  .ambient-anim {
    display: none !important;
  }
  .ambient-orbit__arm,
  .ambient-arc__spin {
    animation: none;
  }
}
