/* Fang Speare — pure artwork scroll */

:root {
  --font-display: 'Boska', 'Georgia', serif;
  --amber: #eba64a;
  --amber-soft: rgba(235, 166, 74, 0.85);
  --ink: #0c1016;
  --wire: #9db2c4;
}

html, body {
  overflow-x: hidden;
}

body {
  margin: 0;
  background: linear-gradient(
    to bottom,
    #aabecd 0%,
    #c3d1db 6%,
    #55677a 14%,
    #46586a 22%,
    #3c4d5e 32%,
    #3a4b59 42%,
    #37485a 52%,
    #334455 62%,
    #2c3b4a 72%,
    #232f3b 82%,
    #171f27 92%,
    #0e1319 100%
  );
}

/* ---------- Fixed controls ---------- */

.menu-toggle,
.sound-toggle {
  position: fixed;
  top: 20px;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(10, 14, 20, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 70;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.menu-toggle:hover,
.sound-toggle:hover {
  background: rgba(10, 14, 20, 0.72);
  border-color: rgba(235, 166, 74, 0.4);
}

.menu-toggle {
  left: 20px;
  flex-direction: column;
  gap: 4px;
}

.menu-toggle .bar {
  width: 20px;
  height: 2px;
  background: #f2f0ec;
  border-radius: 1px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.menu-toggle.is-open .bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.menu-toggle.is-open .bar:nth-child(2) {
  opacity: 0;
}
.menu-toggle.is-open .bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.sound-toggle {
  right: 20px;
  color: #f2f0ec;
}

.sound-toggle[aria-pressed="true"] {
  color: var(--amber);
  border-color: rgba(235, 166, 74, 0.5);
}

/* ---------- Menu drawer ---------- */

.menu-scrim {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 11, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease;
  z-index: 60;
}

.menu-scrim.is-open {
  opacity: 1;
  pointer-events: auto;
}

.site-menu {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(84vw, 360px);
  height: 100dvh;
  background: linear-gradient(165deg, #10151d 0%, #1a222c 100%);
  border-right: 1px solid rgba(235, 166, 74, 0.15);
  box-shadow: 12px 0 50px rgba(0, 0, 0, 0.5);
  transform: translateX(-100%);
  transition: transform 0.4s cubic-bezier(0.22, 0.68, 0, 1);
  z-index: 65;
  padding: 28px 30px;
  display: flex;
  flex-direction: column;
}

.site-menu.is-open {
  transform: translateX(0);
}

.menu-close {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: transparent;
  border: none;
  color: #cdd6df;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.menu-close:hover {
  color: var(--amber);
}

.menu-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  margin-bottom: 40px;
  color: #f2f0ec;
  font-family: var(--font-display);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.menu-mark {
  width: 26px;
  height: 26px;
  color: var(--amber);
}

.menu-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.menu-list li {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.menu-list a {
  display: block;
  padding: 18px 2px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.35rem;
  color: #e7ebef;
  text-decoration: none;
  letter-spacing: 0.01em;
  transition: color 0.2s ease, padding-left 0.2s ease;
}

.menu-list a:hover,
.menu-list a:focus-visible {
  color: var(--amber);
  padding-left: 8px;
}

/* ---------- Artwork ---------- */

.artwork-page {
  position: relative;
  width: 100%;
}

.artwork-stack {
  position: relative;
  width: 100%;
  max-width: 1536px;
  margin: 0 auto;
  transform-origin: 50% 0%;
  will-change: transform, filter;
}

.artwork-stack img {
  display: block;
  width: 100%;
  height: auto;
}

.glow {
  position: absolute;
  top: var(--top);
  left: var(--left);
  width: var(--size);
  height: var(--size);
  max-width: 480px;
  max-height: 480px;
  transform: translate(-50%, -50%) scale(0.9);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 197, 120, 0.95) 0%, rgba(255, 170, 90, 0.35) 45%, rgba(255, 170, 90, 0) 75%);
  filter: blur(18px);
  mix-blend-mode: screen;
  opacity: 0.12;
  pointer-events: none;
  animation: wub-glow 2.6s ease-in-out infinite;
  animation-delay: calc(var(--depth) * 0.16s);
}

@media (prefers-reduced-motion: no-preference) {
  .artwork-stack {
    animation: wub-breathe 2.6s ease-in-out infinite;
  }
}

@keyframes wub-breathe {
  0%, 100% { transform: scale(1); filter: brightness(1) saturate(1); }
  10%      { transform: scale(1.007); filter: brightness(1.035) saturate(1.06); }
  18%      { transform: scale(0.999); filter: brightness(0.985) saturate(1); }
  26%      { transform: scale(1.012); filter: brightness(1.06) saturate(1.1); }
  36%      { transform: scale(1); filter: brightness(1) saturate(1); }
}

@keyframes wub-glow {
  0%   { opacity: 0.12; transform: translate(-50%, -50%) scale(0.85); }
  10%  { opacity: 0.55; transform: translate(-50%, -50%) scale(1.15); }
  18%  { opacity: 0.22; transform: translate(-50%, -50%) scale(0.95); }
  26%  { opacity: 0.62; transform: translate(-50%, -50%) scale(1.22); }
  36%  { opacity: 0.14; transform: translate(-50%, -50%) scale(0.9); }
  100% { opacity: 0.14; transform: translate(-50%, -50%) scale(0.9); }
}

/* Wordmark surge: the surface ice letters echo whatever note the resonance
   core is currently playing — quiet at rest (no base .glow animation), a
   soft colored breath in the note's own hue on each beat that carries a
   note, gone again on rest steps. */
.wordmark-glow {
  animation: none;
  opacity: 0;
  background: radial-gradient(circle, var(--seq-color, rgba(170, 210, 255, 0.85)) 0%, transparent 76%);
  mix-blend-mode: screen;
  transition: opacity 0.45s ease-out, background 0.18s ease;
}

.wordmark-glow.is-beat {
  opacity: 0.4;
  transition: opacity 0.09s ease-in, background 0.09s ease;
}

/* the big central glow behind the whole wordmark stays a touch dimmer than
   the five letter-level spots so the color reads without washing the ice */
.wordmark-glow-center.is-beat {
  opacity: 0.22;
}

/* ---------- Resonance core patch matrix ---------- */

.node-light {
  position: absolute;
  top: var(--top);
  left: var(--left);
  width: var(--size);
  height: var(--size);
  max-width: 130px;
  max-height: 130px;
  min-width: 34px;
  min-height: 34px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  cursor: pointer;
  pointer-events: auto;
  z-index: 40;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

.node-light::before {
  /* hover/focus affordance ring */
  content: "";
  position: absolute;
  inset: -6%;
  border-radius: 50%;
  border: 1px solid rgba(120, 190, 255, 0);
  transition: border-color 0.25s ease, transform 0.25s ease;
}

.node-light:hover::before,
.node-light:focus-visible::before {
  border-color: rgba(140, 200, 255, 0.55);
  transform: scale(1.08);
}

.node-light::after {
  /* the level-driven glow: gold at rest, then a widening cool-to-hot sweep
     with a matching box-shadow so the color/saturation jump reads clearly,
     not just a brightness change */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, var(--lvl-color, rgba(255, 197, 120, 0)) 0%, transparent 72%);
  box-shadow: 0 0 16px 5px var(--lvl-color, transparent);
  filter: blur(6px);
  mix-blend-mode: color;
  opacity: var(--lvl-opacity, 0);
  transform: scale(var(--lvl-scale, 1));
  transition: opacity 0.35s ease, transform 0.35s ease, background 0.35s ease, box-shadow 0.35s ease;
  pointer-events: none;
}

.node-light.is-playing::after {
  mix-blend-mode: screen;
  box-shadow: 0 0 0 2px rgba(130, 195, 255, 0.4) inset;
  animation: hub-pulse 1.1s ease-in-out infinite;
}

@keyframes hub-pulse {
  0%, 100% { filter: blur(6px) brightness(1); }
  50%      { filter: blur(6px) brightness(1.35); }
}

/* levels 4-5: switch to a brighter additive blend so the top of the range
   feels charged/hot rather than just a bit more opaque than level 3 */
.node-light.is-charged:not(.is-playing)::after {
  mix-blend-mode: screen;
}

.node-light.is-maxed:not(.is-playing)::after {
  animation: node-maxed-pulse 1s ease-in-out infinite;
}

@keyframes node-maxed-pulse {
  0%, 100% { filter: blur(6px) brightness(1); }
  50%      { filter: blur(6px) brightness(1.5); }
}

/* quick punchy feedback on the actual tap, on top of the settled state */
.node-light.is-tapped::after {
  transition: opacity 0.05s linear, transform 0.05s linear, background 0.05s linear, box-shadow 0.05s linear;
  transform: scale(calc(var(--lvl-scale, 1) * 1.22));
}

/* Sequencer step lights: smaller satellites orbiting the hub. Each note now
   gets its own vivid rainbow hue (set via --pitch-hue/sat/light in JS) with a
   matching glow, so tapping through notes is an obvious color change rather
   than a shade shift; a faint neutral ring stays for undiscovered steps. */
.step-light {
  z-index: 41;
}

.step-light::before {
  border-color: hsla(var(--pitch-hue, 210), var(--pitch-sat, 15%), var(--pitch-light, 55%), var(--pitch-idle-alpha, 0.20));
  box-shadow: 0 0 13px 3px hsla(var(--pitch-hue, 210), var(--pitch-sat, 15%), var(--pitch-light, 55%), calc(var(--pitch-idle-alpha, 0.2) * 0.7));
  transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.25s ease;
}

.step-light:hover::before,
.step-light:focus-visible::before {
  border-color: rgba(140, 200, 255, 0.85);
}

.step-light.is-current::before {
  border-color: rgba(255, 255, 255, 0.95);
  box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.55);
  transform: scale(1.3);
  transition: border-color 0.05s linear, box-shadow 0.05s linear, transform 0.05s linear;
}

/* quick punchy feedback the instant a note is tapped/cycled */
.step-light.is-tapped::before {
  transition: border-color 0.05s linear, box-shadow 0.05s linear, transform 0.05s linear;
  transform: scale(1.45);
  box-shadow: 0 0 22px 6px hsla(var(--pitch-hue, 210), var(--pitch-sat, 15%), var(--pitch-light, 55%), 0.9);
}

.core-legend {
  position: absolute;
  top: 13.4%;
  left: 50%;
  transform: translate(-50%, -100%);
  width: min(78vw, 380px);
  text-align: center;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: rgba(220, 235, 250, 0.82);
  background: rgba(8, 12, 18, 0.5);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(140, 200, 255, 0.18);
  border-radius: 10px;
  padding: 8px 14px;
  pointer-events: none;
  opacity: 0;
  animation: legend-fade 9s ease-in-out 1.2s 1 forwards;
  transition: opacity 0.5s ease;
  z-index: 39;
}

#effects-legend {
  width: min(80vw, 400px);
}

@keyframes legend-fade {
  0%   { opacity: 0; }
  8%   { opacity: 1; }
  78%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ---------- Descent-shaft percussion nodes ---------- */
/* Idle: a quiet amber glow, close to the artwork's own baked-in gold so an
   un-armed voice reads as latent rather than broken. Armed voices (at least
   one step set) get a steady warm ring so you can see which of the six are
   contributing at a glance. A tick pulses very softly every time that
   voice's own clock advances — the polyrhythm becomes visible even before
   anything is armed. A hit flashes bright white-gold on trigger. */
.perc-light::before {
  border-color: rgba(235, 166, 74, 0);
}

.perc-light:hover::before,
.perc-light:focus-visible::before {
  border-color: rgba(255, 200, 120, 0.65);
}

.perc-light::after {
  background: radial-gradient(circle, var(--perc-color, rgba(235, 166, 74, 0.55)) 0%, transparent 72%);
  opacity: var(--perc-opacity, 0.22);
  transform: scale(var(--perc-scale, 1));
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.perc-light.is-armed::after {
  animation: perc-breathe 1.8s ease-in-out infinite;
}

@keyframes perc-breathe {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.25); }
}

/* actively capturing taps for one lap of the voice's own cycle — a faster,
   brighter pulse than the settled is-armed breathe, so it's clear the node
   is still listening and will lock in shortly. */
.perc-light.is-recording::after {
  animation: perc-record-pulse 0.5s ease-in-out infinite;
}

@keyframes perc-record-pulse {
  0%, 100% { filter: brightness(1) saturate(1); }
  50%      { filter: brightness(1.7) saturate(1.4); }
}

.perc-light.is-tick::after {
  transition: opacity 0.05s ease, transform 0.05s ease;
}

.perc-light.is-hit::after {
  transition: opacity 0.03s ease, transform 0.03s ease;
  box-shadow: 0 0 14px 3px rgba(255, 235, 200, 0.6);
}

#perc-legend {
  width: min(80vw, 400px);
}

