/* ═══════════════════════════════════
   VFX ENGINE — CSS Animations
   Used by js/vfx-engine.js
   Selectors: .cg-card (game cards)
   ═══════════════════════════════════ */

/* ── FRAGMENT PIECES (JS-created) ── */
.fx-fragment {
  position: absolute;
  overflow: hidden;
  border-radius: 4px;
}
.fx-fragment img {
  position: absolute;
  display: block;
}

/* ═══════════════════════════════════
   SLASH — fast colored cut line, THEN halves split
   ═══════════════════════════════════ */
.fx-slash .slash-top, .fx-slash .slash-bot {
  position: absolute; inset: 0; overflow: hidden; border-radius: 8px;
}
.fx-slash .slash-top img, .fx-slash .slash-bot img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.fx-slash .slash-top {
  clip-path: polygon(0 0, 100% 0, 0 100%);
  animation: slashTopFall var(--dur) 0.45s ease-in forwards;
}
.fx-slash .slash-bot {
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  animation: slashBotFall var(--dur) 0.45s ease-in forwards;
}
.fx-slash .slash-line {
  position: absolute; inset: -20px; z-index: 5; pointer-events: none;
  overflow: hidden;
}
.fx-slash .slash-line::before {
  content: '';
  position: absolute;
  width: 200%; height: 6px;
  left: -50%; top: 50%;
  background: linear-gradient(90deg, transparent 0%, var(--color) 20%, #fff 45%, #fff 55%, var(--color) 80%, transparent 100%);
  box-shadow: 0 0 20px 6px var(--color), 0 0 40px 12px var(--color);
  transform: rotate(135deg) translateX(-100%);
  animation: slashSwipe 0.4s ease-out forwards;
  border-radius: 3px;
}
@keyframes slashSwipe {
  0% { transform: rotate(135deg) translateX(-100%); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: rotate(135deg) translateX(100%); opacity: 0; }
}
@keyframes slashTopFall {
  0% { transform: none; opacity: 1; }
  100% { transform: translate(-30px, -40px) rotate(-12deg); opacity: 0; }
}
@keyframes slashBotFall {
  0% { transform: none; opacity: 1; }
  100% { transform: translate(30px, 40px) rotate(12deg); opacity: 0; }
}

/* ═══════════════════════════════════
   BURN — realistic fire eating card
   ═══════════════════════════════════ */
.fx-burn .cg-card {
  overflow: visible;
}
.burn-under {
  position: absolute; inset: 0; border-radius: 8px; z-index: 0;
  background: #0a0500;
}
.burn-char {
  position: absolute; inset: 0; border-radius: 8px; z-index: 2;
  background: linear-gradient(to top, #0a0400 0%, #1a0800 30%, #552200 90%, #ff6600 96%, #ffaa00 100%);
}
.fx-burn .cg-card img {
  position: relative; z-index: 3;
  filter: brightness(1);
  transition: filter 0.3s;
}
.burn-fire-wrap {
  position: absolute;
  inset: -30px;
  pointer-events: none;
  z-index: 5;
  overflow: hidden;
  border-radius: 12px;
}
.burn-particle {
  position: absolute;
  border-radius: 50%;
  box-shadow: 0 0 3px 1px currentColor;
  filter: blur(1px);
}
.burn-ember {
  position: absolute;
  border-radius: 50%;
  background: #ffcc00;
  box-shadow: 0 0 4px 2px #ff8800;
  pointer-events: none;
  z-index: 9;
  opacity: 0;
}
@keyframes burnPRise {
  0% { transform: translateY(0) scaleX(1); opacity: 1; }
  40% { opacity: 0.9; }
  100% { transform: translateY(-90px) scaleX(0.3); opacity: 0; }
}
@keyframes burnEmberFloat {
  0% { opacity: 0; transform: translateY(0) translateX(0); }
  10% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-120px) translateX(var(--ex, 10px)); }
}

/* ═══════════════════════════════════
   MELT — card softens, sags, drips away
   ═══════════════════════════════════ */
.fx-melt .cg-card {
  animation: meltCard var(--dur) ease-in forwards;
}
.fx-melt .melt-drips {
  position: absolute; bottom: -40px; left: -5%; width: 110%; height: 60px;
  pointer-events: none; z-index: 3;
  animation: meltDripsDown var(--dur) ease-in forwards;
}
@keyframes meltCard {
  0% {
    clip-path: path('M0,0 L200,0 L200,290 L0,290 Z');
    filter: none; transform: none;
  }
  12% {
    clip-path: path('M0,0 L200,0 L200,290 L0,290 Z');
    filter: saturate(1.3) hue-rotate(var(--hue));
    transform: scaleX(1.01) scaleY(1.005);
  }
  25% {
    clip-path: path('M0,0 L200,0 L200,290 C190,288 180,292 170,286 C160,280 150,290 140,284 C130,278 120,288 110,282 C100,276 90,286 80,280 C70,274 60,284 50,278 C40,272 30,282 20,276 C10,270 5,280 0,275 Z');
    filter: saturate(1.5) hue-rotate(var(--hue)) brightness(0.95);
    transform: scaleX(1.03) translateY(5px);
  }
  42% {
    clip-path: path('M0,0 L200,0 L200,230 C194,250 186,240 178,258 C170,248 162,265 152,255 C142,245 134,262 124,250 C114,238 106,258 96,245 C86,235 78,252 68,240 C58,230 48,248 38,235 C28,225 18,242 8,230 C2,224 0,234 0,225 Z');
    filter: saturate(1.7) hue-rotate(var(--hue)) brightness(0.85);
    transform: scaleX(1.06) translateY(14px);
  }
  60% {
    clip-path: path('M0,0 L200,0 L200,160 C195,180 188,170 180,190 C172,178 164,195 154,182 C144,170 136,188 126,175 C116,162 108,180 98,168 C88,156 80,174 70,160 C60,148 52,166 42,152 C32,140 22,158 12,144 C4,134 0,148 0,140 Z');
    filter: saturate(1.4) hue-rotate(var(--hue)) brightness(0.7);
    transform: scaleX(1.1) translateY(28px);
  }
  78% {
    clip-path: path('M0,0 L200,0 L200,80 C196,100 190,92 182,110 C174,98 166,115 156,102 C146,90 138,108 128,95 C118,82 110,100 100,88 C90,76 82,94 72,80 C62,68 54,86 44,72 C34,60 24,78 14,64 C6,54 0,68 0,58 Z');
    filter: saturate(0.5) brightness(0.45) blur(1px);
    transform: scaleX(1.15) translateY(45px);
  }
  100% {
    clip-path: path('M0,0 L200,0 L200,10 C196,22 192,16 186,24 C180,14 174,22 168,12 C162,4 156,14 150,6 C144,-2 138,8 132,0 C126,-6 120,4 114,-2 C108,-8 102,2 96,-4 C90,-10 84,0 78,-6 C72,-12 66,-2 60,-8 C54,-14 48,-4 42,-10 C36,-16 30,-6 24,-12 C18,-18 12,-8 6,-14 C2,-18 0,-10 0,-5 Z');
    filter: blur(3px); opacity: 0;
    transform: scaleX(1.2) translateY(60px);
  }
}
@keyframes meltDripsDown {
  0% { opacity: 0; transform: translateY(-60px); }
  30% { opacity: 0; }
  50% { opacity: 0.7; transform: translateY(-15px); }
  100% { opacity: 0; transform: translateY(40px); }
}

