/* stage.css — the themed tier's pinned set-piece, ranks 11-25.
 *
 * The bespoke levels each ship a hand-written stylesheet for their
 * set-piece. This one sheet serves all fifteen themed levels, so it may not
 * name a single colour: everything is mixed from the level's own palette
 * tokens (--field --ink --muted --accent --accent2), which build.py has
 * already written into :root before this file is parsed.
 *
 * The scattered pieces carry their geometry in a style attribute written by
 * tools/gen_setpiece.py. That split is deliberate — this file owns what a
 * layer looks like, the generator owns where its pieces are — and it is the
 * only reason fifteen distinct compositions fit in one stylesheet.
 *
 * Class names are prefixed .stage / .ig__ / .orb__ and so on rather than the
 * bespoke tier's .sig--ignite / .ignite__core. They style entirely separate
 * markup and must never collide: solar-flare.css defines .sig--ignite and
 * loads after this file.
 */

/* Shell ------------------------------------------------------------------ */

.stage {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-content: center;
  overflow: hidden;
  isolation: isolate;
  border-top: var(--rule) solid var(--rule-colour);
  background:
    radial-gradient(
      ellipse 78% 66% at 50% 44%,
      color-mix(in srgb, var(--accent) 13%, var(--field)) 0%,
      var(--field) 74%
    );
}

/* A wash of the second accent, offset from the first, so the frame is never
   one flat hue behind the subject. */
.stage__wash {
  position: absolute;
  inset: -10%;
  z-index: 0;
  background:
    radial-gradient(
      ellipse 46% 40% at 22% 26%,
      color-mix(in srgb, var(--accent2) 26%, transparent) 0%,
      transparent 70%
    ),
    radial-gradient(
      ellipse 40% 46% at 82% 74%,
      color-mix(in srgb, var(--accent) 20%, transparent) 0%,
      transparent 70%
    );
  filter: blur(40px);
  pointer-events: none;
}

/* Corners down, so the copy always sits on the darkest part of the frame. */
.stage__vig {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse 74% 62% at 50% 46%,
      transparent 52%,
      color-mix(in srgb, var(--field) 82%, transparent) 100%
    ),
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--field) 55%, transparent) 0%,
      transparent 22%,
      transparent 74%,
      var(--field) 100%
    );
}

/* Only the copy is a grid item. That is load-bearing twice over.
   .ig__rays is 160vmax square, and as a grid item it sized the row and made
   the stage sixteen screens tall. And an absolutely positioned child WITH a
   definite grid position takes the grid area as its containing block -- the
   row, which align-content centres inside the taller stage -- so every
   centred layer sat about a hundred pixels low. With no grid position they
   fall back to the padding box of .stage, which is the frame itself. */
.stage__copy {
  grid-area: 1 / 1;
  position: relative;
  z-index: 5;
  align-self: center;
  width: 100%;
}

.stage__eyebrow {
  color: color-mix(in srgb, var(--accent) 50%, var(--ink));
  margin-bottom: var(--space-4);
}

.stage__line {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 9vw, 7.5rem);
  font-weight: 900;
  line-height: 0.92;
  letter-spacing: -0.04em;
  margin: 0 0 var(--space-6);
  text-wrap: balance;
  color: var(--ink);
  /* The stages are bright in the middle by design. A soft plate in the
     field colour keeps the headline off the artwork without reading as a
     box drawn behind it. */
  text-shadow:
    0 0 2.2rem color-mix(in srgb, var(--field) 92%, transparent),
    0 0 5rem color-mix(in srgb, var(--field) 78%, transparent),
    0 0 0.4rem color-mix(in srgb, var(--field) 60%, transparent);
}

.stage__sub {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.72;
  color: color-mix(in srgb, var(--ink) 82%, var(--muted));
  margin: 0;
  text-shadow: 0 0 1.4rem color-mix(in srgb, var(--field) 88%, transparent);
}

/* Shared particles ------------------------------------------------------- */

.stage__speck {
  position: absolute;
  z-index: 3;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
}

