/* ============================================
   VETUU — Status Effect Visuals
   Visual states for status effects on actors
   ============================================ */

/* ---------- Status Effect Visuals ---------- */
.is-stunned {
  filter: brightness(0.6) saturate(0.5);
  outline: 2px solid var(--color-cream);
  box-shadow: 0 0 8px oklch(from var(--color-cream) l c h / 0.6);
  /* No animation - avoids potential conflicts with position transforms */
}

.is-rooted {
  filter: brightness(0.85);
  outline: 2px solid oklch(0.45 0.080 45);
  box-shadow: 0 0 8px oklch(0.45 0.080 45 / 0.6);
}

.is-slowed {
  filter: brightness(0.9) hue-rotate(180deg);
  outline: 2px dashed oklch(0.72 0.140 220);
}

.is-vulnerable {
  filter: brightness(1.2);
  outline: 2px solid oklch(0.65 0.200 35);
  animation: vuln-pulse 0.5s ease-in-out infinite;
}

@keyframes vuln-pulse {
  /* Use transform scale instead of outline-width for GPU acceleration */
  0%, 100% { transform: scale3d(1, 1, 1); }
  50% { transform: scale3d(1.05, 1.05, 1); }
}

/* .is-immune - no visual styling, functional only */
.is-immune {
  /* No visual indicator */
}

.is-burning {
  outline: 2px solid oklch(0.65 0.200 35);
  box-shadow: 0 0 12px oklch(0.60 0.200 35 / 0.8), 0 0 24px oklch(0.70 0.180 50 / 0.4);
  /* PERF: Use opacity flicker instead of filter animation */
  animation: burn-flicker 0.3s ease-in-out infinite;
}

/* Guard Push - brief flash when enemy gets pushed
   PERF: Uses opacity animation instead of outline-width/box-shadow */
.pushed {
  outline: 4px solid oklch(0.80 0.165 220);
  box-shadow: 0 0 20px oklch(0.75 0.165 220 / 0.9);
  animation: pushed-flash 0.4s ease-out forwards;
}

@keyframes pushed-flash {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* PERF: Animate opacity instead of filter for GPU acceleration */
@keyframes burn-flicker {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.85; }
}

/* Retreating enemies - no visual effects, just functional */
.retreating {
  /* No visual changes */
}

/* Spawn immunity - brief invulnerability (800ms duration)
   No visual indicator - just blocks damage/interaction during materialize.
   The .spawning fade-in is the only visual feedback needed. */
.spawn-immune {
  pointer-events: none; /* Can't interact during immunity */
}

/* ============================================
   SENSE ABILITY EFFECTS (Push/Pull)
   ============================================ */

/* Floating ability text (PUSH!/PULL!) - GPU accelerated via transform */
.sense-ability-text {
  letter-spacing: 0.1em;
}

@keyframes stamina-text-float {
  0% {
    opacity: 1;
    transform: translate3d(calc(var(--pos-x, 0) - 50%), var(--pos-y, 0), 0);
  }
  100% {
    opacity: 0;
    transform: translate3d(calc(var(--pos-x, 0) - 50%), calc(var(--pos-y, 0) - 32px), 0);
  }
}

/* Legacy alias */
@keyframes sense-text-float {
  0% {
    opacity: 1;
    transform: translate3d(calc(var(--pos-x, 0) - 50%), var(--pos-y, 0), 0);
  }
  100% {
    opacity: 0;
    transform: translate3d(calc(var(--pos-x, 0) - 50%), calc(var(--pos-y, 0) - 32px), 0);
  }
}

/* Enemy outline flash when affected by Push/Pull (stamina ability effects)
   PERF: Uses opacity animation instead of outline-width/box-shadow */
.stamina-affected {
  outline: 4px solid var(--player-stamina-color) !important;
  box-shadow: 0 0 20px var(--player-stamina-color), inset 0 0 10px oklch(0.58 0.075 205 / 0.4) !important;
  filter: brightness(1.3) saturate(1.3);
  animation: stamina-affected-flash 0.4s ease-out forwards;
}