/* ═══════════════════════════════════
   SHATTER — JS creates pieces, CSS animates
   ═══════════════════════════════════ */
@keyframes shatterPc0 { 0%{transform:none;opacity:1} 100%{transform:translate(-70px,-50px) rotate(-30deg) scale(0.4);opacity:0} }
@keyframes shatterPc1 { 0%{transform:none;opacity:1} 100%{transform:translate(60px,-60px) rotate(25deg) scale(0.3);opacity:0} }
@keyframes shatterPc2 { 0%{transform:none;opacity:1} 100%{transform:translate(-50px,55px) rotate(-20deg) scale(0.5);opacity:0} }
@keyframes shatterPc3 { 0%{transform:none;opacity:1} 100%{transform:translate(70px,45px) rotate(35deg) scale(0.3);opacity:0} }
@keyframes shatterPc4 { 0%{transform:none;opacity:1} 100%{transform:translate(-20px,-70px) rotate(-40deg) scale(0.35);opacity:0} }
@keyframes shatterPc5 { 0%{transform:none;opacity:1} 100%{transform:translate(30px,70px) rotate(15deg) scale(0.45);opacity:0} }
@keyframes shatterFlash {
  0%{opacity:0} 10%{opacity:1} 30%{opacity:0.5} 100%{opacity:0}
}
.fx-shatter-flash {
  position: absolute; inset: -30px; border-radius: 50%; z-index: 10; pointer-events: none;
  background: radial-gradient(circle, var(--color) 0%, transparent 70%);
  animation: shatterFlash calc(var(--dur) * 0.5) ease-out forwards;
}

/* ═══════════════════════════════════
   GLOW — pulse once then stay lit
   ═══════════════════════════════════ */
@keyframes glowPulse {
  0% { box-shadow: 0 0 0 0 transparent; }
  40% { box-shadow: 0 0 50px 15px var(--color), inset 0 0 25px 5px var(--color); }
  70% { box-shadow: 0 0 25px 8px var(--color), inset 0 0 12px 3px var(--color); }
  100% { box-shadow: 0 0 30px 10px var(--color), inset 0 0 15px 4px var(--color); }
}
/* Apply glow to any card-like element inside the container */
.fx-glow .cg-card,
.fx-glow .cg-set-card,
.fx-glow.cg-set-slot { animation: glowPulse var(--dur) ease-in-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   SHINE — diagonal light sweep
   ═══════════════════════════════════ */
.fx-shine .shine-bar {
  position: absolute; top: -50%; left: 0; width: 90%; height: 200%;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.03) 25%, var(--color) 45%, rgba(255,255,255,0.9) 50%, var(--color) 55%, rgba(255,255,255,0.03) 75%, transparent 100%);
  animation: shineSlide var(--dur) ease-in-out forwards;
  z-index: 3; pointer-events: none;
  border-radius: 8px;
  transform-origin: center center;
  rotate: 25deg;
}
@keyframes shineSlide {
  0% { translate: -120% 0; opacity: 0.8; }
  100% { translate: 280% 0; opacity: 0; }
}

/* ═══════════════════════════════════
   SHAKE
   ═══════════════════════════════════ */
@keyframes shakeViolent {
  0% { transform: translate(0) rotate(0); }
  5% { transform: translate(-15px, 8px) rotate(-5deg); }
  10% { transform: translate(14px, -10px) rotate(4deg); }
  15% { transform: translate(-12px, -6px) rotate(-6deg); }
  20% { transform: translate(16px, 5px) rotate(5deg); }
  25% { transform: translate(-18px, 3px) rotate(-7deg); }
  30% { transform: translate(12px, -12px) rotate(6deg); }
  35% { transform: translate(-8px, 14px) rotate(-4deg); }
  40% { transform: translate(18px, -4px) rotate(7deg); }
  45% { transform: translate(-14px, -8px) rotate(-5deg); }
  50% { transform: translate(10px, 12px) rotate(4deg); }
  55% { transform: translate(-16px, 6px) rotate(-6deg); }
  60% { transform: translate(14px, -14px) rotate(5deg); }
  65% { transform: translate(-10px, 10px) rotate(-3deg); }
  70% { transform: translate(8px, -8px) rotate(3deg); }
  75% { transform: translate(-6px, 6px) rotate(-2deg); }
  80% { transform: translate(5px, -5px) rotate(2deg); }
  85% { transform: translate(-3px, 3px) rotate(-1deg); }
  90% { transform: translate(2px, -2px) rotate(1deg); }
  95% { transform: translate(-1px, 1px) rotate(0); }
  100% { transform: translate(0) rotate(0); }
}
.fx-shake .cg-card { animation: shakeViolent var(--dur) ease-in-out forwards; }

/* ═══════════════════════════════════
   DISSOLVE — violent breakup
   ═══════════════════════════════════ */