/* ---------- Full-scene reverb flash (shoggoth giant wub) ---------- */

.scene-flash {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  background: radial-gradient(circle at 50% 68%, rgba(198, 158, 255, 0.6) 0%, rgba(120, 90, 220, 0.3) 35%, rgba(0, 0, 0, 0) 72%);
  opacity: 0;
  mix-blend-mode: screen;
}

.scene-flash.is-active {
  animation: scene-flash-pulse 1.5s cubic-bezier(0.22, 0.9, 0.3, 1) 1;
}

@keyframes scene-flash-pulse {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  22%  { opacity: 0.35; }
  38%  { opacity: 0.85; }
  55%  { opacity: 0.25; }
  100% { opacity: 0; }
}

/* Brief shockwave shake on the whole artwork stack, layered on top of its
   own continuous ambient breathe animation while active. */
.artwork-stack.is-impact {
  animation: wub-breathe 2.6s ease-in-out infinite, scene-shake 0.9s cubic-bezier(0.36, 0.07, 0.19, 0.97) 1;
}

@keyframes scene-shake {
  0%   { transform: translate(0, 0) scale(1); }
  10%  { transform: translate(-1.2%, 0.6%) scale(1.012); }
  20%  { transform: translate(1.4%, -0.8%) scale(0.99); }
  30%  { transform: translate(-1.6%, 0.9%) scale(1.02); }
  40%  { transform: translate(1.2%, -0.6%) scale(0.985); }
  50%  { transform: translate(-0.9%, 0.5%) scale(1.015); }
  60%  { transform: translate(0.7%, -0.4%) scale(0.995); }
  70%  { transform: translate(-0.5%, 0.3%) scale(1.008); }
  80%  { transform: translate(0.3%, -0.2%) scale(1); }
  100% { transform: translate(0, 0) scale(1); }
}

