/* assets/ruch.css
   Purpose: stany ruchu — słowa wchodzące z rozmycia, wejścia bloków, kurtyna zdjęcia,
            choreografia nagłówka po załadowaniu, pasek postępu
   NOT for: logiki wyzwalającej (→ ruch.js) ani uzbrajania stanu ukrytego (→ uzbrojenie.js)

   ZASADA NADRZĘDNA: treść NIGDY nie czeka na skrypt. Stan ukryty istnieje TYLKO pod
   `html.reveal-armed` — klasę dokłada uzbrojenie.js (synchronicznie w <head>, zanim
   cokolwiek się namaluje) i zdejmuje własnym licznikiem, jeśli ruch.js się nie zgłosi.
   Bez skryptów, przy błędnym wdrożeniu albo przy prośbie o mniej ruchu: wszystko stoi
   widoczne. Lekcja z 17.08.2026 (dwie sekcje PUSTE na zrzucie) i wzorzec z IRBIS.

   Selektory po ATRYBUTACH z HTML (data-entry, data-words, data-flow), nie po klasach
   dokładanych skryptem — klasa z `defer` przyszłaby po pierwszym malowaniu i treść
   mignęłaby, zanim zniknie. CSP zabrania atrybutów style=, więc opóźnienia
   (--wd, --i-ms) ustawia ruch.js przez CSSOM (`el.style.setProperty`). */

/* ── słowa: podnoszą się o .45em i wyostrzają z rozmycia 6 px ───────────── */
[data-words] .w, .hero [data-flow='words'] .w {
  display: inline-block;
  transition:
    opacity var(--dur-word) var(--ease-out),
    transform var(--dur-word) var(--ease-out),
    filter var(--dur-word) var(--ease-out);
}
[data-words] .w { transition-delay: var(--wd, 0ms); }
html.reveal-armed [data-words]:not([data-reveal]) .w {
  opacity: 0;
  transform: translateY(.45em);
  filter: blur(6px);
}

/* ── bloki: z dołu i odrobinę z głębi, kaskadą wg --i-ms ─────────────────
   Przejście wejścia obowiązuje tylko do `data-reveal="gotowe"` (ruch.js dokłada po
   zakończeniu). Potem blok wraca do WŁASNYCH przejść — inaczej karta unosiłaby się
   przy najechaniu przez sekundę, z opóźnieniem kaskady. */
html.reveal-armed [data-entry]:not([data-reveal='gotowe']) {
  transition:
    opacity var(--dur-block) var(--ease-out) var(--i-ms, 0ms),
    transform var(--dur-block) var(--ease-out) var(--i-ms, 0ms);
}
html.reveal-armed [data-entry]:not([data-reveal]) {
  opacity: 0;
  transform: translateY(var(--travel)) scale(.97);
}

/* ── kurtyna: przycina się WEWNĘTRZNY .wipe, nie element obserwowany ─────
   Chrome nie zgłasza przecięcia dla elementu zasłoniętego własnym clip-path,
   więc kurtyna na samym obserwowanym nie ruszyłaby nigdy (IRBIS, 07.10.2026). */
html.reveal-armed [data-entry].entry-wipe:not([data-reveal]) { opacity: 1; transform: none; }
.entry-wipe > .wipe { transition: clip-path 1100ms var(--ease-in-out); }
html.reveal-armed .entry-wipe:not([data-reveal]) > .wipe { clip-path: inset(100% 0 0 0); }

/* ── choreografia nagłówka po załadowaniu ──────────────────────────────────
   Kolejność i tempo z referencji: etykieta 120 ms → nagłówek od 260 ms po 90 ms na
   słowo → lead 640 ms → przyciski 1050 ms → liczby 1300 ms. Opóźnienia siedzą w CSS
   po wartości data-flow, więc działają także wtedy, gdy ruch.js nie dojdzie.
   Start = `data-flow-go` na <html>, dawany przez uzbrojenie.js po załadowaniu fontu —
   słowa nie mogą ruszyć czcionką zastępczą, bo przy podmianie przeskoczyłyby. */
.hero [data-flow='eyebrow'] { --fd: 120ms; }
.hero [data-flow='words']   { --fd: 260ms; }
.hero [data-flow='stos']    { --fd: 300ms; }
.hero [data-flow='lead']    { --fd: 640ms; }
.hero [data-flow='aside']   { --fd: 900ms; }
.hero [data-flow='cta']     { --fd: 1050ms; }
.hero [data-flow='stats']   { --fd: 1300ms; }

.hero [data-flow]:not([data-flow='words']):not([data-flow='stos']) {
  transition:
    opacity var(--dur-block) var(--ease-out) var(--fd, 0ms),
    transform var(--dur-block) var(--ease-out) var(--fd, 0ms);
}
html.reveal-armed:not([data-flow-go]) .hero [data-flow]:not([data-flow='words']):not([data-flow='stos']) {
  opacity: 0;
  transform: translateY(18px);
}
/* Nagłówek: sam blok stoi, ruszają słowa (opóźnienie bloku + opóźnienie słowa). */
.hero [data-flow='words'] .w { transition-delay: calc(var(--fd, 0ms) + var(--wd, 0ms)); }
html.reveal-armed:not([data-flow-go]) .hero [data-flow='words'] .w {
  opacity: 0;
  transform: translateY(.45em);
  filter: blur(6px);
}
/* Zrzuty w nagłówku BEZ zmiany przezroczystości: to kandydaci na LCP, a przezroczysty
   obraz nie liczy się jako namalowany. Tylko osiadają z lekkiego zbliżenia. */
.hero [data-flow='stos'] img { transition: transform 1400ms var(--ease-out) var(--fd, 0ms); }
html.reveal-armed:not([data-flow-go]) .hero [data-flow='stos'] img { transform: scale(1.06); }

/* ── pasek postępu przewijania: 2 px u góry, rośnie od lewej ───────────── */
.postep {
  position: fixed; inset: 0 0 auto 0; z-index: 110;
  height: 2px; background: var(--amber);
  transform-origin: left; transform: scaleX(var(--postep, 0));
  pointer-events: none;
}

/* ── mniej ruchu albo brak skryptów → wszystko po prostu stoi ──────────── */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  html.reveal-armed [data-words]:not([data-reveal]) .w,
  html.reveal-armed [data-entry]:not([data-reveal]),
  html.reveal-armed:not([data-flow-go]) .hero [data-flow]:not([data-flow='words']):not([data-flow='stos']),
  html.reveal-armed:not([data-flow-go]) .hero [data-flow='words'] .w,
  html.reveal-armed:not([data-flow-go]) .hero [data-flow='stos'] img {
    opacity: 1; transform: none; filter: none; transition: none;
  }
  html.reveal-armed .entry-wipe:not([data-reveal]) > .wipe { clip-path: none; }
  .postep { display: none; }
}
