/* ==========================================================================
   scene.css — disco environment for Gigi's birthday card
   Owns layout/positioning of ALL of #scene's layers (incl. #frank-mount)
   plus the visuals for the floor, disco ball, light rig, and balloons.
   Palette custom props (--night, --pink, --gold, --aqua, --purple,
   --cream, --ink) come from styles/base.css.
   Beat = 116 BPM -> ~0.517s; loop durations are multiples of ~1.034s.
   ========================================================================== */

/* ---------- The stage ---------- */

#scene {
  position: relative;
  width: 100%;
  height: 100vh;   /* fallback */
  height: 100dvh;
  overflow: hidden;
  touch-action: manipulation; /* no Safari double-tap smart-zoom on the stage */
}

#scene *,
#scene *::before,
#scene *::after {
  box-sizing: border-box;
}

/* Ambient venue glow behind everything */
#scene::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(139, 92, 246, 0.30), rgba(139, 92, 246, 0) 60%),
    radial-gradient(90% 55% at 50% 108%, rgba(255, 79, 163, 0.16), rgba(255, 79, 163, 0) 60%);
}

/* ---------- Headline (top, z 2) ---------- */

#headline {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 0;
  right: 0;
  z-index: 2;
  padding: 0 16px;
  text-align: center;
  transform: rotate(-2deg); /* hand-placed sticker tilt */
  pointer-events: none;
}

/* ---------- Dance floor (bottom ~34%, z 1) ---------- */

#floor {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 34%;
  z-index: 1;
  overflow: hidden;
  perspective: 520px;
  perspective-origin: 50% 0%;
}

/* Horizon glow where the floor meets the night */
#floor::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -2px;
  height: 40%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(79, 216, 235, 0.22), rgba(79, 216, 235, 0));
}

/* Far-edge haze for depth + a soft reflective sheen */
#floor::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(23, 16, 58, 0.55), rgba(23, 16, 58, 0) 42%),
    radial-gradient(60% 45% at 50% 60%, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0) 70%);
}

.floor-plane {
  position: absolute;
  top: 0;
  left: 50%;
  width: 190%;
  height: 260%;
  margin-left: -95%;
  transform: rotateX(54deg);
  transform-origin: 50% 0;
  display: grid;
  grid-template-columns: repeat(10, 1fr); /* fallback; scene.js sets 10 or 16 inline */
  grid-template-rows: repeat(5, 1fr);
  gap: 2px;
  background: rgba(79, 216, 235, 0.16); /* glowing grout lines through the gaps */
  will-change: transform;
}

.floor-tile {
  background-color: #1c1446;
  transition: background-color 1.034s ease-out, box-shadow 1.034s ease-out;
}

.floor-tile.alt {
  background-color: #241a58;
}

.floor-tile.lit {
  background-color: var(--tc, var(--gold));
  box-shadow:
    0 0 18px var(--tc, var(--gold)),
    inset 0 0 12px rgba(255, 255, 255, 0.45);
  transition-duration: 0.13s;
}

/* ---------- Frank's spot (z 3) — feet planted on the floor ---------- */

#frank-mount {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 9%;
  margin: 0 auto;
  z-index: 3;
  height: 50vh;   /* he's the star — let him fill the room */
  height: 50dvh;
  width: min(86vw, 58vh);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

@media (min-width: 700px) {
  #frank-mount {
    height: 60vh;
    height: 60dvh;
    bottom: 8%;
    width: min(52vw, 72vh);
  }
}

/* ---------- Disco ball (top-center, z 2) ---------- */

#disco-ball-mount {
  --ball-size: clamp(68px, 20vw, 112px);
  --ball-x: 50%;
  --ball-y: 29vh;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 0; /* children hang from the ceiling via absolute offsets */
  z-index: 2;
  pointer-events: none;
}

@media (min-width: 700px) {
  #disco-ball-mount {
    --ball-size: clamp(100px, 11vw, 148px);
    --ball-x: 36%; /* off-axis, 70s-poster composition; cord clears the subhead */
    --ball-y: 24vh;
  }
}