/* Conduit clear switches: the three coupling-ring disks on the shaft's
   central pipe. Invisible hit-area at rest (inherited from .node-light) with
   a cool metallic ring on hover/focus, then a bright shockwave that rings
   outward on tap to sell the "wipe" action. */
.conduit-disk::before {
  border-color: rgba(200, 225, 255, 0);
}

.conduit-disk:hover::before,
.conduit-disk:focus-visible::before {
  border-color: rgba(210, 235, 255, 0.6);
  transform: scale(1.35);
}

.conduit-disk::after {
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(190, 225, 255, 0.5) 45%, transparent 78%);
  box-shadow: 0 0 16px 5px rgba(210, 235, 255, 0.55);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.45s ease-out, transform 0.45s ease-out;
}

.conduit-disk.is-cleared::after {
  opacity: 0.9;
  transform: scale(2.2);
  transition: opacity 0.5s ease-out, transform 0.5s ease-out;
}

/* Generic cool white-blue "wipe" flash, reused by any node-light that needs
   to signal a reset/clear action (e.g. the hub on a triple-tap full reset). */
.node-light.is-cleared::after {
  background: radial-gradient(circle, rgba(225, 240, 255, 0.9) 0%, transparent 75%);
  box-shadow: 0 0 20px 6px rgba(210, 235, 255, 0.6);
  opacity: 0.9;
  transform: scale(1.5);
  transition: opacity 0.45s ease-out, transform 0.45s ease-out, background 0.1s ease;
}

