/* ==========================================================================
   Login page landing animation -- three illustrated feature cards.
   One choreography: 2-6 s loops with staggered delays, each timing used once,
   so its timings are written here rather than as theme tokens; this file is
   the token rule's one exemption, for animation timings only
   (stylelint.config.js). Loaded by templates/login.html after auth.css.
   ========================================================================== */

@keyframes pulse-node { 0%, 100% { fill: var(--color-accent-primary); r: 4; filter: drop-shadow(0 0 var(--glow-blur-xs) var(--color-accent-primary)); } 50% { fill: var(--color-accent-hover); r: 6; filter: drop-shadow(0 0 var(--glow-blur-lg) var(--color-accent-hover)); } }
@keyframes flow-data { 0% { stroke-dashoffset: 100; opacity: 0; } 20% { opacity: 1; } 80% { opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes json-glow { 0%, 100% { stroke: var(--color-accent-primary); filter: drop-shadow(0 0 0 transparent); } 50% { stroke: var(--color-accent-hover); filter: drop-shadow(0 0 var(--glow-blur-xl) var(--color-accent-hover)); } }
@keyframes laser-scan { 0% { transform: translateY(0); opacity: 0; } 10% { opacity: 1; } 80% { opacity: 1; } 90% { transform: translateY(80px); opacity: 0; } 100% { transform: translateY(80px); opacity: 0; } }
@keyframes check-pop { 0%, 70% { transform: scale(0); opacity: 0; } 80% { transform: scale(1.2); opacity: 1; } 85% { transform: scale(1); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes doc-pulse { 0%, 100% { stroke: var(--color-text-secondary); } 80% { stroke: var(--color-success); filter: drop-shadow(0 0 var(--glow-blur-sm) var(--color-success)); } }
@keyframes morph-json { 0%, 20% { opacity: 1; transform: translateX(0); } 40%, 80% { opacity: 0; transform: translateX(20px); } 100% { opacity: 1; transform: translateX(0); } }
@keyframes morph-text { 0%, 20% { opacity: 0; transform: translateX(-20px); } 40%, 80% { opacity: 1; transform: translateX(0); } 100% { opacity: 0; transform: translateX(-20px); } }
@keyframes ai-sparkle { 0% { transform: rotate(0deg) scale(0.8); opacity: 0.5; } 50% { transform: rotate(180deg) scale(1.2); opacity: 1; filter: drop-shadow(0 0 var(--glow-blur-lg) var(--color-accent-hover)); } 100% { transform: rotate(360deg) scale(0.8); opacity: 0.5; } }

.anim1-node-1 { animation: pulse-node 3s infinite 0s paused; }
.anim1-node-2 { animation: pulse-node 3s infinite 0.5s paused; }
.anim1-node-3 { animation: pulse-node 3s infinite 1s paused; }
.anim1-flow { stroke-dasharray: 10; animation: flow-data 2s linear infinite paused; }
.anim1-json { animation: json-glow 3s infinite 1.5s paused; }
.anim2-laser { animation: laser-scan 3s cubic-bezier(0.4, 0, 0.2, 1) infinite paused; }
.anim2-check-1 { animation: check-pop 3s ease-out infinite paused; transform-origin: 155px 40px; }
.anim2-check-2 { animation: check-pop 3s ease-out infinite 0.2s paused; transform-origin: 155px 70px; }
.anim2-check-3 { animation: check-pop 3s ease-out infinite 0.4s paused; transform-origin: 155px 100px; }
.anim2-doc { animation: doc-pulse 3s infinite paused; }
.anim3-json { animation: morph-json 6s cubic-bezier(0.4, 0, 0.2, 1) infinite paused; }
.anim3-text { animation: morph-text 6s cubic-bezier(0.4, 0, 0.2, 1) infinite paused; }
.anim3-spark { animation: ai-sparkle 3s linear infinite paused; transform-origin: 150px 40px; }
