/* Match finale — last-10-seconds tension + the victory reveal.
   Paired with public/js/finale.js. Kept out of app.css so the end-of-match
   theatre is one file you can read, tune, or rip out on its own.

   Layering: the countdown sits at z-index 4 — UNDER the HUD (5), the timer (6)
   and the scoreboard (5) — and never takes pointer events, so it can never cost
   a player the match it is trying to make exciting. The reveal sits at 19, just
   above the results overlay (18), and fades out to hand over to it. */

/* ---- Last ten seconds ---- */
#finaleLayer {
  position: fixed; inset: 0; z-index: 4; pointer-events: none;
  display: none; align-items: center; justify-content: center;
}
#finaleLayer.on { display: flex; }

/* Arena edge — one breath per second in the arena's own blue (#7fe3ff), kept
   deliberately faint: this is a heartbeat, not an alarm. Deeper in the last
   three, and the FINAL pulse takes its colour from where you placed:
   green + gold for 1st, purple + red for the rest of the podium, red for
   everyone else. You feel the result a second before you read it. */
#finaleRing {
  position: absolute; inset: 0; opacity: 0;
  box-shadow: inset 0 0 120px 20px rgba(127, 227, 255, 0.28);
}
#finaleRing.pulse { animation: fin-ring 1s ease-out; }
#finaleLayer.hot #finaleRing { box-shadow: inset 0 0 165px 28px rgba(127, 227, 255, 0.36); }
#finaleLayer.win #finaleRing {
  box-shadow: inset 0 0 175px 30px rgba(125, 255, 166, 0.5), inset 0 0 90px 12px rgba(255, 209, 92, 0.45);
}
#finaleLayer.podium #finaleRing {
  box-shadow: inset 0 0 175px 30px rgba(178, 112, 255, 0.5), inset 0 0 90px 12px rgba(255, 70, 70, 0.4);
}
#finaleLayer.lose #finaleRing { box-shadow: inset 0 0 175px 30px rgba(255, 62, 62, 0.5); }
@keyframes fin-ring {
  0% { opacity: 0; }
  18% { opacity: 0.85; }
  100% { opacity: 0; }
}

/* The count sits in the band between the top UI and the top of your own blob —
   JS sets `top`, `height` and `font-size` each frame, because that gap closes as
   you grow. Never over the player, never under the HUD. */
#finaleBig {
  position: absolute; left: 0; right: 0; display: flex;
  align-items: center; justify-content: center;
  line-height: 1; font-weight: 900;
  font-variant-numeric: tabular-nums; letter-spacing: -0.04em;
  color: rgba(255, 255, 255, 0.16);
  /* Glow for mood, dark halo for legibility — a screen-filling blob leaves no
     clear space, and the number still has to read against it. */
  text-shadow: 0 0 60px rgba(127, 227, 255, 0.35), 0 2px 18px rgba(0, 0, 0, 0.55);
  transform: scale(1);
}
#finaleLayer.hot #finaleBig { color: rgba(190, 240, 255, 0.24); }
#finaleLayer.win #finaleBig { color: rgba(160, 255, 190, 0.34); text-shadow: 0 0 60px rgba(255, 209, 92, 0.5); }
#finaleLayer.podium #finaleBig { color: rgba(210, 170, 255, 0.32); text-shadow: 0 0 60px rgba(255, 70, 70, 0.4); }
#finaleLayer.lose #finaleBig { color: rgba(255, 140, 140, 0.3); text-shadow: 0 0 60px rgba(255, 62, 62, 0.4); }
#finaleBig.punch { animation: fin-punch 1s cubic-bezier(0.16, 1, 0.3, 1); }
/* Punch stays close to 1× — a bigger overshoot would swing the number out of its
   band and back onto the player for a few frames. */
@keyframes fin-punch {
  0% { transform: scale(1.22); opacity: 0; }
  12% { opacity: 1; }
  100% { transform: scale(0.92); opacity: 0.35; }
}

/* Banner goes BELOW your blob — the count is above it, so the two never stack
   and neither one lands on the player. Clears the mobile sticks too. */
#finaleBanner {
  position: absolute; bottom: 24vh; left: 50%; transform: translateX(-50%);
  font-size: clamp(16px, 3.4vw, 30px); font-weight: 800; letter-spacing: 5px;
  color: #ff6b6b; text-shadow: 0 4px 30px rgba(255, 60, 60, 0.6);
  opacity: 0; white-space: nowrap;
}
#finaleBanner.play { animation: fin-banner 2.2s ease-out forwards; }
@keyframes fin-banner {
  0% { opacity: 0; transform: translate(-50%, 14px) scale(0.9); letter-spacing: 14px; }
  14% { opacity: 1; transform: translate(-50%, 0) scale(1); }
  70% { opacity: 1; }
  100% { opacity: 0; letter-spacing: 5px; }
}

/* The real clock joins in — the precise number stays readable at all times. */
#timer.finale { color: #ff8f8f; box-shadow: 0 0 0 1px rgba(255, 90, 90, 0.5), 0 0 26px rgba(255, 60, 60, 0.35); }
#timer.finale-hot { animation: fin-tick 1s ease-out infinite; }
@keyframes fin-tick {
  0% { transform: translateX(-50%) scale(1.12); color: #fff; }
  40% { transform: translateX(-50%) scale(1); color: #ff8f8f; }
  100% { transform: translateX(-50%) scale(1); }
}

/* ---- Victory reveal ---- */
#finaleReveal {
  position: fixed; inset: 0; z-index: 19; display: none;
  align-items: center; justify-content: center; overflow: hidden;
  background: radial-gradient(circle at center, rgba(12, 14, 30, 0.86), rgba(3, 4, 10, 0.97));
  color: #fff; text-align: center;
}
#finaleReveal.show { display: flex; animation: fin-in 0.28s ease-out; }
#finaleReveal.out { animation: fin-out 0.4s ease-in forwards; }
@keyframes fin-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes fin-out { to { opacity: 0; } }

#finaleReveal .fr-flash {
  position: absolute; inset: 0; background: #fff; opacity: 0;
  animation: fin-flash 0.45s ease-out;
}
@keyframes fin-flash { 0% { opacity: 0.75; } 100% { opacity: 0; } }