.fx-dissolve .cg-card {
  animation: dissolveCard var(--dur) ease-in forwards;
}
.fx-dissolve .dissolve-chunk {
  position: absolute; overflow: hidden; border-radius: 3px; pointer-events: none;
}
.fx-dissolve .dissolve-chunk img {
  position: absolute; display: block;
}
@keyframes dissolveCard {
  0% { filter: none; transform: none; }
  10% { filter: contrast(1.5) brightness(1.2); transform: scale(1.02); }
  25% {
    filter: contrast(1.8) brightness(0.9) saturate(0.6);
    clip-path: polygon(0 0, 100% 0, 100% 100%, 80% 95%, 60% 100%, 40% 92%, 20% 100%, 0 96%);
  }
  45% {
    filter: contrast(2) brightness(0.5) saturate(0.3);
    clip-path: polygon(5% 3%, 95% 0, 92% 85%, 70% 80%, 55% 88%, 35% 78%, 15% 85%, 3% 75%);
    transform: scale(1.01) rotate(0.5deg);
  }
  65% {
    filter: brightness(0.3) saturate(0.1);
    clip-path: polygon(10% 8%, 88% 5%, 85% 65%, 65% 58%, 50% 68%, 30% 55%, 12% 62%);
    transform: scale(0.98) rotate(1deg);
  }
  80% {
    filter: brightness(0.15) blur(1px);
    clip-path: polygon(18% 15%, 80% 12%, 75% 42%, 55% 35%, 35% 42%, 18% 35%);
    transform: scale(0.95) rotate(1.5deg);
    opacity: 0.6;
  }
  100% {
    filter: blur(3px) brightness(0);
    clip-path: polygon(40% 25%, 60% 22%, 55% 32%, 45% 30%);
    transform: scale(0.9) rotate(2deg);
    opacity: 0;
  }
}
@keyframes dissolveFall0 { 0%{transform:none;opacity:1} 100%{transform:translate(-20px,80px) rotate(-15deg);opacity:0} }
@keyframes dissolveFall1 { 0%{transform:none;opacity:1} 100%{transform:translate(30px,90px) rotate(20deg);opacity:0} }
@keyframes dissolveFall2 { 0%{transform:none;opacity:1} 100%{transform:translate(-40px,70px) rotate(-25deg);opacity:0} }
@keyframes dissolveFall3 { 0%{transform:none;opacity:1} 100%{transform:translate(15px,100px) rotate(10deg);opacity:0} }
@keyframes dissolveFall4 { 0%{transform:none;opacity:1} 100%{transform:translate(-10px,85px) rotate(-12deg);opacity:0} }
@keyframes dissolveFall5 { 0%{transform:none;opacity:1} 100%{transform:translate(45px,75px) rotate(18deg);opacity:0} }

/* ═══════════════════════════════════
   FREEZE
   ═══════════════════════════════════ */