/* Legacy alias */
.sense-affected {
  outline: 4px solid var(--player-stamina-color) !important;
  box-shadow: 0 0 20px var(--player-stamina-color), inset 0 0 10px oklch(0.58 0.075 205 / 0.4) !important;
  filter: brightness(1.3) saturate(1.3);
  animation: stamina-affected-flash 0.4s ease-out forwards;
}

@keyframes stamina-affected-flash {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* Legacy alias */
@keyframes sense-affected-flash {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* Push/Pull animations moved to combat.css with GPU acceleration */

/* ============================================
   STUN ABILITY EFFECT
   Expanding ring with flash, centered on target
   PERF: Uses scale3d instead of width/height animation
   ============================================ */
.stun-effect {
  position: absolute;
  /* Fixed size - animation uses scale3d for GPU acceleration */
  width: var(--radius, 144px);
  height: var(--radius, 144px);
  pointer-events: none;
  border: 3px solid var(--color-cream);
  border-radius: 50%;
  box-shadow: 0 0 12px var(--color-cream), inset 0 0 8px oklch(0.9 0.02 90 / 0.5);
  animation: stun-expand 0.5s ease-out forwards;
  /* Position via CSS custom properties - centered */
  left: var(--pos-x, 0);
  top: var(--pos-y, 0);
  transform: translate3d(-50%, -50%, 0) scale3d(0, 0, 1);
}

@keyframes stun-expand {
  0% {
    transform: translate3d(-50%, -50%, 0) scale3d(0, 0, 1);
    opacity: 1;
  }
  100% {
    transform: translate3d(-50%, -50%, 0) scale3d(1, 1, 1);
    opacity: 0;
  }
}

/* ============================================
   BLAST ABILITY EFFECTS
   Pull phase: imploding ring
   Push phase: expanding explosion ring
   PERF: Uses scale3d instead of width/height animation
   ============================================ */
.blast-pull-effect {
  position: absolute;
  /* Fixed size at max (192px) - animation scales down */
  width: 192px;
  height: 192px;
  pointer-events: none;
  border: 4px solid var(--player-stamina-color);
  border-radius: 50%;
  box-shadow: 0 0 20px var(--player-stamina-color), inset 0 0 30px oklch(0.58 0.075 205 / 0.4);
  animation: blast-pull 0.4s ease-in forwards;
  left: var(--pos-x, 0);
  top: var(--pos-y, 0);
  transform: translate3d(-50%, -50%, 0) scale3d(1, 1, 1);
}

@keyframes blast-pull {
  0% {
    transform: translate3d(-50%, -50%, 0) scale3d(1, 1, 1);
    opacity: 0.8;
  }
  100% {
    /* Scale to 24/192 = 0.125 */
    transform: translate3d(-50%, -50%, 0) scale3d(0.125, 0.125, 1);
    opacity: 1;
  }
}

.blast-push-effect {
  position: absolute;
  /* Fixed size at max (240px) - animation scales from small to full */
  width: 240px;
  height: 240px;
  pointer-events: none;
  border: 4px solid oklch(0.70 0.180 50);
  border-radius: 50%;
  background: oklch(0.65 0.200 35 / 0.3);
  box-shadow: 0 0 30px oklch(0.70 0.180 50), 0 0 60px oklch(0.60 0.200 35 / 0.5);
  animation: blast-push 0.6s ease-out forwards;
  left: var(--pos-x, 0);
  top: var(--pos-y, 0);
  transform: translate3d(-50%, -50%, 0) scale3d(0.1, 0.1, 1);
}

@keyframes blast-push {
  0% {
    /* Scale from 24/240 = 0.1 */
    transform: translate3d(-50%, -50%, 0) scale3d(0.1, 0.1, 1);
    opacity: 1;
  }
  100% {
    transform: translate3d(-50%, -50%, 0) scale3d(1, 1, 1);
    opacity: 0;
  }
}

/* ============================================
   FOG REVEAL FADE
   Dithered fade elements for smooth fog transitions
   ============================================ */
.fog-fade {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--tile-size, 24px);
  height: var(--tile-size, 24px);
  pointer-events: none;
  animation: fog-reveal 250ms ease-out forwards;
  /* GPU compositing - position via transform */
  transform: translate3d(var(--pos-x, 0), var(--pos-y, 0), 0);
  /* PERF: Removed will-change - animation auto-promotes to compositor */
}

/* Inner ring fade: sparse 50% dither pattern (8/16 Bayer cells) */
.fog-fade-inner {
  background-color: transparent;
  background-image: 
    linear-gradient(oklch(0.12 0.015 55 / 0.95), oklch(0.12 0.015 55 / 0.95));
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='0' y='0' width='1' height='1' fill='white'/%3E%3Crect x='2' y='0' width='1' height='1' fill='white'/%3E%3Crect x='0' y='1' width='1' height='1' fill='white'/%3E%3Crect x='1' y='1' width='1' height='1' fill='white'/%3E%3Crect x='2' y='1' width='1' height='1' fill='white'/%3E%3Crect x='3' y='1' width='1' height='1' fill='white'/%3E%3Crect x='1' y='2' width='1' height='1' fill='white'/%3E%3Crect x='3' y='2' width='1' height='1' fill='white'/%3E%3Crect x='0' y='3' width='1' height='1' fill='white'/%3E%3Crect x='2' y='3' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  mask-size: 4px 4px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='0' y='0' width='1' height='1' fill='white'/%3E%3Crect x='2' y='0' width='1' height='1' fill='white'/%3E%3Crect x='0' y='1' width='1' height='1' fill='white'/%3E%3Crect x='1' y='1' width='1' height='1' fill='white'/%3E%3Crect x='2' y='1' width='1' height='1' fill='white'/%3E%3Crect x='3' y='1' width='1' height='1' fill='white'/%3E%3Crect x='1' y='2' width='1' height='1' fill='white'/%3E%3Crect x='3' y='2' width='1' height='1' fill='white'/%3E%3Crect x='0' y='3' width='1' height='1' fill='white'/%3E%3Crect x='2' y='3' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  -webkit-mask-size: 4px 4px;
}

/* Outer ring fade: the DIFFERENCE between solid and outer dither (4/16 cells) */
.fog-fade-outer {
  background-color: transparent;
  background-image: 
    linear-gradient(oklch(0.12 0.015 55 / 0.95), oklch(0.12 0.015 55 / 0.95));
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='1' y='0' width='1' height='1' fill='white'/%3E%3Crect x='3' y='0' width='1' height='1' fill='white'/%3E%3Crect x='1' y='2' width='1' height='1' fill='white'/%3E%3Crect x='3' y='2' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  mask-size: 4px 4px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='1' y='0' width='1' height='1' fill='white'/%3E%3Crect x='3' y='0' width='1' height='1' fill='white'/%3E%3Crect x='1' y='2' width='1' height='1' fill='white'/%3E%3Crect x='3' y='2' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  -webkit-mask-size: 4px 4px;
}

/* Transition from outer dither to inner dither (4/16 cells fade out) */
.fog-fade-mid {
  background-color: transparent;
  background-image: 
    linear-gradient(oklch(0.12 0.015 55 / 0.95), oklch(0.12 0.015 55 / 0.95));
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='0' y='0' width='1' height='1' fill='white'/%3E%3Crect x='2' y='0' width='1' height='1' fill='white'/%3E%3Crect x='0' y='2' width='1' height='1' fill='white'/%3E%3Crect x='2' y='2' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  mask-size: 4px 4px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='0' y='0' width='1' height='1' fill='white'/%3E%3Crect x='2' y='0' width='1' height='1' fill='white'/%3E%3Crect x='0' y='2' width='1' height='1' fill='white'/%3E%3Crect x='2' y='2' width='1' height='1' fill='white'/%3E%3C/svg%3E");
  -webkit-mask-size: 4px 4px;
}

@keyframes fog-reveal {
  0% { opacity: 0.4; }
  100% { opacity: 0; }
}

/* ============================================
   ROLE-BASED ENEMY EFFECTS
   Marksman aiming, Grenadier telegraphs
   ============================================ */

/* Marksman aiming indicator - red glow, charging up */
.aiming {
  outline: 2px solid oklch(0.62 0.200 25 / 0.9) !important;
  box-shadow: 0 0 16px oklch(0.62 0.200 25 / 0.6), 0 0 32px oklch(0.55 0.200 25 / 0.3);
  animation: aim-charge 0.6s ease-in-out;
}

.aiming::before {
  content: '🎯';
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translate3d(-50%, 0, 0);
  font-size: 14px;
  animation: aim-pulse 0.3s ease-in-out infinite alternate;
  /* PERF: Removed will-change - animation auto-promotes to compositor */
}

/* PERF: Only animate transform (GPU-accelerated) - outline is static */
@keyframes aim-charge {
  0% {
    transform: scale3d(1, 1, 1);
    opacity: 0.7;
  }
  50% {
    transform: scale3d(1.03, 1.03, 1);
    opacity: 0.9;
  }
  100% {
    transform: scale3d(1.05, 1.05, 1);
    opacity: 1;
  }
}

@keyframes aim-pulse {
  0% { transform: translate3d(-50%, 0, 0) scale3d(1, 1, 1); }
  100% { transform: translate3d(-50%, -2px, 0) scale3d(1.1, 1.1, 1); }
}

/* Grenade telegraph - pulsing danger zone */
.grenade-telegraph {
  position: absolute;
  left: var(--pos-x, 0);
  top: var(--pos-y, 0);
  width: var(--size, 120px);
  height: var(--size, 120px);
  background: radial-gradient(
    circle,
    oklch(0.65 0.180 50 / 0.4) 0%,
    oklch(0.60 0.200 35 / 0.2) 70%,
    transparent 100%
  );
  border: 2px solid oklch(0.65 0.180 50 / 0.8);
  border-radius: 50%;
  pointer-events: none;
  z-index: 15;
  animation: grenade-pulse 0.3s ease-in-out infinite alternate;
  /* PERF: Removed will-change - animation auto-promotes to compositor */
}

@keyframes grenade-pulse {
  0% {
    opacity: 0.6;
    transform: scale3d(1, 1, 1);
  }
  100% {
    opacity: 1;
    transform: scale3d(1.05, 1.05, 1);
  }
}

/* Grenade explosion - expanding burst */
.grenade-explosion {
  position: absolute;
  left: var(--pos-x, 0);
  top: var(--pos-y, 0);
  width: var(--size, 120px);
  height: var(--size, 120px);
  background: radial-gradient(
    circle,
    oklch(0.85 0.150 80 / 0.9) 0%,
    oklch(0.65 0.180 50 / 0.6) 50%,
    transparent 100%
  );
  pointer-events: none;
  z-index: 20;
  animation: explosion-burst 0.4s ease-out forwards;
  /* PERF: Removed will-change - animation auto-promotes to compositor */
}

@keyframes explosion-burst {
  0% {
    opacity: 1;
    transform: scale3d(0.5, 0.5, 1);
  }
  30% {
    opacity: 1;
    transform: scale3d(1.2, 1.2, 1);
  }
  100% {
    opacity: 0;
    transform: scale3d(1.5, 1.5, 1);
  }
}

/* ============================================
   ENEMY ABILITY EFFECTS
   Gap closer leaps, ability telegraphs
   ============================================ */

/* -------- GAP CLOSER LEAP ANIMATION -------- */

/* Leaping enemy - raised z-index during jump arc */
.enemy.leaping {
  z-index: 50;
  pointer-events: none; /* Can't click while leaping */
  /* Shadow shrinks/lightens during leap (set via JS custom properties) */
}

/* Landing state - just a marker, visual handled by impact effect */
.enemy.landing {
  z-index: 50;
}

/* Leap impact effect - dust burst at landing point */
.leap-impact {
  position: absolute;
  width: 32px;
  height: 32px;
  pointer-events: none;
  z-index: 13;
  transform: translate3d(-50%, -50%, 0);
  animation: leap-impact-burst 300ms ease-out forwards;
}

/* Standard impact - medium dust cloud */
.leap-impact::before,
.leap-impact::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    circle,
    oklch(0.6 0.05 60 / 0.7) 0%,
    oklch(0.5 0.04 55 / 0.3) 50%,
    transparent 70%
  );
}