.stage__speck--rise {
  animation: stage-rise var(--dur, 5s) linear infinite;
  animation-delay: var(--delay, 0s);
}

.stage__speck--twinkle {
  background: var(--ink);
  animation: stage-twinkle var(--dur, 4s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

.stage__speck--blow {
  background: var(--ink);
  animation: stage-blow var(--dur, 4s) linear infinite;
  animation-delay: var(--delay, 0s);
}

@keyframes stage-rise {
  from { transform: translateY(0) scale(1); opacity: 0; }
  18%  { opacity: 1; }
  to   { transform: translateY(-42vh) scale(0.4); opacity: 0; }
}

@keyframes stage-twinkle {
  from { opacity: 0.12; transform: scale(0.7); }
  to   { opacity: 1; transform: scale(1.25); }
}

@keyframes stage-blow {
  from { transform: translate3d(-14vw, 0, 0); opacity: 0; }
  20%  { opacity: 1; }
  to   { transform: translate3d(96vw, -12vh, 0); opacity: 0; }
}

/* ignite — Idols, Firework ----------------------------------------------- */

.ig__core {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(38vmin, 22rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 2;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--ink) 92%, var(--accent)) 0%,
    var(--accent) 34%,
    var(--accent2) 68%,
    color-mix(in srgb, var(--accent2) 30%, var(--field)) 100%
  );
  filter: blur(1px);
  box-shadow: 0 0 14vmin color-mix(in srgb, var(--accent) 55%, transparent);
}

.ig__halo {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(96vmin, 62rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 1;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--accent) 34%, transparent) 0%,
    transparent 62%
  );
}

/* Stretched rather than sized. Every other centred layer is in vmin, so it
   always fits its frame and `margin: auto` centres it; the rays have to
   overrun the frame to reach the corners, and an auto margin that would have
   to go negative resolves to zero instead -- which left them left-aligned.
   A negative inset centres by construction at any size. */
