/* ambient.css: the night table behind a page (js/ambient.js). Self-contained: no rule here reads anything but its own
   custom properties, so another site can load this file and ambient.js as they are.
   Colours: set --amb-ground, --amb-pool-a, --amb-pool-b, --amb-warm, --amb-mote on :root to retheme (defaults: SPAM Meta).
   Motion: the paint flows inside its own canvas (a fragment shader, nothing on the page moves for it); the dust takes a
   few px of pointer parallax (transform); the scroll depth is a CSS scroll timeline (compositor-driven, only while
   scrolling). Reduced motion: a still picture. */

:root {
  --amb-ground: #15122c;                         /* the page ground the field sits on (Night Indigo) */
  --amb-pool-a: rgba(42, 36, 82, .9);            /* lifted pool, top left (Panel Lifted) */
  --amb-pool-b: rgba(59, 52, 112, .5);           /* cool pools, bottom right and low left (Line Indigo) */
  --amb-warm: rgba(240, 202, 155, .07);          /* one faint warm lamp (the S+ apricot), never a colour wash */
  --amb-mote: rgba(245, 242, 255, .5);           /* dust motes (Cream Lavender), each dot at its own low opacity */
}

/* the page ground shows through: the script adds .amb-on to <html>, which keeps the ground colour */
html.amb-on { background-color: var(--amb-ground); }
html.amb-on body { background-color: transparent; }

.amb { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; contain: strict; background: var(--amb-ground); }
/* two depths (pools and paint far, dust nearer), two nested layers each: .amb-l takes the pointer parallax (script, the
   dust only), .amb-s the scroll depth (CSS). 6% of slack around the screen covers both. */
.amb-l { position: absolute; inset: -6%; }
.amb-mid { will-change: transform; }
.amb-s { position: absolute; inset: 0; }

/* far: the light pools (a lamp over a dark table), wide enough to dress the whole screen at every scroll position: a lifted
   pool top left, a cool one bottom right, a fainter cool one low on the left, and the faint warm lamp top right */
.amb-far .amb-s {
  background:
    radial-gradient(58% 52% at 16% 10%, var(--amb-pool-a), transparent 72%),
    radial-gradient(60% 56% at 88% 90%, var(--amb-pool-b), transparent 70%),
    radial-gradient(44% 40% at 8% 78%, var(--amb-pool-b), transparent 72%),
    radial-gradient(38% 34% at 80% 24%, var(--amb-warm), transparent 72%);
}
/* far, over the pools: the painted corners. Live, one canvas over the whole layer, drawn by the script's shader (washes
   and dry-brush sweeps gathered in two corners, gone before the middle of the screen, their lightness capped so Dusk
   Lavender text keeps 5:1 on the brightest paint). */
.amb-flow { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* where it cannot be drawn live: the same painting, baked once by tools/make_ambient.py, held still */
.amb-paint { position: absolute; width: min(64vmax, 110vw, 1100px); aspect-ratio: 1; background: 0 0 / 100% 100% no-repeat; }
/* anchored on the screen's corners, inside the layer's 6% of slack (6 / 112 of its size), as the live paint is */
.amb-paint-tl { left: calc(600% / 112); top: calc(600% / 112); background-image: url("../assets/ambient/paint-tl.webp"); }
.amb-paint-br { right: calc(600% / 112); bottom: calc(600% / 112); background-image: url("../assets/ambient/paint-br.webp"); }
/* mid: dust motes, an inline SVG drawn once by the script */
.amb-s svg { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--amb-mote); }

/* depth on scroll: the dust travels further than the pools and paint (Chromium and Safari; elsewhere the layers stay put) */
@supports (animation-timeline: scroll()) {
  .amb-s { will-change: transform; animation: amb-scroll-far linear both; animation-timeline: scroll(root block); }
  .amb-mid .amb-s { animation-name: amb-scroll-mid; }
  @keyframes amb-scroll-far { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, -2%, 0); } }
  @keyframes amb-scroll-mid { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, -5%, 0); } }
}

/* still: reduced motion, or the page asked for it. The field stays as a still picture (the script holds the paint on one
   frame); nothing follows or scrolls. */
.amb.amb-still .amb-s { animation: none; }
.amb.amb-still .amb-l, .amb.amb-still .amb-s { will-change: auto; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .amb .amb-s { animation: none !important; }
  .amb .amb-l, .amb .amb-s { will-change: auto; transform: none !important; }
}