/* Matching cool white-blue flash on the two percussion lights a clear switch
   just wiped — distinct from the warm amber is-hit flash, so "erased" reads
   differently from "played". */
.perc-light.is-cleared::after {
  background: radial-gradient(circle, rgba(225, 240, 255, 0.85) 0%, transparent 75%);
  box-shadow: 0 0 18px 5px rgba(210, 235, 255, 0.6);
  opacity: 0.85;
  transform: scale(1.3);
  transition: opacity 0.4s ease-out, transform 0.4s ease-out, background 0.1s ease;
}

/* Shoggoth: a shapeshifting presence that surfaces on the antechamber floor
   while the sequencer plays. Hidden and still by default; fades in and
   starts a slow continuous pulse once playback starts, then mutates into a
   new form (new frame + a quick brightness flash + a small dance sway) on
   every beat. Purely decorative, never intercepts clicks. */
.shoggoth {
  position: absolute;
  top: var(--top);
  left: var(--left);
  width: var(--w);
  height: var(--h);
  transform: translate(-50%, -100%);
  pointer-events: none;
  opacity: 0;
  z-index: 50;
  transition: opacity 1.1s ease;
  filter: drop-shadow(0 6px 22px rgba(90, 30, 140, 0.4));
}

.shoggoth.is-visible {
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
  animation: shoggoth-breathe 2.6s ease-in-out infinite;
}

