/* Combat effects (src/ui/fx.js), from the Cape Sounion demo. */

.fx-impact { position: absolute; width: 120px; height: 120px; margin: -60px 0 0 -60px; border-radius: 50%; z-index: 11; pointer-events: none; background: radial-gradient(circle, rgba(255, 255, 255, .95) 0, rgba(190, 140, 255, .7) 30%, rgba(150, 90, 255, 0) 68%); }
@keyframes fxHit { 0%, 45% { filter: brightness(2.1) saturate(.5) drop-shadow(0 0 14px #b57cff); } 100% { filter: none; } }
.fx-hit { animation: fxHit .3s ease-out; }

/* Floating numbers. */
@keyframes fxFloat { from { opacity: 1; transform: translate(-50%, 0); } to { opacity: 0; transform: translate(-50%, -46px); } }
.fx-float { position: absolute; z-index: 12; pointer-events: none; white-space: nowrap; font-family: var(--f-display); font-weight: 700; font-size: 28px; text-shadow: 0 0 6px #000, 0 2px 4px #000; animation: fxFloat 1s ease-out forwards; }
.fx-dmg { color: #ff7a68; }

/* A creature fading out when it falls and in when it arrives; lunging when it bites. */
.fx-fade { transition: opacity .45s ease, transform .45s ease; }
.fx-gone { opacity: 0; transform: translateY(26px) scale(.94); }
.fx-falling { transition-delay: .35s; } /* let the last spell land first (it flies for .39 s) */
.fx-lunge { transform: translateX(-26px) scale(1.04); transition: transform .12s ease; }

/* A bite: claw marks across the flask, which shakes. */
.fx-slash { position: absolute; left: 50%; top: 0; width: 52px; height: 62px; margin-left: -26px; z-index: 7; pointer-events: none; }
.fx-slash svg { width: 100%; height: 100%; overflow: visible; }
.fx-slash path { stroke: #fff; stroke-width: 3.4; stroke-linecap: round; fill: none; stroke-dasharray: 75; stroke-dashoffset: 75; opacity: 0; filter: drop-shadow(0 0 3px #ff4a3a) drop-shadow(0 0 6px #ff2a1a); animation: fxSlash .55s ease-out forwards; }
.fx-slash path:nth-child(2) { animation-delay: .07s; }
.fx-slash path:nth-child(3) { animation-delay: .14s; }
@keyframes fxSlash { 0% { stroke-dashoffset: 75; opacity: 1; } 28% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes fxHurt { 0%, 100% { translate: 0 0; } 20% { translate: -4px 2px; } 45% { translate: 4px -2px; } 70% { translate: -3px 1px; } }
.fx-hurt .vial-glass, .duel-gem.fx-hurt { animation: fxHurt .28s linear; }
@keyframes fxFlash { 0% { filter: drop-shadow(0 0 10px var(--glow, #ffe9a8)) brightness(1.6); } 100% { filter: none; } }
.fx-flash .vial-glass { animation: fxFlash .45s ease-out; }
.fx-hurt.fx-flash .vial-glass { animation: fxHurt .28s linear, fxFlash .45s ease-out; }

/* Essence orb flying into its flask. */
.fx-orb { position: absolute; z-index: 12; width: 34px; height: 34px; border-radius: 50%; pointer-events: none; display: grid; place-items: center; background: radial-gradient(circle, rgba(255, 255, 255, .9) 0, rgba(255, 220, 160, .55) 45%, rgba(255, 200, 120, 0) 72%); filter: drop-shadow(0 0 8px rgba(255, 220, 150, .9)); }
.fx-orb img { width: 22px; height: 22px; object-fit: contain; }
.vial { position: relative; }
.fx-gain { color: var(--gold); font-size: 20px; }

/* Reduce motion: no flights or shakes; the numbers still appear. */
.reduce-motion .fx-gone { transform: none; }

/* Duel casts flying from their button or corner (fx.js castFrom). */
.fx-cast { position: absolute; left: 0; top: 0; height: auto; z-index: 11; opacity: 0; pointer-events: none; filter: drop-shadow(0 0 6px var(--pc, #fff)); }

/* Timer tubes (src/ui/tubes.js; Canvas ElementTube and BeastTube, 2026-10-26). */
.tube { position: relative; width: 100%; aspect-ratio: 1774 / 190; }
.tube-art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.tube-empty { position: absolute; inset: 0; filter: brightness(.1) saturate(.35); }
.tube-sym { position: absolute; object-fit: contain; filter: brightness(0) invert(1) drop-shadow(0 0 3px var(--g)) drop-shadow(0 0 6px var(--g)); }
@keyframes tubeHit { 0% { filter: brightness(1); } 25% { filter: brightness(1.55) drop-shadow(0 0 9px rgba(255, 236, 170, .95)); } 100% { filter: brightness(1); } }
.tube-hit { animation: tubeHit .5s linear; }
/* The beast is a little taller than an elemental tube: it sits in the same slot, centred on its body, head and tail overhanging. */
.tube-slot { position: relative; width: 100%; aspect-ratio: 1774 / 190; }
.beast { position: absolute; left: 0; right: 0; top: -17.5%; aspect-ratio: 2133 / 292; }
.beast-empty { filter: brightness(.15) saturate(.35); }
.beast-eye { position: absolute; left: 4.36%; top: 38%; width: 5%; aspect-ratio: 1; margin: -2.5% 0 0 -2.5%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen; opacity: 0; background: radial-gradient(circle, rgba(255, 255, 255, .95) 0%, rgba(255, 70, 45, .95) 20%, rgba(255, 0, 0, .55) 45%, rgba(255, 0, 0, 0) 70%); }
@keyframes eyeFlash { 0% { opacity: 0; scale: .6; } 25% { opacity: 1; scale: 1.3; } 75% { opacity: .4; scale: 1; } 100% { opacity: 0; scale: .7; } }
.eye-flash { animation: eyeFlash .6s linear; }

/* Realm fights (fx.js launch and drain; Canvas RealmFight, 2026-10-26). */
.fx-flight { position: absolute; z-index: 11; opacity: 0; pointer-events: none; object-fit: contain; filter: drop-shadow(0 0 4px var(--sc)) drop-shadow(0 0 9px var(--sc)); }
.fx-spell-burst { position: absolute; width: 76px; height: 76px; margin: -38px 0 0 -38px; border-radius: 50%; z-index: 11; pointer-events: none; opacity: 0; background: radial-gradient(circle, rgba(255, 255, 255, .95) 0%, var(--sc) 35%, transparent 70%); }
.fx-drain-ring { position: absolute; width: 40px; height: 40px; margin: -20px 0 0 -20px; box-sizing: border-box; border-radius: 50%; z-index: 9; pointer-events: none; opacity: 0; border: 2px solid var(--gc); box-shadow: 0 0 10px var(--gc), inset 0 0 8px var(--gc); }
.fx-drain-x { position: absolute; width: 0; height: 0; z-index: 9; pointer-events: none; }
.fx-drain-y { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.fx-drain-icon { position: absolute; left: 0; top: 0; max-width: none; opacity: 0; object-fit: contain; filter: drop-shadow(0 0 2px #fff) drop-shadow(0 0 7px var(--gc)); }
/* A tube without caps (duels): the body band of the art, with the glow above and below the rim trimmed. */
.tube.tube-bare { aspect-ratio: 1366 / 114; }
.tube-body { position: absolute; left: -15.08%; width: 129.87%; top: -33.33%; height: 166.67%; clip-path: inset(20% 11.39% 20% 11.61%); }