@keyframes freezeOver {
  0% { filter: none; box-shadow: none; }
  40% { filter: saturate(0.3) brightness(1.3) hue-rotate(180deg); box-shadow: 0 0 20px 5px rgba(100,200,255,0.5); }
  70% { filter: saturate(0.1) brightness(1.5) hue-rotate(200deg); box-shadow: 0 0 40px 10px rgba(100,200,255,0.7); }
  100% { filter: saturate(0) brightness(0.8); box-shadow: 0 0 5px 2px rgba(100,200,255,0.3); transform: scale(0.98); }
}
.fx-freeze .cg-card { animation: freezeOver var(--dur) ease-in-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   STEAL
   ═══════════════════════════════════ */
@keyframes stealAway {
  0% { transform: none; opacity: 1; }
  20% { transform: translateY(-10px) scale(1.05); opacity: 1; }
  100% { transform: translate(300px, -100px) scale(0.5) rotate(20deg); opacity: 0; }
}
.fx-steal .cg-card { animation: stealAway var(--dur) ease-in forwards; }

/* ═══════════════════════════════════
   SHIELD — rectangular frame glow
   ═══════════════════════════════════ */
.fx-shield .shield-frame {
  position: absolute; inset: -6px; border: 3px solid var(--color); border-radius: 12px;
  z-index: 3; pointer-events: none;
  box-shadow: 0 0 15px 4px var(--color), inset 0 0 15px 4px var(--color);
  animation: shieldFrameIn var(--dur) ease-out forwards;
}
.fx-shield .shield-fill {
  position: absolute; inset: 0; border-radius: 8px; z-index: 2; pointer-events: none;
  background: var(--color);
  opacity: 0;
  animation: shieldFillPulse var(--dur) ease-in-out forwards;
}
@keyframes shieldFrameIn {
  0% { opacity: 0; transform: scale(1.3); }
  20% { opacity: 1; transform: scale(1.02); }
  50% { opacity: 0.9; transform: scale(1); }
  80% { opacity: 0.7; }
  100% { opacity: 0; }
}
@keyframes shieldFillPulse {
  0% { opacity: 0; }
  20% { opacity: 0.15; }
  50% { opacity: 0.1; }
  80% { opacity: 0.05; }
  100% { opacity: 0; }
}

/* ═══════════════════════════════════
   LIGHTNING
   ═══════════════════════════════════ */
@keyframes lightningFlash {
  0% { opacity: 0; } 5% { opacity: 1; background: rgba(255,255,255,0.9); }
  10% { opacity: 0; } 15% { opacity: 1; background: rgba(200,220,255,0.7); }
  25% { opacity: 0; } 30% { opacity: 0.8; background: rgba(150,180,255,0.5); }
  50% { opacity: 0; } 100% { opacity: 0; }
}
@keyframes lightningShake {
  0%,100%{transform:none} 5%{transform:translate(4px,-4px)} 10%{transform:translate(-4px,4px)}
  15%{transform:translate(6px,-2px)} 20%{transform:translate(-6px,2px)} 30%{transform:none}
}
.fx-lightning .cg-card { animation: lightningShake var(--dur) ease-out; }
.fx-lightning .lightning-flash {
  position: absolute; inset: 0; border-radius: 8px; z-index: 5; pointer-events: none;
  animation: lightningFlash var(--dur) ease-out forwards;
}

/* ═══════════════════════════════════
   POISON — bubbly gas drip
   ═══════════════════════════════════ */
.fx-poison .cg-card {
  animation: poisonTint var(--dur) ease-in-out forwards;
}
.fx-poison .poison-drip {
  position: absolute; inset: 0; z-index: 3; pointer-events: none; border-radius: 8px;
  background: var(--color);
  animation: poisonBubbleDrip var(--dur) ease-in forwards;
}
.fx-poison .poison-bubbles {
  position: absolute; inset: 0; z-index: 4; pointer-events: none; border-radius: 8px;
  animation: poisonBubblesUp var(--dur) ease-in-out forwards;
}
@keyframes poisonTint {
  0% { filter: none; }
  40% { filter: hue-rotate(60deg) saturate(1.4) brightness(0.85); }
  100% { filter: hue-rotate(90deg) saturate(0.5) brightness(0.6); }
}
@keyframes poisonBubbleDrip {
  0% {
    clip-path: path('M0,0 L200,0 L200,0 C198,5 195,8 190,4 C185,0 180,6 175,2 C170,-2 165,5 160,1 C155,-3 150,4 145,0 C140,-4 135,3 130,0 C125,-3 120,2 115,0 C110,-2 105,3 100,0 L0,0 Z');
    opacity: 0.45;
  }
  25% {
    clip-path: path('M0,0 L200,0 L200,50 C196,62 188,55 182,68 C176,80 168,65 162,78 C156,72 148,85 140,72 C132,60 126,75 118,65 C110,55 104,70 96,58 C88,48 82,62 74,52 C66,42 58,55 50,45 C42,38 34,50 26,40 C18,32 10,42 0,35 Z');
    opacity: 0.48;
  }
  55% {
    clip-path: path('M0,0 L200,0 L200,120 C194,135 186,125 180,140 C174,155 166,138 158,150 C150,142 144,158 136,145 C128,132 122,148 114,138 C106,128 98,142 90,130 C82,120 76,135 68,125 C60,115 52,130 44,118 C36,108 28,122 20,110 C12,100 6,112 0,100 Z');
    opacity: 0.52;
  }
  80% {
    clip-path: path('M0,0 L200,0 L200,210 C195,225 188,215 182,230 C176,240 168,225 160,238 C152,228 146,242 138,232 C130,222 124,235 116,225 C108,215 100,228 92,218 C84,208 78,222 70,212 C62,202 54,215 46,205 C38,195 30,208 22,198 C14,190 8,200 0,192 Z');
    opacity: 0.55;
  }
  100% {
    clip-path: path('M0,0 L200,0 L200,290 L0,290 Z');
    opacity: 0.55;
  }
}
@keyframes poisonBubblesUp {
  0% { opacity: 0; background: none; }
  30% {
    opacity: 0.7;
    background:
      radial-gradient(circle 6px at 25% 70%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 4px at 60% 55%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 8px at 80% 75%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 3px at 40% 45%, var(--color) 60%, transparent 100%);
  }
  60% {
    opacity: 0.5;
    background:
      radial-gradient(circle 5px at 20% 40%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 7px at 55% 30%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 4px at 75% 50%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 6px at 35% 25%, var(--color) 60%, transparent 100%),
      radial-gradient(circle 3px at 85% 35%, var(--color) 60%, transparent 100%);
  }
  100% { opacity: 0; }
}

/* ═══════════════════════════════════
   EXPLODE — flying pieces + flash
   ═══════════════════════════════════ */
@keyframes explodeFlash {
  0% { opacity: 0; transform: scale(0.5); }
  15% { opacity: 1; transform: scale(1.5); }
  100% { opacity: 0; transform: scale(3); }
}
.fx-explode-flash {
  position: absolute; width: 250px; height: 250px; border-radius: 50%; z-index: 10; pointer-events: none;
  background: radial-gradient(circle, rgba(255,255,255,0.9) 0%, var(--color) 40%, transparent 70%);
  animation: explodeFlash calc(var(--dur) * 0.6) ease-out forwards;
  left: 50%; top: 50%; margin-left: -125px; margin-top: -125px;
}

/* ═══════════════════════════════════
   FLIP — fast snap flip with glow burst
   ═══════════════════════════════════ */
@keyframes flipSnap {
  0% { transform: perspective(600px) rotateY(0deg); filter: none; }
  15% { transform: perspective(600px) rotateY(40deg); filter: brightness(1.2); }
  35% { transform: perspective(600px) rotateY(85deg); filter: brightness(0.3); }
  40% { transform: perspective(600px) rotateY(90deg) scaleX(0.02); filter: brightness(2); }
  45% { transform: perspective(600px) rotateY(95deg); filter: brightness(0.3); }
  65% { transform: perspective(600px) rotateY(140deg); filter: brightness(1.2); }
  100% { transform: perspective(600px) rotateY(180deg); filter: none; box-shadow: 0 0 25px 5px var(--color); }
}
.fx-flip .cg-card { animation: flipSnap var(--dur) ease-in-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   VORTEX
   ═══════════════════════════════════ */
@keyframes vortexSpin {
  0% { transform: none; opacity: 1; }
  100% { transform: rotate(720deg) scale(0); opacity: 0; }
}
.fx-vortex .cg-card { animation: vortexSpin var(--dur) ease-in forwards; }

/* ═══════════════════════════════════
   RISE
   ═══════════════════════════════════ */
@keyframes riseUp {
  0% { transform: none; box-shadow: none; opacity: 1; }
  50% { transform: translateY(-30px); box-shadow: 0 20px 40px rgba(0,0,0,0.5), 0 0 30px var(--color); }
  100% { transform: translateY(-60px) scale(0.9); box-shadow: 0 40px 60px rgba(0,0,0,0.3); opacity: 0; }
}
.fx-rise .cg-card { animation: riseUp var(--dur) ease-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   HEAL — warm glow + rising particles
   ═══════════════════════════════════ */
.fx-heal .cg-card {
  animation: healPulse var(--dur) ease-in-out forwards;
  overflow: visible;
}
.fx-heal .heal-particle {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--color);
  box-shadow: 0 0 8px 3px var(--color);
  pointer-events: none;
  z-index: 8;
  opacity: 0;
}
.fx-heal .heal-cross {
  position: absolute;
  z-index: 7; pointer-events: none;
  opacity: 0;
  font-size: 24px;
  color: var(--color);
  text-shadow: 0 0 10px var(--color), 0 0 20px var(--color);
}
@keyframes healPulse {
  0% { box-shadow: none; filter: none; }
  20% { box-shadow: 0 0 25px 8px var(--color), inset 0 0 15px 3px var(--color); filter: brightness(1.2); }
  40% { box-shadow: 0 0 10px 3px var(--color); filter: brightness(1.05); }
  60% { box-shadow: 0 0 30px 10px var(--color), inset 0 0 20px 5px var(--color); filter: brightness(1.3); }
  80% { box-shadow: 0 0 15px 5px var(--color); filter: brightness(1.1); }
  100% { box-shadow: 0 0 8px 2px var(--color); filter: brightness(1); }
}
@keyframes healParticleRise {
  0% { opacity: 0; transform: translateY(0) scale(1); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-100px) scale(0.3); }
}
@keyframes healCrossFloat {
  0% { opacity: 0; transform: translateY(0) scale(0.5); }
  20% { opacity: 0.9; transform: translateY(-15px) scale(1); }
  60% { opacity: 0.7; transform: translateY(-40px) scale(0.8); }
  100% { opacity: 0; transform: translateY(-70px) scale(0.4); }
}

/* ═══════════════════════════════════
   STAMP
   ═══════════════════════════════════ */
@keyframes stampDown {
  0% { transform: scale(2) translateY(-100px); opacity: 0; }
  40% { transform: scale(1.1) translateY(5px); opacity: 1; }
  50% { transform: scale(1); }
  60% { box-shadow: 0 0 40px 10px var(--color); }
  100% { box-shadow: 0 0 0 0 transparent; transform: scale(1); }
}
.fx-stamp .cg-card { animation: stampDown var(--dur) ease-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   CRUSH — progressive paper rip
   ═══════════════════════════════════ */
.fx-crush .crush-piece {
  position: absolute; inset: 0; overflow: hidden; border-radius: 4px;
}
.fx-crush .crush-piece img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
@keyframes crushPc0 {
  0% { transform: none; opacity: 1; }
  20% { transform: translate(-2px, -1px) rotate(-0.3deg); }
  50% { transform: translate(-25px, -15px) rotate(-8deg); opacity: 0.9; }
  100% { transform: translate(-80px, -40px) rotate(-18deg) scale(0.7); opacity: 0; }
}
@keyframes crushPc1 {
  0% { transform: none; opacity: 1; }
  25% { transform: translate(2px, -1px) rotate(0.3deg); }
  55% { transform: translate(20px, -20px) rotate(6deg); opacity: 0.9; }
  100% { transform: translate(75px, -50px) rotate(15deg) scale(0.7); opacity: 0; }
}
@keyframes crushPc2 {
  0% { transform: none; opacity: 1; }
  30% { transform: translate(-1px, 2px) rotate(-0.2deg); }
  60% { transform: translate(-30px, 25px) rotate(-10deg); opacity: 0.8; }
  100% { transform: translate(-70px, 60px) rotate(-20deg) scale(0.6); opacity: 0; }
}
@keyframes crushPc3 {
  0% { transform: none; opacity: 1; }
  35% { transform: translate(1px, 2px) rotate(0.2deg); }
  65% { transform: translate(25px, 30px) rotate(8deg); opacity: 0.8; }
  100% { transform: translate(65px, 70px) rotate(16deg) scale(0.6); opacity: 0; }
}

/* ═══════════════════════════════════
   GROW
   ═══════════════════════════════════ */
@keyframes growUp {
  0% { transform: scale(1); box-shadow: 0 4px 20px rgba(0,0,0,0.5); }
  50% { transform: scale(1.3); box-shadow: 0 0 40px 15px var(--color), 0 0 80px 30px var(--color); }
  100% { transform: scale(1.15); box-shadow: 0 0 20px 5px var(--color); }
}
.fx-grow .cg-card,
.fx-grow .cg-set-card,
.fx-grow.cg-set-slot { animation: growUp var(--dur) ease-in-out forwards; overflow: visible; }

/* ═══════════════════════════════════
   BLINK — rapid phase in/out
   ═══════════════════════════════════ */
@keyframes blinkPhase {
  0% { transform: scale(1); opacity: 1; filter: none; }
  8% { transform: scale(1.15); opacity: 0; filter: brightness(3); }
  16% { transform: scale(0.9); opacity: 1; filter: brightness(1.5) hue-rotate(30deg); }
  24% { transform: scale(1.1); opacity: 0; filter: brightness(3); }
  32% { transform: scale(0.95); opacity: 0.8; filter: brightness(1.2) hue-rotate(60deg); }
  40% { transform: scale(1.08); opacity: 0; filter: brightness(3); }
  50% { transform: scale(1); opacity: 1; filter: brightness(1) hue-rotate(90deg); }
  62% { transform: scale(1.05); opacity: 0.3; filter: brightness(2); }
  74% { transform: scale(0.98); opacity: 1; filter: brightness(1.1); }
  86% { transform: scale(1.02); opacity: 0.5; filter: brightness(1.5); }
  100% { transform: scale(1); opacity: 1; filter: none; }
}
.fx-blink .cg-card {
  animation: blinkPhase var(--dur) ease-in-out forwards;
  overflow: visible;
}

/* ═══════════════════════════════════
   SNARE — net pattern from center
   ═══════════════════════════════════ */
.fx-snare .cg-card { overflow: visible; }
.snare-net-svg {
  position: absolute; inset: -8px; z-index: 8; pointer-events: none;
  opacity: 0; animation: snareAppear var(--dur) ease-out forwards;
}
@keyframes snareAppear {
  0% { opacity: 0; transform: scale(0.3); }
  25% { opacity: 0.9; transform: scale(1.05); }
  40% { transform: scale(0.98); }
  100% { opacity: 0.7; transform: scale(1); filter: drop-shadow(0 0 6px var(--color)); }
}
@keyframes snareCatch {
  0% { transform: none; }
  15% { transform: translateX(-4px) rotate(-0.5deg); }
  25% { transform: translateX(5px) rotate(0.8deg); }
  40% { transform: translateY(4px) scale(0.98); }
  100% { transform: translateY(6px) scale(0.97); filter: brightness(0.85); }
}

/* ═══════════════════════════════════
   PULSE — 3 rapid glow flashes
   ═══════════════════════════════════ */
.fx-pulse .cg-card {
  animation: pulseTriple var(--dur) ease-in-out forwards; overflow: visible;
}
@keyframes pulseTriple {
  0% { box-shadow: none; filter: none; }
  10% { box-shadow: 0 0 40px 15px var(--color), inset 0 0 20px 5px var(--color); filter: brightness(1.4); }
  20% { box-shadow: 0 0 5px 2px var(--color); filter: brightness(1); }
  35% { box-shadow: 0 0 50px 20px var(--color), inset 0 0 25px 8px var(--color); filter: brightness(1.5); }
  45% { box-shadow: 0 0 5px 2px var(--color); filter: brightness(1); }
  60% { box-shadow: 0 0 60px 25px var(--color), inset 0 0 30px 10px var(--color); filter: brightness(1.6); transform: scale(1.05); }
  75% { box-shadow: 0 0 20px 8px var(--color); filter: brightness(1.1); transform: scale(1.02); }
  100% { box-shadow: 0 0 10px 3px var(--color); filter: none; transform: scale(1); }
}

/* ═══════════════════════════════════
   WHIP — horizontal energy slash, top/bottom split
   ═══════════════════════════════════ */
.fx-whip .whip-line {
  position: absolute; inset: -20px; z-index: 5; pointer-events: none; overflow: hidden;
}
.fx-whip .whip-line::before {
  content: '';
  position: absolute;
  width: 200%; height: 5px;
  left: -50%; top: 50%;
  background: linear-gradient(90deg, transparent 0%, var(--color) 25%, #fff 48%, #fff 52%, var(--color) 75%, transparent 100%);
  box-shadow: 0 0 15px 5px var(--color), 0 0 30px 10px var(--color);
  transform: translateX(-110%);
  animation: whipSwipe 0.35s ease-out forwards;
  border-radius: 2px;
}
.fx-whip .whip-top, .fx-whip .whip-bot {
  position: absolute; inset: 0; overflow: hidden; border-radius: 8px;
}
.fx-whip .whip-top img, .fx-whip .whip-bot img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.fx-whip .whip-top {
  clip-path: polygon(0 0, 100% 0, 100% 50%, 0 50%);
  animation: whipTopFall var(--dur) 0.4s ease-in forwards;
}
.fx-whip .whip-bot {
  clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
  animation: whipBotFall var(--dur) 0.4s ease-in forwards;
}
@keyframes whipSwipe {
  0% { transform: translateX(-110%); opacity: 1; }
  60% { opacity: 1; }
  100% { transform: translateX(110%); opacity: 0; }
}
@keyframes whipTopFall {
  0% { transform: none; opacity: 1; }
  100% { transform: translateY(-35px) rotate(-5deg); opacity: 0; }
}
@keyframes whipBotFall {
  0% { transform: none; opacity: 1; }
  100% { transform: translateY(35px) rotate(5deg); opacity: 0; }
}

/* ═══════════════════════════════════
   GRAB — ghost trails, card snatched laterally
   ═══════════════════════════════════ */
.fx-grab .cg-card {
  animation: grabSnatch var(--dur) cubic-bezier(0.2,0,0.8,1) forwards;
}
.fx-grab .grab-trail {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border-radius: 6px; opacity: 0;
  border: 2px solid var(--color);
  box-shadow: 0 0 15px var(--color);
  animation: grabTrail var(--dur) ease-out forwards;
}
.fx-grab .grab-trail:nth-child(2) { animation-delay: calc(var(--dur) * 0.15); }
.fx-grab .grab-trail:nth-child(3) { animation-delay: calc(var(--dur) * 0.22); }
@keyframes grabSnatch {
  0% { transform: none; opacity: 1; }
  20% { transform: translateX(8px) rotate(2deg); opacity: 1; }
  30% { transform: translateX(-10px) rotate(-1deg); opacity: 1; }
  50% { transform: translateX(-80px) rotate(-8deg); opacity: 0.9; }
  100% { transform: translateX(-400px) rotate(-15deg) scale(0.7); opacity: 0; }
}
@keyframes grabTrail {
  0% { opacity: 0; transform: none; }
  20% { opacity: 0.6; transform: translateX(10px); }
  60% { opacity: 0.3; transform: translateX(30px); }
  100% { opacity: 0; transform: translateX(60px) scale(0.9); }
}
@keyframes grabPull {
  0% { transform: none; opacity: 1; }
  30% { transform: none; }
  40% { transform: translateX(15px) rotate(3deg); }
  100% { transform: translateX(300px) rotate(15deg) scale(0.6); opacity: 0; }
}

/* ═══════════════════════════════════
   INFECT — dark spots spread
   ═══════════════════════════════════ */
.fx-infect .cg-card {
  animation: infectDarken var(--dur) ease-in forwards;
}
.fx-infect .infect-spot {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 4;
  background: radial-gradient(circle, rgba(0,0,0,0.8) 30%, var(--color) 60%, transparent 80%);
  opacity: 0; transform: scale(0);
}
@keyframes infectDarken {
  0% { filter: none; }
  50% { filter: saturate(0.5) brightness(0.7); }
  100% { filter: saturate(0.1) brightness(0.3); }
}
@keyframes infectGrow {
  0% { opacity: 0; transform: scale(0); }
  30% { opacity: 0.8; transform: scale(0.5); }
  100% { opacity: 0.9; transform: scale(1); }
}

/* ═══════════════════════════════════
   TORNADO — 3D horizontal spin vortex
   ═══════════════════════════════════ */
.fx-tornado .cg-card {
  animation: tornadoSpin var(--dur) ease-in forwards;
}
@keyframes tornadoSpin {
  0% { transform: perspective(400px) rotateY(0) scale(1); opacity: 1; }
  25% { transform: perspective(400px) rotateY(180deg) scale(0.85); }
  50% { transform: perspective(400px) rotateY(360deg) scale(0.65) translateY(-20px); }
  75% { transform: perspective(400px) rotateY(540deg) scale(0.4) translateY(-40px); opacity: 0.6; }
  100% { transform: perspective(400px) rotateY(720deg) scale(0.1) translateY(-60px); opacity: 0; }
}

/* ═══════════════════════════════════
   DRAIN — golden streaks fall off
   ═══════════════════════════════════ */
.fx-drain .cg-card {
  animation: drainFade var(--dur) ease-in forwards;
}
.fx-drain .drain-streak {
  position: absolute; top: 0; width: 3px; pointer-events: none; z-index: 5;
  border-radius: 2px;
  background: linear-gradient(to bottom, transparent, var(--color) 30%, var(--color) 70%, transparent);
  opacity: 0;
}
@keyframes drainFade {
  0% { filter: none; }
  40% { filter: saturate(0.6) brightness(0.8); }
  100% { filter: saturate(0.2) brightness(0.5); }
}
@keyframes drainFall {
  0% { transform: translateY(-20px); opacity: 0; }
  15% { opacity: 0.9; }
  100% { transform: translateY(calc(100% + 40px)); opacity: 0; }
}

/* ═══════════════════════════════════
   VANISH — smoke puff, card disappears
   ═══════════════════════════════════ */
.fx-vanish .cg-card {
  animation: vanishPoof var(--dur) ease-out forwards;
}
.fx-vanish .vanish-puff {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 6;
  background: radial-gradient(circle, rgba(180,180,180,0.6) 0%, rgba(100,100,100,0.3) 50%, transparent 75%);
  opacity: 0; filter: blur(4px);
}
@keyframes vanishPoof {
  0% { transform: scale(1); opacity: 1; filter: none; }
  30% { transform: scale(1.05); opacity: 0.9; filter: brightness(1.3); }
  50% { transform: scale(0.8); opacity: 0.4; filter: blur(2px) brightness(0.7); }
  100% { transform: scale(0.3); opacity: 0; filter: blur(8px); }
}
@keyframes vanishPuffGrow {
  0% { opacity: 0; transform: scale(0.3); }
  40% { opacity: 0.7; transform: scale(1.2); }
  100% { opacity: 0; transform: scale(2); }
}

/* ═══════════════════════════════════
   BARRIER — hexagonal shield grid
   ═══════════════════════════════════ */
.fx-barrier .cg-card { overflow: visible; }
.fx-barrier .barrier-hex {
  position: absolute; inset: -10px; z-index: 7; pointer-events: none;
  border: 3px solid var(--color); border-radius: 14px;
  box-shadow: 0 0 20px 6px var(--color), inset 0 0 20px 6px var(--color);
  opacity: 0;
  animation: barrierIn var(--dur) ease-out forwards;
}
.fx-barrier .barrier-line {
  position: absolute; pointer-events: none; z-index: 8;
  background: var(--color); opacity: 0;
  box-shadow: 0 0 4px 1px var(--color);
}
@keyframes barrierIn {
  0% { opacity: 0; transform: scale(1.4); }
  20% { opacity: 1; transform: scale(1.02); }
  50% { opacity: 0.8; box-shadow: 0 0 30px 10px var(--color), inset 0 0 30px 10px var(--color); }
  80% { opacity: 0.6; }
  100% { opacity: 0.3; }
}
@keyframes barrierLineIn {
  0% { opacity: 0; transform: scaleX(0); }
  30% { opacity: 0.6; transform: scaleX(1); }
  100% { opacity: 0.2; }
}

/* ═══════════════════════════════════
   REINFORCE — layered borders growing stronger
   ═══════════════════════════════════ */
.fx-reinforce .cg-card {
  animation: reinforceGrow var(--dur) ease-in-out forwards; overflow: visible;
}
.fx-reinforce .reinforce-ring {
  position: absolute; border-radius: 12px; pointer-events: none;
  border: 2px solid var(--color); opacity: 0;
  box-shadow: 0 0 8px 2px var(--color);
}
@keyframes reinforceGrow {
  0% { transform: scale(1); box-shadow: none; }
  40% { transform: scale(1.08); box-shadow: 0 0 20px 6px var(--color); }
  70% { transform: scale(1.15); box-shadow: 0 0 35px 12px var(--color), inset 0 0 15px 4px var(--color); }
  100% { transform: scale(1.12); box-shadow: 0 0 25px 8px var(--color), inset 0 0 10px 3px var(--color); }
}
@keyframes reinforceRingIn {
  0% { opacity: 0; transform: scale(1.5); }
  40% { opacity: 0.7; transform: scale(1); }
  100% { opacity: 0.3; transform: scale(1); }
}

/* ═══════════════════════════════════
   REFLECT — flash mirror bounce
   ═══════════════════════════════════ */
.fx-reflect .cg-card {
  animation: reflectBounce var(--dur) ease-out forwards; overflow: visible;
}
.fx-reflect .reflect-flash {
  position: absolute; inset: 0; border-radius: 8px; z-index: 5; pointer-events: none;
  background: linear-gradient(135deg, transparent 30%, rgba(255,255,255,0.9) 50%, transparent 70%);
  opacity: 0;
  animation: reflectFlash calc(var(--dur) * 0.4) ease-out forwards;
}
@keyframes reflectBounce {
  0% { transform: none; }
  10% { transform: scale(0.92) translateX(-8px); }
  25% { transform: scale(1.08) translateX(15px); filter: brightness(1.5); }
  40% { transform: scale(1.02) translateX(-5px); filter: brightness(1.1); }
  60% { transform: scale(1); }
  100% { transform: none; filter: none; }
}
@keyframes reflectFlash {
  0% { opacity: 0; }
  15% { opacity: 1; }
  40% { opacity: 0.5; }
  100% { opacity: 0; }
}

/* ═══════════════════════════════════
   SIPHON — suction spiral inward
   ═══════════════════════════════════ */
.fx-siphon .cg-card {
  animation: siphonSuck var(--dur) ease-in forwards; overflow: visible;
}
@keyframes siphonSuck {
  0% { transform: none; opacity: 1; filter: none; }
  20% { transform: scale(1.05); filter: brightness(1.2) hue-rotate(20deg); }
  40% { transform: scale(0.85) rotate(15deg); filter: brightness(1.1) hue-rotate(40deg); box-shadow: 0 0 30px 10px var(--color); }
  60% { transform: scale(0.6) rotate(60deg); filter: brightness(0.8) hue-rotate(60deg); box-shadow: 0 0 40px 15px var(--color); }
  80% { transform: scale(0.3) rotate(180deg); opacity: 0.5; filter: brightness(0.5); }
  100% { transform: scale(0) rotate(360deg); opacity: 0; }
}

/* ═══════════════════════════════════
   SPARK — electric crackle with flying sparks
   ═══════════════════════════════════ */
.fx-spark .cg-card {
  animation: sparkShake var(--dur) ease-in-out forwards; overflow: visible;
}
.fx-spark .spark-dot {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 8;
  background: var(--color);
  box-shadow: 0 0 6px 3px var(--color);
  opacity: 0;
}
@keyframes sparkShake {
  0% { transform: none; filter: none; }
  5% { transform: translate(3px,-2px); filter: brightness(1.4); }
  10% { transform: translate(-4px,3px); filter: brightness(1); }
  15% { transform: translate(2px,-4px); filter: brightness(1.6); }
  20% { transform: translate(-3px,1px); filter: brightness(1); }
  25% { transform: translate(5px,2px); filter: brightness(1.3); }
  30% { transform: none; filter: none; }
  50% { transform: translate(-2px,3px); filter: brightness(1.5); }
  55% { transform: translate(3px,-1px); filter: brightness(1); }
  70% { filter: brightness(1.3); }
  100% { transform: none; filter: none; }
}
@keyframes sparkFly {
  0% { opacity: 1; transform: translate(0,0) scale(1); }
  100% { opacity: 0; transform: translate(var(--sx,30px), var(--sy,-40px)) scale(0.2); }
}

/* ═══════════════════════════════════
   RIP — tear pieces off
   ═══════════════════════════════════ */
.fx-rip .rip-piece {
  position: absolute; overflow: hidden; border-radius: 3px; z-index: 5;
}
.fx-rip .rip-piece img {
  position: absolute; display: block;
}
.fx-rip .cg-card {
  animation: ripBase var(--dur) ease-in-out forwards;
}
@keyframes ripBase {
  0% { transform: none; filter: none; }
  15% { transform: translateX(-5px) rotate(-1deg); }
  30% { transform: translateX(4px) rotate(0.5deg); }
  50% { transform: translateX(-2px); filter: brightness(0.85); }
  100% { transform: none; filter: brightness(0.7) saturate(0.6); }
}
@keyframes ripFly0 { 0%{transform:none;opacity:1} 100%{transform:translate(100px,-70px) rotate(20deg) scale(0.5);opacity:0} }
@keyframes ripFly1 { 0%{transform:none;opacity:1} 100%{transform:translate(-90px,-50px) rotate(-25deg) scale(0.4);opacity:0} }
@keyframes ripFly2 { 0%{transform:none;opacity:1} 100%{transform:translate(70px,60px) rotate(15deg) scale(0.5);opacity:0} }
@keyframes ripFly3 { 0%{transform:none;opacity:1} 100%{transform:translate(-60px,80px) rotate(-20deg) scale(0.4);opacity:0} }

/* ═══════════════════════════════════
   YOINK — smoke burst, cards fly down
   ═══════════════════════════════════ */
.fx-yoink .cg-card {
  animation: yoinkPull var(--dur) ease-in forwards; overflow: visible;
}
.fx-yoink .yoink-smoke {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 8;
  background: radial-gradient(circle, rgba(200,200,200,0.8) 0%, rgba(120,120,120,0.4) 40%, transparent 70%);
  filter: blur(6px); opacity: 0;
}
@keyframes yoinkPull {
  0% { transform: none; opacity: 1; filter: none; }
  20% { transform: scale(1.05); opacity: 1; filter: brightness(1.3); }
  30% { transform: scale(0.3); opacity: 0; filter: brightness(2); }
  45% { transform: scale(0.3) translateY(30px); opacity: 0; }
  55% { transform: scale(0.7) translateY(60px); opacity: 0.8; filter: brightness(1.2);
        box-shadow: 0 0 20px 6px var(--color); }
  70% { transform: scale(0.6) translateY(120px); opacity: 0.6;
        box-shadow: 0 0 10px 3px var(--color); }
  100% { transform: scale(0.4) translateY(250px); opacity: 0; }
}
@keyframes yoinkSmokeOut {
  0% { opacity: 0; transform: scale(0.3); }
  25% { opacity: 0.9; transform: scale(1.5); }
  60% { opacity: 0.5; transform: scale(2); }
  100% { opacity: 0; transform: scale(2.5); }
}

/* ═══════════════════════════════════
   ARROWS — rain of arrows, card falls back
   ═══════════════════════════════════ */
.fx-arrows .cg-card {
  overflow: visible;
  transform-style: preserve-3d;
  perspective: 600px;
}
.arrow-shaft {
  position: absolute;
  width: 3px;
  height: 40px;
  background: linear-gradient(to top, #8B6914, #5C4A1E);
  z-index: 10;
  pointer-events: none;
  opacity: 0;
  transform-origin: bottom center;
}
.arrow-shaft::before {
  content: '';
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 10px solid #888;
}
.arrow-shaft::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 8px; height: 12px;
  background: linear-gradient(to top, transparent 40%, #8B6914 40%, #8B6914 60%, transparent 60%),
              linear-gradient(135deg, transparent 40%, #8B6914 40%, #8B6914 60%, transparent 60%);
  opacity: 0.5;
}
@keyframes arrowFall {
  0% { transform: translateY(-200px) rotate(0deg); opacity: 0; }
  15% { opacity: 1; }
  60% { transform: translateY(0px) rotate(2deg); opacity: 1; }
  65% { transform: translateY(-3px) rotate(1deg); opacity: 1; }
  100% { transform: translateY(0px) rotate(0deg); opacity: 1; }
}
@keyframes arrowFallDown {
  0% { transform: translateY(-250px) rotate(180deg); opacity: 0; }
  15% { opacity: 1; }
  55% { transform: translateY(0px) rotate(180deg); opacity: 1; }
  62% { transform: translateY(-4px) rotate(180deg); opacity: 1; }
  70% { transform: translateY(0px) rotate(180deg); opacity: 1; }
  100% { transform: translateY(0px) rotate(180deg); opacity: 1; }
}
@keyframes cardFallBack {
  0% { transform: perspective(600px) rotateX(0deg); opacity: 1; }
  60% { transform: perspective(600px) rotateX(0deg); opacity: 1; }
  100% { transform: perspective(600px) rotateX(70deg) translateY(30px); opacity: 0.3; }
}

/* ═══════════════════════════════════
   SET CARD COMPATIBILITY
   VFX applied on .cg-set-slot containers — need .cg-set-card to inherit
   all the same animations that .cg-card gets
   ═══════════════════════════════════ */
.fx-shake .cg-set-card { animation: shakeViolent var(--dur) ease-in-out forwards; }
.fx-freeze .cg-set-card { animation: freezeOver var(--dur) ease-in-out forwards; overflow: visible; }
.fx-steal .cg-set-card { animation: stealAway var(--dur) ease-in forwards; }
.fx-flip .cg-set-card { animation: flipSnap var(--dur) ease-in-out forwards; overflow: visible; }
.fx-vortex .cg-set-card { animation: vortexSpin var(--dur) ease-in forwards; }
.fx-rise .cg-set-card { animation: riseUp var(--dur) ease-out forwards; overflow: visible; }
.fx-stamp .cg-set-card { animation: stampDown var(--dur) ease-out forwards; overflow: visible; }
.fx-tornado .cg-set-card { animation: tornadoSpin var(--dur) ease-in-out forwards; }
.fx-lightning .cg-set-card { animation: lightningShake var(--dur) ease-out; }

/* Direct glow on the whole set slot when VFX is applied directly */
.fx-glow.cg-set-slot,
.fx-grow.cg-set-slot {
  position: relative;
  z-index: 5;
}
