/* Event accents share the table palette; all controls remain underneath and usable. */
.actionfx-layer { position: fixed; inset: 0; z-index: 165; overflow: hidden; pointer-events: none; contain: layout paint; }
.actionfx-layer * { pointer-events: none !important; box-sizing: border-box; }
.actionfx-attack { color: var(--ds-accent-bright); --actionfx-rgb: var(--ds-accent-bright-rgb); }
.actionfx-instant { color: var(--ds-spell); --actionfx-rgb: var(--ds-spell-rgb); }
.actionfx-block { color: var(--ds-spell); --actionfx-rgb: var(--ds-spell-rgb); }
.actionfx-clash { color: var(--ds-accent-bright); --actionfx-rgb: var(--ds-accent-bright-rgb); }
.actionfx-route { position: absolute; height: 2px; transform-origin: left center; }
.actionfx-trace { width: 100%; height: 2px; transform-origin: left; background: linear-gradient(90deg, transparent, currentColor); opacity: 0; }
.actionfx-spark { position: absolute; top: -1px; left: 0; width: 18px; height: 4px; border-radius: 50%; background: var(--ds-text); box-shadow: 0 0 9px 2px rgba(var(--actionfx-rgb), .7); opacity: 0; }
.actionfx-ring { position: absolute; width: 72px; height: 72px; margin: -36px; }
.actionfx-disc { width: 100%; height: 100%; border: 2px solid currentColor; border-radius: 50%; box-shadow: inset 0 0 16px rgba(var(--actionfx-rgb), .16), 0 0 18px rgba(var(--actionfx-rgb), .23); opacity: 0; }
.actionfx-ring.commit { width: 44px; height: 44px; margin: -22px; }
.actionfx-ring.commit .actionfx-disc { border-radius: 10px; border-bottom-color: transparent; }
.actionfx-ring.spell .actionfx-disc { border-inline-color: transparent; }
.actionfx-ring.echo { width: 104px; height: 104px; margin: -52px; }
.actionfx-ring.echo .actionfx-disc { border: 1px dashed currentColor; box-shadow: none; }
/* A raised guard on the blocker, a dashed meeting ring on its attacker. */
.actionfx-ring.guard { width: 46px; height: 46px; margin: -23px; }
.actionfx-ring.guard .actionfx-disc { border-radius: 12px 12px 50% 50%; }
.actionfx-ring.meet { width: 58px; height: 58px; margin: -29px; }
.actionfx-ring.meet .actionfx-disc { border-style: dashed; box-shadow: none; }
/* Crossed blades where an attacker and its blocker fight. */
.actionfx-collision { position: absolute; width: 0; height: 0; }
.actionfx-blade { position: absolute; left: -38px; top: -3px; width: 76px; height: 6px; border-radius: 6px; background: linear-gradient(90deg, transparent, var(--ds-text) 45%, currentColor 70%, transparent); box-shadow: 0 0 12px 2px rgba(var(--actionfx-rgb), .75); opacity: 0; }
.actionfx-flash { position: absolute; left: -34px; top: -34px; width: 68px; height: 68px; border-radius: 50%; background: radial-gradient(circle, var(--ds-text) 0 12%, rgba(var(--actionfx-rgb), .75) 30%, transparent 68%); opacity: 0; }
/* Fighting creatures light up: ember for attackers, blue for blockers. */
.actionfx-frame { position: absolute; border: 2px solid currentColor; border-radius: 7px; box-shadow: 0 0 16px rgba(var(--actionfx-rgb), .6), inset 0 0 12px rgba(var(--actionfx-rgb), .28); opacity: 0; }
.actionfx-frame.blocker { color: var(--ds-spell); --actionfx-rgb: var(--ds-spell-rgb); }
.actionfx-banner { position: absolute; display: flex; align-items: center; gap: 10px; padding: 9px 18px 9px 12px; border: 1px solid rgba(var(--actionfx-rgb), .5); border-radius: 10px; background: rgba(var(--ds-panel-rgb), .95); box-shadow: 0 12px 34px rgba(var(--ds-table-rgb), .6), 0 0 26px rgba(var(--actionfx-rgb), .22); white-space: nowrap; opacity: 0; }
.actionfx-banner .gameicon { width: 28px; height: 28px; flex: 0 0 auto; }
.actionfx-banner b { display: block; color: currentColor; font: 800 16px/1.2 var(--ds-font-display); letter-spacing: .1em; }
.actionfx-banner small { display: block; color: var(--ds-copy); font: 600 12px/1.35 var(--ds-font-body); }
.actionfx-label { position: absolute; width: max-content; max-width: 184px; padding: 5px 9px; border-radius: 6px; background: rgba(var(--ds-panel-rgb), .93); box-shadow: 0 3px 12px rgba(var(--ds-table-rgb), .25); text-align: center; opacity: 0; }
.actionfx-label b { display: block; color: inherit; font: 750 11px/1.4 var(--ds-font-body); letter-spacing: .04em; }
.actionfx-label span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ds-copy); font: 500 12px/1.4 var(--ds-font-body); }
/* Combat hits play one after another (ui.showDamageEffect): every part of a
   delayed impact, including the large-hit number punch, waits for its turn. */
.gamefx-impact.combat > :is(span, i, strong, small) { animation-delay: var(--combat-delay, 0ms) !important; }
/* Live combat: a copy of each charging card crosses the table to its target;
   the real card stays in place, faded, until the copy is back. */
.actionfx-charge { position: absolute; z-index: 2; transform-origin: center; will-change: transform; }
.actionfx-charge > * { position: relative !important; display: block !important; width: 100% !important; height: 100% !important; margin: 0 !important; transform: none !important; overflow: hidden; border-radius: 7px; box-shadow: 0 14px 34px rgba(var(--ds-table-rgb), .7), 0 0 0 2px rgba(var(--ds-accent-bright-rgb), .9), 0 0 26px rgba(var(--ds-accent-bright-rgb), .5); }
.actionfx-charge img { width: 100%; height: 100%; object-fit: cover; }
.actionfx-brace { position: absolute; border: 2px solid var(--ds-spell); border-radius: 7px; box-shadow: 0 0 18px rgba(var(--ds-spell-rgb), .55), inset 0 0 12px rgba(var(--ds-spell-rgb), .3); opacity: 0; }
#game .fx-charging { opacity: .28 !important; transition: opacity 120ms ease-out; }
body:not(.game-active) .actionfx-layer, body.reduced-motion .actionfx-layer { display: none; }
@media (prefers-reduced-motion: reduce) { .actionfx-layer { display: none; } }
