/*
 * Glassmorphism Agent Visualization — Premium Visual Effects Layer
 * ════════════════════════════════════════════════════════════════════
 *
 * Flagship animation system for the Polymorph Pipeline dashboard.
 * Provides glassmorphism effects, state-driven animations, data flow
 * visualizations, micro-interactions, and ambient life effects that
 * make the pipeline feel like a living mission-control HUD.
 *
 * DEPENDENCIES: Requires variables from ayva-theme.css
 *   --pipeline-*   (glass surfaces, animation durations, glows)
 *   --accent-*     (brand colors)
 *   --success/error/warning/info-* (status colors)
 *   --transition-* (timing presets)
 *   --radius-*     (border radii)
 *   --border-*     (border colors)
 *
 * USAGE:
 *   - Apply .viz-* classes to elements in component markup
 *   - Reference @keyframes in component .razor.css files
 *   - All effects degrade gracefully with prefers-reduced-motion
 *   - All colors come from CSS variables — never hardcoded
 *
 * GPU-ACCELERATED: Animates only transform, opacity, filter, box-shadow
 * PERFORMANCE: Lightweight CSS-only — no JS animation libraries
 */


/* ═══════════════════════════════════════════════════════════════════
   1. ANIMATABLE CUSTOM PROPERTIES (@property)
   CSS Houdini — enables smooth transitions on custom properties
   that standard CSS cannot interpolate (gradients, colors, angles).
   ═══════════════════════════════════════════════════════════════════ */

@property --viz-glow-opacity {
    syntax: '<number>';
    initial-value: 0;
    inherits: false;
}

@property --viz-border-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

@property --viz-flow-offset {
    syntax: '<percentage>';
    initial-value: 0%;
    inherits: false;
}

@property --viz-shimmer-pos {
    syntax: '<percentage>';
    initial-value: -100%;
    inherits: false;
}


/* ═══════════════════════════════════════════════════════════════════
   2. GLASSMORPHISM SURFACE CLASSES
   Reusable frosted-glass effects at different depth levels.
   Combine with state animation classes for full effect.
   ═══════════════════════════════════════════════════════════════════ */

/* Deep layer — background panels, dashboard canvas */
.viz-glass-deep {
    background: var(--pipeline-glass-deep);
    backdrop-filter: var(--pipeline-glass-deep-blur);
    -webkit-backdrop-filter: var(--pipeline-glass-deep-blur);
    border: 1px solid var(--border-subtle);
}

/* Surface layer — standard cards, panels */
.viz-glass-surface {
    background: var(--pipeline-glass-surface);
    backdrop-filter: var(--pipeline-glass-surface-blur);
    -webkit-backdrop-filter: var(--pipeline-glass-surface-blur);
    border: 1px solid var(--border-color);
    box-shadow: 0 4px 16px color-mix(in srgb, var(--bg-base) 50%, transparent);
}

/* Elevated layer — focused/active cards, popover content */
.viz-glass-elevated {
    background: var(--pipeline-glass-elevated);
    backdrop-filter: var(--pipeline-glass-elevated-blur);
    -webkit-backdrop-filter: var(--pipeline-glass-elevated-blur);
    border: 1px solid var(--border-color-medium);
    box-shadow:
        0 8px 32px color-mix(in srgb, var(--bg-base) 40%, transparent),
        inset 0 1px 0 color-mix(in srgb, white 5%, transparent);
}

/* Luminous border — gradient border that rotates for premium feel */
.viz-glass-luminous {
    position: relative;
    background: var(--pipeline-glass);
    backdrop-filter: var(--pipeline-glass-blur);
    -webkit-backdrop-filter: var(--pipeline-glass-blur);
    border: 1px solid transparent;
    overflow: hidden;
}

.viz-glass-luminous::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    padding: 1px;
    background: conic-gradient(
        from var(--viz-border-angle, 0deg),
        var(--pipeline-border-glow),
        transparent 30%,
        var(--pipeline-border-glow-secondary),
        transparent 70%,
        var(--pipeline-border-glow)
    );
    -webkit-mask: linear-gradient(white, white) content-box, linear-gradient(white, white);
    mask: linear-gradient(white, white) content-box, linear-gradient(white, white);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    animation: vizBorderRotate var(--pipeline-border-glow-duration) linear infinite;
    pointer-events: none;
}