.leap-impact::after {
  animation: impact-ring 300ms ease-out forwards;
}

/* Light impact (Pounce) - smaller, quicker */
.leap-impact.impact-light {
  width: 24px;
  height: 24px;
}

.leap-impact.impact-light::before {
  background: radial-gradient(
    circle,
    oklch(0.55 0.04 70 / 0.5) 0%,
    transparent 60%
  );
}

/* Heavy impact (Charge) - larger, more dramatic */
.leap-impact.impact-heavy {
  width: 44px;
  height: 44px;
}

.leap-impact.impact-heavy::before {
  background: radial-gradient(
    circle,
    oklch(0.65 0.08 50 / 0.8) 0%,
    oklch(0.5 0.06 45 / 0.4) 50%,
    transparent 75%
  );
}

@keyframes leap-impact-burst {
  0% {
    opacity: 1;
    transform: translate3d(-50%, -50%, 0) scale3d(0.5, 0.5, 1);
  }
  30% {
    opacity: 0.9;
    transform: translate3d(-50%, -50%, 0) scale3d(1.2, 1.2, 1);
  }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale3d(1.5, 0.8, 1);
  }
}

@keyframes impact-ring {
  0% {
    opacity: 0.6;
    transform: scale3d(0.3, 0.3, 1);
    border: 2px solid oklch(0.7 0.06 60 / 0.8);
  }
  100% {
    opacity: 0;
    transform: scale3d(2, 2, 1);
    border: 2px solid oklch(0.6 0.04 55 / 0);
  }
}

