/**
 * Keyframe Animations
 *
 * All @keyframes definitions are centralised here so components can reference
 * them by name from their own stylesheets.
 */

/** Pulsing glow — used by the live indicator dot and urgent bet timers. */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.3; }
}

/** Brief scale-up when the points total changes. */
@keyframes pointsBump {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.15); }
  100% { transform: scale(1); }
}

/** Confetti pieces fall from the top of the viewport. */
@keyframes confettiFall {
  0%   { opacity: 1; transform: translateY(0)     rotate(0deg)   scale(1); }
  100% { opacity: 0; transform: translateY(100vh) rotate(720deg) scale(0.3); }
}

/** Suspense dots bounce while waiting for the win reveal. */
@keyframes suspenseDot {
  0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
  40%           { opacity: 1;   transform: translateY(-5px); }
}

/** Clutch Time — screen-edge red/gold glow, pulses to signal urgency. */
@keyframes clutchEdgePulse {
  0%, 100% {
    box-shadow: inset 0 0 0 3px rgba(255, 55, 55, 0.65),
                inset 0 0 60px rgba(255, 55, 55, 0.08),
                inset 0 0 0 6px rgba(255, 213, 79, 0.22);
  }
  50% {
    box-shadow: inset 0 0 0 5px rgba(255, 55, 55, 0.95),
                inset 0 0 90px rgba(255, 55, 55, 0.18),
                inset 0 0 0 10px rgba(255, 213, 79, 0.40);
  }
}

/** Clutch countdown number — scales down once per second for a heartbeat feel. */
@keyframes clutchCountdownTick {
  0%   { transform: scale(1.35); opacity: 0.7; }
  40%  { transform: scale(1);    opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}

/** Clutch banner slides in from the top. */
@keyframes clutchBannerSlideIn {
  from { opacity: 0; transform: translateY(-100%); }
  to   { opacity: 1; transform: translateY(0); }
}

/** Loading skeleton shimmer — sweeps a highlight across a placeholder block. */
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}

/** Gentle fade-and-rise used for brief cards and featured player cards. */
@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/** Bet card blink-out — three quick flashes then fade, before a replacement bet appears. */
@keyframes betBlinkOut {
  0%   { opacity: 1; }
  18%  { opacity: 0.08; }
  36%  { opacity: 0.9; }
  54%  { opacity: 0.08; }
  72%  { opacity: 0.75; }
  100% { opacity: 0; }
}

/* ─── Card Physics Animations ──────────────────────────────────────────────── */

/** New card enters from the left with spring overshoot. */
@keyframes cardSlideInLeft {
  0%   { opacity: 0; transform: translateX(-105%) rotate(-2deg); }
  55%  { opacity: 1; transform: translateX(3%)    rotate(0.3deg); }
  75%  {             transform: translateX(-1%)   rotate(0deg); }
  100% { opacity: 1; transform: translateX(0)     rotate(0deg); }
}

/** New card enters from the right with spring overshoot. */
@keyframes cardSlideInRight {
  0%   { opacity: 0; transform: translateX(105%) rotate(2deg); }
  55%  { opacity: 1; transform: translateX(-3%)  rotate(-0.3deg); }
  75%  {             transform: translateX(1%)   rotate(0deg); }
  100% { opacity: 1; transform: translateX(0)    rotate(0deg); }
}

/** Old card flings off to the right with accelerating rotation. */
@keyframes cardSlideOutRight {
  0%   { opacity: 1; transform: translateX(0)    rotate(0deg); }
  30%  { opacity: 1; transform: translateX(8%)   rotate(1.5deg); }
  100% { opacity: 0; transform: translateX(115%) rotate(8deg); }
}

/** Old card flings off to the left with accelerating rotation. */
@keyframes cardSlideOutLeft {
  0%   { opacity: 1; transform: translateX(0)     rotate(0deg); }
  30%  { opacity: 1; transform: translateX(-8%)   rotate(-1.5deg); }
  100% { opacity: 0; transform: translateX(-115%) rotate(-8deg); }
}

/** Won card celebrates with a satisfying pop-and-settle. */
@keyframes cardWinPop {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(102, 187, 106, 0); }
  35%  { transform: scale(1.04); box-shadow: 0 0 20px 4px rgba(102, 187, 106, 0.35); }
  70%  { transform: scale(0.98); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(102, 187, 106, 0); }
}

/** Lost card slumps with a slight tilt and fade. */
@keyframes cardLoseSlump {
  0%   { opacity: 1;   transform: translateX(0) rotate(0deg); }
  40%  { opacity: 0.8; transform: translateX(3px) rotate(0.8deg); }
  100% { opacity: 0.7; transform: translateX(0) rotate(0deg); }
}

/** Expired card quietly shrinks away. */
@keyframes cardExpireShrink {
  0%   { opacity: 1;   transform: scale(1); }
  100% { opacity: 0.5; transform: scale(0.97); }
}

/** Resolved card slides down into the results section. */
@keyframes cardSettleDown {
  0%   { opacity: 0; transform: translateY(-12px) scale(0.97); }
  60%  { opacity: 1; transform: translateY(2px)   scale(1); }
  100% { opacity: 1; transform: translateY(0)     scale(1); }
}