/* ═══════════════════════════════════════════════════════════════════
   3. CORE KEYFRAME ANIMATIONS
   The four specified animations plus supporting definitions.
   Named descriptively — components reference these by name.
   ═══════════════════════════════════════════════════════════════════ */

/* ── agentStatusPulse — Subtle glow ring for active agents ──
   Radiates outward from the element like a heartbeat monitor.
   Uses box-shadow for GPU-accelerated glow. */
@keyframes agentStatusPulse {
    0% {
        box-shadow:
            0 0 0 0 color-mix(in srgb, var(--agent-active) 35%, transparent),
            var(--pipeline-glow-active);
    }
    40% {
        box-shadow:
            0 0 0 8px transparent,
            var(--pipeline-glow-active-strong);
    }
    100% {
        box-shadow:
            0 0 0 12px transparent,
            var(--pipeline-glow-active);
    }
}

/* ── taskProgressSlide — Progress bar fill with leading shimmer ──
   Expands width while a light sweep chases the edge.
   Note: Width animation is intentional here for progress bars. */
@keyframes taskProgressSlide {
    0% {
        transform: scaleX(0);
        opacity: 0.6;
    }
    20% {
        opacity: 1;
    }
    100% {
        transform: scaleX(1);
        opacity: 1;
    }
}

/* ── cardSlideIn — Smooth entrance for agent/task cards ──
   Combines upward slide, scale-up, and fade for depth feel. */
@keyframes cardSlideIn {
    0% {
        opacity: 0;
        transform: translateY(16px) scale(0.96);
        filter: blur(4px);
    }
    60% {
        filter: blur(0px);
    }
    100% {
        opacity: 1;
        transform: translateY(0) scale(1);
        filter: blur(0px);
    }
}

/* ── stateTransition — Crossfade when task status changes ──
   Brief flash-then-settle for attention without distraction. */
@keyframes stateTransition {
    0% {
        opacity: 0.5;
        transform: scale(0.98);
        filter: brightness(1.3);
    }
    50% {
        opacity: 1;
        filter: brightness(1.1);
    }
    100% {
        opacity: 1;
        transform: scale(1);
        filter: brightness(1);
    }
}


/* ═══════════════════════════════════════════════════════════════════
   4. AGENT STATE ANIMATIONS
   Classes applied to agent cards based on their current state.
   Each provides visually distinct behavior appropriate to the state.
   ═══════════════════════════════════════════════════════════════════ */

/* Deploying — spinning up, anticipation building */
.viz-state-deploying {
    animation:
        vizDeployPulse 1.2s var(--pipeline-ambient-easing) infinite,
        cardSlideIn var(--pipeline-card-enter-duration) var(--pipeline-card-enter-easing) both;
}

@keyframes vizDeployPulse {
    0%, 100% {
        border-color: var(--border-color-medium);
        box-shadow: 0 0 12px color-mix(in srgb, var(--accent-color) 10%, transparent);
    }
    50% {
        border-color: var(--pipeline-border-glow);
        box-shadow: 0 0 24px color-mix(in srgb, var(--accent-color) 25%, transparent);
    }
}

/* Active — energetic, processing, alive */
.viz-state-active {
    animation: agentStatusPulse var(--pipeline-pulse-duration) var(--pipeline-ambient-easing) infinite;
    border-color: color-mix(in srgb, var(--agent-active) 40%, var(--border-color));
}

.viz-state-active::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(
        135deg,
        color-mix(in srgb, var(--accent-color) 5%, transparent) 0%,
        transparent 50%,
        color-mix(in srgb, var(--secondary-accent) 3%, transparent) 100%
    );
    pointer-events: none;
    animation: vizActiveSheen 3s ease-in-out infinite alternate;
}

@keyframes vizActiveSheen {
    0% { opacity: 0.3; }
    100% { opacity: 0.8; }
}

/* Idle — gentle breathing glow, ambient life */
.viz-state-idle {
    animation: vizIdleBreathe var(--pipeline-ambient-duration) var(--pipeline-ambient-easing) infinite;
}

@keyframes vizIdleBreathe {
    0%, 100% {
        box-shadow: 0 0 8px color-mix(in srgb, var(--agent-idle) 8%, transparent);
        border-color: var(--border-color);
    }
    50% {
        box-shadow: 0 0 16px color-mix(in srgb, var(--agent-idle) 15%, transparent);
        border-color: var(--border-color-medium);
    }
}

