/* =========================================================
   animations.css — All @keyframes Definitions
   ========================================================= */

/* -------------------------------------------------------
   blink — cursor / indicator blinking
------------------------------------------------------- */

@keyframes blink {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0;
    }
}

/* -------------------------------------------------------
   glow-pulse — breathing neon glow on hero name + elements
------------------------------------------------------- */

@keyframes glow-pulse {
    0%,
    100% {
        text-shadow:
            0 0 6px rgba(0, 255, 65, 0.5),
            0 0 18px rgba(0, 255, 65, 0.2),
            0 0 40px rgba(0, 255, 65, 0.08);
    }
    50% {
        text-shadow:
            0 0 4px rgba(0, 255, 65, 0.3),
            0 0 12px rgba(0, 255, 65, 0.12),
            0 0 28px rgba(0, 255, 65, 0.05);
    }
}

/* Glow pulse for box-shadow (cards, borders) */
@keyframes glow-pulse-box {
    0%,
    100% {
        box-shadow:
            0 0 10px rgba(0, 255, 65, 0.25),
            0 0 30px rgba(0, 255, 65, 0.1),
            inset 0 0 20px rgba(0, 255, 65, 0.03);
    }
    50% {
        box-shadow:
            0 0 6px rgba(0, 255, 65, 0.15),
            0 0 18px rgba(0, 255, 65, 0.06),
            inset 0 0 12px rgba(0, 255, 65, 0.02);
    }
}

/* -------------------------------------------------------
   glitch — sporadic text displacement for .glitch elements
   Uses clip-path "slice" technique on pseudo-elements
------------------------------------------------------- */

/* Glitch layer 1 — cyan tint, clips top bands */
@keyframes glitch-clip-1 {
    /* Resting state — invisible. Only the brief 81-84% window is visible. */
    0%,
    80%,
    85%,
    100% {
        clip-path: polygon(0 0%, 100% 0%, 100% 100%, 0 100%);
        transform: translate(0, 0) skewX(0deg);
        opacity: 0;
    }
    81% {
        clip-path: polygon(0 5%, 100% 5%, 100% 28%, 0 28%);
        transform: translate(-5px, -2px) skewX(-1deg);
        opacity: 0.75;
    }
    82% {
        clip-path: polygon(0 62%, 100% 62%, 100% 78%, 0 78%);
        transform: translate(5px, 2px) skewX(1deg);
        opacity: 0.75;
    }
    83% {
        clip-path: polygon(0 18%, 100% 18%, 100% 45%, 0 45%);
        transform: translate(-3px, 1px) skewX(0.5deg);
        opacity: 0.65;
    }
    84% {
        clip-path: polygon(0 0%, 100% 0%, 100% 12%, 0 12%);
        transform: translate(3px, -1px) skewX(-0.5deg);
        opacity: 0.75;
    }
}

/* Glitch layer 2 — amber tint, clips bottom bands */
@keyframes glitch-clip-2 {
    /* Resting state — invisible. Only the brief 89-91% window is visible. */
    0%,
    88%,
    92%,
    100% {
        clip-path: polygon(0 0%, 100% 0%, 100% 100%, 0 100%);
        transform: translate(0, 0) skewX(0deg);
        opacity: 0;
    }
    89% {
        clip-path: polygon(0 50%, 100% 50%, 100% 72%, 0 72%);
        transform: translate(6px, 1px) skewX(1.5deg);
        opacity: 0.75;
    }
    90% {
        clip-path: polygon(0 10%, 100% 10%, 100% 35%, 0 35%);
        transform: translate(-6px, -1px) skewX(-1.5deg);
        opacity: 0.75;
    }
    91% {
        clip-path: polygon(0 82%, 100% 82%, 100% 96%, 0 96%);
        transform: translate(4px, 2px) skewX(0.5deg);
        opacity: 0.65;
    }
}

/* Main element flash during glitch window */
@keyframes glitch-flash {
    0%,
    80%,
    86%,
    100% {
        opacity: 1;
    }
    81%,
    83%,
    85% {
        opacity: 0.85;
    }
    82%,
    84% {
        opacity: 1;
    }
}