/* -------- LEGACY DASH TRAIL (kept for backwards compat) -------- */
.dash-trail {
  position: absolute;
  height: 4px;
  pointer-events: none;
  z-index: 12;
  opacity: 0.8;
  transition: opacity var(--fade-quick) ease-out;
}

/* Dashing enemy - slightly brighter during dash */
.enemy.dashing {
  filter: brightness(1.3);
  z-index: 25;
}

/* Ground pound effect */
@keyframes ground-pound {
  0% {
    opacity: 0.8;
    transform: translate3d(-50%, -50%, 0) scale3d(0.3, 0.3, 1);
  }
  50% {
    opacity: 0.6;
    transform: translate3d(-50%, -50%, 0) scale3d(1, 1, 1);
  }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale3d(1.2, 1.2, 1);
  }
}

/* AoE buff pulse */
@keyframes aoe-pulse {
  0% {
    opacity: 0.6;
    transform: translate3d(-50%, -50%, 0) scale3d(0.5, 0.5, 1);
  }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale3d(1.2, 1.2, 1);
  }
}

/* Enemy casting state
   PERF: Uses opacity pulse instead of filter animation */
.enemy.casting {
  filter: brightness(1.25);
  animation: casting-pulse 0.5s ease-in-out infinite alternate;
}

