/* ==========================================================================
   animations.css — keyframes, klasy animacji i obsługa prefers-reduced-motion
   ========================================================================== */

/* Zmienna kąta do animowanych obramowań (conic-gradient). */
@property --border-angle {
    syntax: "<angle>";
    initial-value: 0deg;
    inherits: false;
}

/* ---------- Keyframes ---------- */

@keyframes border-rotate {
    to {
        --border-angle: 360deg;
    }
}

@keyframes gradient-shift {
    0%,
    100% {
        background-position: 0% 50%;
    }
    50% {
        background-position: 100% 50%;
    }
}

@keyframes float-y {
    0%,
    100% {
        transform: translateY(0);
    }
    50% {
        transform: translateY(-12px);
    }
}

@keyframes pulse-glow {
    0%,
    100% {
        opacity: 0.65;
        transform: scale(1);
    }
    50% {
        opacity: 1;
        transform: scale(1.06);
    }
}

@keyframes ping-ring {
    0% {
        transform: scale(0.8);
        opacity: 0.8;
    }
    100% {
        transform: scale(2.2);
        opacity: 0;
    }
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes spin-reverse {
    to {
        transform: rotate(-360deg);
    }
}

@keyframes grid-drift {
    from {
        background-position: 0 0, 0 0;
    }
    to {
        background-position: 64px 64px, 64px 64px;
    }
}

@keyframes scan-line {
    0% {
        transform: translateY(-100%);
        opacity: 0;
    }
    10%,
    90% {
        opacity: 1;
    }
    100% {
        transform: translateY(100%);
        opacity: 0;
    }
}

@keyframes shimmer {
    from {
        background-position: -200% 0;
    }
    to {
        background-position: 200% 0;
    }
}

@keyframes fade-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes fade-up {
    from {
        opacity: 0;
        transform: translateY(24px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes toast-in {
    from {
        opacity: 0;
        transform: translateY(16px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

@keyframes progress-fill {
    from {
        transform: scaleX(0);
    }
    to {
        transform: scaleX(1);
    }
}

@keyframes carousel-progress {
    from {
        transform: scaleX(0);
    }
    to {
        transform: scaleX(1);
    }
}

/* ---------- Klasy narzędziowe ---------- */

/* Animowane obramowanie gradientowe (wymaga position: relative na elemencie). */
.animated-border {
    position: relative;
    isolation: isolate;
}

.animated-border::before {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: -1;
    padding: 1px;
    border-radius: inherit;
    background: var(--gradient-conic);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    opacity: 0.55;
    animation: border-rotate 6s linear infinite;
    transition: opacity var(--duration-base) var(--ease-standard);
    pointer-events: none;
}

.animated-border:hover::before,
.animated-border:focus-within::before,
.animated-border.is-active::before {
    opacity: 1;
}

.animated-border--hover-only::before {
    opacity: 0;
}

.animate-gradient {
    background-size: 220% 220%;
    animation: gradient-shift 10s var(--ease-in-out) infinite;
}

.animate-float {
    animation: float-y 6s var(--ease-in-out) infinite;
}

.animate-pulse-glow {
    animation: pulse-glow 3.2s var(--ease-in-out) infinite;
}

.animate-spin-slow {
    animation: spin 24s linear infinite;
}

.animate-spin-reverse {
    animation: spin-reverse 32s linear infinite;
}

.animate-delay-1 {
    animation-delay: -1.5s;
}

.animate-delay-2 {
    animation-delay: -3s;
}

.animate-delay-3 {
    animation-delay: -4.5s;
}

/* Animacje pojawiania się podczas przewijania.
   main.js dodaje klasę .reveal-ready do <html> tylko wtedy, gdy
   IntersectionObserver jest dostępny i ruch nie jest ograniczony —
   dzięki temu bez JS treść jest zawsze widoczna. */
.reveal-ready .reveal {
    opacity: 0;
    transform: translateY(26px);
    transition:
        opacity var(--duration-slower) var(--ease-out),
        transform var(--duration-slower) var(--ease-out);
    will-change: opacity, transform;
}

.reveal-ready .reveal--scale {
    transform: scale(0.96);
}

.reveal-ready .reveal.is-visible {
    opacity: 1;
    transform: none;
}

.reveal-delay-1 {
    transition-delay: 80ms !important;
}

.reveal-delay-2 {
    transition-delay: 160ms !important;
}

.reveal-delay-3 {
    transition-delay: 240ms !important;
}

.reveal-delay-4 {
    transition-delay: 320ms !important;
}

.skeleton {
    background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-shine) 50%, var(--skeleton-base) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.6s linear infinite;
    border-radius: var(--radius-sm);
}

.spinner {
    inline-size: 1.1em;
    block-size: 1.1em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    display: inline-block;
    vertical-align: -0.15em;
}

/* ---------- Ograniczenie ruchu ---------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    .animated-border::before,
    .animate-gradient,
    .animate-float,
    .animate-pulse-glow,
    .animate-spin-slow,
    .animate-spin-reverse {
        animation: none !important;
    }

    .reveal-ready .reveal,
    .reveal-ready .reveal--scale {
        opacity: 1;
        transform: none;
        transition: none;
    }

    /* Spinner i skeleton pozostają czytelnym wskaźnikiem bez ruchu. */
    .spinner {
        animation: none;
        border-right-color: currentColor;
        opacity: 0.6;
    }

    .skeleton {
        animation: none;
    }
}
