/* ============================================================
   SPIS TRESCI - animations.css (animacje wejscia on-scroll, bez biblioteki)
   1. KEYFRAMES WEJSC (revele)
   2. MECHANIZM WEJSC - IntersectionObserver (reveal.js) + keyframes
   2a. EFEKT OD PROGU (data-anim-sm / -md / -lg) - chowanie przed startem reveal.js
   3. SCRUB - progresywny dodatek CSS scroll-driven (tylko dekoracje)
   4. REDUKCJA RUCHU (w tym wideo w tle z video.js)
   5. STAN POCZATKOWY MODULU GSAP (data-gsap-hide)
   6. TEMPO PROJEKTU (zmienne: czas, easing, przesuniecie, linia startu; strona PBW: pbw.css 1b)
   ------------------------------------------------------------
   Uzycie: atrybut  data-anim="..."  na elemencie. Katalog:
     REVELE:  fade | fade-up | fade-down | fade-left | fade-right |
              zoom | rise | blur-up | flip-up | rotate-in | mask-reveal |
              slide-left | slide-right (wjazd o 100% szerokosci bez zanikania, jak AOS slide-*)
     SCRUB:   parallax | parallax-fast | scale-scrub
   Opcja:  data-anim-reverse  (re-arm takze przy wyjsciu gora, animacja przy powrocie).
   Modyfikator:  data-anim-delay="200"  (ms, stagger; reveal.js przepisuje
   go na animation-delay, fill backwards trzyma stan startowy w czasie delayu).
   Modyfikatory per element (reveal.js, wszystkie opcjonalne):
     data-anim-duration="2000"  czas animacji w ms
     data-anim-shift="100"      przesuniecie w px dla fade-up/-down/-left/-right
     data-anim-start="90"       linia startu w % wysokosci viewportu (gora elementu
                                ja przecina; 100 = od razu po wejsciu dolem)
     data-anim-offset="200"     linia startu w px nad dolna krawedzia okna (jak offset AOS);
                                domyslnie --wb-anim-offset (strona PBW, pbw.css), data-anim-start
                                ma pierwszenstwo
     data-anim-sm / -md / -lg   efekt od progu 480 / 768 / 992 px (mobile-first jak
                                klasy TW); "none" = bez animacji od tego progu.
                                data-anim zostaje zawsze (wartosc bazowa, moze byc "none")
   Ustawienia projektu (sekcja 6, czyta reveal.js): --wb-anim-once: 1 (kazdy element
   animuje sie tylko raz), --wb-anim-after-load: 1 (start po window.load). Skala startowa
   zoom: --wb-anim-zoom (domyslnie 0.92). Strona PBW ma wlasne tempo (pbw.css, sekcja 1b).
   Grupa:  data-anim-stagger="350" na kontenerze - dzieci z data-anim wchodza razem
           (wyzwala kontener), kazde kolejne o 350 ms pozniej. Do list z blokow-dzieci:
           delay nie siedzi w definicji dziecka, wiec klient moze dodawac pozycje.

   Kiedy co:
   - REVELE = tresc, ktora ma dojsc do pozycji z Figmy piksel w piksel
     (naglowki, karty, obrazy). Stan koncowy = design.
   - SCRUB = elementy DEKORACYJNE (tlo, ksztalty), ktore dryfuja wraz ze
     scrollem. NIE dawac na tresc pixel-perfect. Dziala tylko w silnikach
     z animation-timeline (w praktyce Chrome); gdzie indziej element stoi.
   - mask-reveal (clip-path) stosowac ostroznie, dopiero gdy baza sekcji
     jest stabilna; domyslny bezpieczny zestaw to fade / fade-up /
     fade-left / fade-right / zoom.

   Jak to dziala (mechanizm glowny = IntersectionObserver, nie scroll-driven):
   - Klase wb-anim na <html> stawia skrypt w <head> (inc/enqueue.php, sekcja 2d) przed
     pierwszym renderem; DOPIERO ona chowa elementy. Bez tego tresc pierwszego ekranu
     rysowala sie, znikala po wczytaniu reveal.js (defer) i wjezdzala. Gdy reveal.js nie
     wystartuje w 4 s, skrypt zdejmuje klase. reveal.js dodaje ja tez sam (kanwa PG).
     Brak JS, brak IO albo prefers-reduced-motion = nic nie jest chowane.
   - Wejscie robi ANIMACJA keyframes w klasie .anim-in (nie transition),
     BEZ fill forwards. Dzieki temu nie nadpisujemy transition elementu
     (hovery przyciskow dzialaja), a po animacji element wraca do stanu
     naturalnego, wiec filled animation nie blokuje transformow z :hover.
   - Replay tylko w dol: reveal.js zdejmuje .anim-in wylacznie gdy element
     wyszedl calkowicie POD viewport. Scroll w gore niczego nie odtwarza.
   - Animujemy transform + opacity (dla blur-up/mask-reveal takze
     filter / clip-path). Zero layout-shift: nie ruszamy width/height/margin.
   - Testowanie: front, plik otwarty w przegladarce albo kanwa Pinegrow
     (wykonuje skrypty podpiete w pliku). Edytor Gutenberga nie wykonuje
     JS i celowo zeruje data-anim (editor.css).
   ============================================================ */