@keyframes casting-pulse {
  0% { opacity: 0.85; }
  100% { opacity: 1; }
}

/* Enemy buffed state */
.enemy.buffed {
  box-shadow: 0 0 8px oklch(0.6 0.15 200 / 0.8);
}

/* Enemy shielded state */
.enemy.shielded {
  box-shadow: 0 0 10px oklch(0.7 0.1 220 / 0.9);
  outline: 2px solid oklch(0.7 0.1 220 / 0.6);
}

/* Enemy repositioning (teleport, fade) */
.enemy.repositioning {
  opacity: 0.5;
  transition: transform 0.2s ease-out, opacity 0.2s ease-out;
}

/* Enemy healing (self or receiving heal) */
.enemy.healing {
  box-shadow: 0 0 10px oklch(0.7 0.15 140 / 0.8);
  animation: healing-pulse 0.5s ease-out;
}

@keyframes healing-pulse {
  0% { filter: brightness(1.3); }
  100% { filter: brightness(1); }
}

/* Enemy summoning reinforcements */
.enemy.summoning {
  filter: brightness(1.2);
  box-shadow: 0 0 15px oklch(0.6 0.18 280 / 0.7);
}

/* Enemy cast interrupted */
.enemy.interrupted {
  filter: brightness(0.7);
  animation: interrupt-flash 0.3s ease-out;
}

