/* =============================================================================
   RUCH — przejścia, animacje wejścia, efekty przy przewijaniu
   -----------------------------------------------------------------------------
   Zasady, których się trzymamy:

   1. Ruch nigdy nie odbiera funkcji. Nie przechwytujemy kliknięć, nie blokujemy
      przewijania, nie zastępujemy natywnego scrolla własnym. Zepsuty link boli
      bardziej niż brak animacji.
   2. Jedno mocne miejsce — hero. Pasek miar „budzi się” jak tablica przyrządów.
      To sygnatura projektu, więc ruch ją wzmacnia. Reszta strony jest cicha.
   3. Wszystko respektuje prefers-reduced-motion. Blok na końcu pliku wyłącza
      ruch globalnie, a nie po kawałku w każdym komponencie.
   4. Animujemy wyłącznie transform i opacity — te własności obsługuje kompozytor,
      więc nie wymuszają przeliczania układu ani przemalowania.
   ========================================================================== */


/* =============================================================================
   1. PRZEJŚCIA MIĘDZY STRONAMI (View Transitions, nawigacja międzydokumentowa)
   -----------------------------------------------------------------------------
   Obsługuje to przeglądarka na podstawie reguły @view-transition — bez JS.
   Tam, gdzie API nie jest wspierane (dziś m.in. Firefox), linki po prostu
   działają normalnie. Żadnego zapasowego kodu nie potrzeba.
   ========================================================================== */

@view-transition { navigation: auto; }

/* Migawka przejścia leży na całej stronie jako warstwa nad treścią.
   Bez tego kliknięcie w menu w trakcie animacji trafiało w obrazek, a nie
   w link — wyglądało to jak „nie łapie za pierwszym razem, trzeba kliknąć
   dwa razy”. Z pointer-events: none kliknięcia przechodzą do prawdziwego DOM. */
::view-transition { pointer-events: none; }

/* Elementy trwałe: nagłówek i stopka nie przenikają razem z treścią,
   tylko zostają na miejscu. Dzięki temu nawigacja sprawia wrażenie
   zmiany treści, a nie przeładowania całej strony. */
.naglowek-strony { view-transition-name: naglowek; }
.stopka          { view-transition-name: stopka; }

/* Hero NIE dostaje własnej migawki — świadoma decyzja.
   Osobna nazwa oznacza morfowanie: zdjęcie jechałoby z wysokości hero
   poprzedniej strony (na stronie głównej 100svh) do wysokości hero podstrony
   (~470 px). Tło kurczyło się już po wejściu nowej treści i za każdym razem
   czytało się to jako błąd ładowania. Bez nazwy hero wchodzi w migawkę "root"
   i przenika razem z resztą strony — nudno, ale zawsze tak samo. */

/* Treść: stara wysuwa się w górę, nowa wjeżdża od dołu.
   Czasy dobrane tak, żeby ruch był widoczny, ale nie opóźniał czytania —
   420 ms to górna granica, powyżej której przejście zaczyna irytować
   przy szybkim przeklikiwaniu menu. */