.shoggoth.is-visible:focus-visible {
  outline: 2px solid rgba(198, 158, 255, 0.85);
  outline-offset: 10px;
  border-radius: 16px;
}

@keyframes shoggoth-breathe {
  0%, 100% { transform: translate(-50%, -100%) scale(1); }
  50%      { transform: translate(-50%, -100%) scale(1.04); }
}

.shoggoth img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 50% 100%;
  display: block;
  transition: transform 0.5s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.shoggoth.is-mutating img {
  animation: shoggoth-mutate-flash 0.4s ease-out;
}

@keyframes shoggoth-mutate-flash {
  0%   { filter: brightness(2.4) saturate(1.9) contrast(1.35); }
  100% { filter: brightness(1) saturate(1) contrast(1); }
}

.core-toggle {
  position: fixed;
  top: 72px;
  right: 20px;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(10, 14, 20, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 70;
  color: rgba(140, 200, 255, 0.85);
  transition: background 0.2s ease, border-color 0.2s ease, opacity 0.3s ease;
  opacity: 0;
  pointer-events: none;
}

.core-toggle.is-armed {
  opacity: 1;
  pointer-events: auto;
}

.core-toggle:hover {
  background: rgba(10, 14, 20, 0.72);
  border-color: rgba(140, 200, 255, 0.45);
}

.core-toggle[aria-pressed="true"] {
  color: rgba(120, 130, 145, 0.7);
}

@media (max-width: 600px) {
  .core-toggle { right: 14px; top: 66px; }
  .core-legend { font-size: 11.5px; width: min(86vw, 340px); }
  .scene-flash.is-active { animation-duration: 1.1s; }
}

/* ---------- Transmitter vibration ---------- */

.transmitter {
  position: absolute;
  top: var(--top);
  left: var(--left);
  width: var(--width);
  height: var(--height);
  min-width: 10px;
  max-width: 34px;
  background: linear-gradient(
    to bottom,
    rgba(255, 225, 170, 0) 0%,
    rgba(255, 210, 140, 0.55) 18%,
    rgba(255, 232, 190, 0.8) 50%,
    rgba(255, 210, 140, 0.55) 82%,
    rgba(255, 225, 170, 0) 100%
  );
  filter: blur(5px);
  mix-blend-mode: screen;
  opacity: 0.4;
  pointer-events: none;
  transform: translateX(-50%);
  animation:
    transmitter-flicker 2.6s ease-in-out infinite,
    transmitter-vibrate 0.22s linear infinite;
}

@keyframes transmitter-flicker {
  0%, 100% { opacity: 0.32; }
  15%      { opacity: 0.7; }
  30%      { opacity: 0.38; }
  45%      { opacity: 0.78; }
  60%      { opacity: 0.34; }
  75%      { opacity: 0.6; }
}

@keyframes transmitter-vibrate {
  0%   { transform: translateX(-50%) translate(0, 0); }
  25%  { transform: translateX(-50%) translate(0.9px, -0.5px); }
  50%  { transform: translateX(-50%) translate(-0.7px, 0.5px); }
  75%  { transform: translateX(-50%) translate(0.6px, 0.6px); }
  100% { transform: translateX(-50%) translate(0, 0); }
}

/* ---------- Energy pulses (visible current along conduits) ---------- */

.pulse {
  position: absolute;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 232, 190, 1) 0%, rgba(255, 190, 100, 0.75) 42%, rgba(255, 160, 70, 0) 78%);
  filter: blur(2.5px);
  mix-blend-mode: screen;
  opacity: 0;
  transform: translate(-50%, -50%);
  pointer-events: none;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