/* Completing — success glow that fades to settled state */
.viz-state-completing {
    animation: vizCompleteFlash 0.8s var(--pipeline-card-enter-easing) both;
}

@keyframes vizCompleteFlash {
    0% {
        box-shadow: var(--pipeline-glow-success);
        border-color: var(--success-color);
        filter: brightness(1.15);
    }
    60% {
        box-shadow: 0 0 30px color-mix(in srgb, var(--success-color) 30%, transparent);
        filter: brightness(1.05);
    }
    100% {
        box-shadow: 0 0 8px color-mix(in srgb, var(--success-color) 10%, transparent);
        border-color: color-mix(in srgb, var(--success-color) 30%, var(--border-color));
        filter: brightness(1);
    }
}

/* Error — attention-grabbing shake + red flash */
.viz-state-error {
    animation: vizErrorShake var(--pipeline-error-shake-duration) ease-out;
    border-color: color-mix(in srgb, var(--agent-errored) 40%, var(--border-color));
    box-shadow: var(--pipeline-glow-error);
}

@keyframes vizErrorShake {
    0%    { transform: translateX(0);    filter: brightness(1); }
    10%   { transform: translateX(-4px); filter: brightness(1.2); }
    20%   { transform: translateX(4px);  filter: brightness(1.1); }
    30%   { transform: translateX(-3px); }
    40%   { transform: translateX(3px); }
    50%   { transform: translateX(-2px); }
    60%   { transform: translateX(2px); }
    80%   { transform: translateX(-1px); }
    100%  { transform: translateX(0);    filter: brightness(1); }
}

/* Error persistent pulse — ongoing error glow after initial shake */
.viz-state-error-persistent {
    animation: vizErrorPulse 2s var(--pipeline-ambient-easing) infinite;
    border-color: color-mix(in srgb, var(--agent-errored) 35%, var(--border-color));
}

@keyframes vizErrorPulse {
    0%, 100% {
        box-shadow: 0 0 10px color-mix(in srgb, var(--error-color) 15%, transparent);
    }
    50% {
        box-shadow: 0 0 22px color-mix(in srgb, var(--error-color) 30%, transparent);
    }
}

/* Waiting — amber patience pulse */
.viz-state-waiting {
    animation: vizWaitingPulse 2.5s var(--pipeline-ambient-easing) infinite;
}

@keyframes vizWaitingPulse {
    0%, 100% {
        box-shadow: 0 0 6px color-mix(in srgb, var(--warning-color) 10%, transparent);
        border-color: var(--border-color);
    }
    50% {
        box-shadow: 0 0 14px color-mix(in srgb, var(--warning-color) 22%, transparent);
        border-color: color-mix(in srgb, var(--warning-color) 25%, var(--border-color));
    }
}


/* ═══════════════════════════════════════════════════════════════════
   5. DATA FLOW & CONNECTION LINE ANIMATIONS
   SVG stroke animations and CSS-based flowing particle effects
   for visualizing data moving between pipeline stages/agents.
   ═══════════════════════════════════════════════════════════════════ */

/* SVG connection line — animated flowing dashes */
.viz-flow-line {
    stroke: var(--accent-color);
    stroke-width: 2;
    stroke-dasharray: 8 4;
    stroke-dashoffset: 0;
    fill: none;
    animation: vizFlowDash var(--pipeline-data-flow-speed) linear infinite;
}

@keyframes vizFlowDash {
    to {
        stroke-dashoffset: -24;
    }
}

/* Flow line — idle/dim state */
.viz-flow-line-idle {
    stroke: var(--border-color);
    stroke-width: 1;
    stroke-dasharray: 4 6;
    fill: none;
    opacity: 0.4;
}

/* Flow line — active with glow */
.viz-flow-line-active {
    stroke: var(--accent-color);
    stroke-width: 2;
    stroke-dasharray: 12 4;
    fill: none;
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent-color) 40%, transparent));
    animation: vizFlowDash var(--pipeline-data-flow-speed) linear infinite;
}

/* Flow line — completed */
.viz-flow-line-done {
    stroke: var(--success-color);
    stroke-width: 1.5;
    stroke-dasharray: none;
    fill: none;
    opacity: 0.5;
}

/* Flow line — error */
.viz-flow-line-error {
    stroke: var(--error-color);
    stroke-width: 2;
    stroke-dasharray: 4 4;
    fill: none;
    animation: vizFlowDash 0.8s linear infinite;
}

