/* ============================================
   Aurora Backgrounds — @property animated gradients
   Browsers without @property see static gradients (graceful fallback).
   ============================================ */

@property --aurora-1 {
  syntax: "<color>";
  initial-value: #1a1a2e;
  inherits: false;
}

@property --aurora-2 {
  syntax: "<color>";
  initial-value: #2d1b69;
  inherits: false;
}

@keyframes aurora-shift {
  0%,
  100% {
    --aurora-1: #1a1a2e;
    --aurora-2: #2d1b69;
  }
  33% {
    --aurora-1: #1e1a35;
    --aurora-2: #351d78;
  }
  66% {
    --aurora-1: #181e38;
    --aurora-2: #291560;
  }
}

/**
 * K-Pop Demon Hunters — Animations
 * All animations use transform and opacity only for 60fps GPU-accelerated performance.
 * No layout-triggering properties (width, height, margin, padding) in keyframes.
 */

/* ============================================
   1. Micro-Animations (UI Feedback)
   ============================================ */

/* Pulsing text, hints — 1.5s loop */
@keyframes sparkle-pulse {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
}

/* Popups, rewards, new elements — 300ms */
@keyframes bounce-in {
  0% {
    transform: scale(0.7);
    opacity: 0;
  }
  65% {
    transform: scale(1.08);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Idle character sprites, demon icons on map — 600ms loop */
@keyframes bounce-subtle {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4px);
  }
}

/* Wrong puzzle input, locked item tap — 200ms */
@keyframes shake-wrong {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-4px);
  }
  50% {
    transform: translateX(4px);
  }
  75% {
    transform: translateX(-4px);
  }
}

/* Selected cards, upgrade-ready weapons — 2s loop */
@keyframes glow-pulse {
  0%,
  100% {
    box-shadow: 0 0 10px var(--gold-30);
  }
  50% {
    box-shadow:
      0 0 24px var(--gold-70),
      0 0 48px var(--gold-20);
  }
}

/* Button press feedback — 100ms */
@keyframes scale-tap {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}

