/* Motion with meaning: pages rise in, rows cascade, cards lift, counters pulse when late, Kanban cards glide, toasts spring. */
@keyframes page-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes rise-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes row-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(18px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes drawer-in { from { transform: translateX(calc(100% * var(--dir, 1))); } to { transform: none; } } [dir="rtl"] .drawer { --dir: -1; }
@keyframes drop-in { from { opacity: 0; transform: translateY(-6px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes toast-in { from { opacity: 0; transform: translateY(16px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(.96); } }
@keyframes grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes shimmer { to { transform: translateX(100%); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse-dot { 0%, 100% { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px rgba(180,224,39,.0); } 50% { box-shadow: 0 0 0 2px var(--surface), 0 0 0 7px rgba(180,224,39,.45); } }
@keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(240,68,106,.45); } 70% { box-shadow: 0 0 0 10px rgba(240,68,106,0); } 100% { box-shadow: 0 0 0 0 rgba(240,68,106,0); } }
@keyframes float-y { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes pop { 0% { transform: scale(.6); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }
@keyframes wiggle { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-3deg); } 75% { transform: rotate(3deg); } }
@keyframes glow { 0%, 100% { box-shadow: 0 0 0 0 rgba(83,71,214,.0); } 50% { box-shadow: 0 0 22px 2px rgba(83,71,214,.35); } }
@keyframes count-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes blink { 50% { opacity: .35; } }
@keyframes confetti { 0% { transform: translateY(0) rotate(0); opacity: 1; } 100% { transform: translateY(-120px) rotate(540deg); opacity: 0; } }
@keyframes stripe { to { background-position: 40px 0; } }
@keyframes live-flash { 0%, 25% { box-shadow: inset 4px 0 0 var(--lime); background-color: color-mix(in srgb, var(--lime) 22%, transparent); } 100% { box-shadow: inset 4px 0 0 transparent; background-color: transparent; } }
[dir="rtl"] .tbl tbody tr.just-changed { animation-name: live-flash-rtl; } @keyframes live-flash-rtl { 0%, 25% { box-shadow: inset -4px 0 0 var(--lime); background-color: color-mix(in srgb, var(--lime) 22%, transparent); } 100% { box-shadow: inset -4px 0 0 transparent; background-color: transparent; } }
@keyframes bell-wiggle { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(-14deg); } 40% { transform: rotate(12deg); } 60% { transform: rotate(-8deg); } 80% { transform: rotate(5deg); } }
@keyframes chart-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes bar-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes rail-in { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.stagger > * { animation: rise-in var(--t-slow) var(--ease-out) both; }
.stagger > *:nth-child(1) { animation-delay: 0ms; } .stagger > *:nth-child(2) { animation-delay: 40ms; } .stagger > *:nth-child(3) { animation-delay: 80ms; } .stagger > *:nth-child(4) { animation-delay: 120ms; }
.stagger > *:nth-child(5) { animation-delay: 160ms; } .stagger > *:nth-child(6) { animation-delay: 200ms; } .stagger > *:nth-child(7) { animation-delay: 240ms; } .stagger > *:nth-child(8) { animation-delay: 280ms; }
.stagger > *:nth-child(n+9) { animation-delay: 320ms; }
.tbl tbody tr:nth-child(1) { animation-delay: 0ms; } .tbl tbody tr:nth-child(2) { animation-delay: 25ms; } .tbl tbody tr:nth-child(3) { animation-delay: 50ms; } .tbl tbody tr:nth-child(4) { animation-delay: 75ms; }
.tbl tbody tr:nth-child(5) { animation-delay: 100ms; } .tbl tbody tr:nth-child(6) { animation-delay: 125ms; } .tbl tbody tr:nth-child(7) { animation-delay: 150ms; } .tbl tbody tr:nth-child(n+8) { animation-delay: 175ms; }
.pop { animation: pop var(--t-slow) var(--ease-spring) both; } .float { animation: float-y 4s var(--ease) infinite; } .glow { animation: glow 2.4s var(--ease) infinite; }
.pulse-danger { animation: pulse-ring 1.8s var(--ease) infinite; } .blink { animation: blink 1.2s steps(1) infinite; }
.count { animation: count-up var(--t-slow) var(--ease-out) both; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); display: inline-block; box-shadow: 0 0 0 0 rgba(22,179,100,.5); animation: pulse-ring 2s infinite; }
.striped { background-image: linear-gradient(45deg, rgba(255,255,255,.18) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.18) 50%, rgba(255,255,255,.18) 75%, transparent 75%); background-size: 40px 40px; animation: stripe 1.2s linear infinite; }
.confetti { position: absolute; width: 8px; height: 8px; border-radius: 2px; animation: confetti 1.1s var(--ease-out) forwards; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; } }
@keyframes attention { 0%, 100% { transform: none; } 25% { transform: scale(1.012); } 60% { transform: scale(.996); } }
