/* ============================================================
   ambient.css — Dynamic Ambient Background
   ------------------------------------------------------------
   A self-contained background module. It owns:

     · the ambient palette custom properties
     · the 9-region spatial gradient backdrop
     · the blurred artwork layer + darkening veil
     · the film grain overlay

   It only ever WRITES the --amb-* variables. Other stylesheets
   may read them (with a fallback) without knowing this file
   exists, so the module can be removed without breaking them.
   ============================================================ */

:root {
  /* nine spatial regions + one base wash — all r,g,b triplets */
  --amb-tl: 32, 32, 36;
  --amb-tc: 32, 32, 36;
  --amb-tr: 32, 32, 36;
  --amb-ml: 32, 32, 36;
  --amb-c: 32, 32, 36;
  --amb-mr: 32, 32, 36;
  --amb-bl: 32, 32, 36;
  --amb-bc: 32, 32, 36;
  --amb-br: 32, 32, 36;
  --amb-base: 10, 10, 10;
}

/* ---------- the backdrop ----------
   Each radial-gradient lights one region of the stage, so the
   environment reacts spatially instead of showing a flat tint. */

.ambient {
  position: absolute;
  inset: -12%;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(ellipse 45% 40% at 0%    0%,   rgba(var(--amb-tl), 1), transparent 72%),
    radial-gradient(ellipse 45% 40% at 50%   0%,   rgba(var(--amb-tc), 1), transparent 72%),
    radial-gradient(ellipse 45% 40% at 100%  0%,   rgba(var(--amb-tr), 1), transparent 72%),
    radial-gradient(ellipse 50% 45% at 0%    50%,  rgba(var(--amb-ml), 1), transparent 75%),
    radial-gradient(ellipse 55% 55% at 50%   50%,  rgba(var(--amb-c),  1), transparent 78%),
    radial-gradient(ellipse 50% 45% at 100%  50%,  rgba(var(--amb-mr), 1), transparent 75%),
    radial-gradient(ellipse 45% 40% at 0%    100%, rgba(var(--amb-bl), 1), transparent 72%),
    radial-gradient(ellipse 45% 40% at 50%   100%, rgba(var(--amb-bc), 1), transparent 72%),
    radial-gradient(ellipse 45% 40% at 100%  100%, rgba(var(--amb-br), 1), transparent 72%),
    linear-gradient(135deg, rgb(var(--amb-base)), #050505);
  /* no filter here on purpose: the backdrop is repainted on every ambient
     update, and a full-screen filter would double that cost. The saturation
     boost is baked into the colours by ambient.js instead. */
}

/* heavily blurred copy of the artwork — the coarse half of the light.
   Two layers are crossfaded by ambient.js. */
.ambient-img {
  position: absolute;
  inset: -10%;
  width: 120%; height: 120%;
  object-fit: cover;
  opacity: 0;
  filter: blur(90px) saturate(1.35) brightness(0.62);
  transform: scale(1.08);
  transition: opacity 1.1s ease;
  will-change: opacity;
}

.ambient-img.on { opacity: 0.38; }

/* keeps the centre readable and pushes the edges back into darkness */
.ambient-veil {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse at center,
    transparent 12%,
    rgba(0, 0, 0, 0.32) 45%,
    rgba(5, 5, 6, 0.88) 100%
  );
}

/* ---------- film grain ----------
   Sits above the stage content so the whole frame shares one texture.
   No mix-blend-mode: blending has to re-read the (constantly animating)
   backdrop every frame. Plain low-opacity grain is visually equivalent
   here but stays on the fast compositing path. */

.noise {
  position: absolute;
  inset: 0;
  z-index: 400;
  pointer-events: none;
  opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.8'/%3E%3C/svg%3E");
}
