/* ============ base ============ */
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --ink: #fffdf5;
  --accent: #ffd23f;
  --bg1: #1c2340;
  --bg2: #0b0e1c;
}

html, body {
  height: 100%;
  overflow: hidden;
}

body {
  font-family: Impact, "Arial Black", "Franklin Gothic Bold", sans-serif;
  color: var(--ink);
  background: radial-gradient(ellipse 120% 90% at 50% 20%, var(--bg1), var(--bg2) 75%);
  transition: background 0.6s ease;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* per-player color moods */
.theme-intro   { --bg1: #1c2340; --bg2: #0b0e1c; --accent: #ffd23f; }
.theme-lp      { --bg1: #1f4d24; --bg2: #0a1c0c; --accent: #a4e05a; }
.theme-bp      { --bg1: #143a1c; --bg2: #050f07; --accent: #6fbf44; }
.theme-lpa     { --bg1: #58152b; --bg2: #1c0510; --accent: #ff5d8f; }
.theme-ak      { --bg1: #4d3a12; --bg2: #171004; --accent: #ffb129; }
.theme-sink    { --bg1: #123c52; --bg2: #04121b; --accent: #52c7ff; }
.theme-commit  { --bg1: #3c1a5c; --bg2: #12061f; --accent: #c68bff; }
.theme-afraid  { --bg1: #24404a; --bg2: #0a1418; --accent: #6fe3c1; }
.theme-lm      { --bg1: #54430e; --bg2: #191303; --accent: #ffe14d; }
.theme-finale  { --bg1: #21356b; --bg2: #0a1023; --accent: #ffd23f; }

/* ============ layout ============ */
#stage {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.scene {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(4px, 1.5vh, 16px);
  padding: max(20px, env(safe-area-inset-top)) 12px max(46px, env(safe-area-inset-bottom));
  animation: scene-in 0.45s ease both;
  position: relative;
  overflow: hidden;
}
.scene > :not(.fx) { position: relative; z-index: 1; }

@keyframes scene-in { from { opacity: 0; transform: scale(1.05); } to { opacity: 1; transform: none; } }

.art {
  width: min(96vw, 760px);
  flex: 0 1 auto;
  min-height: 0;
  animation: cam 8s ease-out both;
}
@keyframes cam { from { transform: scale(1); } to { transform: scale(1.06); } }
.art svg {
  width: 100%;
  height: auto;
  max-height: 56vh;
  display: block;
  overflow: visible;
}

/* ambient floating particles */
.fx {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.fx .p {
  position: absolute;
  bottom: -12px;
  border-radius: 50%;
  background: var(--accent);
  animation: rise linear infinite;
}
@keyframes rise { to { transform: translateY(-112vh); } }

/* ============ scene wipe transition ============ */
#wipe {
  position: fixed;
  inset: -12% -35%;
  z-index: 9;
  pointer-events: none;
  background: linear-gradient(105deg, var(--wc, #ffd23f) 55%, rgba(10, 10, 16, 0.94));
  transform: translateX(-135%) skewX(-14deg);
}
#wipe.run { animation: wipe-run 0.62s cubic-bezier(0.7, 0, 0.25, 1) both; }
@keyframes wipe-run {
  from { transform: translateX(-135%) skewX(-14deg); }
  to   { transform: translateX(135%) skewX(-14deg); }
}

/* ============ nickname title ============ */
.kicker {
  font-size: clamp(0.8rem, 2.6vw, 1.1rem);
  letter-spacing: 0.35em;
  text-transform: uppercase;
  opacity: 0;
  color: var(--accent);
  animation: fade-up 0.5s 0.15s ease forwards;
}

.nick {
  font-size: clamp(2rem, 9.5vw, 5rem);
  line-height: 1;
  text-transform: uppercase;
  font-style: italic;
  text-align: center;
  letter-spacing: 0.02em;
  text-shadow: 0.06em 0.06em 0 rgba(0,0,0,0.45);
  color: var(--ink);
}
.nick .ltr {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.6em) rotate(8deg) scale(0.6);
  animation: ltr-pop 0.45s cubic-bezier(0.2, 1.6, 0.4, 1) forwards;
}
.nick .sp { display: inline-block; width: 0.35em; }
@keyframes ltr-pop { to { opacity: 1; transform: none; } }

.tag {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-size: clamp(1rem, 3.6vw, 1.5rem);
  text-align: center;
  max-width: 34em;
  opacity: 0;
  color: #f3ecd8;
  animation: fade-up 0.6s 0.9s ease forwards;
  text-shadow: 0 2px 6px rgba(0,0,0,0.6);
}

@keyframes fade-up {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.late-fade { opacity: 0; animation: fade-up 0.6s 2.2s ease forwards; }

/* ============ intro / finale chrome ============ */
.title-xl {
  font-size: clamp(2.6rem, 12vw, 7rem);
  font-style: italic;
  text-transform: uppercase;
  line-height: 0.95;
  text-align: center;
  text-shadow: 0.06em 0.06em 0 rgba(0,0,0,0.5);
}
.title-xl .hl { color: var(--accent); }

.btn {
  font: inherit;
  font-size: clamp(1.05rem, 3.5vw, 1.4rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #14140d;
  background: var(--accent);
  border: none;
  border-radius: 999px;
  padding: 0.8em 2.2em;
  cursor: pointer;
  box-shadow: 0 6px 0 rgba(0,0,0,0.4);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  animation: fade-up 0.5s 0.5s ease both;
}
.btn:hover  { transform: translateY(-2px); }
.btn:active { transform: translateY(3px); box-shadow: 0 2px 0 rgba(0,0,0,0.4); }

/* ============ progress dots + timer ============ */
#dots {
  position: fixed;
  bottom: max(14px, env(safe-area-inset-bottom));
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  gap: 9px;
  z-index: 5;
}
#dots:empty { display: none; }
#dots .dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: rgba(255,255,255,0.28);
  cursor: pointer;
  transition: transform 0.2s, background 0.2s;
}
#dots .dot.on { background: var(--accent); transform: scale(1.45); }

#timer {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 4px;
  z-index: 5;
  background: rgba(255,255,255,0.08);
  opacity: 0;
}
#timer.running { opacity: 1; }
#timer-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
}
#timer.running #timer-fill { animation: timer-run linear forwards; }
@keyframes timer-run { from { width: 0; } to { width: 100%; } }

#hint {
  position: fixed;
  bottom: max(34px, calc(env(safe-area-inset-bottom) + 20px));
  left: 0; right: 0;
  text-align: center;
  font-family: Georgia, serif;
  font-style: italic;
  font-size: 0.8rem;
  color: rgba(255,255,255,0.45);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s;
  z-index: 4;
}
#hint.show { opacity: 1; }

/* ============ entrances ============ */
.enter-left  { animation: enter-left 0.7s 0.1s cubic-bezier(0.2, 1.2, 0.4, 1) both; }
.enter-right { animation: enter-right 0.7s 0.1s cubic-bezier(0.2, 1.2, 0.4, 1) both; }
@keyframes enter-left  { from { transform: translateX(-520px); } to { transform: none; } }
@keyframes enter-right { from { transform: translateX(520px); } to { transform: none; } }

.enter-hop { animation: enter-hop 1s 0.1s ease-out both; }
@keyframes enter-hop {
  0%   { transform: translate(-460px, 0); }
  15%  { transform: translate(-391px, -56px); }
  30%  { transform: translate(-322px, 0); }
  45%  { transform: translate(-253px, -44px); }
  60%  { transform: translate(-184px, 0); }
  75%  { transform: translate(-92px, -30px); }
  90%  { transform: translate(0, 0); }
  95%  { transform: translate(0, 0) scale(1.06, 0.92); }
  100% { transform: translate(0, 0); }
}
.enter-hop, .squash-origin { transform-box: fill-box; transform-origin: 50% 100%; }

/* ============ svg character animation classes ============ */
.bob            { animation: bob 2.2s ease-in-out infinite; }
.bob-2          { animation: bob 2.2s 0.4s ease-in-out infinite; }
@keyframes bob  { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

.blink circle.eye,
.blink ellipse.eye { animation: blink 3.4s infinite; }
@keyframes blink { 0%, 93%, 100% { transform: scaleY(1); } 96% { transform: scaleY(0.08); } }
.eye { transform-box: fill-box; transform-origin: center; }

/* keepy-uppy ball: soft up/down juggle bob, no spin, seamless loop */
.keepy {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: keepy 1.15s ease-in-out infinite;
}
@keyframes keepy {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-46px); }
}

/* intro ball: a real gravity bounce — fast at the floor, hangs at the
   apex, squashes on impact. Start/end both at the apex so it loops
   seamlessly (no spin, no snap). */
.bounce {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: bounce 1.15s infinite;
}
@keyframes bounce {
  0%   { transform: translateY(-96px); animation-timing-function: cubic-bezier(0.4, 0, 1, 1); }
  46%  { transform: translateY(0) scaleY(1); animation-timing-function: ease-out; }
  54%  { transform: translateY(0) scale(1.16, 0.8); animation-timing-function: ease-in; }
  62%  { transform: translateY(0) scale(1); animation-timing-function: cubic-bezier(0, 0, 0.6, 1); }
  100% { transform: translateY(-96px); }
}
/* shadow shrinks/fades as the ball rises, grows/darkens as it lands */
.bounce-shadow {
  transform-box: fill-box;
  transform-origin: center;
  animation: bounce-shadow 1.15s infinite;
}
@keyframes bounce-shadow {
  0%      { transform: scale(0.5); opacity: 0.1; animation-timing-function: cubic-bezier(0.4, 0, 1, 1); }
  46%, 62% { transform: scale(1); opacity: 0.32; animation-timing-function: ease-out; }
  100%    { transform: scale(0.5); opacity: 0.1; }
}

/* Big Pickle: telegraphed crash-landing. Timeline:
   0-1.1s   growing landing shadow + whoosh lines
   1.1-2.2s the drop itself (lands ~1.75s)
   1.75s    screen shake + dust */
.bp-drop {
  animation: bp-drop 1.15s 1.1s cubic-bezier(0.55, 0, 0.8, 0.4) both;
}
@keyframes bp-drop {
  0%   { transform: translateY(-620px); }
  55%  { transform: translateY(0); }
  68%  { transform: translateY(0) scale(1.14, 0.8); }
  84%  { transform: translateY(0) scale(0.95, 1.06); }
  100% { transform: translateY(0) scale(1, 1); }
}
.bp-drop { transform-box: fill-box; transform-origin: 50% 100%; }

.grow-shadow { animation: grow-shadow 1.65s ease-in both; transform-box: fill-box; transform-origin: center; }
@keyframes grow-shadow {
  from { opacity: 0; transform: scale(0.1); }
  to   { opacity: 1; transform: scale(1); }
}

.whoosh { animation: whoosh 1.1s 1s ease-in both; }
@keyframes whoosh {
  0%   { transform: translateY(-300px); opacity: 0; }
  35%  { opacity: 0.55; }
  100% { transform: translateY(60px); opacity: 0; }
}

.shake-late { animation: shake 0.5s 1.78s linear both; }
@keyframes shake {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(-8px, 5px); }
  40% { transform: translate(7px, -4px); }
  60% { transform: translate(-6px, 3px); }
  80% { transform: translate(5px, -2px); }
}

.dust { opacity: 0; animation: dust 1.3s 1.78s ease-out both; transform-box: fill-box; transform-origin: center; }
@keyframes dust {
  0%   { opacity: 0; transform: scale(0.2); }
  15%  { opacity: 0.9; }
  100% { opacity: 0; transform: scale(2.6) translateY(-12px); }
}

/* thrown volleyballs (little pickle abuser) */
.ball-throw   { animation: ball-throw 1.6s 0.7s cubic-bezier(0.3, 0, 0.7, 1) infinite; }
.ball-throw-2 { animation: ball-throw 1.6s 1.25s cubic-bezier(0.3, 0, 0.7, 1) infinite; }
.ball-throw-3 { animation: ball-throw 1.6s 1.8s cubic-bezier(0.3, 0, 0.7, 1) infinite; }
@keyframes ball-throw {
  0%   { transform: translate(0, 0) rotate(0deg); opacity: 0; }
  8%   { opacity: 1; }
  55%  { transform: translate(300px, 118px) rotate(340deg); opacity: 1; }
  60%  { transform: translate(300px, 118px) rotate(360deg); opacity: 0; }
  100% { opacity: 0; }
}
.spike-arm {
  animation: spike-arm 1.6s 0.7s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: 20% 85%;
}
@keyframes spike-arm {
  0%, 100% { transform: rotate(0deg); }
  10% { transform: rotate(-38deg); }
  22% { transform: rotate(14deg); }
  40% { transform: rotate(0deg); }
}
.pickle-hit { animation: pickle-hit 1.6s 1.55s linear infinite; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes pickle-hit {
  0%, 100% { transform: rotate(0); }
  4%  { transform: rotate(9deg) translateX(6px); }
  9%  { transform: rotate(-5deg); }
  14% { transform: rotate(0); }
}
.impact-star { opacity: 0; animation: impact 1.6s 1.56s linear infinite; transform-box: fill-box; transform-origin: center; }
@keyframes impact {
  0%, 100% { opacity: 0; transform: scale(0.3); }
  4%  { opacity: 1; transform: scale(1.25); }
  16% { opacity: 0; transform: scale(1.7); }
}

/* vet clinic (animal killer) */
.tremble { animation: tremble 0.16s linear infinite; }
@keyframes tremble {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-1.6px, 1px); }
  75% { transform: translate(1.6px, -1px); }
}
.cat-slide { animation: cat-slide 5s ease-in-out infinite alternate; }
@keyframes cat-slide { from { transform: translateX(0); } to { transform: translateX(78px); } }

.wag { animation: wag 0.5s ease-in-out infinite alternate; transform-box: fill-box; transform-origin: 10% 90%; }
@keyframes wag { from { transform: rotate(-16deg); } to { transform: rotate(22deg); } }

.sign-sway { animation: sway 4.5s ease-in-out infinite; transform-box: fill-box; transform-origin: top center; }
@keyframes sway { 0%,100% { transform: rotate(-1.6deg); } 50% { transform: rotate(1.6deg); } }

.ekg { stroke-dasharray: 60 260; animation: ekg-scroll 1.5s linear infinite; }
@keyframes ekg-scroll { to { stroke-dashoffset: -320; } }
.ekg-hide { animation: ekg-hide 7s linear infinite; }
@keyframes ekg-hide { 0%, 60% { opacity: 1; } 63%, 92% { opacity: 0; } 96%, 100% { opacity: 1; } }
.flat-blink { opacity: 0; animation: flat-blink 7s linear infinite; }
@keyframes flat-blink {
  0%, 60% { opacity: 0; }
  63%, 68% { opacity: 1; }
  70%, 73% { opacity: 0.3; }
  75%, 92% { opacity: 1; }
  95%, 100% { opacity: 0; }
}

.halo { animation: halo-wobble 2.6s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes halo-wobble { 0%,100% { transform: rotate(-14deg); } 50% { transform: rotate(6deg) translateY(-3px); } }

.note { opacity: 0; animation: note-float 2.4s ease-out infinite; }
.note-2 { opacity: 0; animation: note-float 2.4s 1.2s ease-out infinite; }
@keyframes note-float {
  0%   { opacity: 0; transform: translate(0, 0); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: translate(26px, -70px); }
}

/* bathroom sink */
.drip { animation: drip 1.7s ease-in infinite; }
@keyframes drip {
  0%   { transform: translateY(0) scale(1); opacity: 0; }
  20%  { opacity: 1; transform: translateY(4px); }
  75%  { transform: translateY(172px); opacity: 1; }
  78%  { transform: translateY(174px) scale(1.4, 0.4); opacity: 0.7; }
  100% { transform: translateY(174px); opacity: 0; }
}
.ripple { opacity: 0; animation: ripple 1.7s 1.25s ease-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes ripple {
  0%   { opacity: 0; transform: scale(0.3); }
  15%  { opacity: 0.8; }
  100% { opacity: 0; transform: scale(2); }
}
.bub   { opacity: 0; animation: bub 3.4s ease-in infinite; }
.bub-2 { opacity: 0; animation: bub 3.4s 1.1s ease-in infinite; }
.bub-3 { opacity: 0; animation: bub 3.4s 2.2s ease-in infinite; }
@keyframes bub {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.5); }
  12%  { opacity: 0.85; }
  100% { opacity: 0; transform: translate(16px, -130px) scale(1.1); }
}
.glint { opacity: 0; animation: glint 2.8s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.glint-2 { opacity: 0; animation: glint 2.8s 1.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes glint {
  0%, 100% { opacity: 0; transform: scale(0.4) rotate(0deg); }
  12% { opacity: 1; transform: scale(1.15) rotate(20deg); }
  24% { opacity: 0; transform: scale(0.4) rotate(40deg); }
}

/* commitment dive */
.dive-slide { animation: dive-slide 2.6s ease-in-out infinite; }
@keyframes dive-slide {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(85px); }
}
.zoom-line { stroke-dasharray: 30 22; animation: zoom-line 0.6s linear infinite; }
@keyframes zoom-line { to { stroke-dashoffset: -52; } }
.spark { opacity: 0; animation: spark 0.9s ease-out infinite; transform-box: fill-box; transform-origin: center; }
.spark-2 { opacity: 0; animation: spark 0.9s 0.45s ease-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes spark {
  0%   { opacity: 0; transform: scale(0.2); }
  25%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(0.4) translateY(-14px); }
}
.ball-tease { animation: ball-tease 2.6s ease-in-out infinite; }
@keyframes ball-tease {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50% { transform: translate(72px, -8px) rotate(200deg); }
}

/* afraid of commitment */
.lean-away { animation: lean-away 2.8s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes lean-away {
  0%, 100% { transform: rotate(10deg); }
  45% { transform: rotate(15deg); }
}
/* shuffles toward the exit while the ball bounces, snaps back while it's gone */
.step-back { animation: step-back 2.8s linear infinite; }
@keyframes step-back {
  0%, 52% { transform: translateX(0); }
  60% { transform: translateX(-12px); }
  70% { transform: translateX(-24px); }
  82% { transform: translateX(-34px); }
  94% { transform: translateX(-34px); }
  100% { transform: translateX(0); }
}
.ball-drop-loop { animation: ball-drop-loop 2.8s cubic-bezier(0.4, 0, 0.9, 0.6) infinite; }
@keyframes ball-drop-loop {
  0%   { transform: translateY(-420px); opacity: 0; }
  10%  { opacity: 1; }
  55%  { transform: translateY(0); }
  63%  { transform: translateY(-60px); }
  72%  { transform: translateY(0); }
  77%  { transform: translateY(-22px); }
  83%  { transform: translateY(0); opacity: 1; }
  97%  { transform: translateY(0); opacity: 0; }
  100% { opacity: 0; }
}
.sweat { opacity: 0; animation: sweat 1.4s ease-in infinite; }
.sweat-2 { opacity: 0; animation: sweat 1.4s 0.7s ease-in infinite; }
@keyframes sweat {
  0%   { opacity: 0; transform: translate(0, 0); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-8px, 34px); }
}
.bubble-pop { opacity: 0; animation: bubble-pop 2.8s ease infinite; transform-box: fill-box; transform-origin: 20% 90%; }
@keyframes bubble-pop {
  0%, 30% { opacity: 0; transform: scale(0); }
  38% { opacity: 1; transform: scale(1.1); }
  44% { transform: scale(1); }
  80% { opacity: 1; transform: scale(1); }
  90%, 100% { opacity: 0; transform: scale(0); }
}
.exit-glow { animation: exit-glow 1.5s ease-in-out infinite alternate; }
@keyframes exit-glow { from { opacity: 0.55; } to { opacity: 1; } }

/* legal midget */
.stamp {
  opacity: 0;
  animation: stamp 0.55s 1.15s cubic-bezier(0.2, 2.2, 0.4, 1) forwards;
  transform-box: fill-box;
  transform-origin: center;
}
@keyframes stamp {
  0%   { opacity: 0; transform: scale(3) rotate(-25deg); }
  100% { opacity: 1; transform: scale(1) rotate(-9deg); }
}
.stamp-star { opacity: 0; animation: impact-once 0.6s 1.25s ease-out both; transform-box: fill-box; transform-origin: center; }
@keyframes impact-once {
  0%   { opacity: 0; transform: scale(0.3); }
  30%  { opacity: 1; transform: scale(1.4); }
  100% { opacity: 0; transform: scale(2.1); }
}
.measure-arrow { animation: measure 2s ease-in-out infinite; }
@keyframes measure { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
.lm-jump { animation: lm-jump 2.6s ease-in-out infinite; }
@keyframes lm-jump {
  0%, 52%, 100% { transform: translateY(0); }
  60% { transform: translateY(-34px); }
  64% { transform: translateY(-36px); }
  72% { transform: translateY(0); }
  76% { transform: translateY(-4px); }
  80% { transform: translateY(0); }
}

/* little pickle scale ghost */
.ghost-fade { opacity: 0; animation: ghost-fade 0.8s 1.1s ease forwards; }
@keyframes ghost-fade { to { opacity: 0.35; } }

/* finale */
.team-in { animation: team-in 0.85s cubic-bezier(0.2, 1, 0.4, 1) both; }
@keyframes team-in { from { transform: translateX(var(--fromX, -650px)); } to { transform: none; } }
.rally-ball { animation: rally 3.4s 1.2s ease-in-out infinite; }
@keyframes rally {
  0%   { transform: translate(0, 0) rotate(0deg); }
  25%  { transform: translate(190px, -120px) rotate(180deg); }
  50%  { transform: translate(380px, 0) rotate(360deg); }
  75%  { transform: translate(190px, -150px) rotate(540deg); }
  100% { transform: translate(0, 0) rotate(720deg); }
}
.net-sway { animation: sway 4s ease-in-out infinite; transform-box: fill-box; transform-origin: top center; }

/* confetti */
.confetti {
  position: fixed;
  top: -24px;
  width: 11px;
  height: 15px;
  z-index: 6;
  pointer-events: none;
  animation: confetti-fall linear infinite;
}
@keyframes confetti-fall {
  0%   { transform: translate(0, -6vh) rotate(0turn); opacity: 1; }
  25%  { transform: translate(3vw, 22vh) rotate(0.8turn); }
  50%  { transform: translate(-2vw, 48vh) rotate(1.6turn); }
  75%  { transform: translate(3vw, 76vh) rotate(2.4turn); }
  92%  { opacity: 1; }
  100% { transform: translate(-1vw, 108vh) rotate(3.1turn); opacity: 0; }
}

/* ============ small screens ============ */
@media (max-width: 640px) {
  .art svg { max-height: 48vh; }
  #hint { font-size: 0.72rem; }
}

/* No reduced-motion override on purpose: the animation IS the content
   on this site, and Windows' "show animations" toggle would otherwise
   silently turn the whole montage into a slideshow. */