/* Generic element appearance — 200ms */
@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Generic element exit — 200ms */
@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* List items, staggered entry — 300ms */
@keyframes slide-up-in {
  from {
    transform: translateY(20px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* ============================================
   2. Scene Transitions
   ============================================
   Applied by app.js scene manager.
   Forward: slide in from right, exit to left.
   Back: slide in from left, exit to right.
   Exit slides use -30% (partial slide) for a layered feel.
   ============================================ */

@keyframes scene-slide-in-right {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

@keyframes scene-slide-out-left {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-30%);
  }
}

@keyframes scene-slide-in-left {
  from {
    transform: translateX(-30%);
  }
  to {
    transform: translateX(0);
  }
}

@keyframes scene-slide-out-right {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}

.scene-enter {
  animation: scene-slide-in-right 300ms var(--ease-out-expo) forwards;
  will-change: transform, opacity;
}

.scene-exit {
  animation: scene-slide-out-left 300ms var(--ease-out-expo) forwards;
  will-change: transform, opacity;
}

.scene-enter-back {
  animation: scene-slide-in-left 300ms var(--ease-out-expo) forwards;
  will-change: transform, opacity;
}

.scene-exit-back {
  animation: scene-slide-out-right 300ms var(--ease-out-expo) forwards;
  will-change: transform, opacity;
}

/* ============================================
   3. Overlay Animations
   ============================================
   Overlays render on top of current scene.
   Backdrop fades, content slides up.
   ============================================ */

@keyframes overlay-backdrop-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes overlay-backdrop-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

@keyframes overlay-content-up {
  from {
    transform: translateY(40px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes overlay-content-down {
  from {
    transform: translateY(0);
    opacity: 1;
  }
  to {
    transform: translateY(40px);
    opacity: 0;
  }
}

/* Popup/toast entry with bounce easing */
@keyframes popup-bounce-in {
  from {
    transform: scale(0.8);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

.overlay-enter .overlay-backdrop {
  animation: overlay-backdrop-in 200ms var(--ease-out-quart) forwards;
}

.overlay-enter .overlay-content {
  animation: overlay-content-up 300ms var(--ease-out-expo) forwards;
}

.overlay-exit .overlay-backdrop {
  animation: overlay-backdrop-out 200ms ease-in forwards;
}

.overlay-exit .overlay-content {
  animation: overlay-content-down 200ms ease-in forwards;
}

/* Tab content crossfade */
@keyframes tab-crossfade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.tab-enter {
  animation: tab-crossfade 200ms ease-in-out forwards;
}

/* ============================================
   4. Sparkle Particle System (CSS-only)
   ============================================
   Particles are <span> elements with absolute positioning.
   CSS custom properties (--delay, --x, --y, --size)
   are randomized via JS on creation.
   Particles are removed from DOM after animation ends.
   ============================================ */

/* --- Sparkle Ambient ---
   Slow floating dots, gold/white, 4-8s staggered loop.
   Used on splash screen, HQ background. */

@keyframes sparkle-float-up {
  0% {
    transform: translate(var(--x, 0), 0) scale(var(--size, 1));
    opacity: 0;
  }
  15% {
    opacity: 0.8;
  }
  85% {
    opacity: 0.8;
  }
  100% {
    transform: translate(calc(var(--x, 0) + var(--drift-x, 10px)), -60px) scale(calc(var(--size, 1) * 0.6));
    opacity: 0;
  }
}

.sparkle-ambient {
  position: relative;
  overflow: hidden;
}

.sparkle-ambient .sparkle-particle {
  position: absolute;
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: var(--border-radius-circle);
  background: var(--color, #ffd700);
  pointer-events: none;
  animation: sparkle-float-up var(--duration, 6s) ease-in-out var(--delay, 0s) infinite;
}

/* --- Sparkle Burst ---
   Radiate outward from center, 600ms fade out.
   Used on correct puzzle input, weapon charge, celebrations. */

@keyframes sparkle-burst-out {
  0% {
    transform: translate(0, 0) scale(1);
    opacity: 1;
  }
  100% {
    transform: translate(var(--burst-x, 20px), var(--burst-y, -20px)) scale(0.3);
    opacity: 0;
  }
}

.sparkle-burst {
  position: relative;
}

.sparkle-burst .sparkle-particle {
  position: absolute;
  width: var(--size, 4px);
  height: var(--size, 4px);
  border-radius: var(--border-radius-circle);
  background: var(--color, #ffd700);
  pointer-events: none;
  animation: sparkle-burst-out 600ms ease-out var(--delay, 0s) forwards;
  will-change: transform, opacity;
}

/* Star-shaped burst particles (larger, for celebrations) */
.sparkle-burst .sparkle-star {
  position: absolute;
  width: var(--size, 6px);
  height: var(--size, 6px);
  background: var(--color, #ffd700);
  pointer-events: none;
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  animation: sparkle-burst-out 600ms ease-out var(--delay, 0s) forwards;
  will-change: transform, opacity;
}

/* --- Sparkle Rain ---
   Fall from top, rainbow colors, 3-5s staggered loop.
   Used on victory screen (Phase 3). */

@keyframes sparkle-fall {
  0% {
    transform: translate(var(--x, 0), -20px) rotate(0deg) scale(var(--size, 1));
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 0.8;
  }
  100% {
    transform: translate(calc(var(--x, 0) + var(--drift-x, 15px)), calc(100dvh + 20px)) rotate(360deg)
      scale(calc(var(--size, 1) * 0.5));
    opacity: 0;
  }
}

/* Sparkle Rain, Trail, Collect — @keyframes kept for future particle systems.
   Parent container classes removed (unused). */

/* ============================================
   5. Animation Utility Classes
   ============================================ */

/* Direct animation applications */
.anim-pulse {
  animation: sparkle-pulse 1.5s ease-in-out infinite;
}

.anim-bounce {
  animation: bounce-in 300ms var(--ease-out-expo) forwards;
}

.anim-bounce-loop {
  animation: bounce-subtle 600ms ease-in-out infinite;
}

.anim-shake {
  animation: shake-wrong 200ms ease-in-out;
}

/* Badge pulse for nav notification dots */
@keyframes badge-pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.4);
  }
}

/* NEW! badge sparkle pulse on Sparkle Map demon icons */
.map-demon-badge {
  animation: badge-new-pulse 2s ease-in-out infinite;
}

@keyframes badge-new-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.15);
    opacity: 0.85;
  }
}

/* Button press feedback on :active */
.anim-tap:active {
  animation: scale-tap 150ms var(--ease-out-quart);
}

/* ============================================
   6. Special Effects
   ============================================ */

/* --- Sparkle Text Shimmer ---
   Animated gradient that slides across text.
   Apply to headings for sparkle effect. */

@keyframes shimmer-slide {
  0% {
    background-position: -200% center;
  }
  100% {
    background-position: 200% center;
  }
}

.sparkle-text {
  background: linear-gradient(
    90deg,
    #ffffff 0%,
    #ffd700 15%,
    #fff8e1 35%,
    #ff69b4 50%,
    #fff8e1 65%,
    #ffd700 85%,
    #ffffff 100%
  );
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shimmer-slide 2.5s linear infinite;
}

/* ============================================
   7. Puzzle Animations
   ============================================ */

/* Correct input pulse — 300ms, scale up then back */
@keyframes correct-pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

/* Hint shimmer — fast pulse for auto-hint stars */
@keyframes hint-shimmer {
  0%,
  100% {
    opacity: 0.55;
    transform: scale(0.95);
  }
  50% {
    opacity: 1;
    transform: scale(1.05);
  }
}

/* Hint glow on input buttons */
@keyframes hint-glow-btn {
  0%,
  100% {
    box-shadow: 0 0 4px var(--white-20);
  }
  50% {
    box-shadow: 0 0 18px rgba(255, 255, 255, 0.7);
  }
}

/* Button activate bounce */
@keyframes btn-activate {
  0% {
    transform: scale(0.9);
    opacity: 0.6;
  }
  60% {
    transform: scale(1.05);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* White flash on wrong input */
@keyframes white-flash {
  0% {
    background-color: var(--white-80);
  }
  100% {
    background-color: transparent;
  }
}

.pm-btn.white-flash-anim {
  animation: white-flash 100ms ease-out;
}

/* Full sparkle burst on puzzle complete */
@keyframes puzzle-complete-burst {
  0% {
    transform: scale(0.5);
    opacity: 1;
  }
  60% {
    transform: scale(1.5);
    opacity: 0.8;
  }
  100% {
    transform: scale(2);
    opacity: 0;
  }
}

.puzzle-complete-burst {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 200px;
  margin: -100px 0 0 -100px;
  border-radius: var(--border-radius-circle);
  background: radial-gradient(
    circle,
    rgba(255, 215, 0, 0.95),
    rgba(255, 105, 180, 0.55),
    rgba(147, 112, 219, 0.2),
    transparent
  );
  pointer-events: none;
  animation: puzzle-complete-burst 800ms ease-out forwards;
  z-index: var(--z-header);
}

/* ============================================
   8. Screen-Specific Animations
   ============================================ */

/* --- Splash: Logo sparkle drift ---
   Gold dots orbit slowly around logo text. */

@keyframes logo-orbit {
  0% {
    transform: rotate(0deg) translateX(var(--orbit-radius, 60px)) rotate(0deg) scale(var(--size, 1));
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: rotate(360deg) translateX(var(--orbit-radius, 60px)) rotate(-360deg) scale(var(--size, 1));
    opacity: 0.6;
  }
}

.logo-sparkle {
  position: absolute;
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: var(--border-radius-circle);
  background: var(--text-gold);
  pointer-events: none;
  animation: logo-orbit var(--duration, 8s) linear var(--delay, 0s) infinite;
}

/* --- Character Pick: Card selection ---
   Selected card scales up with glow. */

@keyframes card-select {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(1.05);
  }
}

.card-selected {
  animation: card-select 200ms ease-out forwards;
}

/* --- Weapon Charge: Charge glow & pulse ---
   Weapon brightness ramps per tap, scale pulse on tap. */

@keyframes charge-pulse {
  0% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

/* Charge brightness levels (set via JS: data-charge="1" through "5") */
.weapon-charging[data-charge="0"] {
  filter: brightness(0.3) grayscale(0.5);
}
.weapon-charging[data-charge="1"] {
  filter: brightness(0.5) grayscale(0.3);
}
.weapon-charging[data-charge="2"] {
  filter: brightness(0.7) grayscale(0.15);
}
.weapon-charging[data-charge="3"] {
  filter: brightness(0.85) grayscale(0);
}
.weapon-charging[data-charge="4"] {
  filter: brightness(1) grayscale(0);
}
.weapon-charging[data-charge="5"] {
  filter: brightness(1.2) grayscale(0);
}

/* Full charge explosion */
@keyframes charge-complete {
  0% {
    transform: scale(1);
  }
  30% {
    transform: scale(1.4);
  }
  60% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.charge-complete {
  animation: charge-complete 600ms ease-out forwards;
  filter: brightness(1.3) grayscale(0) !important;
}

/* --- Puzzle: Correct step celebration ---
   Reuses correct-pulse keyframe (line 517). */

.puzzle-correct {
  animation: correct-pulse 150ms ease-out;
}

/* --- Puzzle: Wrong input flash ---
   Brief white overlay flash on wrong answer. */

@keyframes wrong-flash {
  0% {
    opacity: 0;
  }
  30% {
    opacity: 0.4;
  }
  100% {
    opacity: 0;
  }
}

.wrong-flash::after {
  content: "";
  position: absolute;
  inset: 0;
  background: white;
  border-radius: inherit;
  pointer-events: none;
  animation: wrong-flash 100ms ease-out forwards;
}

/* --- Victory: Phase 3 title ---
   Big sparkle title bounces in. */

@keyframes victory-title {
  0% {
    transform: scale(0.2);
    opacity: 0;
  }
  55% {
    transform: scale(1.15);
    opacity: 1;
  }
  75% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.victory-title {
  animation: victory-title 500ms var(--ease-out-expo) forwards;
}

/* --- Upgrade: Weapon sprite crossfade ---
   Old sprite fades out, new fades in. */

@keyframes upgrade-fade-out {
  from {
    opacity: 1;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(0.8);
  }
}

@keyframes upgrade-fade-in {
  from {
    opacity: 0;
    transform: scale(1.2);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.upgrade-out {
  animation: upgrade-fade-out 500ms ease-in forwards;
}

.upgrade-in {
  animation: upgrade-fade-in 500ms ease-out 500ms forwards;
  opacity: 0;
}

/* --- XP Bar Fill ---
   Animated progress bar fill. */

@keyframes xp-fill {
  from {
    transform: scaleX(var(--xp-from, 0));
  }
  to {
    transform: scaleX(var(--xp-to, 1));
  }
}

.xp-bar-fill {
  transform-origin: left center;
  animation: xp-fill 500ms ease-out forwards;
}

/* --- Typewriter Text ---
   Characters revealed one at a time by JS,
   but the cursor blink is CSS. */

@keyframes cursor-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

.typewriter-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: var(--text-primary);
  animation: cursor-blink 800ms step-end infinite;
  vertical-align: text-bottom;
}

/* --- Advance Indicator ---
   Pulsing chevron for dialogue tap-to-advance. */

@keyframes advance-pulse {
  0%,
  100% {
    opacity: 0.4;
    transform: translateY(0);
  }
  50% {
    opacity: 1;
    transform: translateY(3px);
  }
}

.advance-indicator {
  animation: advance-pulse 1s ease-in-out infinite;
}

/* ============================================
   9. Performance Hints
   ============================================
   Apply will-change to elements about to animate.
   Remove after animation completes to free GPU memory.
   ============================================ */

/* ============================================
   10. Reduced Motion
   ============================================
   Respect user preferences for reduced motion.
   Collapse all animations to near-instant.
   ============================================ */

/* ============================================
   11. Pattern Match+ & Medley Puzzle Animations
   ============================================ */

/* Shadow flicker — opacity pulses for Shade King round 2 */
@keyframes shadow-flicker {
  0%,
  100% {
    opacity: 1;
  }
  30% {
    opacity: 0.3;
  }
  35% {
    opacity: 1;
  }
  70% {
    opacity: 0.4;
  }
  75% {
    opacity: 1;
  }
}

/* Shadow glitch — rapid opacity + scale jitter for Shade King round 3 */
@keyframes shadow-glitch {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  10% {
    opacity: 0.2;
    transform: scale(0.9);
  }
  20% {
    opacity: 1;
    transform: scale(1);
  }
  40% {
    opacity: 0.3;
    transform: scale(0.95);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
  60% {
    opacity: 0.15;
    transform: scale(0.9);
  }
  70% {
    opacity: 0.9;
    transform: scale(1);
  }
  80% {
    opacity: 0.2;
    transform: scale(0.92);
  }
  90% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0.8;
    transform: scale(0.98);
  }
}

.puzzle-demon-circle.shadow-stable {
  /* no animation */
}

.puzzle-demon-circle.shadow-flickering {
  animation: shadow-flicker 3s ease-in-out infinite;
}

.puzzle-demon-circle.shadow-glitching {
  animation: shadow-glitch 700ms ease-in-out infinite;
}

/* Timer bar pulse for warning states */
@keyframes timer-pulse {
  0%,
  100% {
    box-shadow: 0 0 4px rgba(92, 224, 214, 0.3);
  }
  50% {
    box-shadow: 0 0 12px rgba(92, 224, 214, 0.7);
  }
}

/* Timer bar critical flash */
@keyframes timer-critical-flash {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

/* Round star fill animation for medley */
@keyframes round-star-fill {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  60% {
    transform: scale(1.3);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Medley round title card entrance */
@keyframes medley-round-title-in {
  0% {
    transform: scale(0.5);
    opacity: 0;
  }
  70% {
    transform: scale(1.1);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Onboarding: pulsing glow to draw attention to first-time actions */
@keyframes onboard-glow {
  0%,
  100% {
    box-shadow: 0 0 18px rgba(255, 215, 0, 0.12);
    border-color: var(--gold-25);
  }
  50% {
    box-shadow:
      0 0 28px rgba(255, 215, 0, 0.55),
      0 0 56px rgba(255, 215, 0, 0.22);
    border-color: rgba(255, 215, 0, 0.65);
  }
}

/* --- Equip Sparkle ---
   Quick gold glow pop when equipping a wardrobe item. */

@keyframes equip-pop {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 transparent;
  }
  40% {
    transform: scale(1.08);
    box-shadow: 0 0 18px var(--gold-60);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 transparent;
  }
}

.anim-equip-pop {
  animation: equip-pop 350ms var(--ease-out-expo) forwards;
}

/* --- Character Pick Celebration ---
   Excited wiggle when player selects a favorite character. */

@keyframes pick-celebrate {
  0% {
    transform: scale(1.15);
  }
  25% {
    transform: scale(1.2) rotate(-2deg);
  }
  50% {
    transform: scale(1.18) rotate(1.5deg);
  }
  75% {
    transform: scale(1.2) rotate(-1deg);
  }
  100% {
    transform: scale(1.15) rotate(0);
  }
}

/* --- Earned Item Bounce ---
   Satisfying bounce when tapping a collected sticker/card. */

@keyframes earned-bounce {
  0% {
    transform: scale(1);
  }
  30% {
    transform: scale(0.92);
  }
  60% {
    transform: scale(1.06);
  }
  100% {
    transform: scale(1);
  }
}

.anim-earned-bounce {
  animation: earned-bounce 300ms var(--ease-out-expo);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