/* === 1. KEYFRAMES WEJSC === */
@keyframes wb-fade         { from { opacity: 0; }                                           to { opacity: 1; } }
@keyframes wb-fade-up      { from { opacity: 0; transform: translateY(var(--wb-anim-shift, 2rem)); }               to { opacity: 1; transform: none; } }
@keyframes wb-fade-down    { from { opacity: 0; transform: translateY(calc(-1 * var(--wb-anim-shift, 2rem))); }    to { opacity: 1; transform: none; } }
@keyframes wb-fade-left    { from { opacity: 0; transform: translateX(var(--wb-anim-shift, 2rem)); }               to { opacity: 1; transform: none; } }
@keyframes wb-fade-right   { from { opacity: 0; transform: translateX(calc(-1 * var(--wb-anim-shift, 2rem))); }    to { opacity: 1; transform: none; } }
@keyframes wb-zoom         { from { opacity: 0; transform: scale(var(--wb-anim-zoom, 0.92)); } to { opacity: 1; transform: none; } }
@keyframes wb-rise         { from { opacity: 0; transform: translateY(3.5rem); }            to { opacity: 1; transform: none; } }
@keyframes wb-blur-up      { from { opacity: 0; transform: translateY(2rem); filter: blur(12px); } to { opacity: 1; transform: none; filter: blur(0); } }
@keyframes wb-flip-up      { from { opacity: 0; transform: perspective(800px) rotateX(12deg); }    to { opacity: 1; transform: perspective(800px) rotateX(0); } }
@keyframes wb-rotate-in    { from { opacity: 0; transform: rotate(-4deg) scale(0.96); }     to { opacity: 1; transform: none; } }
@keyframes wb-mask-reveal  { from { opacity: 0.001; clip-path: inset(0 0 100% 0); }         to { opacity: 1; clip-path: inset(0 0 0 0); } }
@keyframes wb-slide-left   { from { transform: translateX(100%); }                          to { transform: none; } }
@keyframes wb-slide-right  { from { transform: translateX(-100%); }                         to { transform: none; } }

/* === 2. MECHANIZM WEJSC (IntersectionObserver + keyframes) === */
/* Chowanie wylacznie pod html.wb-anim (dodaje reveal.js) i TYLKO wartosci z katalogu.
   Obcy kod albo biblioteka z innymi wartosciami data-anim nie zostanie schowana
   (zadnego podwojnego sterowania opacity, zadnej niewidocznej tresci). */
html.wb-anim [data-anim="fade"],
html.wb-anim [data-anim="fade-up"],
html.wb-anim [data-anim="fade-down"],
html.wb-anim [data-anim="fade-left"],
html.wb-anim [data-anim="fade-right"],
html.wb-anim [data-anim="zoom"],
html.wb-anim [data-anim="rise"],
html.wb-anim [data-anim="blur-up"],
html.wb-anim [data-anim="flip-up"],
html.wb-anim [data-anim="rotate-in"],
html.wb-anim [data-anim="mask-reveal"],
html.wb-anim [data-anim="slide-left"],
html.wb-anim [data-anim="slide-right"] { opacity: 0; }

/* === 2a. EFEKT OD PROGU (przed startem reveal.js) === */
/* reveal.js przepisuje data-anim na efekt wlasciwy dla szerokosci, ale dopiero po wczytaniu.
   Do tego czasu chowaja te reguly: te same progi co BREAKPOINTS w reveal.js, mobile-first
   (pozniejszy prog nadpisuje wczesniejszy). "none" od progu cofa chowanie z wartosci bazowej
   (revert-layer = opacity z klas TW elementu albo naturalna). Po starcie JS obie strony
   wskazuja ten sam efekt, wiec reguly nie koliduja. */
