@keyframes scan { from { transform: translateY(-20%); } to { transform: translateY(480%); } }
@keyframes pulse { 0%,100% { opacity:.45; transform:scale(.9); } 50% { opacity:1; transform:scale(1.14); } }
@keyframes itemIn { from { opacity:0; transform:translateY(-24px) scale(.97); } to { opacity:1; transform:none; } }
@keyframes itemOut { to { opacity:0; transform:translateY(-28px) scale(.96); } }
@keyframes shake { 0%,100%{transform:none}25%{transform:translateX(-5px)}75%{transform:translateX(5px)} }
@keyframes toastIn { from { opacity:0; transform:translateX(22px); } to { opacity:1; transform:none; } }
@keyframes toastOut { to { opacity:0; transform:translateY(8px); } }
@keyframes reveal { from { opacity:0; transform:scale(.88); } to { opacity:1; transform:none; } }
@keyframes xpFlash { 50% { color:#fff; text-shadow:0 0 14px var(--mint); transform:scale(1.08); } }
.scan-line { animation: scan 9s linear infinite; }
.status-dot,.live-label i,.pulse-ring { animation: pulse 1.8s ease-in-out infinite; }
.stack-item.is-entering { animation: itemIn .28s ease-out; }
.stack-item.is-leaving { animation: itemOut .25s ease-in forwards; }
.stack-visual.has-error { animation: shake .28s ease; }
.toast { animation: toastIn .22s ease-out; }.toast.is-leaving { animation: toastOut .2s ease-in forwards; }
.discovery-dialog[open] .discovery-content { animation: reveal .42s cubic-bezier(.2,.9,.25,1.2); }
.xp-flash { animation: xpFlash .45s ease; }
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
.reduce-motion *, .reduce-motion *::before, .reduce-motion *::after { animation-duration:.01ms!important; animation-iteration-count:1!important; transition-duration:.01ms!important; }