/* Quick flash for shutdown glitch bars */
@keyframes glitch-bar-flash {
    0% {
        opacity: 0.8;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

/* -------------------------------------------------------
   fadeInUp — section reveal / scroll animations
------------------------------------------------------- */

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(32px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes fadeInLeft {
    from {
        opacity: 0;
        transform: translateX(-24px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* -------------------------------------------------------
   drift — ambient background layer slow movement
------------------------------------------------------- */

@keyframes drift {
    0% {
        background-position: 0% 0%;
        transform: scale(1) translate(0, 0);
    }
    33% {
        background-position: 5% 3%;
        transform: scale(1.02) translate(10px, -5px);
    }
    66% {
        background-position: -3% 6%;
        transform: scale(1.01) translate(-8px, 8px);
    }
    100% {
        background-position: 4% -2%;
        transform: scale(1.03) translate(6px, 2px);
    }
}

/* Dot-grid drift on body */
@keyframes dot-drift {
    0% {
        background-position: 0px 0px;
    }
    100% {
        background-position: 36px 36px;
    }
}

/* -------------------------------------------------------
   scanline — moving scan beam (optional CRT effect)
------------------------------------------------------- */

@keyframes scanline {
    0% {
        transform: translateY(-8px);
        opacity: 0;
    }
    5% {
        opacity: 0.06;
    }
    95% {
        opacity: 0.04;
    }
    100% {
        transform: translateY(100vh);
        opacity: 0;
    }
}

/* Static scanline shimmer */
@keyframes scanline-shimmer {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: 0 8px;
    }
}

/* -------------------------------------------------------
   packet-pulse — SVG stroke-dashoffset for "data flow"
   on topology links
------------------------------------------------------- */

@keyframes packet-pulse {
    0% {
        stroke-dashoffset: 200;
        opacity: 0;
        stroke: var(--color-green);
    }
    15% {
        opacity: 0.8;
    }
    60% {
        opacity: 0.6;
        stroke: var(--color-cyan);
    }
    85% {
        opacity: 0.3;
    }
    100% {
        stroke-dashoffset: 0;
        opacity: 0;
        stroke: var(--color-cyan);
    }
}

/* Packet node pulse */
@keyframes node-ping {
    0%,
    100% {
        transform: scale(1);
        opacity: 0.8;
    }
    50% {
        transform: scale(1.4);
        opacity: 0.3;
    }
}

/* -------------------------------------------------------
   Scroll cue bounce
------------------------------------------------------- */

@keyframes bounce-down {
    0%,
    100% {
        transform: translateX(-50%) translateY(0);
        opacity: 0.6;
    }
    50% {
        transform: translateX(-50%) translateY(8px);
        opacity: 1;
    }
}

/* -------------------------------------------------------
   Terminal typing cursor
------------------------------------------------------- */

@keyframes type-cursor-blink {
    0%,
    100% {
        border-right-color: var(--color-green);
    }
    50% {
        border-right-color: transparent;
    }
}

/* -------------------------------------------------------
   Skill tag reveal
   tagPopIn is the canonical name used by observer.js
   tag-appear is kept as an alias
------------------------------------------------------- */

@keyframes tagPopIn {
    from {
        opacity: 0;
        transform: translateY(14px) scale(0.88);
    }
    60% {
        transform: translateY(-3px) scale(1.04);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* Alias */
@keyframes tag-appear {
    from {
        opacity: 0;
        transform: translateY(16px) scale(0.9);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* -------------------------------------------------------
   Contact card reveal
   cardReveal is the canonical name used by observer.js
------------------------------------------------------- */

@keyframes cardReveal {
    from {
        opacity: 0;
        transform: translateY(24px);
    }
    70% {
        transform: translateY(-4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* -------------------------------------------------------
   Contact card hover shimmer
------------------------------------------------------- */

@keyframes card-glitch-shake {
    0%,
    100% {
        transform: translateX(0) skewX(0deg);
    }
    10% {
        transform: translateX(-4px) skewX(-1.5deg);
    }
    20% {
        transform: translateX(4px) skewX(1.5deg);
    }
    30% {
        transform: translateX(-3px) skewX(-1deg);
    }
    40% {
        transform: translateX(3px) skewX(1deg);
    }
    50% {
        transform: translateX(-2px) skewX(-0.5deg);
    }
    60% {
        transform: translateX(2px) skewX(0.5deg);
    }
    70% {
        transform: translateX(-1px);
    }
    80% {
        transform: translateX(1px);
    }
    90% {
        transform: translateX(0);
    }
}

@keyframes card-glitch-bg {
    0%,
    100% {
        background: transparent;
        border-color: var(--color-amber-20);
    }
    15% {
        background: rgba(0, 229, 255, 0.06);
        border-color: var(--color-cyan);
    }
    30% {
        background: rgba(0, 255, 65, 0.06);
        border-color: var(--color-green);
    }
    50% {
        background: rgba(255, 176, 0, 0.08);
        border-color: var(--color-amber);
    }
    65% {
        background: rgba(0, 229, 255, 0.04);
        border-color: var(--color-cyan);
    }
    80% {
        background: transparent;
        border-color: var(--color-green);
    }
}

@keyframes card-shimmer {
    0% {
        background-position: -200% center;
    }
    100% {
        background-position: 200% center;
    }
}

/* -------------------------------------------------------
   Nav logo cursor spin-in
------------------------------------------------------- */

@keyframes spin-in {
    from {
        transform: rotate(-90deg);
        opacity: 0;
    }
    to {
        transform: rotate(0deg);
        opacity: 1;
    }
}

/* -------------------------------------------------------
   Hero meta text slide-in
------------------------------------------------------- */

@keyframes slide-in-from-left {
    from {
        opacity: 0;
        transform: translateX(-20px);
        letter-spacing: 0.2em;
    }
    to {
        opacity: 0.6;
        transform: translateX(0);
        letter-spacing: var(--ls-wider);
    }
}