@keyframes interrupt-flash {
  0% { filter: brightness(0.5); }
  100% { filter: brightness(1); }
}

/* Enemy stunned (from player Stun ability) */
.enemy.stunned {
  filter: saturate(0.5) brightness(0.8);
  animation: stun-wobble 0.3s ease-in-out infinite;
}

@keyframes stun-wobble {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-1px); }
  75% { transform: translateX(1px); }
}

/* Enemy burning (from player Blast ability) */
.enemy.burning {
  filter: brightness(1.2) sepia(0.3);
  box-shadow: 0 0 8px oklch(0.7 0.25 30 / 0.8);
}

/* Player casting (network players) */
.player.casting {
  filter: brightness(1.2);
  animation: player-cast-pulse 0.5s ease-in-out infinite alternate;
}

@keyframes player-cast-pulse {
  0% { opacity: 0.85; }
  100% { opacity: 1; }
}

/* Player cast interrupted */
.player.interrupted {
  animation: interrupt-flash 0.3s ease-out;
}

/* Enemy disengaging (smoke bomb, etc) */
.enemy.disengaging {
  opacity: 0.3;
  transition: transform var(--fade-quick) ease-out, opacity var(--fade-quick) ease-out;
}

/* Enemy fading (teleport) */
.enemy.fading {
  opacity: 0;
  transition: transform var(--fade-snappy) ease-out, opacity var(--fade-snappy) ease-out;
}

/* ============================================
   BOSS PHASE EFFECTS
   Visual feedback for boss phase transitions
   ============================================ */

/* Phase transition flash
   PERF: Uses opacity flash instead of filter animation */
.enemy.phase-transition {
  filter: brightness(1.5) saturate(0.8);
  animation: boss-phase-flash 0.5s ease-out forwards;
}

@keyframes boss-phase-flash {
  0% {
    opacity: 0.5;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 1;
  }
}

/* Enraged boss - red glow, pulsing */
.enemy.enraged {
  animation: boss-enrage-pulse 1s ease-in-out infinite;
}

.enemy.enraged > .sprite {
  filter: 
    drop-shadow(1px 0 0 var(--sprite-outline)) drop-shadow(-1px 0 0 var(--sprite-outline))
    drop-shadow(0 1px 0 var(--sprite-outline)) drop-shadow(0 -1px 0 var(--sprite-outline))
    hue-rotate(-30deg) saturate(1.5) brightness(1.1);
}

@keyframes boss-enrage-pulse {
  0%, 100% {
    box-shadow: 0 0 12px oklch(0.55 0.25 25 / 0.7);
  }
  50% {
    box-shadow: 0 0 20px oklch(0.60 0.28 25 / 0.9);
  }
}

/* Screen shake on enrage */
#game.boss-enrage-shake {
  animation: enrage-shake 0.3s ease-out;
}

@keyframes enrage-shake {
  0%, 100% { transform: translate3d(0, 0, 0); }
  20% { transform: translate3d(-3px, 2px, 0); }
  40% { transform: translate3d(3px, -2px, 0); }
  60% { transform: translate3d(-2px, 1px, 0); }
  80% { transform: translate3d(2px, -1px, 0); }
}

/* Summon effect - expanding ring with glow */
.summon-effect {
  background: radial-gradient(
    circle,
    oklch(0.5 0.15 280 / 0.4) 0%,
    oklch(0.4 0.12 280 / 0.2) 50%,
    transparent 70%
  );
  border: 2px solid oklch(0.6 0.18 280 / 0.6);
  border-radius: 50%;
  animation: summon-pulse 0.6s ease-out forwards;
}

@keyframes summon-pulse {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale3d(0.3, 0.3, 1);
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale3d(1.2, 1.2, 1);
  }
}