.ig__rays {
  position: absolute;
  inset: -42%;
  z-index: 1;
  background: repeating-conic-gradient(
    from 0deg,
    color-mix(in srgb, var(--accent) 30%, transparent) 0deg 4deg,
    transparent 4deg 13deg
  );
  mask-image: radial-gradient(circle, #000 8%, transparent 56%);
  -webkit-mask-image: radial-gradient(circle, #000 8%, transparent 56%);
}

.ig__cog {
  position: absolute;
  z-index: 2;
  border-radius: 50%;
  border: 0.5vmin dashed color-mix(in srgb, var(--accent2) 62%, transparent);
  opacity: 0.5;
}

.ig__cog::before {
  content: "";
  position: absolute;
  inset: 22%;
  border-radius: 50%;
  border: 0.35vmin solid color-mix(in srgb, var(--accent) 55%, transparent);
}

.ig__lick {
  position: absolute;
  bottom: -6vmin;
  z-index: 2;
  width: 0.5vmin;
  border-radius: 50% 50% 20% 20%;
  background: linear-gradient(
    to top,
    var(--accent) 0%,
    color-mix(in srgb, var(--accent2) 70%, transparent) 55%,
    transparent 100%
  );
  filter: blur(2px);
  animation: ig-lick var(--dur, 4s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

@keyframes ig-lick {
  from { transform: scaleY(0.6) translateX(0); opacity: 0.35; }
  to   { transform: scaleY(1.15) translateX(1.5vmin); opacity: 0.9; }
}

/* ascend — Aerial Gleam --------------------------------------------------- */
/* descend's mirror. Its ridges sit low and get pushed further down by the
   timeline, so the frame reads as the ground leaving rather than the walls
   rushing up. */

.as__sky {
  position: absolute;
  inset: -20% 0 0 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent) 34%, var(--field)) 0%,
    color-mix(in srgb, var(--accent2) 16%, var(--field)) 46%,
    var(--field) 100%
  );
}

.as__ridge {
  position: absolute;
  left: -6%;
  right: -6%;
  z-index: 2;
  background: var(--field);
  clip-path: polygon(
    0% 100%, 0% 42%, 9% 18%, 18% 46%, 27% 12%, 37% 40%, 46% 6%,
    56% 38%, 65% 14%, 74% 44%, 83% 20%, 92% 48%, 100% 26%, 100% 100%
  );
}

.as__ridge--far  { opacity: 0.34; }
.as__ridge--mid  { opacity: 0.6; }
.as__ridge--near { opacity: 0.9; }

.as__cloud {
  position: absolute;
  z-index: 3;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 45%, transparent);
  filter: blur(14px);
  animation: as-drift var(--dur, 14s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

@keyframes as-drift {
  from { transform: translateX(-6vmin); }
  to   { transform: translateX(6vmin); }
}

.as__shaft {
  position: absolute;
  top: -10%;
  height: 80%;
  z-index: 2;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--ink) 30%, transparent) 0%,
    transparent 100%
  );
  filter: blur(6px);
  animation: as-shaft var(--dur, 9s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

@keyframes as-shaft {
  from { opacity: 0.2; transform: scaleX(0.7); }
  to   { opacity: 0.7; transform: scaleX(1.2); }
}

/* orbit — Zodiac, Andromeda ---------------------------------------------- */

.orb__void {
  position: absolute;
  inset: -20%;
  z-index: 0;
  background: radial-gradient(
    ellipse at 50% 42%,
    color-mix(in srgb, var(--accent2) 22%, transparent) 0%,
    transparent 62%
  );
}

.orb__ring {
  position: absolute;
  inset: 0;
  margin: auto;
  border-radius: 50%;
  z-index: 2;
  border: 0.28vmin solid color-mix(in srgb, var(--accent) 70%, transparent);
  transform: rotateX(72deg) rotateZ(var(--tilt, 0deg));
  animation: orb-spin var(--spin, 50s) linear infinite;
}

.orb__ring::after {
  content: "";
  position: absolute;
  inset: -1.5%;
  border-radius: 50%;
  border-top: 0.5vmin solid color-mix(in srgb, var(--accent2) 85%, transparent);
  border-right: 0.2vmin solid transparent;
  border-bottom: 0.2vmin solid transparent;
  border-left: 0.2vmin solid transparent;
}

@keyframes orb-spin {
  from { transform: rotateX(72deg) rotateZ(var(--tilt, 0deg)); }
  to   { transform: rotateX(72deg) rotateZ(calc(var(--tilt, 0deg) + 360deg)); }
}

.orb__body {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(26vmin, 16rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 2;
  background:
    radial-gradient(
      circle at 36% 32%,
      color-mix(in srgb, var(--ink) 88%, var(--accent)) 0%,
      var(--accent) 30%,
      var(--accent2) 66%,
      color-mix(in srgb, var(--field) 78%, var(--accent2)) 100%
    );
  box-shadow:
    inset -1.5vmin -1.5vmin 5vmin color-mix(in srgb, var(--field) 80%, transparent),
    0 0 10vmin color-mix(in srgb, var(--accent) 40%, transparent);
}

.orb__moon {
  position: absolute;
  z-index: 3;
  border-radius: 50%;
  background: var(--accent2);
  box-shadow: 0 0 1.4vmin color-mix(in srgb, var(--accent2) 70%, transparent);
  animation: stage-twinkle var(--dur, 4s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

/* pulse — Bloodlust ------------------------------------------------------ */

.pl__loom {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(70vmin, 44rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 1;
  background: radial-gradient(
    circle,
    var(--accent) 0%,
    color-mix(in srgb, var(--accent) 42%, transparent) 34%,
    transparent 68%
  );
  filter: blur(6px);
}

.pl__ring {
  position: absolute;
  inset: 0;
  margin: auto;
  border-radius: 50%;
  z-index: 2;
  border: 0.4vmin solid color-mix(in srgb, var(--accent) 75%, transparent);
}

.pl__ribs {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: repeating-conic-gradient(
    from 12deg at 50% 50%,
    color-mix(in srgb, var(--accent2) 22%, transparent) 0deg 2deg,
    transparent 2deg 22deg
  );
  mask-image: radial-gradient(circle, transparent 18%, #000 40%, transparent 76%);
  -webkit-mask-image: radial-gradient(circle, transparent 18%, #000 40%, transparent 76%);
}

.pl__drip {
  position: absolute;
  top: 0;
  z-index: 3;
  width: 0.4vmin;
  border-radius: 0 0 60% 60%;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    color-mix(in srgb, var(--accent) 80%, transparent) 70%,
    var(--accent) 100%
  );
  animation: pl-drip var(--dur, 6s) ease-in infinite;
  animation-delay: var(--delay, 0s);
}

@keyframes pl-drip {
  from { transform: translateY(-100%); opacity: 0; }
  25%  { opacity: 0.9; }
  to   { transform: translateY(120vh); opacity: 0; }
}

/* fracture — Titan Complex ----------------------------------------------- */

.fr__field {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.fr__shard {
  position: absolute;
  background: linear-gradient(
    148deg,
    color-mix(in srgb, var(--accent) 62%, transparent) 0%,
    color-mix(in srgb, var(--accent2) 26%, transparent) 52%,
    transparent 100%
  );
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  clip-path: polygon(12% 0%, 100% 8%, 88% 100%, 0% 82%);
}

.fr__crack {
  position: absolute;
  width: 2px;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    color-mix(in srgb, var(--ink) 70%, transparent) 30%,
    color-mix(in srgb, var(--ink) 70%, transparent) 70%,
    transparent 100%
  );
  opacity: 0.35;
}

/* descend — Maniacal Chains ---------------------------------------------- */

.ds__wall {
  position: absolute;
  inset: -30% 0 -30% 0;
  z-index: 1;
}

.ds__wall--far {
  background: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--accent) 9%, transparent) 0 3rem,
    transparent 3rem 7rem
  );
}

.ds__wall--mid {
  background:
    linear-gradient(
      90deg,
      color-mix(in srgb, var(--accent) 30%, transparent) 0%,
      transparent 22%,
      transparent 78%,
      color-mix(in srgb, var(--accent) 30%, transparent) 100%
    );
  z-index: 2;
}

.ds__wall--near {
  z-index: 3;
  background: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--accent2) 16%, transparent) 0 1.2rem,
    transparent 1.2rem 9rem
  );
}