::view-transition-old(root) {
  animation: fv-tresc-wyjscie 200ms cubic-bezier(0.65, 0, 0.35, 1) both;
}
::view-transition-new(root) {
  animation: fv-tresc-wejscie 420ms 60ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes fv-tresc-wyjscie {
  to { opacity: 0; transform: translateY(-16px) scale(0.995); }
}
@keyframes fv-tresc-wejscie {
  from { opacity: 0; transform: translateY(26px) scale(0.995); }
}

/* Nagłówek i stopka: samo przenikanie, bez przesuwania */
::view-transition-old(naglowek),
::view-transition-new(naglowek),
::view-transition-old(stopka),
::view-transition-new(stopka) {
  animation-duration: 200ms;
  animation-timing-function: ease;
}

/* -----------------------------------------------------------------------------
   Przeglądarki bez nawigacyjnych View Transitions (m.in. Firefox).
   Klasę ustawia skrypt w <head> — patrz includes/header.php.

   Animujemy tylko wejście: wyjście wymagałoby przechwytywania kliknięć w linki,
   a to już raz zepsuło nawigację z menu mobilnego. Samo wejście wystarczy,
   żeby zmiana strony nie była suchym przeskokiem, i nie może niczego zablokować.
   -------------------------------------------------------------------------- */

.bez-przejsc-dokumentu main {
  animation: fv-tresc-wejscie 420ms 20ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.bez-przejsc-dokumentu .naglowek-strony {
  animation: fv-naglowek-wejscie 300ms ease both;
}

@keyframes fv-naglowek-wejscie {
  from { opacity: 0; }
}

/* Samo przenikanie, bez ruchu — wersja dla prefers-reduced-motion (sekcja na końcu pliku) */
@keyframes fv-przenikanie-wyjscie { to   { opacity: 0; } }
@keyframes fv-przenikanie-wejscie { from { opacity: 0; } }


/* =============================================================================
   2. HERO — orkiestracja wejścia
   -----------------------------------------------------------------------------
   Jedna sekwencja, nie zbiór osobnych efektów: nadtytuł, nagłówek, lead
   i przyciski wchodzą kaskadą, a na końcu „włącza się” pasek miar —
   najpierw rysuje się kreska, potem podnoszą się wartości.
   ========================================================================== */

/* Sekwencja startuje dopiero, gdy zdjęcie tła jest na ekranie.
   Wcześniej napisy zdążyły wjechać na puste tło, a zdjęcie z gradientem
   pojawiało się po nich — wyglądało to jak dwa osobne ładowania strony.
   Klasę `hero--gotowe` dokłada main.js po wczytaniu obrazu (z awaryjnym
   limitem czasu), a `both` trzyma elementy na pierwszej klatce.
   Reguła działa tylko przy włączonym JS — inaczej treść byłaby niewidoczna. */
.js .hero:not(.hero--gotowe) :is(
  .hero__marka, .hero__tytul, .hero__lead, .hero__akcje, .hero__miary .miara
),
.js .hero:not(.hero--gotowe) .hero__miary::before,
.js .hero:not(.hero--gotowe) .hero__miary .miara + .miara::before {
  animation-play-state: paused;
}

/* Zdjęcie i przyciemnienie wchodzą razem, jednym przenikaniem.
   Wcześniej gradient był widoczny od pierwszej klatki, więc do czasu
   pobrania fotografii hero było szarym prostokątem — użytkownik odbierał to
   jako „najpierw pusty pasek, potem zdjęcie”. */
.js .hero .hero__tlo,
.js .hero .hero__zaslona {
  transition: opacity 360ms var(--ease-out);
}
.js .hero:not(.hero--gotowe) .hero__tlo,
.js .hero:not(.hero--gotowe) .hero__zaslona {
  opacity: 0;
}

.hero__marka,
.hero__tytul,
.hero__lead,
.hero__akcje {
  animation: fv-hero-wejscie 800ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.hero__marka  { animation-delay: 80ms; }
.hero__tytul  { animation-delay: 160ms; }
.hero__lead   { animation-delay: 280ms; }
.hero__akcje  { animation-delay: 380ms; }

@keyframes fv-hero-wejscie {
  from { opacity: 0; transform: translateY(1.5rem); }
}

/* ---- Pasek miar: kreska rysuje się, potem wstają wartości ---------------- */

/* Górna krawędź paska jest osobnym elementem, bo border-top nie da się
   animować „od lewej do prawej” — a właśnie o to tu chodzi. */
.hero__miary {
  position: relative;
  border-block-start: 0;
}
.hero__miary::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 1px;
  background: color-mix(in oklab, var(--fv-white) 26%, transparent);
  transform: scaleX(0);
  transform-origin: left center;
  animation: fv-kreska 900ms 480ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes fv-kreska {
  to { transform: scaleX(1); }
}

/* Wartości i jednostki wchodzą po kolei, w ślad za kreską */
.hero__miary .miara {
  animation: fv-miara-wejscie 620ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.hero__miary .miara:nth-child(1) { animation-delay: 620ms; }
.hero__miary .miara:nth-child(2) { animation-delay: 720ms; }
.hero__miary .miara:nth-child(3) { animation-delay: 820ms; }
.hero__miary .miara:nth-child(4) { animation-delay: 920ms; }

@keyframes fv-miara-wejscie {
  from { opacity: 0; transform: translateY(0.75rem); }
}

/* Pionowe kreski między miarami dociągają się na końcu sekwencji */
@media (min-width: 48rem) {
  .hero__miary .miara + .miara {
    border-inline-start: 0;
    position: relative;
  }
  .hero__miary .miara + .miara::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: 1px;
    background: color-mix(in oklab, var(--fv-white) 20%, transparent);
    transform: scaleY(0);
    transform-origin: center top;
    animation: fv-kreska-pion 520ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  .hero__miary .miara:nth-child(2)::before { animation-delay: 760ms; }
  .hero__miary .miara:nth-child(3)::before { animation-delay: 860ms; }
  .hero__miary .miara:nth-child(4)::before { animation-delay: 960ms; }
}

@keyframes fv-kreska-pion {
  to { transform: scaleY(1); }
}


/* =============================================================================
   3. PARALAKSA HERO
   -----------------------------------------------------------------------------
   Sterowana pozycją przewijania przez natywną oś czasu CSS (animation-timeline).
   Bez JS, bez nasłuchiwania scrolla — działa na kompozytorze, więc nie obciąża
   głównego wątku i nie psuje płynności.

   Zdjęcie jest wstępnie powiększone o 12%, a przesuwa się o 6% — powiększenie
   musi być większe niż przesunięcie, inaczej przy krawędzi odsłoniłaby się luka.
   ========================================================================== */

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero__tlo {
      scale: 1.12;
      animation: fv-paralaksa linear both;
      animation-timeline: scroll();
      animation-range: 0 100svh;
      will-change: transform;
    }
    /* Zasłona ciemnieje w miarę przewijania — tekst pozostaje czytelny,
       a zdjęcie nie „ucieka” białym pasem */
    .hero__zaslona {
      animation: fv-zaslona linear both;
      animation-timeline: scroll();
      animation-range: 0 100svh;
    }
  }
}

@keyframes fv-paralaksa {
  to { translate: 0 6%; }
}
@keyframes fv-zaslona {
  to { opacity: 1.25; }
}


/* =============================================================================
   4. WEJŚCIA SEKCJI PRZY PRZEWIJANIU
   -----------------------------------------------------------------------------
   Dwie ścieżki:
   • przeglądarki z animation-timeline: view() — czysty CSS, zero JS;
   • pozostałe — IntersectionObserver z main.js (klasy .reveal/.jest-widoczny).

   JS sprawdza wsparcie i nie rusza elementów, którymi zajmuje się CSS,
   więc nigdy nie animują się dwa razy.
   ========================================================================== */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal] {
      animation: fv-odslon linear both;
      animation-timeline: view();
      /* Start tuż po wejściu w kadr, koniec gdy element jest w 1/4 widoczny —
         animacja kończy się, zanim użytkownik zdąży na niej zawiesić wzrok */
      animation-range: entry 0% cover 18%;
    }
  }
}