@media (min-width: 30rem) {
  html.wb-anim [data-anim-sm="fade"],
  html.wb-anim [data-anim-sm="fade-up"],
  html.wb-anim [data-anim-sm="fade-down"],
  html.wb-anim [data-anim-sm="fade-left"],
  html.wb-anim [data-anim-sm="fade-right"],
  html.wb-anim [data-anim-sm="zoom"],
  html.wb-anim [data-anim-sm="rise"],
  html.wb-anim [data-anim-sm="blur-up"],
  html.wb-anim [data-anim-sm="flip-up"],
  html.wb-anim [data-anim-sm="rotate-in"],
  html.wb-anim [data-anim-sm="mask-reveal"],
  html.wb-anim [data-anim-sm="slide-left"],
  html.wb-anim [data-anim-sm="slide-right"] { opacity: 0; }
  html.wb-anim [data-anim-sm="none"] { opacity: revert-layer; }
}
@media (min-width: 48rem) {
  html.wb-anim [data-anim-md="fade"],
  html.wb-anim [data-anim-md="fade-up"],
  html.wb-anim [data-anim-md="fade-down"],
  html.wb-anim [data-anim-md="fade-left"],
  html.wb-anim [data-anim-md="fade-right"],
  html.wb-anim [data-anim-md="zoom"],
  html.wb-anim [data-anim-md="rise"],
  html.wb-anim [data-anim-md="blur-up"],
  html.wb-anim [data-anim-md="flip-up"],
  html.wb-anim [data-anim-md="rotate-in"],
  html.wb-anim [data-anim-md="mask-reveal"],
  html.wb-anim [data-anim-md="slide-left"],
  html.wb-anim [data-anim-md="slide-right"] { opacity: 0; }
  html.wb-anim [data-anim-md="none"] { opacity: revert-layer; }
}
@media (min-width: 62rem) {
  html.wb-anim [data-anim-lg="fade"],
  html.wb-anim [data-anim-lg="fade-up"],
  html.wb-anim [data-anim-lg="fade-down"],
  html.wb-anim [data-anim-lg="fade-left"],
  html.wb-anim [data-anim-lg="fade-right"],
  html.wb-anim [data-anim-lg="zoom"],
  html.wb-anim [data-anim-lg="rise"],
  html.wb-anim [data-anim-lg="blur-up"],
  html.wb-anim [data-anim-lg="flip-up"],
  html.wb-anim [data-anim-lg="rotate-in"],
  html.wb-anim [data-anim-lg="mask-reveal"],
  html.wb-anim [data-anim-lg="slide-left"],
  html.wb-anim [data-anim-lg="slide-right"] { opacity: 0; }
  html.wb-anim [data-anim-lg="none"] { opacity: revert-layer; }
}

/* Przesuniecie liczone per element: reset na kazdym [data-anim], bo zmienna dziedziczy
   sie w dol (kontener z data-anim-shift="55" nie moze przesuwac swoich dzieci o 55px).
   Wartosc z data-anim-shift reveal.js wpisuje inline, wiec wygrywa z tym resetem. */
[data-anim] { --wb-anim-shift: var(--wb-anim-shift-default, 2rem); }

/* Stan widoczny: element ujawniony przez IO oraz scrub (dekoracja,
   ktorej nie chowamy - jej ruch robi sekcja 3, nie wejscie). */
html.wb-anim [data-anim].anim-in,
html.wb-anim [data-anim="parallax"],
html.wb-anim [data-anim="parallax-fast"],
html.wb-anim [data-anim="scale-scrub"] { opacity: 1; }

/* Wejscia: keyframes bez fill forwards (backwards trzyma stan startowy
   w czasie animation-delay, po koncu element wraca do stanu naturalnego). */
html.wb-anim [data-anim="fade"].anim-in        { animation: wb-fade var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="fade-up"].anim-in     { animation: wb-fade-up var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="fade-down"].anim-in   { animation: wb-fade-down var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="fade-left"].anim-in   { animation: wb-fade-left var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="fade-right"].anim-in  { animation: wb-fade-right var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="zoom"].anim-in        { animation: wb-zoom var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="rise"].anim-in        { animation: wb-rise .8s cubic-bezier(0.22, 0.61, 0.36, 1) backwards; }
html.wb-anim [data-anim="blur-up"].anim-in     { animation: wb-blur-up .8s ease-out backwards; }
html.wb-anim [data-anim="flip-up"].anim-in     { animation: wb-flip-up .8s cubic-bezier(0.22, 0.61, 0.36, 1) backwards; }
html.wb-anim [data-anim="rotate-in"].anim-in   { animation: wb-rotate-in .7s ease-out backwards; }
html.wb-anim [data-anim="mask-reveal"].anim-in { animation: wb-mask-reveal .8s cubic-bezier(0.22, 0.61, 0.36, 1) backwards; }
html.wb-anim [data-anim="slide-left"].anim-in  { animation: wb-slide-left var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }
html.wb-anim [data-anim="slide-right"].anim-in { animation: wb-slide-right var(--wb-anim-duration, .7s) var(--wb-anim-ease, ease-out) backwards; }