/* A chain is a column of links: one repeating gradient, no elements. */
.ds__chain {
  position: absolute;
  z-index: 3;
  width: var(--link, 1.4vmin);
  background:
    repeating-linear-gradient(
      to bottom,
      color-mix(in srgb, var(--accent) 85%, transparent) 0 calc(var(--link, 1.4vmin) * 0.8),
      transparent calc(var(--link, 1.4vmin) * 0.8) calc(var(--link, 1.4vmin) * 1.5)
    );
  mask-image: repeating-linear-gradient(
    to bottom, #000 0 60%, transparent 60% 100%
  );
  -webkit-mask-image: repeating-linear-gradient(
    to bottom, #000 0 60%, transparent 60% 100%
  );
}

.ds__tooth {
  position: absolute;
  z-index: 3;
  aspect-ratio: 1 / 1.6;
  background: color-mix(in srgb, var(--accent2) 60%, transparent);
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}

.ds__dark {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: linear-gradient(
    180deg, transparent 0%, var(--field) 100%
  );
  opacity: 0;
}

/* surge — Edge of Destiny ------------------------------------------------ */

.sg__sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent2) 26%, var(--field)) 0%,
    var(--field) 62%
  );
}

.sg__swell {
  position: absolute;
  inset: 26% -20% -30% -20%;
  z-index: 2;
  border-radius: 50% 50% 0 0 / 30% 30% 0 0;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent) 72%, transparent) 0%,
    color-mix(in srgb, var(--accent2) 40%, transparent) 34%,
    color-mix(in srgb, var(--field) 88%, var(--accent2)) 100%
  );
  box-shadow: 0 -2vmin 8vmin color-mix(in srgb, var(--accent) 40%, transparent);
}