/* Data flow particle — a dot that travels along a path */
.viz-flow-particle {
    fill: var(--accent-color);
    r: 3;
    filter: drop-shadow(0 0 3px var(--accent-color));
}

/* CSS data stream — horizontal flowing gradient for inline use */
.viz-data-stream {
    position: relative;
    overflow: hidden;
}

.viz-data-stream::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 0%,
        color-mix(in srgb, var(--accent-color) 8%, transparent) 30%,
        color-mix(in srgb, var(--accent-color) 15%, transparent) 50%,
        color-mix(in srgb, var(--accent-color) 8%, transparent) 70%,
        transparent 100%
    );
    background-size: 200% 100%;
    animation: vizStreamFlow var(--pipeline-data-flow-speed) linear infinite;
    pointer-events: none;
    border-radius: inherit;
}

@keyframes vizStreamFlow {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}


/* ═══════════════════════════════════════════════════════════════════
   6. ROTATING BORDER GLOW (LUMINOUS EDGES)
   Conic gradient border that orbits the element perimeter.
   Creates a premium "scanning" or "active field" visual.
   ═══════════════════════════════════════════════════════════════════ */

@keyframes vizBorderRotate {
    0%   { --viz-border-angle: 0deg; }
    100% { --viz-border-angle: 360deg; }
}

/* Quick variant for active states */
@keyframes vizBorderRotateFast {
    0%   { --viz-border-angle: 0deg; }
    100% { --viz-border-angle: 360deg; }
}

.viz-border-scan {
    position: relative;
}

.viz-border-scan::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    padding: 1px;
    background: conic-gradient(
        from var(--viz-border-angle, 0deg),
        color-mix(in srgb, var(--accent-color) 50%, transparent),
        transparent 25%,
        transparent 75%,
        color-mix(in srgb, var(--accent-color) 50%, transparent)
    );
    -webkit-mask: linear-gradient(white, white) content-box, linear-gradient(white, white);
    mask: linear-gradient(white, white) content-box, linear-gradient(white, white);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    animation: vizBorderRotate var(--pipeline-border-glow-duration) linear infinite;
    pointer-events: none;
    z-index: 0;
}


/* ═══════════════════════════════════════════════════════════════════
   7. MICRO-INTERACTIONS
   Hover reveals, click feedback, focus states for interactive cards.
   All GPU-accelerated via transform + opacity + box-shadow.
   ═══════════════════════════════════════════════════════════════════ */

/* Hover — lift + glow reveal */
.viz-hover-glow {
    transition:
        transform var(--transition-smooth),
        box-shadow var(--transition-smooth),
        border-color var(--transition-fast);
}

.viz-hover-glow:hover {
    transform: translateY(var(--hover-lift));
    box-shadow:
        var(--pipeline-glow-active),
        0 8px 24px color-mix(in srgb, var(--bg-base) 40%, transparent);
    border-color: var(--pipeline-border-glow);
}

/* Hover — subtle border-only glow (for less prominent elements) */
.viz-hover-subtle {
    transition:
        border-color var(--transition-fast),
        box-shadow var(--transition-fast);
}

.viz-hover-subtle:hover {
    border-color: var(--border-color-medium);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent-color) 8%, transparent);
}

/* Click — tactile press feedback */
.viz-click-press {
    transition: transform 0.1s ease;
}

.viz-click-press:active {
    transform: scale(var(--click-scale));
}

/* Focus — accessible glow ring */
.viz-focus-ring:focus-visible {
    outline: none;
    box-shadow:
        0 0 0 2px var(--bg-base),
        0 0 0 4px var(--border-focus);
}

/* Hover info reveal — hidden content slides in on hover */
.viz-hover-reveal {
    opacity: 0;
    transform: translateY(4px);
    transition:
        opacity var(--transition-fast),
        transform var(--transition-fast);
    pointer-events: none;
}

.viz-hover-trigger:hover .viz-hover-reveal {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}


/* ═══════════════════════════════════════════════════════════════════
   8. PROGRESS BAR EFFECTS
   Enhanced progress bar animations with shimmer and glow.
   ═══════════════════════════════════════════════════════════════════ */

/* Progress fill with leading-edge shimmer */
.viz-progress-fill {
    transform-origin: left center;
    animation: taskProgressSlide 0.8s var(--pipeline-card-enter-easing) both;
    position: relative;
}

