/* THE VISUALISER — see viz.js. Two states and one of them is the background.

   Matt, 2026-10-07: "enable it as a background when the track starts playing
   with the UI as an overlay." So the canvas is fixed behind the whole page at
   z-index -1, which puts it above the body's own background and below every
   bit of content without a single z-index needing to change in the host. The
   interface then floats: whatever the host hangs off body.viz-live. */
.vizbg {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0; transition: opacity .9s ease; overflow: hidden;
}
.vizbg canvas { width: 100%; height: 100%; display: block; }
/* The top sixth is where a header and a title live on both surfaces. Fading
   the field out up there keeps type on near-flat ground and leaves the bloom
   down where the transport is. Both spellings: iOS wants the prefix. */
.vizbg canvas {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,.35) 15%, #000 46%);
          mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,.35) 15%, #000 46%);
}

/* ---- full bleed, the UI out of the way ---- */
body.viz-full { overflow: hidden; }
body.viz-full .vizbg {
  z-index: 90; pointer-events: auto; background: #06020c;   /* viz.js overrides on a light peel */
}
body.viz-full .vizbg canvas { -webkit-mask-image: none; mask-image: none; }
.viz-cap {
  position: fixed; left: 0; right: 0; bottom: 7vh; z-index: 91; display: none;
  text-align: center; pointer-events: none; text-shadow: 0 2px 18px #000;
  color: #f4eeff;
}
body.viz-full .viz-cap { display: block; }
/* On a light peel full screen is a bright room, so the caption has to stop
   being white type with a black shadow. */
body.viz-pale .viz-cap { color: #2a0f1e; text-shadow: 0 2px 18px rgba(255,255,255,.9); }
body.viz-pale .viz-cap i, body.viz-pale .viz-cap .viz-off { color: #7a4a63; }
body.viz-pale .viz-cap .viz-off {
  background: rgba(0, 0, 0, .05); border-color: rgba(0, 0, 0, .14);
}
.viz-cap b { display: block; font-size: 24px; font-weight: 800; }
.viz-cap span { display: block; color: var(--tint, var(--banana)); font-weight: 700; margin-top: 2px; }
.viz-cap i {
  display: block; color: #a99cc6; font-style: normal;
  font-size: 12px; margin-top: 14px; letter-spacing: .1em; text-transform: uppercase;
}
/* The way back out of a thing that reroutes your audio has to be in the thing
   itself, not in a settings screen that does not exist. */
.viz-cap .viz-off {
  pointer-events: auto; margin-top: 16px; font: inherit; font-size: 12.5px;
  color: #a99cc6; background: rgba(255, 255, 255, .06); cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 99px; padding: 8px 15px;
}

/* ---- the one failure this thing can cause, and the one tap that fixes it ----
   A suspended AudioContext between the element and the speakers is silence
   with no error anywhere. The watchdog in viz.js puts this up after six
   seconds of it, because a tap is exactly what iOS wants in order to resume
   and a tap is what a person does when they notice the music has stopped. */
.viz-stuck {
  position: fixed; left: 12px; right: 12px; bottom: 16px; z-index: 120;
  padding: 13px 16px; border-radius: 16px; text-align: center; cursor: pointer;
  background: rgba(20, 8, 32, .94); border: 1px solid rgba(255, 79, 216, .5);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .6); color: #f4eeff;
}
.viz-stuck[hidden] { display: none; }
.viz-stuck b { display: block; font-size: 15px; font-weight: 800; }
.viz-stuck span { display: block; font-size: 12.5px; color: #a99cc6; margin-top: 3px; }

/* A feedback field is the one effect that has no quiet version -- the whole
   image moves, every frame. So it does not run at all here. */
@media (prefers-reduced-motion: reduce) { .vizbg, .viz-cap { display: none; } }