.sg__current {
  position: absolute;
  left: -30%;
  width: 160%;
  z-index: 3;
  border-radius: 50%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--ink) 42%, transparent) 40%,
    color-mix(in srgb, var(--ink) 42%, transparent) 60%,
    transparent 100%
  );
  filter: blur(3px);
}

.sg__foam {
  position: absolute;
  left: 0;
  bottom: 6%;
  width: 200%;
  height: 8vmin;
  z-index: 3;
  display: flex;
}

.sg__foam i {
  flex: 1;
  background: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--ink) 50%, transparent) 0 0.6vmin,
    transparent 0.6vmin 2.4vmin
  );
  mask-image: linear-gradient(180deg, #000 0%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 100%);
}

.sg__spray {
  position: absolute;
  z-index: 4;
  aspect-ratio: 1;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 60%, transparent);
  filter: blur(2px);
  animation: sg-spray var(--dur, 5s) ease-out infinite;
  animation-delay: var(--delay, 0s);
}

@keyframes sg-spray {
  from { transform: translateY(0) scale(0.3); opacity: 0; }
  30%  { opacity: 0.8; }
  to   { transform: translateY(-26vh) scale(1.4); opacity: 0; }
}

/* prism — Subsonic ------------------------------------------------------- */

.pr__lattice {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.pr__cell {
  position: absolute;
  border: 1px solid color-mix(in srgb, var(--accent) 62%, transparent);
  background: linear-gradient(
    140deg,
    color-mix(in srgb, var(--accent2) 20%, transparent) 0%,
    transparent 70%
  );
}

.pr__tri {
  position: absolute;
  width: var(--s, 4vmin);
  height: var(--s, 4vmin);
  background: color-mix(in srgb, var(--accent2) 50%, transparent);
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}

.pr__beam {
  position: absolute;
  inset: 0 auto 0 0;
  width: 34vmin;
  z-index: 3;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--accent) 30%, transparent) 45%,
    color-mix(in srgb, var(--ink) 62%, transparent) 50%,
    color-mix(in srgb, var(--accent) 30%, transparent) 55%,
    transparent 100%
  );
  filter: blur(4px);
}

.pr__scan {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--ink) 6%, transparent) 0 1px,
    transparent 1px 4px
  );
}

/* flood — Freedom08 ------------------------------------------------------ */

.fl__hall {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.fl__pillar {
  position: absolute;
  bottom: 0;
  background: linear-gradient(
    180deg,
    transparent 0%,
    color-mix(in srgb, var(--accent) 48%, transparent) 22%,
    color-mix(in srgb, var(--accent2) 60%, transparent) 100%
  );
  border-inline: 1px solid color-mix(in srgb, var(--ink) 26%, transparent);
}

.fl__pillar::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1.6vmin;
  background: color-mix(in srgb, var(--ink) 40%, transparent);
}

.fl__banner {
  position: absolute;
  z-index: 3;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent) 70%, transparent) 0%,
    color-mix(in srgb, var(--accent2) 30%, transparent) 100%
  );
  clip-path: polygon(0% 0%, 100% 0%, 100% 88%, 50% 100%, 0% 88%);
  transform-origin: top center;
  animation: fl-sway var(--dur, 6s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

@keyframes fl-sway {
  from { transform: rotate(-2.5deg) skewX(-1.5deg); }
  to   { transform: rotate(2.5deg) skewX(1.5deg); }
}

.fl__tide {
  position: absolute;
  inset: auto 0 0 0;
  height: 70%;
  z-index: 4;
  background: linear-gradient(
    180deg,
    transparent 0%,
    color-mix(in srgb, var(--accent) 26%, transparent) 40%,
    color-mix(in srgb, var(--accent2) 52%, var(--field)) 100%
  );
  transform: translateY(70%);
}

/* twin — Codependence ---------------------------------------------------- */

.tw__half {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 1;
}

.tw__half--a {
  top: 0;
  height: 52%;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--accent) 34%, var(--field)) 0%,
    var(--field) 100%
  );
}