.viz-progress-fill::after {
    content: '';
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 30px;
    background: linear-gradient(
        90deg,
        transparent,
        color-mix(in srgb, white 25%, transparent)
    );
    border-radius: inherit;
    animation: vizProgressShimmer 1.5s ease-in-out infinite;
}

@keyframes vizProgressShimmer {
    0%, 100% { opacity: 0.2; }
    50%      { opacity: 0.6; }
}

/* Indeterminate progress — flowing gradient */
.viz-progress-indeterminate {
    background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--accent-color) 30%, transparent) 0%,
        var(--accent-color) 50%,
        color-mix(in srgb, var(--accent-color) 30%, transparent) 100%
    );
    background-size: 200% 100%;
    animation: vizProgressIndeterminate 1.5s ease-in-out infinite;
    border-radius: var(--radius-full);
}

@keyframes vizProgressIndeterminate {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

/* Conic gradient progress ring (for circular indicators) */
.viz-progress-ring {
    background: conic-gradient(
        var(--accent-color) calc(var(--progress, 0) * 3.6deg),
        color-mix(in srgb, var(--accent-color) 10%, transparent) 0deg
    );
    border-radius: var(--radius-full);
    position: relative;
}

.viz-progress-ring::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: var(--radius-full);
    background: var(--pipeline-glass-deep);
}


/* ═══════════════════════════════════════════════════════════════════
   9. LOADING & SKELETON STATES
   Shimmer animations for skeleton loading placeholders.
   ═══════════════════════════════════════════════════════════════════ */

/* Skeleton block with animated shimmer sweep */
.viz-skeleton {
    background: linear-gradient(
        90deg,
        var(--bg-secondary) 25%,
        color-mix(in srgb, var(--bg-hover) 60%, var(--bg-secondary)) 50%,
        var(--bg-secondary) 75%
    );
    background-size: 300% 100%;
    animation: vizSkeletonSweep var(--pipeline-shimmer-duration) ease-in-out infinite;
    border-radius: var(--radius-sm);
}

@keyframes vizSkeletonSweep {
    0%   { background-position: 300% 0; }
    100% { background-position: -300% 0; }
}

/* Skeleton — card-shaped */
.viz-skeleton-card {
    background: var(--pipeline-glass);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
    position: relative;
}

.viz-skeleton-card::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 25%,
        color-mix(in srgb, white 4%, transparent) 50%,
        transparent 75%
    );
    background-size: 300% 100%;
    animation: vizSkeletonSweep var(--pipeline-shimmer-duration) ease-in-out infinite;
}

/* Skeleton text lines */
.viz-skeleton-line {
    height: 0.75rem;
    border-radius: var(--radius-xs);
}

.viz-skeleton-line-short {
    width: 60%;
}

.viz-skeleton-line-medium {
    width: 80%;
}

.viz-skeleton-line-full {
    width: 100%;
}


/* ═══════════════════════════════════════════════════════════════════
   10. DASHBOARD HEARTBEAT — ALIVE INDICATOR
   Subtle ambient effect showing the system is live and processing.
   Applied to the dashboard root or a dedicated "alive" element.
   ═══════════════════════════════════════════════════════════════════ */

/* Heartbeat dot — live indicator */
.viz-heartbeat {
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--success-color);
    animation: vizHeartbeat var(--pipeline-heartbeat-duration) var(--pipeline-ambient-easing) infinite;
}

@keyframes vizHeartbeat {
    0%   { transform: scale(1);    opacity: 1;    box-shadow: 0 0 0 0 color-mix(in srgb, var(--success-color) 40%, transparent); }
    15%  { transform: scale(1.25); opacity: 1;    box-shadow: 0 0 8px color-mix(in srgb, var(--success-color) 30%, transparent); }
    30%  { transform: scale(1);    opacity: 0.85; box-shadow: 0 0 0 0 transparent; }
    45%  { transform: scale(1.15); opacity: 1;    box-shadow: 0 0 6px color-mix(in srgb, var(--success-color) 20%, transparent); }
    60%  { transform: scale(1);    opacity: 0.9; }
    100% { transform: scale(1);    opacity: 1;    box-shadow: 0 0 0 0 transparent; }
}

/* Ambient background glow — subtle radial pulse on the dashboard canvas */
.viz-ambient-canvas {
    position: relative;
}

