/* THE VIBE TIMES — the ambient-life layer's own sheet (wren-drift
 * BP-2026-08-18-505).
 *
 * THE PROPERTY LINT (chartroom/research/ambient-animation-craft.md):
 * every @keyframes block in this file animates transform and opacity
 * ONLY. Those composite on the GPU; top/left/width/background-position
 * force layout or paint on every frame and jank the room. Position and
 * size are set ONCE via inline style (bake-time coordinates from
 * ambient_spec.yaml) and never animated.
 *
 * THE DP-NIGHT SLOT (P4): a night plate is a sibling layer stacked on the
 * day plate, shown only under html[data-edition-state="night"] — an
 * inline style can't lose to a plain CSS rule here (no !important fight)
 * because the day plate's own background-image lives on a DIFFERENT
 * element (decks.py's #plate-<id>), never touched.
 */

.amb-loop, .amb-window-scenery, .amb-scenery-layer, .dp-night {
  position: absolute; background-size: contain; background-repeat: no-repeat;
  background-position: center; pointer-events: none;
}

.amb-loop {
  height: 10%; animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animation-name: ambLoopSway;
  will-change: transform;
}
.amb-loud { animation-name: ambLoopSwayLoud; }
.amb-quiet { animation-name: ambLoopSway; opacity: .82; }

/* the fan/steam idiom: a gentle rotate+drift, transform-only — no two
   elements on a floor share this animation-duration (ambient_spec.yaml's
   own desync-law-checked periods drive it via inline animation-duration/
   animation-delay). */
@keyframes ambLoopSway {
  0%   { transform: translateY(0) rotate(0deg); }
  50%  { transform: translateY(-2%) rotate(3deg); }
  100% { transform: translateY(0) rotate(0deg); }
}
@keyframes ambLoopSwayLoud {
  0%   { transform: translateY(0) rotate(0deg) scale(1); }
  50%  { transform: translateY(-4%) rotate(8deg) scale(1.03); }
  100% { transform: translateY(0) rotate(0deg) scale(1); }
}

/* the probabilistic prop (ambient.js's own domain): quiet at rest, one
   beat brighter while .is-active — opacity only. */
.amb-probabilistic { opacity: .7; transition: opacity .25s ease; }
.amb-probabilistic.is-active { opacity: 1; }

/* the window's scenery crossfade — a shared @keyframes
   (ambient_content._scenery_keyframes, bake-time-generated per floor
   because the layer count varies) plays on every .amb-scenery-layer with
   its own animation-delay; opacity only. */
.amb-window { position: absolute; overflow: hidden; pointer-events: none; }
/* a FULL-PLATE window (2026-09-05): each image is a whole-plate canvas with
   alpha outside the panes, so the layer wears the deck plate's own cover /
   center rule and registers with it at every viewport by construction */
.amb-window-full .amb-scenery-layer { background-size: cover; background-position: center; }
.amb-scenery-layer {
  inset: 0; width: 100%; height: 100%;
  animation-name: ambSceneryCycle; animation-iteration-count: infinite;
  animation-timing-function: linear;
  /* per-layer data from the bake (marten-port law: custom props, not
     inline presentation) — duration/delay/image vary by layer count. */
  animation-duration: var(--dur); animation-delay: var(--delay);
  background-image: var(--img);
}

/* THE NIGHT PLATE SLOT — inset:0, full box, dark by default (display:none
   until the viewer's own clock says night; owl-dim's client-side law). */
.dp-night { inset: 0; width: 100%; height: 100%; z-index: 0; display: none; }
html[data-edition-state="night"] .dp-night { display: block; }

/* THE REDUCED-MOTION KILL — the layer must vanish entirely for a motion-
   sensitive visitor, not just stop animating: display:none removes it
   from paint, animation:none stops any timeline still attached. */
@media (prefers-reduced-motion: reduce) {
  .amb-loop, .amb-window, .amb-scenery-layer {
    animation: none !important;
    display: none !important;
  }
}