.tw__half--b {
  bottom: 0;
  height: 52%;
  background: linear-gradient(
    0deg,
    color-mix(in srgb, var(--accent2) 34%, var(--field)) 0%,
    var(--field) 100%
  );
}

.tw__icon {
  position: absolute;
  width: var(--s, 2.4vmin);
  height: var(--s, 2.4vmin);
  z-index: 3;
  border: 0.32vmin solid currentColor;
  transform: rotate(45deg);
}

.tw__icon--up { color: var(--accent); }
.tw__icon--dn { color: var(--accent2); }

.tw__link {
  position: absolute;
  z-index: 2;
  width: 1px;
  background: repeating-linear-gradient(
    to bottom,
    color-mix(in srgb, var(--ink) 40%, transparent) 0 4px,
    transparent 4px 11px
  );
  opacity: 0.4;
}

.tw__seam {
  position: absolute;
  inset: 49.4% 0 auto 0;
  height: 1.2%;
  z-index: 4;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--ink) 24%,
    var(--ink) 76%,
    transparent 100%
  );
  opacity: 0.5;
  filter: blur(3px);
}

/* whiteout — Black Blizzard ---------------------------------------------- */
/* KrmaL used no colour at all, so this one deliberately reads from --ink
   and never touches the accents. */

.wo__funnel {
  position: absolute;
  inset: -14% 0 -6% 0;
  z-index: 2;
  transform-origin: 50% 20%;
}

.wo__turn {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  height: 1.4%;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ink) 60%, transparent);
  animation: wo-turn var(--dur, 3s) linear infinite;
  animation-delay: var(--delay, 0s);
}

@keyframes wo-turn {
  from { transform: scaleX(0.86) translateX(-2%); }
  50%  { transform: scaleX(1.1) translateX(2%); }
  to   { transform: scaleX(0.86) translateX(-2%); }
}

.wo__gust {
  position: absolute;
  height: 1px;
  z-index: 3;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--ink) 70%, transparent) 50%,
    transparent 100%
  );
}

/* overgrow — The Golden -------------------------------------------------- */

.og__vine {
  position: absolute;
  height: 0.5vmin;
  z-index: 2;
  border-radius: 1vmin;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--accent) 30%,
    color-mix(in srgb, var(--accent2) 70%, transparent) 100%
  );
  transform-origin: left center;
}

.og__frond {
  position: absolute;
  aspect-ratio: 1 / 0.42;
  z-index: 3;
  border-radius: 50% 8% 50% 8%;
  background: color-mix(in srgb, var(--accent) 55%, transparent);
  animation: og-breathe var(--dur, 5s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}

@keyframes og-breathe {
  from { opacity: 0.25; transform: scale(0.9) rotate(0deg); }
  to   { opacity: 0.8; transform: scale(1.08) rotate(6deg); }
}

/* The centre stays clear: the level's trick is visual clutter around the
   line you actually have to read. */
.og__gloom {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: radial-gradient(
    ellipse 46% 38% at 50% 48%,
    color-mix(in srgb, var(--field) 88%, transparent) 0%,
    transparent 76%
  );
}

/* iris — Ocular Miracle -------------------------------------------------- */

.ir__white {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(92vmin, 58rem);
  aspect-ratio: 1 / 0.62;
  border-radius: 50%;
  z-index: 1;
  background: radial-gradient(
    ellipse,
    color-mix(in srgb, var(--ink) 22%, var(--field)) 0%,
    var(--field) 72%
  );
}

.ir__iris {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(56vmin, 34rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 2;
  overflow: hidden;
  background: radial-gradient(
    circle,
    var(--accent2) 0%,
    var(--accent) 58%,
    color-mix(in srgb, var(--field) 70%, var(--accent)) 100%
  );
  box-shadow: 0 0 12vmin color-mix(in srgb, var(--accent) 45%, transparent);
}

/* Every fibre is one element rotated about the iris centre. */
.ir__fibre {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--len, 42%);
  height: 0.5%;
  transform-origin: left center;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--field) 70%, transparent) 0%,
    color-mix(in srgb, var(--ink) 70%, transparent) 100%
  );
}