/* 7 long faint rays fanning out from the ball, slowly rotating */
.ball-rays {
  position: absolute;
  left: var(--ball-x);
  top: var(--ball-y);
  width: 120vmax;
  height: 120vmax;
  margin: -60vmax 0 0 -60vmax;
  background: repeating-conic-gradient(
    from 8deg,
    rgba(255, 243, 224, 0.055) 0deg 7deg,
    rgba(255, 243, 224, 0) 7deg 51.4285deg
  );
  -webkit-mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0.9), transparent 68%);
  mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0.9), transparent 68%);
  animation: rays-rotate 66.2s linear infinite;
}

@keyframes rays-rotate {
  to { transform: rotate(360deg); }
}

.ball-halo {
  position: absolute;
  left: var(--ball-x);
  top: var(--ball-y);
  width: calc(var(--ball-size) * 2.7);
  height: calc(var(--ball-size) * 2.7);
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255, 255, 255, 0.26), rgba(255, 255, 255, 0) 65%);
  animation: halo-breathe 4.138s ease-in-out infinite;
}

@keyframes halo-breathe {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1; }
}

.ball-cord {
  position: absolute;
  left: var(--ball-x);
  top: 0;
  width: 2px;
  margin-left: -1px;
  height: calc(var(--ball-y) - var(--ball-size) / 2 + 4px);
  background: linear-gradient(to bottom, rgba(255, 243, 224, 0), rgba(255, 243, 224, 0.55));
}

.ball {
  position: absolute;
  left: var(--ball-x);
  top: var(--ball-y);
  width: var(--ball-size);
  height: var(--ball-size);
  margin: calc(var(--ball-size) / -2) 0 0 calc(var(--ball-size) / -2);
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(circle at 32% 30%, #eef2ff 0%, #a9b4f2 32%, #5c63b8 68%, #262a5c 100%);
  box-shadow:
    0 0 24px rgba(255, 255, 255, 0.4),
    0 0 70px rgba(139, 92, 246, 0.55),
    0 0 120px rgba(255, 79, 163, 0.25);
}

/* Facet grid that scrolls sideways so the ball reads as spinning */
.ball-facets {
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.45) 0 1px, rgba(255, 255, 255, 0) 1px 11px),
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, 0.34) 0 1px, rgba(255, 255, 255, 0) 1px 11px),
    repeating-linear-gradient(90deg, rgba(23, 16, 58, 0) 0 22px, rgba(23, 16, 58, 0.22) 22px 33px);
  animation: facets-scroll 4.138s linear infinite;
}

@keyframes facets-scroll {
  from { background-position: 0 0,  0 0, 0 0; }
  to   { background-position: 44px 0, 0 0, 66px 0; }
}

/* Spherical shading + rim */
.ball-shade {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0) 28%),
    radial-gradient(circle at 50% 50%, rgba(23, 16, 58, 0) 55%, rgba(23, 16, 58, 0.55) 92%);
}

.ball-glint {
  position: absolute;
  left: 22%;
  top: 16%;
  width: 26%;
  height: 26%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 70%);
  animation: glint-pulse 2.069s ease-in-out infinite;
}

@keyframes glint-pulse {
  0%, 100% { opacity: 0.45; transform: scale(0.8); }
  50%      { opacity: 1;    transform: scale(1.15); }
}

/* ---------- Light rig (z 5, pointer-events none) ---------- */

#light-rig {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  overflow: hidden;
}

.beam {
  position: absolute;
  top: -10vh;
  width: 38vw;
  min-width: 170px;
  height: 150vh;
  transform-origin: 50% 0;
  mix-blend-mode: screen;
  -webkit-clip-path: polygon(40% 0, 60% 0, 100% 100%, 0 100%);
  clip-path: polygon(40% 0, 60% 0, 100% 100%, 0 100%);
  /* soft edge falloff so the wedges read as light, not vector slabs */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 28% 72%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 28% 72%, transparent);
  will-change: transform;
}

.beam-pink {
  left: -12vw;
  background: linear-gradient(to bottom, rgba(255, 79, 163, 0.38), rgba(255, 79, 163, 0) 78%);
  animation: sweep-a 8.276s ease-in-out infinite alternate;   /* 8 beats */
}

.beam-aqua {
  right: -12vw;
  background: linear-gradient(to bottom, rgba(79, 216, 235, 0.34), rgba(79, 216, 235, 0) 78%);
  animation: sweep-b 10.345s ease-in-out infinite alternate;  /* 10 beats */
}

.beam-gold {
  left: 32vw;
  background: linear-gradient(to bottom, rgba(255, 207, 92, 0.30), rgba(255, 207, 92, 0) 72%);
  animation: sweep-c 12.414s ease-in-out infinite alternate;  /* 12 beats */
}