.pulse-1 { animation-name: pulse-1; animation-duration: 2.6s; animation-delay: 0s; }
.pulse-2 { animation-name: pulse-2; animation-duration: 2.6s; animation-delay: 0.3s; }
.pulse-3 { animation-name: pulse-3; animation-duration: 2.6s; animation-delay: 0.15s; }
.pulse-4 { animation-name: pulse-4; animation-duration: 2.6s; animation-delay: 0.45s; }
.pulse-5 { animation-name: pulse-5; animation-duration: 2.2s; animation-delay: 0.5s; }
.pulse-6 { animation-name: pulse-6; animation-duration: 2.4s; animation-delay: 1.1s; }
.pulse-7 { animation-name: pulse-7; animation-duration: 2.8s; animation-delay: 1.7s; }
.pulse-8 { animation-name: pulse-8; animation-duration: 2.6s; animation-delay: 2s; }

@keyframes pulse-1 {
  0%   { top: 16.8%; left: 49%; opacity: 0; }
  10%  { opacity: 0.9; }
  50%  { top: 18.5%; left: 32%; opacity: 0.8; }
  62%, 100% { top: 18.5%; left: 32%; opacity: 0; }
}
@keyframes pulse-2 {
  0%   { top: 16.8%; left: 51%; opacity: 0; }
  10%  { opacity: 0.9; }
  50%  { top: 18.5%; left: 68%; opacity: 0.8; }
  62%, 100% { top: 18.5%; left: 68%; opacity: 0; }
}
@keyframes pulse-3 {
  0%   { top: 17%; left: 49%; opacity: 0; }
  12%  { opacity: 0.85; }
  55%  { top: 27%; left: 38%; opacity: 0.75; }
  66%, 100% { top: 27%; left: 38%; opacity: 0; }
}
@keyframes pulse-4 {
  0%   { top: 17%; left: 51%; opacity: 0; }
  12%  { opacity: 0.85; }
  55%  { top: 27%; left: 62%; opacity: 0.75; }
  66%, 100% { top: 27%; left: 62%; opacity: 0; }
}
@keyframes pulse-5 {
  0%   { top: 19%; left: 50%; opacity: 0; }
  12%  { opacity: 0.85; }
  60%  { top: 34%; left: 50%; opacity: 0.7; }
  72%, 100% { top: 34%; left: 50%; opacity: 0; }
}
@keyframes pulse-6 {
  0%   { top: 34%; left: 50%; opacity: 0; }
  12%  { opacity: 0.8; }
  62%  { top: 45%; left: 50%; opacity: 0.65; }
  74%, 100% { top: 45%; left: 50%; opacity: 0; }
}
@keyframes pulse-7 {
  0%   { top: 45%; left: 50%; opacity: 0; }
  12%  { opacity: 0.8; }
  65%  { top: 59%; left: 50%; opacity: 0.65; }
  76%, 100% { top: 59%; left: 50%; opacity: 0; }
}
@keyframes pulse-8 {
  0%   { top: 47.5%; left: 28%; opacity: 0; }
  12%  { opacity: 0.75; }
  60%  { top: 61%; left: 22%; opacity: 0.6; }
  72%, 100% { top: 61%; left: 22%; opacity: 0; }
}

/* ---------- Eldritch surges (occasional cold blue flares) ---------- */

.glow-eldritch {
  background: radial-gradient(circle, rgba(150, 200, 255, 0.95) 0%, rgba(110, 150, 255, 0.6) 45%, rgba(90, 100, 255, 0) 78%);
  filter: blur(20px);
  mix-blend-mode: color;
  opacity: 0;
  animation-name: eldritch-flare;
  animation-duration: var(--edur, 11s);
  animation-delay: var(--edelay, 0s);
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

.glow-eldritch::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: inherit;
  filter: inherit;
  mix-blend-mode: screen;
  opacity: 0.35;
}

@keyframes eldritch-flare {
  0%, 82%   { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
  87%       { opacity: 0.9; transform: translate(-50%, -50%) scale(1.3); }
  92%       { opacity: 0.45; transform: translate(-50%, -50%) scale(1.05); }
  97%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
}

@media (prefers-reduced-motion: reduce) {
  .artwork-stack,
  .glow,
  .transmitter,
  .pulse,
  .scene-flash,
  .shoggoth {
    animation: none !important;
  }
}

@media (max-width: 640px) {
  .menu-toggle,
  .sound-toggle {
    top: 14px;
    width: 40px;
    height: 40px;
  }
  .menu-toggle { left: 14px; }
  .sound-toggle { right: 14px; }
}