#finaleReveal .fr-shock {
  position: absolute; width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid rgba(255, 209, 92, 0.8); opacity: 0;
  animation: fin-shock 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes fin-shock {
  0% { transform: scale(1); opacity: 0.9; }
  100% { transform: scale(46); opacity: 0; }
}

/* Shaft of light behind the winner — only once the champion beat lands. */
#finaleReveal .fr-beam {
  position: absolute; top: -20%; left: 50%; width: 46vw; height: 140%;
  transform: translateX(-50%) scaleY(0); transform-origin: top center;
  background: linear-gradient(180deg, rgba(255, 209, 92, 0.28), rgba(255, 209, 92, 0));
  filter: blur(22px); opacity: 0;
}
#finaleReveal.step2 .fr-beam { animation: fin-beam 1.6s ease-out forwards; }
@keyframes fin-beam {
  0% { transform: translateX(-50%) scaleY(0.2); opacity: 0; }
  30% { opacity: 1; }
  100% { transform: translateX(-50%) scaleY(1); opacity: 0.75; }
}
#finaleReveal.none .fr-beam { display: none; }

#finaleReveal .fr-over {
  position: absolute; font-size: clamp(34px, 9vw, 92px); font-weight: 900;
  letter-spacing: 8px; color: #fff; text-shadow: 0 10px 50px rgba(0, 0, 0, 0.8);
  animation: fin-slam 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes fin-slam {
  0% { transform: scale(2.6); opacity: 0; filter: blur(10px); }
  100% { transform: scale(1); opacity: 1; filter: blur(0); }
}
#finaleReveal.step2 .fr-over { animation: fin-lift 0.45s ease-in forwards; }
@keyframes fin-lift { to { transform: translateY(-46px) scale(0.7); opacity: 0; } }

#finaleReveal .fr-champ {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  opacity: 0; transform: translateY(18px) scale(0.9); padding: 0 18px;
}
#finaleReveal.step2 .fr-champ { animation: fin-champ 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards; }
@keyframes fin-champ {
  0% { opacity: 0; transform: translateY(18px) scale(0.86); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
#finaleReveal .fr-crown { font-size: clamp(40px, 8vw, 74px); filter: drop-shadow(0 8px 26px rgba(255, 200, 80, 0.6)); }
#finaleReveal.step2 .fr-crown { animation: fin-drop 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) 0.05s backwards; }
@keyframes fin-drop { 0% { transform: translateY(-70px) rotate(-25deg); opacity: 0; } 100% { transform: none; opacity: 1; } }
#finaleReveal.none .fr-crown { display: none; }

#finaleReveal .fr-label {
  font-size: clamp(12px, 2vw, 16px); font-weight: 800; letter-spacing: 7px; color: #ffd15c;
}
#finaleReveal.mine .fr-label { color: #7dffa6; }
#finaleReveal .fr-name {
  font-size: clamp(30px, 7vw, 74px); font-weight: 900; letter-spacing: 0.5px; line-height: 1.05;
  max-width: 92vw; overflow-wrap: anywhere;
  background: linear-gradient(180deg, #fff, #ffd15c);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: 0 12px 60px rgba(255, 200, 80, 0.35);
}
#finaleReveal.none .fr-name { background: none; color: #cdd6ef; -webkit-text-fill-color: #cdd6ef; font-size: clamp(24px, 5vw, 44px); }
#finaleReveal .fr-score { font-size: clamp(14px, 2.4vw, 20px); color: #9fe8ff; font-weight: 700; letter-spacing: 0.4px; }
#finaleReveal .fr-skip { position: absolute; bottom: 26px; font-size: 12px; color: rgba(255, 255, 255, 0.35); letter-spacing: 1px; }

#finaleReveal .fr-confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
#finaleReveal .fr-confetti i {
  position: absolute; top: -6vh; width: 9px; height: 14px; border-radius: 2px;
  animation-name: fin-fall; animation-timing-function: linear; animation-fill-mode: forwards;
}
@keyframes fin-fall {
  0% { transform: translate(0, 0) rotate(0); opacity: 1; }
  100% { transform: translate(var(--drift), 112vh) rotate(var(--spin)); opacity: 0.15; }
}

/* ---- Calm mode: same beats, no assault ---- */
@media (prefers-reduced-motion: reduce) {
  #finaleBig.punch, #finaleRing.pulse, #finaleBanner.play,
  #timer.finale-hot, #finaleReveal .fr-shock, #finaleReveal .fr-flash,
  #finaleReveal .fr-over, #finaleReveal.step2 .fr-over,
  #finaleReveal.step2 .fr-beam, #finaleReveal.step2 .fr-crown,
  #finaleReveal.step2 .fr-champ, #finaleReveal.show { animation: none; }
  #finaleBig { opacity: 0.3; }
  #finaleBanner.play { opacity: 1; }
  #finaleRing.pulse { opacity: 0.4; }
  #finaleReveal .fr-champ { opacity: 1; transform: none; }
  #finaleReveal.step2 .fr-over { display: none; }
  #finaleReveal .fr-beam { opacity: 0.5; transform: translateX(-50%) scaleY(1); }
}