@keyframes sweep-a {
  from { transform: rotate(-26deg); }
  to   { transform: rotate(15deg); }
}

@keyframes sweep-b {
  from { transform: rotate(26deg); }
  to   { transform: rotate(-15deg); }
}

@keyframes sweep-c {
  from { transform: rotate(-10deg); }
  to   { transform: rotate(10deg); }
}

/* Strobe: JS adds .flashing every 16 beats -> 2 quick low-opacity flashes
   (kept under the WCAG 2.3.1 three-flashes-per-second limit with margin) */
.strobe {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
}

.strobe.flashing {
  animation: strobe-flash 0.78s linear;
}

@keyframes strobe-flash {
  0%   { opacity: 0; }
  6%   { opacity: 0.17; }
  13%  { opacity: 0; }
  66%  { opacity: 0.11; }
  76%  { opacity: 0; }
  100% { opacity: 0; }
}

/* ---------- Balloons (z 4) ---------- */

#balloon-layer {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none; /* only the balloons themselves take taps */
  overflow: hidden;
}

.balloon {
  position: absolute;
  pointer-events: auto;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  will-change: transform;
}

.balloon-bob {
  animation: balloon-bob var(--bob-dur, 4.1s) ease-in-out var(--bob-delay, 0s) infinite alternate;
}

.balloon-sway {
  animation: balloon-sway var(--sway-dur, 6.2s) ease-in-out var(--sway-delay, 0s) infinite alternate;
}

@keyframes balloon-bob {
  from { transform: translateY(-8px); }
  to   { transform: translateY(10px); }
}

@keyframes balloon-sway {
  from { transform: translateX(-6px) rotate(-3deg); }
  to   { transform: translateX(6px) rotate(3.5deg); }
}

.balloon .balloon-svg {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 4px 10px rgba(23, 16, 58, 0.5));
}

/* Quick inflate-then-burst */
.balloon.popped {
  pointer-events: none;
}

.balloon.popped .balloon-svg {
  animation: balloon-pop 0.3s ease-out forwards;
}

@keyframes balloon-pop {
  0%   { transform: scale(1);    opacity: 1; }
  40%  { transform: scale(1.25); opacity: 1; }
  100% { transform: scale(1.7);  opacity: 0; }
}

/* ---------- Confetti canvas (z 6, fixed, pointer-events none) ---------- */

#confetti-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 6;
  pointer-events: none;
}

/* ---------- Tap hint + HUD (z 7) ---------- */

/* NOTE: no `display` set here so the [hidden] attribute keeps working.
   scene.css owns tap-hint/hud LAYOUT; base.css owns their skin/typography. */
#tap-hint {
  position: absolute;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 76px);
  transform: translateX(-50%) rotate(-1.2deg); /* hand-drawn tilt */
  z-index: 7;
  margin: 0;
  max-width: 92vw;
  text-align: center;
  pointer-events: none;
  animation: hint-pulse 2.069s ease-in-out infinite;
}

@keyframes hint-pulse {
  0%, 100% {
    opacity: 0.65;
    transform: translateX(-50%) rotate(-1.2deg) translateY(0);
  }
  50% {
    opacity: 1;
    transform: translateX(-50%) rotate(-1.2deg) translateY(-7px);
  }
}

#hud {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 14px);
  z-index: 7;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  padding: 0 16px;
  pointer-events: none;
}

#hud button {
  pointer-events: auto;
}

/* ---------- Reduced motion: no strobe, slower sweeps, calmer everything ----- */

@media (prefers-reduced-motion: reduce) {
  .strobe {
    display: none;
  }

  /* No sweeping — park the beams as static stage lighting. */
  .beam-pink { animation: none; transform: rotate(-8deg); }
  .beam-aqua { animation: none; transform: rotate(8deg); }
  .beam-gold { animation: none; transform: rotate(0deg); }

  .ball-rays   { animation-duration: 180s; }

  .ball-facets,
  .ball-glint,
  .ball-halo,
  #tap-hint {
    animation: none;
  }

  /* JS lights tiles only every 4th beat; let them fade, not flash. */
  .floor-tile.lit {
    transition-duration: 2.068s;
  }

  .balloon-bob  { animation-duration: 9s; }
  .balloon-sway { animation-duration: 12s; }
}