.viz-ambient-canvas::before {
    content: '';
    position: absolute;
    top: 10%;
    left: 15%;
    width: 40%;
    height: 40%;
    border-radius: var(--radius-full);
    background: radial-gradient(
        circle,
        color-mix(in srgb, var(--accent-color) 4%, transparent),
        transparent 70%
    );
    filter: blur(60px);
    animation: vizAmbientDrift 12s ease-in-out infinite alternate;
    pointer-events: none;
    z-index: 0;
}

.viz-ambient-canvas::after {
    content: '';
    position: absolute;
    bottom: 15%;
    right: 10%;
    width: 35%;
    height: 35%;
    border-radius: var(--radius-full);
    background: radial-gradient(
        circle,
        color-mix(in srgb, var(--secondary-accent) 3%, transparent),
        transparent 70%
    );
    filter: blur(50px);
    animation: vizAmbientDrift 15s ease-in-out 3s infinite alternate-reverse;
    pointer-events: none;
    z-index: 0;
}

@keyframes vizAmbientDrift {
    0%   { transform: translate(0, 0) scale(1); opacity: 0.4; }
    50%  { transform: translate(20px, -10px) scale(1.1); opacity: 0.7; }
    100% { transform: translate(-10px, 15px) scale(0.95); opacity: 0.5; }
}


/* ═══════════════════════════════════════════════════════════════════
   11. PARTICLE / FLOATING EFFECT
   CSS-only floating particles for ambient visual depth.
   Uses pseudo-elements with radial gradients — no sprites needed.
   ═══════════════════════════════════════════════════════════════════ */

/* Particle container — position: relative parent */
.viz-particles {
    position: relative;
    overflow: hidden;
}

/* Individual particle — apply to small absolute-positioned spans */
.viz-particle {
    position: absolute;
    width: 3px;
    height: 3px;
    border-radius: var(--radius-full);
    background: var(--accent-color);
    opacity: 0;
    pointer-events: none;
    animation: vizParticleFloat var(--pipeline-particle-duration) ease-in-out infinite;
}

.viz-particle:nth-child(2n) {
    background: var(--secondary-accent);
    animation-duration: calc(var(--pipeline-particle-duration) * 1.3);
    animation-delay: 1.5s;
}

.viz-particle:nth-child(3n) {
    width: 2px;
    height: 2px;
    animation-duration: calc(var(--pipeline-particle-duration) * 0.8);
    animation-delay: 3s;
}

@keyframes vizParticleFloat {
    0% {
        transform: translateY(100%) translateX(0);
        opacity: 0;
    }
    15% {
        opacity: 0.5;
    }
    50% {
        transform: translateY(40%) translateX(15px);
        opacity: 0.3;
    }
    85% {
        opacity: 0.1;
    }
    100% {
        transform: translateY(-10%) translateX(-5px);
        opacity: 0;
    }
}


/* ═══════════════════════════════════════════════════════════════════
   12. EXPAND / COLLAPSE TRANSITIONS
   Panel open/close, card expand/shrink with smooth animation.
   ═══════════════════════════════════════════════════════════════════ */

/* Panel expand — from collapsed to full height */
.viz-expand-enter {
    animation: vizExpandIn var(--pipeline-card-enter-duration) var(--pipeline-card-enter-easing) both;
}

@keyframes vizExpandIn {
    0% {
        opacity: 0;
        transform: scaleY(0.95);
        transform-origin: top center;
    }
    100% {
        opacity: 1;
        transform: scaleY(1);
    }
}

/* Panel collapse */
.viz-expand-exit {
    animation: vizExpandOut 0.2s ease-out both;
}

@keyframes vizExpandOut {
    0% {
        opacity: 1;
        transform: scaleY(1);
        transform-origin: top center;
    }
    100% {
        opacity: 0;
        transform: scaleY(0.95);
    }
}

/* Agent card appear — staggers via --card-index custom property */
.viz-card-appear {
    animation: cardSlideIn var(--pipeline-card-enter-duration) var(--pipeline-card-enter-easing) both;
    animation-delay: calc(var(--card-index, 0) * var(--pipeline-stagger-delay));
}

/* Agent card disappear */
.viz-card-disappear {
    animation: vizCardOut 0.3s ease-out both;
}

