/* ==========================================================================
   Guard the Tower 2D — animations.css
   Menu transitions, geometric background motion, wave notifications, damage
   flashes, reward celebrations, victory animations, screen fades.
   ========================================================================== */

/* ==========================================================================
   KEYFRAMES — general
   ========================================================================== */

@keyframes emblem-pulse {
  0%, 100% { transform: scale(1);    filter: drop-shadow(0 0 18px rgba(196, 204, 216, 0.4)); }
  50%      { transform: scale(1.07); filter: drop-shadow(0 0 34px rgba(196, 204, 216, 0.75)); }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes drop-in {
  from { opacity: 0; transform: translateY(-32px) scale(0.94); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes pop-in {
  0%   { opacity: 0; transform: scale(0.72); }
  70%  { transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes slide-in-left {
  from { opacity: 0; transform: translateX(-26px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes slide-in-right {
  from { opacity: 0; transform: translateX(34px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin-slow { to { transform: rotate(360deg); } }
@keyframes spin-slow-rev { to { transform: rotate(-360deg); } }

@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-14px); }
}

@keyframes pulse-soft {
  0%, 100% { opacity: 0.75; }
  50%      { opacity: 1; }
}

/* ==========================================================================
   KEYFRAMES — main menu geometry & glow
   ========================================================================== */

/*
  IMPORTANT — the surfaces below (.menu-shell, .modal-box, .reward-box, #hud)
  carry a uniform UI scale on their `transform`. A running or fill-mode
  animation that sets `transform` outranks the CSS declaration in the
  cascade, so every keyframe here must re-apply the scale itself; otherwise
  the element silently snaps back to 1:1 and mobile scaling stops working.
*/
@keyframes shell-in {
  0%   { opacity: 0; transform: scale(var(--menu-scale, 1)) translateY(38px) scale(0.96); filter: blur(8px); }
  100% { opacity: 1; transform: scale(var(--menu-scale, 1)) translateZ(0); filter: blur(0); }
}

/* Entrance for scaled modal boxes. */
@keyframes modal-in {
  0%   { opacity: 0; transform: scale(var(--menu-scale, 1)) translateY(-34px) scale(0.94); }
  100% { opacity: 1; transform: scale(var(--menu-scale, 1)); }
}

@keyframes title-in {
  0%   { opacity: 0; transform: translateY(-26px) scale(1.14); letter-spacing: 0.5em; filter: blur(9px); }
  60%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); letter-spacing: 0.14em; }
}

@keyframes panel-in {
  0%   { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes crest-hover {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50%      { transform: translateY(-8px) rotate(3deg); }
}

@keyframes shine-sweep {
  0%   { background-position: 200% center; }
  100% { background-position: -200% center; }
}

@keyframes border-flow {
  0%   { background-position: 0% 50%; }
  100% { background-position: 300% 50%; }
}

/* Opacity + scale only — no shadow repaint. */
@keyframes breathe-glow {
  0%, 100% { opacity: 0.4; transform: scale(0.97); }
  50%      { opacity: 0.85; transform: scale(1.04); }
}

/* One full tile of travel loops seamlessly; transform-only so the
   compositor handles it without re-rasterizing the grid. */
/* Watchfires breathing at the edge of the field. */
@keyframes ember-breathe {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.42; }
  50%      { transform: translate3d(2vw, -1.5vh, 0) scale(1.09); opacity: 0.6; }
}

@keyframes beam-sweep {
  0%   { transform: translateX(0) rotate(14deg); opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateX(160vw) rotate(14deg); opacity: 0; }
}

/* Portrait-lock phone: upright, tip to landscape, hold, return. */
@keyframes tip-to-landscape {
  0%, 18%   { transform: rotate(0deg); }
  42%, 74%  { transform: rotate(-90deg); }
  96%, 100% { transform: rotate(0deg); }
}

/* ==========================================================================
   KEYFRAMES — gameplay feedback
   ========================================================================== */

@keyframes banner-in {
  0%   { opacity: 0; transform: scale(1.6); letter-spacing: 0.5em; filter: blur(6px); }
  60%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: scale(1); letter-spacing: 0.14em; }
}

@keyframes notice-life {
  0%   { opacity: 0; transform: translateY(14px); }
  10%  { opacity: 1; transform: translateY(0); }
  85%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-10px); }
}

@keyframes streak-in {
  0%   { opacity: 0; transform: scale(0.5) translateY(10px); }
  70%  { transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes shake-hud {
  0%, 100% { transform: scale(var(--hud-scale, 1)) translate(0, 0); }
  20% { transform: scale(var(--hud-scale, 1)) translate(-4px, 3px); }
  40% { transform: scale(var(--hud-scale, 1)) translate(4px, -3px); }
  60% { transform: scale(var(--hud-scale, 1)) translate(-3px, -2px); }
  80% { transform: scale(var(--hud-scale, 1)) translate(3px, 2px); }
}

@keyframes damage-vignette {
  0%   { opacity: 0.85; }
  100% { opacity: 0; }
}

@keyframes pulse-border {
  0%, 100% { box-shadow: 0 0 0 0 rgba(196, 204, 216, 0.5); }
  50%      { box-shadow: 0 0 0 5px rgba(196, 204, 216, 0); }
}

@keyframes pulse-border-violet {
  0%, 100% { box-shadow: 0 0 12px rgba(120, 128, 142, 0.4), 0 0 30px rgba(120, 128, 142, 0.18); }
  50%      { box-shadow: 0 0 20px rgba(120, 128, 142, 0.65), 0 0 54px rgba(120, 128, 142, 0.32); }
}

@keyframes glow-throb {
  0%, 100% { box-shadow: 0 0 10px rgba(120, 128, 142, 0.45); }
  50%      { box-shadow: 0 0 22px rgba(120, 128, 142, 0.85); }
}

@keyframes reward-in {
  0%   { opacity: 0; transform: scale(var(--menu-scale, 1)) scale(0.82) translateY(24px); filter: blur(6px); }
  60%  { filter: blur(0); }
  100% { opacity: 1; transform: scale(var(--menu-scale, 1)) translateY(0); }
}

@keyframes victory-shine {
  0%   { background-position: -200% center; }
  100% { background-position: 200% center; }
}

/* ==========================================================================
   APPLIED ANIMATIONS
   ========================================================================== */

.screen:not(.hidden) { animation: fade-in var(--t-slow) var(--ease-out); }

/* modal-in (not drop-in) so the entrance keeps the uniform UI scale. */
.modal-box { animation: modal-in var(--t-med) var(--ease-out); }

.wave-banner { animation: banner-in 0.8s var(--ease-out) both; }

.notice { animation: notice-life 3.2s ease both; }
.notice.achievement { animation-duration: 4.5s; }

.power-slot.ready .power-icon { animation: glow-throb 1.6s ease-in-out infinite; }

#hud.hud-shake { animation: shake-hud 0.4s linear; }

#hud .damage-flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(224, 70, 70, 0.55) 100%);
  animation: damage-vignette 0.55s ease-out forwards;
}

/* Menu buttons stagger in */
.menu-buttons .menu-btn { animation: rise-in 0.45s var(--ease-out) both; }
.menu-buttons .menu-btn:nth-child(1) { animation-delay: 0.06s; }
.menu-buttons .menu-btn:nth-child(2) { animation-delay: 0.12s; }
.menu-buttons .menu-btn:nth-child(3) { animation-delay: 0.18s; }
.menu-buttons .menu-btn:nth-child(4) { animation-delay: 0.24s; }

/* Mode / difficulty / location cards stagger */
.mode-grid .mode-card:nth-child(3n+1) { animation-delay: 0.04s; }
.mode-grid .mode-card:nth-child(3n+2) { animation-delay: 0.09s; }
.mode-grid .mode-card:nth-child(3n+3) { animation-delay: 0.14s; }

.diff-row .diff-card:nth-child(1) { animation-delay: 0.05s; }
.diff-row .diff-card:nth-child(2) { animation-delay: 0.10s; }
.diff-row .diff-card:nth-child(3) { animation-delay: 0.15s; }
.diff-row .diff-card:nth-child(4) { animation-delay: 0.20s; }

.location-grid .location-card:nth-child(4n+1) { animation-delay: 0.04s; }
.location-grid .location-card:nth-child(4n+2) { animation-delay: 0.08s; }
.location-grid .location-card:nth-child(4n+3) { animation-delay: 0.12s; }
.location-grid .location-card:nth-child(4n+4) { animation-delay: 0.16s; }

/* Victory title shine sweep */
.result-title.victory {
  background: linear-gradient(100deg, var(--c-gold) 30%, #fff7dd 50%, var(--c-gold) 70%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: banner-in 0.8s var(--ease-out) both, victory-shine 2.6s linear 0.8s infinite;
}

.result-title.defeat { animation: banner-in 0.9s var(--ease-out) both; }

.stats-grid .stat-box { animation: rise-in 0.45s var(--ease-out) both; }
.stats-grid .stat-box:nth-child(1) { animation-delay: 0.24s; }
.stats-grid .stat-box:nth-child(2) { animation-delay: 0.32s; }
.stats-grid .stat-box:nth-child(3) { animation-delay: 0.40s; }
.stats-grid .stat-box:nth-child(4) { animation-delay: 0.48s; }
.stats-grid .stat-box:nth-child(5) { animation-delay: 0.56s; }
.stats-grid .stat-box:nth-child(6) { animation-delay: 0.64s; }
.stats-grid .stat-box:nth-child(7) { animation-delay: 0.72s; }
.stats-grid .stat-box:nth-child(8) { animation-delay: 0.80s; }

.loading-emblem { animation: emblem-pulse 2.2s ease-in-out infinite; }

.elite-entry { animation: pop-in 0.3s var(--ease-out) both; }

.achievement { animation: fade-in 0.35s ease both; }

/* Reduced motion: stop the ambient loops entirely */
body.reduced-motion .fx-ember-glow,
body.reduced-motion .fx-beam,
body.reduced-motion .menu-shell::before,
body.reduced-motion .start-btn,
body.reduced-motion .menu-crest {
  animation: none !important;
}