/* Element, ktoremu zmiana breakpointu podmienila efekt, gdy byl w kadrze: zostaje
   widoczny bez ponownego odtwarzania (anim-hold dodaje i zdejmuje reveal.js). */
html.wb-anim [data-anim].anim-in.anim-hold { animation: none; }

/* === 3. SCRUB: progresywny dodatek (dryf sterowany scrollem, bez JS) === */
@keyframes wb-parallax      { from { transform: translateY(-2rem); } to { transform: translateY(2rem); } }
@keyframes wb-parallax-fast { from { transform: translateY(-4rem); } to { transform: translateY(4rem); } }
@keyframes wb-scale-scrub   { from { transform: scale(0.94); }       to { transform: scale(1.04); } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-anim="parallax"],
    [data-anim="parallax-fast"],
    [data-anim="scale-scrub"] {
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      animation-timing-function: linear;
      animation-fill-mode: both;
    }
    [data-anim="parallax"]      { animation-name: wb-parallax; }
    [data-anim="parallax-fast"] { animation-name: wb-parallax-fast; }
    [data-anim="scale-scrub"]   { animation-name: wb-scale-scrub; }
  }
}

/* === 4. REDUKCJA RUCHU === */
/* reveal.js przy reduce nie dodaje wb-anim; ta regula domyka reszte
   (np. reduce wlaczone po zaladowaniu strony). */
@media (prefers-reduced-motion: reduce) {
  html.wb-anim [data-anim].anim-in,
  html.wb-anim [data-anim="fade"],
  html.wb-anim [data-anim="fade-up"],
  html.wb-anim [data-anim="fade-down"],
  html.wb-anim [data-anim="fade-left"],
  html.wb-anim [data-anim="fade-right"],
  html.wb-anim [data-anim="zoom"],
  html.wb-anim [data-anim="rise"],
  html.wb-anim [data-anim="blur-up"],
  html.wb-anim [data-anim="flip-up"],
  html.wb-anim [data-anim="rotate-in"],
  html.wb-anim [data-anim="mask-reveal"],
  html.wb-anim [data-anim="slide-left"],
  html.wb-anim [data-anim="slide-right"],
  html.wb-anim [data-anim-sm],
  html.wb-anim [data-anim-md],
  html.wb-anim [data-anim-lg] { opacity: 1; animation: none; }
  [data-anim="parallax"],
  [data-anim="parallax-fast"],
  [data-anim="scale-scrub"] { animation: none; }
  /* Wideo w tle (video.js): schowane od pierwszej klatki, zanim skrypt je zatrzyma; spod
     spodu widac poster <img>. video.js zdejmuje autoplay, wiec natywny poster wraca. */
  video[autoplay]:not([controls]) { visibility: hidden; }
}


/* === 5. STAN POCZATKOWY MODULU GSAP === */
/* Modul opcjonalny 'gsap' (gsapanim.js). Klase wb-gsap dodaje skrypt w <head>
   (inc/enqueue.php), zdejmuje ja gsapanim.js po starcie albo bezpiecznik po 3 s.
   Elementy, ktore timeline ma wprowadzic, dostaja data-gsap-hide. */
html.wb-gsap [data-gsap-hide] { visibility: hidden; }


/* === 6. TEMPO PROJEKTU === */
/* Port Webflow 1:1 (custom code strony: GSAP gsap.from + ScrollTrigger). Bez tych zmiennych
   wracaja wartosci startera (.7s ease-out, 2rem, start 10% elementu w kadrze).
   - czas 1.3s, przesuniecie 35px, start "top 80%" = slide-up / slide-left z Webflow,
   - easing = power1.out (domyslny GSAP; "slow(...)" z Webflow bez EasePack spadal na niego).
   - kazda animacja raz (ScrollTrigger bez toggleActions), start po window.load jak w Webflow
     (reveal.js ma bezpiecznik 3 s, zeby wolne obrazki nie trzymaly schowanej tresci).
   Wyjatki (2s fade, 100px hero, 0.6s listy) ida atrybutami data-anim-* na elemencie. */
:root {
  --wb-anim-duration: 1.3s;
  --wb-anim-ease: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --wb-anim-shift-default: 35px;
  --wb-anim-start: 80;
  --wb-anim-once: 1;
  --wb-anim-after-load: 1;
}