@keyframes vizCardOut {
    0% {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
    100% {
        opacity: 0;
        transform: translateY(-8px) scale(0.96);
        filter: blur(2px);
    }
}


/* ═══════════════════════════════════════════════════════════════════
   13. STAGGER SYSTEM
   Indexed delay system for choreographed list/grid entry.
   Use --card-index on each element for stagger offset.
   ═══════════════════════════════════════════════════════════════════ */

.viz-stagger-1  { animation-delay: calc(var(--pipeline-stagger-delay) * 1); }
.viz-stagger-2  { animation-delay: calc(var(--pipeline-stagger-delay) * 2); }
.viz-stagger-3  { animation-delay: calc(var(--pipeline-stagger-delay) * 3); }
.viz-stagger-4  { animation-delay: calc(var(--pipeline-stagger-delay) * 4); }
.viz-stagger-5  { animation-delay: calc(var(--pipeline-stagger-delay) * 5); }
.viz-stagger-6  { animation-delay: calc(var(--pipeline-stagger-delay) * 6); }
.viz-stagger-7  { animation-delay: calc(var(--pipeline-stagger-delay) * 7); }
.viz-stagger-8  { animation-delay: calc(var(--pipeline-stagger-delay) * 8); }
.viz-stagger-9  { animation-delay: calc(var(--pipeline-stagger-delay) * 9); }
.viz-stagger-10 { animation-delay: calc(var(--pipeline-stagger-delay) * 10); }
.viz-stagger-11 { animation-delay: calc(var(--pipeline-stagger-delay) * 11); }
.viz-stagger-12 { animation-delay: calc(var(--pipeline-stagger-delay) * 12); }


/* ═══════════════════════════════════════════════════════════════════
   14. STATUS INDICATOR ENHANCEMENTS
   Refined dot and badge animations for status displays.
   ═══════════════════════════════════════════════════════════════════ */

/* Status ring — expanding ring around active dots */
.viz-status-ring {
    position: absolute;
    inset: -3px;
    border-radius: var(--radius-full);
    border: 1.5px solid var(--agent-active);
    animation: vizStatusRing var(--pipeline-pulse-duration) ease-out infinite;
    pointer-events: none;
}

@keyframes vizStatusRing {
    0%   { transform: scale(1);   opacity: 0.7; }
    100% { transform: scale(1.8); opacity: 0; }
}

/* Success checkmark flash */
.viz-status-success {
    animation: vizSuccessFlash 0.5s ease-out;
}

@keyframes vizSuccessFlash {
    0%   { transform: scale(0.5); opacity: 0; filter: brightness(2); }
    60%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); filter: brightness(1); }
}


/* ═══════════════════════════════════════════════════════════════════
   15. TOOLTIP / POPOVER ENTRANCE
   Smooth entry for inspection popovers and tooltip panels.
   ═══════════════════════════════════════════════════════════════════ */

.viz-popover-enter {
    animation: vizPopoverIn 0.2s var(--pipeline-card-enter-easing) both;
}

@keyframes vizPopoverIn {
    0% {
        opacity: 0;
        transform: translateY(4px) scale(0.97);
        filter: blur(2px);
    }
    100% {
        opacity: 1;
        transform: translateY(0) scale(1);
        filter: blur(0);
    }
}


/* ═══════════════════════════════════════════════════════════════════
   16. NUMBER VALUE TRANSITIONS
   Smooth visual updates for metric counters and stat displays.
   ═══════════════════════════════════════════════════════════════════ */

.viz-value-update {
    animation: vizValueBounce 0.4s var(--pipeline-card-enter-easing);
}

@keyframes vizValueBounce {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.12); color: var(--accent-color); }
    60%  { transform: scale(0.97); }
    100% { transform: scale(1); }
}

.viz-value-increase {
    animation: vizValueUp 0.3s ease-out;
}

@keyframes vizValueUp {
    0%   { transform: translateY(4px); opacity: 0.5; }
    100% { transform: translateY(0); opacity: 1; }
}

.viz-value-decrease {
    animation: vizValueDown 0.3s ease-out;
}

@keyframes vizValueDown {
    0%   { transform: translateY(-4px); opacity: 0.5; }
    100% { transform: translateY(0); opacity: 1; }
}


/* ═══════════════════════════════════════════════════════════════════
   17. UTILITY ANIMATION CLASSES
   Quick-apply animations for common patterns.
   ═══════════════════════════════════════════════════════════════════ */

/* Entrance animations */
.viz-enter-fade     { animation: fadeIn 0.3s ease-out both; }
.viz-enter-slide    { animation: cardSlideIn var(--pipeline-card-enter-duration) var(--pipeline-card-enter-easing) both; }
.viz-enter-scale    { animation: scaleIn 0.3s ease-out both; }
.viz-enter-state    { animation: stateTransition 0.4s ease-out both; }