@keyframes fv-odslon {
  from { opacity: 0; transform: translateY(1.5rem); }
  to   { opacity: 1; transform: none; }
}


/* =============================================================================
   5. NAGŁÓWEK — przypięty, kurczy się przy przewijaniu
   -----------------------------------------------------------------------------
   Nagłówek zostaje widoczny cały czas (position: fixed), a po przewinięciu
   zmniejsza wysokość i logo. Nawigacja jest zawsze pod ręką, ale zajmuje mniej
   ekranu tam, gdzie użytkownik czyta treść.

   Same przejścia wysokości siedzą przy komponencie w components.css —
   tutaj tylko krzywa dla tła i obramowania.
   ========================================================================== */

.naglowek-strony {
  transition:
    border-color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}


/* =============================================================================
   6. MENU MOBILNE — wejście kaskadowe
   ========================================================================== */

.menu-mobilne {
  transition:
    opacity var(--dur-base) var(--ease-out),
    visibility var(--dur-base),
    clip-path var(--dur-slow) var(--ease-out);
}

.menu-mobilne__lista li {
  opacity: 0;
  transform: translateY(0.9rem);
  transition:
    opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}
.menu-mobilne.jest-otwarte .menu-mobilne__lista li {
  opacity: 1;
  transform: none;
}

/* Kaskada — każda kolejna pozycja rusza 45 ms później.
   Menu ma 10 pozycji, więc ostatnia startuje po 405 ms: dość, żeby ruch
   był czytelny, za mało, żeby zdążył zirytować. */