.ir__pupil {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(22vmin, 13rem);
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 3;
  background: radial-gradient(
    circle,
    var(--field) 0%,
    var(--field) 74%,
    color-mix(in srgb, var(--ink) 30%, var(--field)) 100%
  );
}

.ir__halo {
  position: absolute;
  inset: 0;
  margin: auto;
  border-radius: 50%;
  z-index: 1;
  border: 0.25vmin solid color-mix(in srgb, var(--accent) 60%, transparent);
  animation: ir-halo var(--dur, 6s) ease-in-out infinite alternate;
}

@keyframes ir-halo {
  from { transform: scale(0.94); opacity: 0.25; }
  to   { transform: scale(1.06); opacity: 0.7; }
}

.ir__lid {
  position: absolute;
  left: -10%;
  right: -10%;
  height: 42%;
  z-index: 4;
  background: var(--field);
}

.ir__lid--t {
  top: 0;
  border-radius: 0 0 50% 50% / 0 0 100% 100%;
  box-shadow: 0 1vmin 3vmin color-mix(in srgb, var(--field) 90%, transparent);
}

.ir__lid--b {
  bottom: 0;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  box-shadow: 0 -1vmin 3vmin color-mix(in srgb, var(--field) 90%, transparent);
}

/* corrupt — Killbot ------------------------------------------------------ */

.cr__chan {
  position: absolute;
  inset: 0;
  z-index: 1;
  mix-blend-mode: screen;
}

.cr__chan--r {
  background: radial-gradient(
    ellipse 60% 50% at 42% 46%,
    color-mix(in srgb, var(--accent) 55%, transparent) 0%,
    transparent 72%
  );
}

.cr__chan--g {
  background: radial-gradient(
    ellipse 60% 50% at 58% 54%,
    color-mix(in srgb, var(--accent2) 55%, transparent) 0%,
    transparent 72%
  );
}

.cr__rows {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.cr__row {
  position: absolute;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  mix-blend-mode: overlay;
}

.cr__plate {
  position: absolute;
  z-index: 3;
  background: repeating-linear-gradient(
    -45deg,
    var(--accent) 0 1.2vmin,
    var(--field) 1.2vmin 2.4vmin
  );
  border: 1px solid color-mix(in srgb, var(--ink) 40%, transparent);
  opacity: 0.32;
}

.cr__grid {
  position: absolute;
  inset: 0;
  z-index: 3;
  background:
    repeating-linear-gradient(
      90deg,
      color-mix(in srgb, var(--ink) 7%, transparent) 0 1px,
      transparent 1px 4rem
    ),
    repeating-linear-gradient(
      0deg,
      color-mix(in srgb, var(--ink) 7%, transparent) 0 1px,
      transparent 1px 4rem
    );
}

/* Reduced motion ---------------------------------------------------------- */
/* base.css already neutralises [data-motion] and clamps every animation.
   These stages additionally must not pin: with the timelines never built,
   a stage is just a tall section, which is exactly what is wanted. */

@media (prefers-reduced-motion: reduce) {
  .stage__speck,
  .ig__lick,
  .pl__drip,
  .sg__spray,
  .fl__banner,
  .as__cloud,
  .as__shaft,
  .wo__turn,
  .og__frond,
  .ir__halo,
  .orb__ring,
  .orb__moon {
    animation: none !important;
  }
}

/* Narrow screens ---------------------------------------------------------- */

@media (max-width: 44rem) {
  .stage {
    min-height: 92svh;
  }

  .stage__line {
    font-size: clamp(2.2rem, 12vw, 4rem);
  }

  /* The scatter is tuned for a landscape frame; on a phone the outermost
     pieces sit outside the viewport and only cost layout. */
  .stage__speck {
    display: none;
  }
}