/* Infinite ambient animations */
.viz-anim-pulse     { animation: agentStatusPulse var(--pipeline-pulse-duration) var(--pipeline-ambient-easing) infinite; }
.viz-anim-breathe   { animation: vizIdleBreathe var(--pipeline-ambient-duration) var(--pipeline-ambient-easing) infinite; }
.viz-anim-stream    { animation: vizStreamFlow var(--pipeline-data-flow-speed) linear infinite; }
.viz-anim-heartbeat { animation: vizHeartbeat var(--pipeline-heartbeat-duration) var(--pipeline-ambient-easing) infinite; }

/* Fill direction modifier for stagger */
.viz-fill-both { animation-fill-mode: both; }


/* ═══════════════════════════════════════════════════════════════════
   18. ACCESSIBILITY — prefers-reduced-motion
   Disables all non-essential animations for users who prefer it.
   Preserves functional state indicators (color, border changes).
   ═══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {

    /* Kill ALL keyframe animations */
    .viz-state-deploying,
    .viz-state-active,
    .viz-state-active::after,
    .viz-state-idle,
    .viz-state-completing,
    .viz-state-error,
    .viz-state-error-persistent,
    .viz-state-waiting,
    .viz-flow-line,
    .viz-flow-line-active,
    .viz-flow-line-error,
    .viz-data-stream::after,
    .viz-glass-luminous::before,
    .viz-border-scan::before,
    .viz-heartbeat,
    .viz-ambient-canvas::before,
    .viz-ambient-canvas::after,
    .viz-particle,
    .viz-progress-fill,
    .viz-progress-fill::after,
    .viz-progress-indeterminate,
    .viz-skeleton,
    .viz-skeleton-card::after,
    .viz-status-ring,
    .viz-status-success,
    .viz-popover-enter,
    .viz-value-update,
    .viz-value-increase,
    .viz-value-decrease,
    .viz-expand-enter,
    .viz-expand-exit,
    .viz-card-appear,
    .viz-card-disappear,
    .viz-enter-fade,
    .viz-enter-slide,
    .viz-enter-scale,
    .viz-enter-state,
    .viz-anim-pulse,
    .viz-anim-breathe,
    .viz-anim-stream,
    .viz-anim-heartbeat {
        animation: none !important;
    }

    /* Kill transitions on hover effects */
    .viz-hover-glow,
    .viz-hover-subtle,
    .viz-click-press,
    .viz-hover-reveal {
        transition: none !important;
    }

    /* Preserve static visual state indicators (no motion) */
    .viz-state-active {
        border-color: color-mix(in srgb, var(--agent-active) 40%, var(--border-color));
        box-shadow: var(--pipeline-glow-active);
    }

    .viz-state-error,
    .viz-state-error-persistent {
        border-color: color-mix(in srgb, var(--agent-errored) 35%, var(--border-color));
        box-shadow: var(--pipeline-glow-error);
    }

    .viz-state-completing {
        border-color: color-mix(in srgb, var(--success-color) 30%, var(--border-color));
        box-shadow: var(--pipeline-glow-success);
    }

    .viz-state-waiting {
        border-color: color-mix(in srgb, var(--warning-color) 25%, var(--border-color));
        box-shadow: var(--pipeline-glow-warning);
    }

    /* Make card appear instant instead of animated */
    .viz-card-appear,
    .viz-expand-enter,
    .viz-popover-enter {
        opacity: 1;
        transform: none;
        filter: none;
    }

    /* Progress fills show static instead of animated */
    .viz-progress-fill {
        transform: scaleX(1);
        opacity: 1;
    }

    /* Skeleton shows flat color instead of shimmer */
    .viz-skeleton {
        background: var(--bg-secondary);
    }

    /* Flow lines show static instead of dashing */
    .viz-flow-line,
    .viz-flow-line-active {
        stroke-dasharray: none;
    }

    /* Heartbeat shows static dot */
    .viz-heartbeat {
        opacity: 1;
        transform: none;
    }

    /* Remove ambient canvas effects entirely */
    .viz-ambient-canvas::before,
    .viz-ambient-canvas::after {
        display: none;
    }

    /* Remove particle effects */
    .viz-particle {
        display: none;
    }
}