/** Tap feedback — quick scale-down-and-back with overshoot for satisfying press. */
@keyframes tapBounce {
  0%   { transform: scale(1); }
  40%  { transform: scale(0.93); }
  70%  { transform: scale(1.02); }
  100% { transform: scale(1); }
}

/** Selection pop — brief scale-up when an option is chosen. */
@keyframes selectPop {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}

/* ─── Screen Shake Animations (PopCap juice) ─────────────────────────────── */

/** Light shake — standard win. */
@keyframes shakeWin {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-2px); }
  40%      { transform: translateX(3px); }
  60%      { transform: translateX(-2px); }
  80%      { transform: translateX(1px); }
}

/** Medium shake — big win (200+ pts). */
@keyframes shakeBig {
  0%, 100% { transform: translateX(0) translateY(0); }
  15%      { transform: translateX(-4px) translateY(1px); }
  30%      { transform: translateX(5px) translateY(-1px); }
  45%      { transform: translateX(-3px) translateY(2px); }
  60%      { transform: translateX(4px) translateY(-1px); }
  75%      { transform: translateX(-2px); }
  90%      { transform: translateX(1px); }
}

/** Heavy shake — jackpot (500+ pts). */
@keyframes shakeJackpot {
  0%, 100% { transform: translateX(0) translateY(0) rotate(0); }
  10%      { transform: translateX(-6px) translateY(2px) rotate(-0.5deg); }
  20%      { transform: translateX(7px) translateY(-2px) rotate(0.5deg); }
  30%      { transform: translateX(-5px) translateY(3px) rotate(-0.3deg); }
  40%      { transform: translateX(6px) translateY(-1px) rotate(0.4deg); }
  50%      { transform: translateX(-4px) translateY(2px) rotate(-0.2deg); }
  60%      { transform: translateX(3px) translateY(-1px) rotate(0.2deg); }
  70%      { transform: translateX(-2px) translateY(1px); }
  80%      { transform: translateX(1px); }
}

/** Loss rumble — short, heavy, downward. */
@keyframes shakeLose {
  0%, 100% { transform: translateX(0) translateY(0); }
  25%      { transform: translateX(-3px) translateY(2px); }
  50%      { transform: translateX(3px) translateY(1px); }
  75%      { transform: translateX(-2px) translateY(1px); }
}

/** Streak fire particle — rises from bottom with wobble. */
@keyframes streakFireRise {
  0%   { opacity: 1; transform: translateY(0) scale(1) rotate(0deg); }
  50%  { opacity: 0.9; transform: translateY(-40vh) scale(1.3) rotate(15deg); }
  100% { opacity: 0; transform: translateY(-70vh) scale(0.6) rotate(-10deg); }
}

/** Swipe commit flash — brief glow when a swipe locks in. */
@keyframes swipeCommitFlash {
  0%   { box-shadow: 0 0 0 0 rgba(79, 195, 247, 0.6); }
  50%  { box-shadow: 0 0 25px 5px rgba(79, 195, 247, 0.3); }
  100% { box-shadow: 0 0 0 0 rgba(79, 195, 247, 0); }
}

/** Glow ring — subtle expanding ring on tap, like a ripple. */
@keyframes tapRing {
  0%   { box-shadow: 0 0 0 0 var(--tap-glow); }
  50%  { box-shadow: 0 0 0 6px var(--tap-glow); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/** Score digit change — rolls the number with a subtle bounce. */
@keyframes digitChange {
  0%   { transform: translateY(0);    opacity: 1; }
  30%  { transform: translateY(-30%); opacity: 0.4; }
  60%  { transform: translateY(10%);  opacity: 0.8; }
  100% { transform: translateY(0);    opacity: 1; }
}

/** Streak badge entrance — pops in from nothing. */
@keyframes badgePop {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/** Data-delay badge — fades between full and half opacity to signal stale feed. */
@keyframes feedDelayPulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.5; }
}

/* ─── Logo Splash Animations ───────────────────────────────────────────────── */

/** Logo pops in with a scale + glow burst. */
@keyframes splashLogoIn {
  0%   { opacity: 0; transform: scale(0.6); filter: brightness(0) invert(1) drop-shadow(0 0 0px #4fc3f7); }
  55%  { opacity: 1; transform: scale(1.08); filter: brightness(0) invert(1) drop-shadow(0 0 28px #4fc3f7); }
  75%  {             transform: scale(0.97); filter: brightness(0) invert(1) drop-shadow(0 0 12px #4fc3f7); }
  100% { opacity: 1; transform: scale(1);   filter: brightness(0) invert(1) drop-shadow(0 0 6px rgba(79,195,247,0.5)); }
}

/** Subtitle fades and rises in after the logo settles. */
@keyframes splashSubIn {
  0%   { opacity: 0; transform: translateY(10px); letter-spacing: 0.25em; }
  100% { opacity: 1; transform: translateY(0);    letter-spacing: 0.18em; }
}

/** Whole splash overlay fades out. */
@keyframes splashFadeOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