.menu-mobilne__lista li:nth-child(1)  { transition-delay: 60ms; }
.menu-mobilne__lista li:nth-child(2)  { transition-delay: 105ms; }
.menu-mobilne__lista li:nth-child(3)  { transition-delay: 150ms; }
.menu-mobilne__lista li:nth-child(4)  { transition-delay: 195ms; }
.menu-mobilne__lista li:nth-child(5)  { transition-delay: 240ms; }
.menu-mobilne__lista li:nth-child(6)  { transition-delay: 285ms; }
.menu-mobilne__lista li:nth-child(7)  { transition-delay: 330ms; }
.menu-mobilne__lista li:nth-child(8)  { transition-delay: 375ms; }
.menu-mobilne__lista li:nth-child(9)  { transition-delay: 420ms; }
.menu-mobilne__lista li:nth-child(10) { transition-delay: 465ms; }

/* Przy zamykaniu kaskada byłaby irytująca — wszystko znika naraz */
.menu-mobilne:not(.jest-otwarte) .menu-mobilne__lista li {
  transition-delay: 0ms;
  transition-duration: var(--dur-fast);
}

.menu-mobilne__dol {
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out) 380ms;
}
.menu-mobilne.jest-otwarte .menu-mobilne__dol { opacity: 1; }


/* =============================================================================
   7. MIKROINTERAKCJE
   ========================================================================== */

/* Przycisk lekko się ugina — potwierdzenie, że kliknięcie zostało przyjęte */
.btn {
  transition:
    background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-spring);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(1px); }

/* Karty unoszą się przy najechaniu */
.karta {
  transition:
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}
.karta:hover { transform: translateY(-3px); }

/* Kafelki galerii — samo zdjęcie, bez ruchu ramki */
.galeria__kafel img {
  transition: transform var(--dur-slow) var(--ease-out);
}

/* Lightbox pojawia się z lekkim przybliżeniem */
.lightbox:not([hidden]) {
  animation: fv-lightbox 240ms var(--ease-out) both;
}
@keyframes fv-lightbox {
  from { opacity: 0; }
}
.lightbox:not([hidden]) .lightbox__scena img {
  animation: fv-lightbox-obraz 300ms var(--ease-out) both;
}
@keyframes fv-lightbox-obraz {
  from { opacity: 0; transform: scale(0.97); }
}

/* Baner cookies wjeżdża od dołu — już zdefiniowane w components.css,
   tu tylko dopasowanie krzywej */
.cookies { transition: transform var(--dur-slow) var(--ease-out); }


/* =============================================================================
   8. SZANUJ prefers-reduced-motion
   -----------------------------------------------------------------------------
   Jedno miejsce wyłączające cały ruch. Zostawiamy wyłącznie zmiany koloru,
   bo one nie wywołują dolegliwości przedsionkowych, a niosą informację
   (stan hover, focus, aktywna pozycja menu).
   ========================================================================== */

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

  /* Przejścia między stronami ZOSTAJĄ, ale jako samo przenikanie.
     Wcześniej było tu `navigation: none` i nawigacja stawała się suchym
     przeskokiem — a to za dużo. Preferencja dotyczy ruchu: przesuwania,
     skalowania, paralaksy. Zmiana samej przezroczystości nie wywołuje
     dolegliwości przedsionkowych, więc ją zachowujemy — bez niej nawigacja
     traci ciągłość, której nic nie zastępuje. */

  ::view-transition-old(root) {
    animation: fv-przenikanie-wyjscie 180ms ease both;
  }
  ::view-transition-new(root) {
    animation: fv-przenikanie-wejscie 180ms ease both;
  }
  /* plus-lighter daje czyste przenikanie — bez niego przez chwilę prześwituje
     tło strony i przejście „mruga” */
  ::view-transition-old(root),
  ::view-transition-new(root) { mix-blend-mode: plus-lighter; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Elementy animowane „od zera” muszą wylądować w stanie końcowym,
     a nie zostać niewidoczne */
  .hero__marka, .hero__tytul, .hero__lead, .hero__akcje,
  .hero__miary .miara,
  [data-reveal],
  .menu-mobilne__lista li,
  .menu-mobilne__dol {
    opacity: 1 !important;
    transform: none !important;
  }
  .hero__miary::before,
  .hero__miary .miara + .miara::before {
    transform: none !important;
  }
  .hero__tlo { scale: 1; translate: none; }

  .btn:hover, .karta:hover { transform: none; }
}
