/* ═══════════════════════════════════════════════════════════════════════
   OneValuate — strona wizytówka
   ───────────────────────────────────────────────────────────────────────
   Cała animacja przewijania jest ZROBIONA W CSS (scroll-driven animations,
   `view-timeline` + `animation-timeline`). Ani jednej linii JavaScriptu:
   te animacje działają na wątku kompozytora, więc nie da się nimi zaciąć
   przewijania - w przeciwieństwie do scrollowania obsługiwanego skryptem,
   które przy każdym zdarzeniu przelicza układ.

   Przeglądarki bez wsparcia dostają zwykłą, pionową stronę - wszystko jest
   widoczne, tylko bez ruchu (patrz `@supports not` na końcu pliku).
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* Strona jest projektowo ciemna i nie ma jasnego wariantu. Deklaracja
     `color-scheme` sprawia, że przeglądarka renderuje natywne elementy
     (paski, formularze) po ciemnemu i - razem z `darkreader-lock`
     w <head> - powstrzymuje automatyczne przyciemniacze przed
     "poprawianiem" strony, która ciemna już jest. */
  color-scheme: dark;

  /* Grunt jest CIEMNIEJSZY niż w samej aplikacji (#0a0a0d). To celowe:
     interfejs w ramce ma na nim świecić jak produkt na czarnym tle
     w katalogu, a nie zlewać się ze stroną. */
  --void:   #07080b;
  --panel:  #101219;
  --raised: #171a23;
  --line:   #222634;
  --line-soft: #191c26;

  --ink:   #f4f6fa;
  --dim:   #949cb0;
  /* Etykiety mono i przypisy. Podniesione z #5b6273: tamten dawał 3,3:1
     na tle strony, czyli poniżej progu czytelności (4,5:1) - a to nie jest
     dekoracja, tylko tekst do przeczytania. #757d90 daje 4,9:1 na stronie
     i 4,5:1 na jaśniejszym panelu, więc trzyma próg w obu miejscach. */
  --faint: #757d90;

  /* Fiolet ze znaku firmowego - jedyne miejsce, gdzie strona ma własny
     kolor. Reszta barw pochodzi z produktu (zakładki aplikacji), bo to on
     ma tu nieść kolor, nie dekoracja. */
  --brand: #863bff;
  --spark: #4f8bff;

  /* Kolumna rośnie razem z ekranem. Sztywne 1180 px sprawiało, że na
     monitorze 1440p strona zajmowała mniej niż połowę szerokości, a ramka
     z aplikacją wychodziła na ~610 px - czyli zrzut o treści szerokiej na
     1150 px był skalowany do 53% i tekst w nim robił się nieczytelny.
     Górna granica zostaje, bo wiersz tekstu szerszy niż ~90 znaków czyta
     się gorzej, ale jest znacznie wyżej. */
  --shell: min(92vw, 1860px);
  --ease: cubic-bezier(.22, 1, .36, 1);
}

* { box-sizing: border-box; }

html {
  /* PASEK PRZEWIJANIA JEST PRAWDZIWY I STOI PO PRAWEJ.
     Wcześniej był zdjęty (`scrollbar-width: none`), a jego rolę udawała
     taśma postępu przy LEWEJ krawędzi. Dwa błędy naraz: wskaźnik stał po
     stronie, po której nikt go nie szuka, i nie dało się go złapać - a
     pasek przewijania jest przede wszystkim UCHWYTEM, nie ozdobą. Kto
     chciał przeskoczyć na środek długiej strony, nie miał czym.
     Zamiast udawać, ubieramy prawdziwy: gradient marki na uchwycie,
     ciemna szyna. Działa myszą, gestem i klawiaturą, bo to system go
     rysuje - my podajemy tylko kolory. */
  scrollbar-width: thin;
  scrollbar-color: var(--brand) var(--line-soft);
  scroll-behavior: smooth;
  /* Kotwice nie mogą chować się pod przyklejonym paskiem. */
  scroll-padding-top: 88px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--void);
  color: var(--dim);
  font-family: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Podstawa pisma rośnie z szerokością okna, więc wszystko wyrażone
     w `rem` skaluje się razem z nią. Bez tego na 1440p trzeba było
     powiększać widok w przeglądarce, żeby cokolwiek wygodnie przeczytać. */
  font-size: clamp(16px, 0.28vw + 14.2px, 19px);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* UWAGA: NIE ma tu `overflow-x: hidden` na <body> i nie może być.
   Gdy jedna oś przestaje być `visible`, druga liczy się jako `auto` -
   body staje się wtedy własnym kontenerem przewijania, co:
     * zrywa `position: sticky` względem okna (produkt przestaje się
       przypinać),
     * odbiera sens `scroll(root)` przy taśmie postępu.
   Poziome wylewanie się treści blokujemy więc `overflow: clip` na
   konkretnym elemencie, który je powoduje - `clip` przycina, ale NIE
   tworzy kontenera przewijania. */

h1, h2, h3 {
  margin: 0;
  color: var(--ink);
  font-family: 'Archivo', system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: -0.032em;
  line-height: 1.06;
  text-wrap: balance;
}

/* Nagłówki dostają `balance` (wiersze równej długości), a tekst ciągły
   `pretty` - ta druga wartość pilnuje głównie SIEROT, czyli pojedynczego
   słowa spadającego do ostatniego wiersza. We wstępie do "Modułów" tak
   właśnie zostawało samo "danych." i akapit wyglądał na urwany.
   Przeglądarki bez obsługi po prostu łamią tekst po staremu. */
p { margin: 0; text-wrap: pretty; }
b, strong { color: var(--ink); font-weight: 600; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--spark);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Silniki WebKit/Blink nie znają `scrollbar-color`, więc te same barwy
   trzeba podać drugi raz. To jest wersja AWARYJNA - widoczna tylko wtedy,
   gdy rail.js nie wstał (brak JS, urządzenie dotykowe). */
html::-webkit-scrollbar { width: 11px; height: 11px; }
html::-webkit-scrollbar-track { background: var(--line-soft); }
html::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--brand), var(--spark));
  background-clip: content-box;
  border: 2px solid transparent;
  border-radius: 999px;
}
html::-webkit-scrollbar-corner { background: var(--line-soft); }

/* ── Szyna przewijania (rail.js) ─────────────────────────────────────────
   Natywny pasek znika WYŁĄCZNIE pod klasą `rail-on`, którą dokłada skrypt
   po zbudowaniu własnej szyny. Bez JavaScriptu albo na dotyku zostaje
   natywny - strona nigdy nie jest bez wskaźnika przewijania.
   ────────────────────────────────────────────────────────────────────── */
html.rail-on { scrollbar-width: none; }
html.rail-on::-webkit-scrollbar { width: 0; height: 0; }

/* Podczas ciągnięcia płynne przewijanie musi ustąpić - inaczej dokument
   goni kursor z opóźnieniem i uchwyt „pływa" pod palcem. */
html.rail-dragging { scroll-behavior: auto; }
html.rail-dragging, html.rail-dragging * { user-select: none; }

.rail {
  position: fixed;
  top: 0; bottom: 0;
  right: 0;
  /* Szyna jest cienka, ale POLE TRAFIENIA szerokie - w pasek 3 px nikt nie
     celuje. Zawartość rysuje się wyśrodkowana w tym polu. */
  width: 18px;
  z-index: 95;
  cursor: pointer;
  touch-action: none;
}
.rail.is-hidden { display: none; }

/* Szyna - cienka kreska po środku pola trafienia.

   WSZYSTKIE SZEROKOŚCI SĄ PARZYSTE i to nie jest przypadek. Pole trafienia
   ma 18 px, więc środek wypada na 9 px; element o nieparzystej szerokości
   zaczyna się wtedy na połówce piksela i przeglądarka go zaokrągla, a
   sąsiedni o parzystej - nie. Efekt: kreska 3 px (7,5..10,5) i kropka 6 px
   (6..12) rysowały się względem siebie przesunięte o piksel, co przy
   elementach tej grubości widać od razu jako „krzywe kropki".

     kreska/wypełnienie   4 px  ->   7 .. 11
     kropka               6 px  ->   6 .. 12
     uchwyt spoczynek     8 px  ->   5 .. 13
     uchwyt najechanie   12 px  ->   3 .. 15                              */
.rail::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 4px;
  margin-left: -2px;
  border-radius: 2px;
  background: var(--line-soft);
}

/* POSTĘP: gradient marki od góry do miejsca, w którym jesteś. Tego natywny
   pasek nie umie i to jest powód, dla którego ta szyna istnieje - widać
   nie tylko GDZIE jesteś, ale ile już za Tobą. */
.rail-fill {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 4px;
  margin-left: -2px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--brand), var(--spark));
  transform-origin: top;
  transform: scaleY(0);
  opacity: .55;
}

/* Znaczniki odsłon.
   Kropka gaśnie, gdy sekcja jest za nami albo przed nami; zapala się tylko
   ta, w której jesteśmy.

   OBWÓDKA W KOLORZE TŁA JEST TU KLUCZOWA, nie ozdobna. Kropka leży raz na
   szynie (`--line-soft`), a raz na fioletowym wypełnieniu postępu - żaden
   pojedynczy kolor nie kontrastuje z obiema powierzchniami:

     --faint na szynie 4,1 : 1   na fiolecie 1,3 : 1
     --dim   na szynie 6,2 : 1   na fiolecie 1,9 : 1

   Pierwsza wersja miała `--line` na `--line-soft`, czyli 1,13 : 1 - kropek
   nie było widać w ogóle, dopóki najechanie nie rozjaśniło wypełnienia.
   Pierścień w kolorze strony wycina wokół kropki szczelinę, więc kontrast
   liczy się już tylko względem tła (--dim na --void: 9,4 : 1) i jest ten
   sam nad szyną i nad gradientem. */
.rail-tick {
  position: absolute;
  left: 50%;
  width: 6px; height: 6px;
  margin-left: -3px;
  /* `top` liczy SKRYPT jako środek uchwytu w tym punkcie, więc kropkę
     cofamy o połowę jej wysokości - inaczej stałaby pod nim. */
  margin-top: -3px;
  border-radius: 50%;
  background: var(--dim);
  box-shadow: 0 0 0 2.5px var(--void);
  /* Nad uchwytem: przejeżdżający uchwyt nie ma zasłaniać punktów odniesienia. */
  z-index: 2;
  transition: background .3s var(--ease), transform .3s var(--ease), box-shadow .3s var(--ease);
}

/* Odsłona, w której jesteśmy: jaśniejsza, większa i z poświatą marki -
   trzy sygnały naraz, bo ten jeden punkt ma się znaleźć wzrokiem od razu. */
.rail-tick.is-on {
  background: var(--ink);
  transform: scale(1.45);
  box-shadow: 0 0 0 2.5px var(--void), 0 0 9px rgb(134 59 255 / .85);
}

/* Uchwyt. Wysokość liczy skrypt z proporcji ekranu do dokumentu, więc
   niesie tę samą informację co natywny. */
.rail-grip {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 1;
  width: 8px;
  margin-left: -4px;
  border-radius: 999px;
  background: var(--ink);
  box-shadow: 0 0 0 3px var(--void);
  transition: width .2s var(--ease), margin-left .2s var(--ease), background .2s var(--ease);
}

.rail:hover .rail-grip,
.rail.is-dragging .rail-grip {
  width: 12px;
  margin-left: -6px;
  background: linear-gradient(180deg, var(--brand), var(--spark));
}

.rail:hover .rail-fill,
.rail.is-dragging .rail-fill { opacity: 1; }

/* Podpis odsłony - pojawia się dopiero, gdy ktoś sięgnie po szynę. Stale
   widoczny byłby kolejnym elementem walczącym o uwagę z treścią. */
.rail-label {
  position: absolute;
  top: 0; right: 22px;
  transform-origin: right center;
  padding: 6px 11px;
  border-radius: 8px;
  background: var(--raised);
  border: 1px solid var(--line);
  color: var(--ink);
  font: 500 0.74rem/1 'IBM Plex Mono', ui-monospace, monospace;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  margin-top: -14px;
  transition: opacity .2s var(--ease);
}
.rail:hover .rail-label,
.rail.is-dragging .rail-label { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .rail-tick, .rail-grip, .rail-label { transition: none; }
}

.wrap { width: var(--shell); margin: 0 auto; }

.eyebrow {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
}

.section-h { font-size: clamp(1.9rem, 4vw, 2.9rem); margin: 12px 0 14px; }
.section-p { max-width: 60ch; font-size: 1.02rem; }

/* ── Taśma postępu ─────────────────────────────────────────────────────
   Cienka kreska przy lewej krawędzi, rosnąca razem z przewijaniem.
   Odwołanie do paska paragonu - strona jest o pieniądzach, więc i jej
   wskaźnik pochodzi z tego świata, zamiast być kolejnym paskiem u góry. */
/* ── Pasek górny ───────────────────────────────────────────────────── */
/* Pasek rozciąga się na CAŁĄ szerokość, a kolumnę trzyma dopiero
   `.topbar-inner`. Gdyby szerokość ograniczał sam pasek, rozmycie tła
   kończyłoby się na krawędzi kolumny i treść przewijałaby się widocznie
   obok niego - jeden z tych błędów, które widać dopiero w ruchu. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 80;
  padding: 18px 0;
  background: color-mix(in srgb, var(--void) 82%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}

.topbar-inner {
  width: var(--shell);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 28px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-right: auto;
  color: var(--ink);
  font-family: 'Archivo', sans-serif;
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -0.02em;
}

.brand-mark { color: var(--brand); flex: 0 0 auto; }
.brand-sm { font-size: 0.9rem; margin-right: 0; }

.topnav { display: flex; gap: 26px; font-size: 0.9rem; }

.topnav a {
  position: relative;
  padding: 4px 0;
  color: var(--dim);
  transition: color .2s var(--ease);
}

.topnav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--spark);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform .28s var(--ease);
}

.topnav a:hover { color: var(--ink); }
.topnav a:hover::after { transform: scaleX(1); transform-origin: left; }

/* ── Przyciski ─────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 22px;
  border-radius: 8px;
  border: 1px solid transparent;
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 0.94rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: transform .2s var(--ease), background .2s var(--ease),
              border-color .2s var(--ease), box-shadow .3s var(--ease);
}

.btn svg { transition: transform .25s var(--ease); }
.btn:hover svg { transform: translateX(3px); }

.btn-primary {
  background: var(--ink);
  color: #0b0d12;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .35) inset;
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 34px -12px rgba(134, 59, 255, .65);
}

.btn-ghost {
  border-color: var(--line);
  color: var(--ink);
}

.btn-ghost:hover { border-color: var(--faint); background: var(--panel); }

/* Wciśnięcie: przycisk ustępuje pod palcem NATYCHMIAST (krótki czas w dół),
   a wraca zwykłym, dłuższym przejściem. Selektory z klasą wariantu muszą tu
   być, żeby przebić `:hover` tych wariantów - o kolejności rozstrzyga
   położenie w pliku, bo specyficzność jest równa. */
.btn:active,
.btn-primary:active,
.btn-ghost:active {
  transform: scale(.97);
  transition-duration: .08s;
}

.btn-sm { padding: 9px 16px; font-size: 0.86rem; border-radius: 7px; }
.btn-lg { padding: 16px 30px; font-size: 1rem; }

/* ── Hero ──────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  width: var(--shell);
  margin: 0 auto;
  overflow: clip;
  padding: clamp(64px, 10vh, 120px) 0 clamp(70px, 12vh, 120px);
  /* Na wysokim ekranie (1440p) hero wypelnia pierwszy widok, a tresc
     stoi wysrodkowana w pionie - bez tego tekst gniotl sie u gory,
     a nizej zostawala czarna pustka az do sceny produktu. `min()` pilnuje,
     zeby na telefonie sekcja NIE rozciagala sie ponad wlasna tresc. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: min(calc(100svh - 118px), 1060px);
}

/* Poświaty za hero. `circle closest-side` gaśnie DOKŁADNIE na krawędzi
   własnego pudełka, a pudełka mieszczą się w sekcji w całości - żadna
   krawędź `overflow: clip` nie ma już czego ucinać (na 1440p poprzedni
   gradient kończył się twardą linią). Dwie barwy: fiolet marki za
   nagłówkiem, iskra błękitu po prawej - ten sam duet, co w podkreśleniu. */
.hero::before {
  content: '';
  position: absolute;
  left: 0; top: 2%;
  width: min(64%, 78vh);
  aspect-ratio: 1;
  background: radial-gradient(circle closest-side, rgba(134, 59, 255, .18), transparent);
  pointer-events: none;
  z-index: -1;
}
.hero::after {
  content: '';
  position: absolute;
  right: 2%; top: 8%;
  width: min(46%, 62vh);
  aspect-ratio: 1;
  background: radial-gradient(circle closest-side, rgba(79, 139, 255, .11), transparent);
  pointer-events: none;
  z-index: -1;
}

/* Szerokość ogranicza NAGŁÓWEK, nie całą kolumnę: `max-width` na
   `.hero-inner` ścisnąłby razem z nim akapit i przyciski, bo dziedziczą
   szerokość rodzica. */
.hero-inner { max-width: 60ch; }
.hero h1 {
  max-width: 15ch;
  font-size: clamp(2.7rem, 7.4vw, 5.2rem);
  margin: 18px 0 0;
}

/* Podkreślenie rysowane po wejściu na stronę - jedyny akcent w nagłówku. */
.hl { position: relative; display: inline-block; color: var(--ink); }

.hl::after {
  content: '';
  position: absolute;
  /* Niżej niż linia bazowa, bo inaczej kreska przecina ogonki „ę" i „g"
     - w polskim nagłówku widać to od razu. */
  left: 0; right: 0; bottom: -.06em;
  height: .08em;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand), var(--spark));
  transform: scaleX(0);
  transform-origin: left;
  animation: draw .9s .55s var(--ease) forwards;
}

@keyframes draw { to { transform: scaleX(1); } }

.lede {
  max-width: 52ch;
  margin-top: 26px;
  font-size: clamp(1rem, 1.6vw, 1.16rem);
}

.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }

.hero-note {
  margin-top: 18px;
  font-size: 0.85rem;
  color: var(--faint);
}

/* Wejście treści hero - jedna orkiestrowana sekwencja zamiast rozsypanych
   efektów: kolejne elementy wchodzą z opóźnieniem rosnącym o 90 ms. */
.hero-inner > * {
  animation: rise .8s var(--ease) backwards;
}
.hero-inner > .eyebrow  { animation-delay: .05s; }
.hero-inner > h1        { animation-delay: .14s; }
.hero-inner > .lede     { animation-delay: .26s; }
.hero-inner > .hero-cta { animation-delay: .36s; }
.hero-inner > .hero-note{ animation-delay: .46s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* ── Chipy hero ──────────────────────────────────────────────────────
   Widoczne od 1360 px - nizej kolumna tekstu siega na tyle daleko,
   ze chipy wchodzilyby jej w droge. Kazdy chip nosi kolor swojego
   modulu (`--c`) i lekki wlasny obrot (`--r`), a dryfuje w pionie
   niezaleznym zegarem (ujemne opoznienia rozstrajaja faze) - cztery
   karty oddychaja osobno, jak przypiete magnesy, nie jak jedna plansza. */
.hero-art { display: none; }

@media (min-width: 1360px) {
  .hero-art {
    display: block;
    position: absolute;
    right: 2%;
    top: 50%;
    width: min(30vw, 540px);
    height: 470px;
    transform: translateY(-52%);
    pointer-events: none;
  }

  .chip {
    position: absolute;
    padding: 13px 17px 14px;
    background: color-mix(in srgb, var(--c) 7%, var(--panel));
    border: 1px solid color-mix(in srgb, var(--c) 30%, var(--line));
    border-radius: 12px;
    box-shadow: 0 22px 44px -20px rgba(0, 0, 0, .65);
    transform: rotate(var(--r, 0deg));
    /* Wejscie SAMYM przenikaniem (chip-in), bo transformacje trzyma
       chip-float - dwie animacje transform by sie nadpisywaly. */
    animation:
      chip-in .9s var(--ease) backwards,
      chip-float 7s ease-in-out infinite alternate;
  }

  .chip span {
    display: block;
    font: 500 0.66rem/1 'IBM Plex Mono', ui-monospace, monospace;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--c) 70%, var(--ink));
    margin-bottom: 6px;
  }
  .chip span::before {
    content: "";
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    margin-right: 7px;
    background: var(--c);
  }
  .chip b { font-size: 0.93rem; color: var(--ink); font-weight: 600; white-space: nowrap; }

  /* Miniaturowy pasek postepu w chipie Celow - kawalek PRAWDZIWEGO
     interfejsu, nie sama typografia. Reset stylu etykiety, bo bazowy
     `.chip span` to mono-naglowek z kropka. */
  .chip .chip-bar {
    display: block;
    height: 3px;
    margin: 9px 0 0;
    border-radius: 2px;
    background: var(--line);
    overflow: hidden;
  }
  .chip .chip-bar::before { content: none; }
  .chip .chip-bar i {
    display: block;
    height: 100%;
    border-radius: 2px;
    background: var(--c);
  }

  .chip:nth-child(1) { top: 2%;  right: 6%;  animation-delay: .5s,  -1s; }
  .chip:nth-child(2) { top: 30%; right: 38%; animation-delay: .62s, -3s; }
  .chip:nth-child(3) { top: 56%; right: 3%;  animation-delay: .74s, -5s; }
  .chip:nth-child(4) { top: 82%; right: 30%; animation-delay: .86s, -2s; }

  @keyframes chip-in { from { opacity: 0; } }
  @keyframes chip-float {
    from { transform: rotate(var(--r, 0deg)) translateY(-5px); }
    to   { transform: rotate(var(--r, 0deg)) translateY(6px); }
  }
}

/* ── Zachęta do przewijania ──────────────────────────────────────────
   Trzy chevronki przy prawej krawędzi, wyśrodkowane w pionie - bez
   pudełka, bez tekstu, sam gest „niżej jest więcej". Towarzyszą przez
   CAŁĄ stronę, ale widać je dopiero po ~5 s bezruchu (html.show-nudge,
   dokłada reveal.js) - pokazują się dokładnie tam, gdzie czytelnik
   utknął. Każdy ruch scrolla je chowa; fala opacity spływa w dół, więc
   kierunek czyta się bez słów. */
.scroll-nudge {
  position: fixed;
  /* Odsuniete od szyny przewijania po prawej. */
  right: clamp(26px, 2.6vw, 40px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 12px 10px;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--dim);
  opacity: 0;
  visibility: hidden;
  transition: opacity .7s var(--ease), visibility .7s, color .2s var(--ease);
}
html.show-nudge .scroll-nudge { opacity: 1; visibility: visible; }
.scroll-nudge:hover { color: var(--ink); }

/* Poswiata pod strzalkami - fioletowy owal za plecami, zeby zacheta
   odcinala sie od kazdego tla (sekcje maja rozne odcienie czerni).
   `closest-side` gasnie przed krawedzia pudelka - bez cietych linii. */
.scroll-nudge::before {
  content: '';
  position: absolute;
  inset: -34px -30px;
  border-radius: 50%;
  background: radial-gradient(circle closest-side, rgba(134, 59, 255, .30), transparent);
  z-index: -1;
  pointer-events: none;
}

.scroll-nudge svg {
  display: block;
  width: 32px;
  height: 15px;
  animation: nudge-wave 1.7s ease-in-out infinite;
}
.scroll-nudge svg:nth-child(2) { animation-delay: .16s; }
.scroll-nudge svg:nth-child(3) { animation-delay: .32s; color: var(--brand); }

@keyframes nudge-wave {
  0%, 55%, 100% { opacity: .3; transform: translateY(0); }
  25% { opacity: 1; transform: translateY(4px); }
}

/* ═══ SCENA: PRODUKT PRZYPIĘTY ══════════════════════════════════════════
   Sekcja jest wysoka (4 ekrany), a jej zawartość przyklejona. Dzięki temu
   ramka aplikacji zostaje na widoku, a przewijanie przesuwa NARRACJĘ, nie
   produkt. Oś czasu `--stage` wystawia cała sekcja; wszystkie animacje
   w środku odwołują się do niej po nazwie, więc mają wspólny zegar i nie
   mogą się rozjechać.
   ═══════════════════════════════════════════════════════════════════════ */
.stage {
  position: relative;
  view-timeline-name: --stage;
  view-timeline-axis: block;
  /* DROGA PRZEWIJANIA SCENY.
     Sekcja jest przypięta przez `.stage-sticky` o wysokości 100vh, więc
     przewijanie „w miejscu" trwa tyle, ile WYSOKOŚĆ SEKCJI MINUS ten
     jeden ekran:

       460vh - 100vh = 360vh   (po 90vh na odsłonę - za dużo)
       250vh - 100vh = 150vh   (po 30vh na odsłonę)

     Odsłony po niemal całym ekranie przewijania znaczyły, że ktoś, kto
     chciał zobaczyć resztę strony, musiał przekręcić kółko kilkanaście razy
     przez jedną sekcję. Trzy razy krócej wystarcza, żeby każdą odsłonę dało
     się przeczytać, i nie zamienia produktu w tunel.

     PRZY DOKŁADANIU ODSŁONY ROŚNIE TA LICZBA, o 30vh na sztukę - inaczej
     pięć odsłon dzieli między siebie drogę wyliczoną dla czterech i każda
     przelatuje o ćwierć szybciej, niż da się ją przeczytać.

     Skryptu ani osi `view-timeline` to nie dotyka: obie liczą postęp jako
     UŁAMEK przebytej sekcji, więc skalują się same. */
  min-height: 250vh;
}

.stage-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  /* `clip`, nie `hidden`: przycina tak samo, ale nie robi z tej sekcji
     kontenera przewijania - a ten potrafi zaskoczyć, gdy przeglądarka
     przewinie do niego element po ustawieniu na nim fokusu. */
  overflow: clip;
}

.stage-grid {
  width: var(--shell);
  margin: 0 auto;
  display: grid;
  /* Ramka dostaje wyraźnie więcej miejsca niż kolumna opisu: to ona jest
     tutaj produktem, a tekst tylko go opisuje. Płaskie okno 16:9 przestało
     się opierać o wysokość ekranu, więc mogło dostać jeszcze więcej. */
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(32px, 6vw, 80px);
  align-items: center;
}

/* ── Panele opisowe ──────────────────────────────────────────────────
   Wszystkie leżą NA SOBIE (grid 1×1) i wymieniają się w tej samej
   ramce - inaczej wysokość kolumny skakałaby przy każdej zmianie tekstu
   i cała scena drgałaby w pionie. */
.panels { display: grid; }
.panels > * { grid-area: 1 / 1; }

.panel { align-self: center; }

.panel-num {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  color: var(--brand);
}

.panel h2 { font-size: clamp(1.55rem, 3.1vw, 2.35rem); margin: 14px 0 16px; }
.panel > p { max-width: 46ch; }

.panel-list {
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-size: 0.92rem;
}

.panel-list li {
  position: relative;
  padding-left: 22px;
  color: var(--dim);
}

.panel-list li::before {
  content: '';
  position: absolute;
  left: 0; top: .62em;
  width: 9px; height: 1px;
  background: var(--faint);
}

/* ── Ramka z aplikacją ─────────────────────────────────────────────── */
/* Zapas na wskaźnik kroku pod ramką: leży on `absolute`, a scena ma
   przycięcie, więc bez tego dopełnienia zostałby ucięty. */
.device-wrap {
  position: relative;
  padding-bottom: 34px;
  width: 100%;
  margin-left: auto;
  /* Na NISKIM oknie (laptop 1366x768) ramka o szerokości z siatki byłaby
     wyższa niż ekran i scena by ją ucięła. Tutaj ograniczamy ją wysokością
     okna, przeliczoną przez proporcję - dopiero mniejsza z dwóch wartości
     decyduje. `svh`, bo na telefonie `vh` liczy się do paska adresu, który
     potrafi zniknąć. */
  max-width: calc((100svh - 165px) * 1.778);
}

/* Poswiata pod ramka: produkt lezy na swietle, nie na plaskiej czerni.
   `closest-side` gasnie przed krawedzia wlasnego pudelka, wiec zadna
   krawedz niczego nie utnie (lekcja z poswiat hero). */
.device-wrap::before {
  content: '';
  position: absolute;
  inset: -14% -9% 0;
  background:
    radial-gradient(circle closest-side at 32% 40%, rgba(134, 59, 255, .16), transparent),
    radial-gradient(circle closest-side at 76% 64%, rgba(79, 139, 255, .12), transparent);
  z-index: -1;
  pointer-events: none;
}

.device {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  overflow: hidden;
  box-shadow:
    0 50px 100px -40px rgba(0, 0, 0, .9),
    0 0 0 1px rgba(255, 255, 255, .03) inset;
  /* Lekkie odchylenie w perspektywie: produkt wygląda jak sfotografowany,
     a nie wklejony. Prostuje się przy przewijaniu (animacja niżej). */
  transform: perspective(1600px) rotateY(-7deg) rotateX(3deg);
  transform-origin: center left;
}

.device-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--raised);
}

.dot { width: 8px; height: 8px; border-radius: 50%; background: #2b3040; }

.device-url {
  margin-left: 12px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  color: var(--faint);
}

/* Ekrany leżą na sobie i wymieniają się razem z panelami. */
.screens {
  display: grid;
  /* 16:9 - proporcja prawdziwego okna przeglądarki i dokładnie ta sama,
     co zrzutów. Zgranie tych dwóch liczb sprawia, że obraz wchodzi w ramkę
     bez przycinania czegokolwiek. */
  aspect-ratio: 16 / 9;
  background: #0a0a0d;
  /* Cztery ekrany leżą na sobie i mają różną wysokość treści. Bez
     przycięcia najwyższy z nich rozpychałby ramkę, a przy zmianie
     proporcji - wystawał poza nią. */
  overflow: hidden;
}

/* Zrzuty leżą na sobie w jednej komórce siatki i wymieniają się razem
   z panelami opisowymi.
   `.screen` to <picture>, więc rozmiar i przycięcie muszą trafić na <img>
   w środku - sam <picture> jest tylko opakowaniem, które wybiera źródło. */
.screen {
  grid-area: 1 / 1;
  display: block;
  width: 100%;
  height: 100%;
  /* Ukrywanie nieaktywnych odslon robi WYLACZNIE `.stage-js .screen`
     (klasa wymaga dzialajacego JS) - bazowo ekran jest widoczny, wiec
     przegladarka bez skryptow niczego nie gubi. */
}

.screen img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* ── Wskaźnik kroku ────────────────────────────────────────────────── */
.steps {
  position: absolute;
  left: 0; bottom: 4px;
  display: flex;
  gap: 6px;
}

.steps span {
  width: 26px; height: 2px;
  border-radius: 1px;
  background: var(--line);
  overflow: hidden;
}

.steps span::after {
  content: '';
  display: block;
  height: 100%;
  background: var(--spark);
  transform: scaleX(0);
  transform-origin: left;
}

/* Kreski krokow w odcieniach fioletu: od barwy marki do iskry blekitu -
   jeden rod barw, cztery odcienie, zadnego jarmarku kolorow. */
.steps span[data-step="1"]::after { background: #863bff; }
.steps span[data-step="2"]::after { background: #7a5cff; }
.steps span[data-step="3"]::after { background: #677bff; }
.steps span[data-step="4"]::after { background: #4f8bff; }
.steps span[data-step="5"]::after { background: #3f9bff; }

/* ═══ ANIMACJE STEROWANE PRZEWIJANIEM ═══════════════════════════════════
   `animation-duration: auto` jest tu obowiązkowe: przy osi przewijania
   czas w sekundach nie znaczy nic - zegarem jest pozycja, nie stoper.
   `both` sprawia, że stan trzyma się także po wyjściu z zakresu, więc nic
   nie „odskakuje" przy przewijaniu w górę.
   ═══════════════════════════════════════════════════════════════════════ */
@supports (animation-timeline: view()) {

  /* Parallax chipow hero: przez pierwszy ekran przewijania kontener
     zyskuje +54 px wzgledem tresci, wiec chipy odplywaja WOLNIEJ niz
     tekst - warstwa blizej tla. Dryf pojedynczych chipow (chip-float)
     siedzi na samych chipach, wiec sie nie gryza. */
  .hero-art {
    animation: art-drift linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 100vh;
  }
  @keyframes art-drift {
    from { transform: translateY(-52%); }
    to   { transform: translateY(-52%) translateY(54px); }
  }

  .topbar {
    animation: bar linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 120px;
  }
  @keyframes bar { to { border-bottom-color: var(--line-soft); } }

  /* SCENY PRODUKTU tu celowo NIE MA. Scrubbowane przelaczanie odslon
     mialo stany posrednie: scroll zatrzymany w polowie przejscia
     zostawial dwie polprzezroczyste odslony naraz (a wersja bez nakladek
     - puste okno miedzy odslonami). Scene prowadzi stage.js WSZEDZIE:
     zmiana data-step wyzwala zwykle przejscia CSS (0,45 s), ktore zawsze
     koncza sie jedna w pelni widoczna odslona - jak w Firefoksie. */

  /* Wejscia sekcji NIE mieszkaja juz tutaj. Byly zszyte z osia
     przewijania, ale wtedy tempo animacji dyktuje kolko myszy - przy
     zwyklym przewijaniu caly ruch mijal w ulamku sekundy i wygladal,
     jakby go nie bylo. Teraz gra je zegar, a wyzwala obserwator
     widocznosci - patrz blok "WEJSCIA SEKCJI" nizej i reveal.js. */

}

/* ═══ WEJŚCIA SEKCJI: OBSERWATOR + ZEGAR ═══════════════════════════════
   Wejscia elementow gra CZAS (0,5-0,7 s), a wyzwala obserwator
   widocznosci (reveal.js dopisuje `.is-seen` przy pierwszym wejsciu
   w kadr). Wczesniej byly zszyte z osia przewijania - ale wtedy tempo
   ruchu dyktuje szybkosc kolka myszy: przy zwyklym przewijaniu animacja
   mijala w ulamku sekundy i wygladala, jakby jej nie bylo. Zegar
   gwarantuje, ze wejscie widac zawsze tak samo. Dziala tez w Firefoksie.

   Bezpieczniki:
   * klase `rv` doklada skrypt w <head> TYLKO gdy jest JS
     i IntersectionObserver - bez nich nic nie jest ukrywane;
   * caly blok siedzi w `prefers-reduced-motion: no-preference`, wiec
     przy ograniczonym ruchu elementy stoja od razu, w pelni widoczne.
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {

  /* Stany startowe - wylacznie pod `html.rv`. */
  .rv .why .wrap > .eyebrow,
  .rv .why .wrap > .section-h,
  .rv .why .wrap > .section-p,
  .rv .pcard,
  .rv .cmp-scroll,
  .rv .faq,
  .rv .pillar,
  .rv .case-lede,
  .rv .bill,
  .rv .split-note,
  .rv .who,
  .rv .case-q,
  .rv .case-row,
  .rv .case-foot,
  .rv .rz-wrap,
  .rv .features .feat,
  .rv .trust-inner > *,
  .rv .final-inner > * { opacity: 0; }

  .rv .hl-scroll::after { transform: scaleX(0); transform-origin: left; }
  .rv .case-row.is-us::before { transform: scaleY(0); transform-origin: top; }

  /* Naglowek sekcji "Dlaczego my" - trzy elementy obserwowane osobno. */
  .why .wrap > .eyebrow.is-seen,
  .why .wrap > .section-h.is-seen,
  .why .wrap > .section-p.is-seen { animation: rise-t .6s var(--ease) both; }

  /* Podkreslenie gradientem rysuje sie chwile po wjechaniu naglowka. */
  .hl-scroll.is-seen::after { animation: drawx-t .55s .35s var(--ease) both; }

  /* Filary: samym rozjasnieniem (kontener przycina - przesuniecie
     odslanialoby jasne szczeliny), kaskada od lewej. */
  .pillars.is-seen .pillar { animation: fade-t .55s var(--ease) both; }
  .pillars.is-seen .pillar:nth-child(2) { animation-delay: .12s; }
  .pillars.is-seen .pillar:nth-child(3) { animation-delay: .24s; }

  .case-lede.is-seen { animation: rise-t .55s var(--ease) both; }

  /* Pasek kwoty buduje sie w kolejnosci czytania: rachunek, podpis,
     segmenty jeden po drugim, akcent Twojej czesci na koncu. */
  .split.is-seen .bill { animation: rise-t .55s var(--ease) both; }
  .split.is-seen .split-note { animation: fade-t .5s .15s var(--ease) both; }
  .split.is-seen .who { animation: drop-t .5s var(--ease) both; }
  .split.is-seen .who:nth-child(1) { animation-delay: .28s; }
  .split.is-seen .who:nth-child(2) { animation-delay: .4s; }
  .split.is-seen .who:nth-child(3) { animation-delay: .52s; }
  .split.is-seen .who:nth-child(4) { animation-delay: .64s; }
  .split.is-seen .who.is-me {
    animation: drop-t .5s .28s var(--ease) both, me-light-t .6s .95s var(--ease) both;
  }

  .case-q.is-seen { animation: rise-t .55s var(--ease) both; }

  /* Wiersze porownania kaskada; wiersz OneValuate dostaje final:
     kreska akcentu rysuje sie wzdluz, tlo nabiera barwy na koncu. */
  .case-rows.is-seen .case-row { animation: rise-t .55s var(--ease) both; }
  .case-rows.is-seen .case-row:nth-child(2) { animation-delay: .1s; }
  .case-rows.is-seen .case-row:nth-child(3) { animation-delay: .2s; }
  .case-rows.is-seen .case-row.is-us {
    animation: rise-t .55s .3s var(--ease) both, us-in-t .6s .8s var(--ease) both;
  }
  .case-rows.is-seen .case-row.is-us::before { animation: drawy-t .45s .85s var(--ease) both; }

  .case-foot.is-seen { animation: fade-t .6s .1s var(--ease) both; }
  .rz-wrap.is-seen { animation: fade-t .6s var(--ease) both; }

  /* Kafelki modulow: fala rozjasnien. */
  .grid.is-seen .feat { animation: fade-t .5s var(--ease) both; }
  .grid.is-seen .feat:nth-child(2) { animation-delay: .06s; }
  .grid.is-seen .feat:nth-child(3) { animation-delay: .12s; }
  .grid.is-seen .feat:nth-child(4) { animation-delay: .18s; }
  .grid.is-seen .feat:nth-child(5) { animation-delay: .24s; }
  .grid.is-seen .feat:nth-child(6) { animation-delay: .3s; }
  .grid.is-seen .feat:nth-child(7) { animation-delay: .36s; }
  .grid.is-seen .feat:nth-child(8) { animation-delay: .42s; }

  /* Plany. Wolniej i z wieksza przerwa niz kafelki modulow (0,12 s zamiast
     0,06 s): kart jest trzy, kazda niesie decyzje, a nie jedno haslo -
     kaskada ma prowadzic wzrok po kolei, a nie mignac. Wyrozniona wchodzi
     jako druga, wiec ta z brzegu nie zostaje sama na koncu. */
  .pcards.is-seen .pcard { animation: rise-t .6s var(--ease) both; }
  .pcards.is-seen .pcard:nth-child(2) { animation-delay: .12s; }
  .pcards.is-seen .pcard:nth-child(3) { animation-delay: .24s; }

  /* Poswiata pod wyrozniona karta rozpala sie PO jej wejsciu - ostatni
     gest sekwencji, ktory mowi "ta". Reszta kart nie ma czego rozpalac. */
  .pcards.is-seen .pcard.is-top::after {
    animation: pcard-glow .9s var(--ease) .5s both;
  }
  @keyframes pcard-glow { from { opacity: 0; } to { opacity: 1; } }

  /* Cena doliczana wzrokiem: liczba wjezdza chwile po karcie, wiec oko
     laduje na niej, a nie na nazwie planu. */
  .pcards.is-seen .pcard-price strong { animation: rise-t .5s var(--ease) both; }
  .pcards.is-seen .pcard:nth-child(2) .pcard-price strong { animation-delay: .2s; }
  .pcards.is-seen .pcard:nth-child(3) .pcard-price strong { animation-delay: .32s; }

  /* Podstrona porownania: tabela wjezdza jako calosc (jeden przedmiot,
     nie dwadziescia wierszy migajacych po kolei), pytania kaskada. */
  .cmp-scroll.is-seen { animation: rise-t .6s var(--ease) both; }
  .faq-list.is-seen .faq { animation: fade-t .5s var(--ease) both; }
  .faq-list.is-seen .faq:nth-child(2) { animation-delay: .08s; }
  .faq-list.is-seen .faq:nth-child(3) { animation-delay: .16s; }
  .faq-list.is-seen .faq:nth-child(4) { animation-delay: .24s; }

  .trust-inner.is-seen > * { animation: rise-t .6s var(--ease) both; }
  .trust-inner.is-seen > *:nth-child(2) { animation-delay: .12s; }

  .final-inner.is-seen > * { animation: rise-t .6s var(--ease) both; }
  .final-inner.is-seen > *:nth-child(2) { animation-delay: .1s; }
  .final-inner.is-seen > *:nth-child(3) { animation-delay: .2s; }

  @keyframes rise-t {
    from { opacity: 0; transform: translateY(22px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes fade-t { from { opacity: 0; } to { opacity: 1; } }
  @keyframes drop-t {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes drawx-t { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  @keyframes drawy-t { from { transform: scaleY(0); } to { transform: scaleY(1); } }

  /* Akcenty startuja z neutralnych wartosci sasiadow; stan koncowy to
     style bazowe klas, wiec wartosci akcentu mieszkaja w jednym miejscu. */
  @keyframes me-light-t {
    from {
      border-color: color-mix(in srgb, var(--brand) 30%, var(--line));
      background: color-mix(in srgb, var(--brand) 9%, var(--raised));
      box-shadow: 0 0 24px -8px rgba(134, 59, 255, 0);
    }
  }
  @keyframes us-in-t { from { background: transparent; } }
}

/* ── Możliwości ────────────────────────────────────────────────────── */
.features { padding: clamp(90px, 15vh, 170px) 0; }

.grid {
  margin-top: 52px;
  display: grid;
  /* Liczba kolumn USTALONA, nie `auto-fit`. Kafelków jest osiem, więc
     dzielą się równo tylko na 4, 2 albo 1. Przy `auto-fit` na szerokim
     ekranie wychodziło ich siedem w rzędzie i ósmy zostawał sam w drugim -
     rząd urwany w połowie wygląda jak błąd, a nie jak układ. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  overflow: hidden;
}

/* Kafelki rozdziela SZCZELINA na tle w kolorze kreski, a nie ramka na
   każdym z osobna - dzięki temu siatka czyta się jak jedna tabela, a nie
   jak osiem osobnych kartek. */
.feat {
  position: relative;
  padding: 26px 24px 28px;
  background: var(--void);
  transition: background .3s var(--ease);
}

.feat:hover { background: var(--panel); }

/* Ikona w kolorze modulu zamiast samej kreski - niesie i kolor,
   i znaczenie. Na najechanie lekko sie unosi, ten sam gest co kiedys
   wydluzajaca sie kreska. */
.feat-icon {
  display: block;
  width: 22px; height: 22px;
  margin-bottom: 14px;
  color: var(--c);
  transition: transform .35s var(--ease);
}

.feat:hover .feat-icon { transform: translateY(-2px) scale(1.08); }

.feat h3 { font-size: 1.06rem; margin-bottom: 7px; letter-spacing: -0.02em; }
.feat p { font-size: 0.88rem; }

@media (max-width: 1180px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .grid { grid-template-columns: minmax(0, 1fr); } }


/* ── Plany ──────────────────────────────────────────────────────────────
   Karty cenowe, a NIE siatka ze szczelina 1 px jak w modulach. Tamten idiom
   sluzy porownaniu wiersz po wierszu - tu kazda karta ma byc osobnym
   przedmiotem, ktory da sie wybrac. Stad odstep miedzy nimi i wlasna ramka
   kazdej.

   Wyroznienie idzie SWIATLEM, nie rozmiarem: obwodka z gradientu marki
   (ten sam, ktory podkresla slowa kluczowe w naglowkach) plus poswiata
   u dolu, jak w karcie `.case`. Karta wieksza od sasiadow psuje porownanie
   wierszy, o ktore w tym ukladzie chodzi.
   ────────────────────────────────────────────────────────────────────── */
.plans { padding: clamp(90px, 15vh, 170px) 0; }
/* Naglowek trzyma te sama kolumne co karty - inaczej wisialby nad nimi
   rozstrzelony na cala szerokosc strony. */
.plans .wrap > .eyebrow,
.plans .wrap > .section-h,
.plans .wrap > .section-p { width: min(100%, 1140px); margin-inline: auto; }
.plans .section-h { max-width: 22ch; }
.plans .section-p { max-width: 58ch; }

.pcards {
  /* WEZSZE NIZ RESZTA STRONY. `--shell` idzie do 1860 px, bo tam mieszka
     ramka z aplikacja - ale karta cenowa czytana na 600 px szerokosci
     rozjezdza sie: trzy slowa w wierszu, reszta pustka. Tu liczy sie
     zwarta kolumna, w ktorej wzrok obejmuje wszystkie trzy naraz. */
  width: min(100%, 1140px);
  margin: clamp(40px, 6vh, 60px) auto 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
  /* Karty roznej dlugosci maja stac na jednej linii u gory. */
  align-items: stretch;
}

.pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 34px 30px 30px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  /* Poswiaty wychodza poza karte - `clip` przycina bez tworzenia
     kontenera przewijania. */
  overflow: clip;
  isolation: isolate;
  transition: border-color .3s var(--ease), transform .3s var(--ease);
}

.pcard:hover { border-color: var(--faint); transform: translateY(-3px); }

/* KARTA WYROZNIONA. Obwodka z gradientu robiona dwoma tlami: jedno maluje
   wnetrze do krawedzi wypelnienia, drugie gradient do krawedzi ramki -
   ramka jest przezroczysta, wiec przeswituje przez nia gradient. Zwykly
   `border-image` nie umie zaokraglen. */
.pcard.is-top {
  background:
    linear-gradient(var(--panel), var(--panel)) padding-box,
    linear-gradient(155deg, var(--brand), var(--spark) 45%, var(--line) 80%) border-box;
  border: 1px solid transparent;
}
.pcard.is-top:hover { transform: translateY(-3px); }

/* Poswiata u dolu wyroznionej karty - ten sam gest co w `.case`. */
.pcard.is-top::after {
  content: "";
  position: absolute;
  left: -20%; right: -20%; bottom: -55%;
  aspect-ratio: 1;
  background: radial-gradient(closest-side, rgb(134 59 255 / .17), transparent 72%);
  pointer-events: none;
  z-index: -1;
}
/* Poświata siedzi POD treścią przez `z-index: -1`, a `isolation: isolate`
   na karcie sprawia, że nie przebija się pod jej własne tło.
   Poprzednio treść wynoszono nad poświatę regułą `.pcard.is-top > *`
   z `position: relative` - a ta miała swoistość (0,2,0) i biła
   `.pcard-badge` (0,1,0). Etykieta traciła `position: absolute` i zamiast
   narożnika rozlewała się paskiem na całą szerokość karty, spychając
   nazwę planu. Reguła na `*` prawie zawsze trafia coś, czego nie miała
   trafić - stąd tu jej nie ma. */

.pcard-badge {
  position: absolute;
  top: 16px; right: 16px;
  z-index: 2;
  padding: 6px 11px;
  border-radius: 999px;
  background: linear-gradient(100deg, var(--brand), var(--spark));
  color: #fff;
  font: 600 0.62rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Nazwa planu jako etykieta w kolorze - ten sam nosnik co `.pillar-n`. */
.pcard-name {
  font: 600 0.72rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c);
  margin-bottom: 18px;
}

.pcard-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 12px;
}
.pcard-price strong {
  font-family: Archivo, system-ui, sans-serif;
  font-size: clamp(2.8rem, 4.6vw, 3.5rem);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 0.9;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.pcard-price span { font-size: 0.95rem; color: var(--dim); }
.pcard-price i { font-style: normal; color: var(--faint); font-size: 0.85rem; }

.pcard-lede {
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--dim);
  padding-bottom: 24px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--line-soft);
}

/* "Wszystko z planu X, plus:" - wzorzec, ktory skraca liste i sprawia, ze
   roznica miedzy planami czyta sie od razu. Bez niego kazda karta musi
   powtarzac wszystko od poczatku i zadna nie mowi, co dochodzi. */
/* Wiersz stoi w KAZDEJ karcie, takze w darmowej - bez niego jej lista
   zaczynala sie wyzej niz dwie pozostale i trzy kolumny nie trzymaly
   jednej linii. */
.pcard-from {
  font-size: 0.82rem;
  color: var(--faint);
  margin-bottom: 14px;
}

.pcard-list {
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  display: grid;
  gap: 12px;
  /* Lista rosnie, przycisk i podpis zostaja przy dole - inaczej trzy karty
     o roznej liczbie punktow maja przyciski na trzech wysokosciach. */
  flex: 1;
  align-content: start;
}

.pcard-list li {
  position: relative;
  padding-left: 26px;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--dim);
}

/* Ptaszek rysowany geometria, nie znakiem - znak zalezy od kroju i na
   czesci systemow wychodzi kolorowe emoji. */
.pcard-list li::before {
  content: "";
  position: absolute;
  left: 3px; top: 0.36em;
  width: 10px; height: 5px;
  border-left: 1.7px solid var(--c);
  border-bottom: 1.7px solid var(--c);
  transform: rotate(-45deg);
  opacity: .9;
}

/* Punkt, dla ktorego bierze sie ten plan - jasniejszy i grubszy. */
.pcard-list li.is-key { color: var(--ink); font-weight: 500; }

.pcard-cta { width: 100%; justify-content: center; }

.pcard-foot {
  margin-top: 12px;
  text-align: center;
  font-size: 0.76rem;
  color: var(--faint);
}

.plans-note {
  margin: 34px auto 0;
  max-width: 66ch;
  text-align: center;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--dim);
}
.plans-note strong { color: var(--ink); font-weight: 500; }

.plans-more { margin-top: 18px; text-align: center; }
.plans-more a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.88rem;
  color: var(--dim);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.plans-more a:hover { color: var(--ink); border-color: var(--faint); }
.plans-more svg { transition: transform .25s var(--ease); }
.plans-more a:hover svg { transform: translateX(3px); }

@media (max-width: 1020px) { .pcards { grid-template-columns: minmax(0, 1fr); max-width: 520px; margin-inline: auto; } }

/* ── Porownanie planow (plany.html) ─────────────────────────────────────
   Tabela, a nie trzy kolumny kart. Karty na stronie glownej odpowiadaja na
   "ktory wybrac"; tutaj czlowiek przyszedl sprawdzic KONKRET, wiec liczy sie
   mozliwosc przejechania wzrokiem po wierszu i porownania trzech wartosci.
   Do tego sluzy tabela i nic jej w tym nie zastapi.
   ────────────────────────────────────────────────────────────────────── */
.cmp { padding: clamp(70px, 11vh, 130px) 0 clamp(50px, 8vh, 90px); }
.cmp .section-h { max-width: 20ch; }
.cmp .section-p { max-width: 62ch; margin-bottom: 46px; }

/* Poziome przewijanie zamknięte w otoczce - strona nigdy nie jedzie w bok. */
.cmp-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--void);
  -webkit-overflow-scrolling: touch;
}

.cmp-table {
  width: 100%;
  min-width: 660px;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.cmp-table th,
.cmp-table td {
  padding: 15px 20px;
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
}
.cmp-table tbody tr:last-child th,
.cmp-table tbody tr:last-child td { border-bottom: none; }

/* Trzy kolumny planow rowne; pierwsza bierze reszte. */
.cmp-table thead th:not(:first-child),
.cmp-table tbody td { width: 17%; text-align: center; }

.cmp-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  vertical-align: top;
  /* Nieprzezroczyste tlo jest tu WYMAGANE, nie kosmetyczne: przy przyklejonym
     naglowku wiersze przejezdzaja pod nim i przez polprzezroczyste tlo widac
     by je bylo nachodzace na nazwy planow. */
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  padding-top: 24px;
  padding-bottom: 22px;
}
.cmp-table thead th:first-child { background: var(--panel); }

/* Naglowek kolumny to MINI-KARTA planu, nie podpis: nazwa w kolorze, cena
   duza i przycisk pod nia. Kto doscrollowal do dwudziestego wiersza, ma
   miec decyzje pod reka, a nie wracac na gore po przycisk. */
.cmp-name {
  display: block;
  font: 600 0.68rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c, var(--ink));
  margin-bottom: 10px;
}

.cmp-price {
  display: block;
  margin-bottom: 12px;
  font-size: 0.82rem;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.cmp-price strong {
  font-family: Archivo, system-ui, sans-serif;
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--ink);
  margin-right: 2px;
}
.cmp-price i { font-style: normal; color: var(--faint); font-size: 0.76rem; }

.cmp-cta { width: 100%; justify-content: center; }

/* Kolumna wyrozniona ciagnie sie przez CALA tabele - pionowa smuga, ktora
   prowadzi wzrok w dol i nie gubi sie miedzy grupami wierszy. */
.cmp-table thead th.is-featured {
  background:
    linear-gradient(180deg, rgb(134 59 255 / .16), transparent),
    var(--raised);
  box-shadow: inset 1px 0 0 rgb(134 59 255 / .3), inset -1px 0 0 rgb(134 59 255 / .3);
}
.cmp-table td.is-featured {
  background: rgb(134 59 255 / 0.05);
  box-shadow: inset 1px 0 0 rgb(134 59 255 / .16), inset -1px 0 0 rgb(134 59 255 / .16);
}

/* Naglowek grupy wierszy. Etykieta mono w wersaliku - ten sam nosnik
   struktury co `.eyebrow` w sekcjach strony glownej. */
.cmp-group th {
  padding-top: 26px;
  padding-bottom: 10px;
  font: 500 0.68rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  background: var(--void);
  border-bottom: 1px solid var(--line);
}

.cmp-table tbody th[scope="row"] {
  font-weight: 400;
  color: var(--ink);
  line-height: 1.45;
}
.cmp-table tbody th[scope="row"] small {
  display: block;
  margin-top: 3px;
  font-size: 0.78rem;
  color: var(--faint);
}
.cmp-table small.inline { display: inline; margin: 0; font-size: 0.76rem; color: var(--faint); }

.cmp-table tbody tr:not(.cmp-group):hover td,
.cmp-table tbody tr:not(.cmp-group):hover th { background: var(--panel); }
.cmp-table tbody tr:not(.cmp-group):hover td.is-featured { background: var(--raised); }

.num {
  font: 500 0.98rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.num.accent { color: var(--brand); }
.all { color: var(--dim); font-size: 0.85rem; }

/* Ptaszek i krzyzyk rysowane geometria, nie znakiem: znak zalezy od kroju
   i na czesci systemow wychodzi kolorowe emoji. */
.yes, .no { display: inline-block; position: relative; width: 14px; height: 14px; }
.yes::before {
  content: "";
  position: absolute;
  left: 2px; top: 2px;
  width: 10px; height: 6px;
  border-left: 1.8px solid #22c55e;
  border-bottom: 1.8px solid #22c55e;
  transform: rotate(-45deg);
}
.no::before {
  content: "";
  position: absolute;
  left: 3px; top: 3px;
  width: 9px; height: 9px;
  background:
    linear-gradient(to bottom right, transparent 43%, var(--faint) 43%, var(--faint) 57%, transparent 57%),
    linear-gradient(to bottom left,  transparent 43%, var(--faint) 43%, var(--faint) 57%, transparent 57%);
}

.cmp-back { margin-top: 30px; text-align: center; }
.cmp-back a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.88rem;
  color: var(--dim);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.cmp-back a:hover { color: var(--ink); border-color: var(--faint); }
.cmp-back svg { transition: transform .25s var(--ease); }
.cmp-back a:hover svg { transform: translateX(-3px); }

/* Podpowiedz o przewijaniu w bok - tylko tam, gdzie tabela sie nie miesci. */
@media (max-width: 720px) {
  .cmp-scroll { position: relative; }
  .cmp-scroll::after {
    content: "Przewiń w bok, żeby zobaczyć wszystkie plany";
    display: block;
    padding: 10px 18px;
    font-size: 0.74rem;
    color: var(--faint);
    border-top: 1px solid var(--line-soft);
  }
}

/* ── Pytania pod tabela ─────────────────────────────────────────────── */
.cmp-faq { padding: 0 0 clamp(90px, 15vh, 170px); }
.cmp-faq .section-h { margin-bottom: 34px; }

.faq-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  overflow: hidden;
}

.faq {
  padding: 26px 24px 28px;
  background: var(--void);
  transition: background .3s var(--ease);
}
.faq:hover { background: var(--panel); }
.faq h3 { font-size: 1rem; margin-bottom: 8px; letter-spacing: -0.02em; }
.faq p { font-size: 0.88rem; }

@media (max-width: 820px) { .faq-list { grid-template-columns: minmax(0, 1fr); } }

/* Tekst wylacznie dla czytnikow ekranu - podpis tabeli. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Co nas wyroznia ───────────────────────────────────────────────────
   Sekcja ma jedno zadanie: powiedziec w kilkanascie sekund, czym ta
   aplikacja rozni sie od reszty. Stad kolejnosc - trzy filary, jedna scena
   z kwotami, a wszystko glebsze pod lista rozwijana.
   Ruch przy przewijaniu jest tu NARRACYJNY, nie ozdobny: diagram podzialu
   rysuje sie w kolejnosci czytania, a akcenty (Twoja karta, wiersz
   OneValuate) laduja na koncu - animacja odgrywa podzial rachunku,
   czyli robi dokladnie to, co tekst obok opisuje. Same reguly ruchu
   mieszkaja w bloku `@supports (animation-timeline: view())` wyzej. */
.why {
  padding: clamp(80px, 13vh, 150px) 0;
  border-top: 1px solid var(--line-soft);
}

/* To samo podkreslenie gradientem co `.hl` w hero, ale rysowane osia
   przewijania (regula w bloku `@supports`), nie zegarem od wejscia na
   strone - sekcja jest daleko w dole. Bazowo kreska STOI narysowana,
   zeby przegladarki bez animacji przewijania niczego nie gubily. */
.hl-scroll { position: relative; display: inline-block; color: var(--ink); }
.hl-scroll::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -.06em;
  height: .08em;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand), var(--spark));
}

/* ── Trzy filary ─────────────────────────────────────────────────────── */
.pillars {
  margin-top: clamp(34px, 5vh, 52px);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  overflow: hidden;
}

.pillar {
  background: var(--panel);
  padding: clamp(22px, 2.4vw, 32px);
  display: flex;
  flex-direction: column;
  /* Ten sam gest co na kafelkach modulow: najechanie podnosi tlo. */
  transition: background .3s var(--ease);
}

.pillar:hover { background: var(--raised); }

/* Kreska w kolorze modulu (`--c` z HTML) - ta sama forma co `.feat-mark`
   w siatce modulow, zeby obie sekcje mowily jednym jezykiem. */
.pillar::before {
  content: "";
  width: 22px; height: 2px;
  border-radius: 1px;
  margin-bottom: 16px;
  background: var(--c, var(--brand));
  transition: width .35s var(--ease);
}
.pillar:hover::before { width: 40px; }

.pillar-n {
  font: 500 0.72rem/1 'JetBrains Mono', ui-monospace, monospace;
  color: var(--c, var(--brand));
  letter-spacing: .1em;
  margin-bottom: 14px;
}
.pillar h3 { font-size: 1.14rem; letter-spacing: -0.02em; margin-bottom: 10px; }
.pillar-d { font-size: 0.92rem; }
/* Podpis domykajacy dosuniety do dolu, zeby stal w jednej linii we
   wszystkich trzech kafelkach, mimo roznej dlugosci opisow. */
.pillar-k {
  margin-top: auto;
  padding-top: 16px;
  font: 500 0.72rem/1.3 'JetBrains Mono', ui-monospace, monospace;
  letter-spacing: .06em;
  color: var(--faint);
}

/* ── Scena z kwotami ─────────────────────────────────────────────────── */
.case {
  position: relative;
  margin-top: clamp(30px, 4vh, 48px);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: clamp(26px, 3.4vw, 44px);
  /* Poswiaty wychodza poza karte - `clip` przycina bez tworzenia
     kontenera przewijania (ta sama uwaga co przy hero). */
  overflow: clip;
}

/* Dwie poswiaty w rogach - ten sam gest co za nagladem hero. Karta
   przestaje byc plaskim prostokatem, a gradienty nie dotykaja tekstu. */
.case::before,
.case::after {
  content: "";
  position: absolute;
  aspect-ratio: 1;
  pointer-events: none;
}
.case::before {
  right: -14%; top: -34%;
  width: 52%;
  background: radial-gradient(circle, rgba(134, 59, 255, .13), transparent 62%);
}
.case::after {
  left: -12%; bottom: -42%;
  width: 48%;
  background: radial-gradient(circle, rgba(79, 139, 255, .10), transparent 62%);
}

.case-lede {
  font-size: clamp(1.02rem, 1.1vw, 1.16rem);
  max-width: 62ch;
}
.case-lede b { color: var(--ink); font-weight: 600; }

/* ── Podzial rachunku ────────────────────────────────────────────────
   NIE graf, tylko PASEK KWOTY. Kreskowe drzewko (rachunek, kreski w dol,
   karty osob) wygladalo jak schemat z prezentacji. Zamiast tego: rachunek
   jest jednym paskiem na pelna szerokosc, a pod nim stoja te same
   pieniadze w czterech segmentach rownej szerokosci - segmenty sumuja sie
   dokladnie do szerokosci paska, wiec "200 zl = 4 x 50 zl" czyta sie
   z samej proporcji ukladu, bez jednej rysowanej kreski. */
.split { max-width: 660px; margin: 26px 0 30px; }

.bill {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 14px 18px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 11px;
}
.bill span { font-size: 0.93rem; color: var(--dim); }
.bill b { font-size: 1.06rem; font-variant-numeric: tabular-nums; }

.split-note {
  text-align: center;
  font-size: 0.78rem;
  color: var(--faint);
  padding: 10px 0;
}

.people {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 7px;
}

/* Segment nosi kolor SWOJEJ osoby (`--c` z HTML): kropka przy imieniu
   jak w legendzie wykresu, tint w tle i ramce. Kolor identyfikuje osobe -
   dokladnie tak, jak robia to aplikacje do dzielenia rachunkow. */
.who {
  text-align: center;
  padding: 12px 8px;
  background: color-mix(in srgb, var(--c, #757d90) 9%, var(--raised));
  border: 1px solid color-mix(in srgb, var(--c, #757d90) 30%, var(--line));
  border-radius: 9px;
}
.who span { display: block; font-size: 0.82rem; color: var(--dim); }
.who span::before {
  content: "";
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  margin-right: 6px;
  background: var(--c, var(--faint));
}
.who b {
  display: block;
  margin-top: 3px;
  font-size: 0.98rem;
  font-variant-numeric: tabular-nums;
  color: var(--dim);
}
/* Twoja czesc - jedyna w pelnej bieli i z poswiata, bo to ona jest
   odpowiedzia. Poswiata to stan KONCOWY animacji `me-light` -
   w przegladarkach bez animacji przewijania po prostu stoi od razu. */
.who.is-me {
  border-color: color-mix(in srgb, var(--brand) 55%, var(--line));
  background: color-mix(in srgb, var(--brand) 13%, var(--raised));
  box-shadow: 0 0 24px -8px rgba(134, 59, 255, .45);
}
.who.is-me span { color: var(--ink); }
.who.is-me b { color: var(--ink); }

.case-q { font-size: 0.98rem; margin-bottom: 4px; }

.case-rows {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--line-soft);
  margin-top: 14px;
}

.case-row {
  display: grid;
  /* Kwota w SRODKU, nie na koncu: cztery kwoty stoja wtedy w jednej
     pionowej linii tuz obok nazwy i oko porownuje je jednym ruchem w dol. */
  grid-template-columns: minmax(150px, .85fr) minmax(96px, auto) minmax(0, 1.9fr);
  align-items: baseline;
  gap: 8px clamp(14px, 2vw, 30px);
  padding: 16px 14px;
  border-bottom: 1px solid var(--line-soft);
}

.case-who { font-size: 0.94rem; color: var(--dim); }

.case-sum {
  font-size: 1.12rem;
  font-weight: 600;
  color: var(--dim);
  text-align: right;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.case-none { color: var(--faint); font-weight: 400; }
.case-why  { font-size: 0.87rem; color: var(--faint); }

/* Werdykt niesie KOLOR, nie tylko kwota: zawyzone sumy w rozu ostrzezenia
   (barwa modulu Wydatki), prawdziwa w zieleni (barwa Rozliczen).
   Domieszka bieli trzyma kontrast na ciemnym panelu. */
.case-sum.is-over { color: color-mix(in srgb, #f43f5e 55%, var(--ink)); }

.case-row.is-us {
  position: relative;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  border-bottom: none;
  border-radius: 10px;
  margin-top: 6px;
}
.case-row.is-us::before {
  content: "";
  position: absolute;
  left: 0; top: 10px; bottom: 10px;
  width: 2px;
  border-radius: 1px;
  background: linear-gradient(180deg, var(--brand), var(--spark));
}
.case-row.is-us .case-who { color: var(--ink); font-weight: 600; }
.case-row.is-us .case-sum { color: color-mix(in srgb, #22c55e 60%, var(--ink)); font-size: 1.24rem; }
.case-row.is-us .case-why { color: var(--dim); }

.case-foot { margin-top: 24px; max-width: 68ch; font-size: 0.95rem; }

/* ── Lista rozwijana ─────────────────────────────────────────────────── */
.rz-wrap { margin-top: clamp(40px, 5vh, 62px); }
.rz-h {
  font: 500 0.72rem/1 'JetBrains Mono', ui-monospace, monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 8px;
}

.rz { border-bottom: 1px solid var(--line-soft); }

.rz summary {
  /* Domyslny trojkat znika w obu skladniach - zastepuje go wlasny znak
     po lewej, zeby wszystkie pozycje zaczynaly sie w jednej linii. */
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 17px 0;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  transition: color .2s var(--ease);
}
.rz summary::-webkit-details-marker { display: none; }
/* Znak sie OBRACA, nie podmienia: "+" przekrecone o 45 stopni to "x",
   a obrot da sie animowac - podmiana tresci "+" na "-" byla skokiem. */
.rz summary::before {
  content: "+";
  flex: none;
  width: 14px;
  font: 400 1.05rem/1 ui-monospace, monospace;
  color: var(--brand);
  transition: transform .3s var(--ease);
}
.rz[open] summary::before { transform: rotate(45deg); }
.rz summary:hover { color: var(--brand); }
.rz summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 4px; border-radius: 4px; }

/* ── Plynne rozwijanie ──
   `::details-content` + przejscie na `block-size` - wysokosc plynie tam,
   gdzie przegladarka umie interpolowac slowo `auto` (patrz `@supports`
   nizej); gdzie nie umie, wysokosc skacze, ale przenikanie zostaje.
   Przegladarki bez `::details-content` otwieraja po staremu, natychmiast.
   `content-visibility` z `allow-discrete` trzyma tresc wyrenderowana
   przez czas DOMYKANIA - bez tego znikalaby w pierwszej klatce. */
.rz::details-content {
  opacity: 0;
  block-size: 0;
  overflow-y: clip;
  transition:
    content-visibility .32s allow-discrete,
    opacity .32s var(--ease),
    block-size .32s var(--ease);
}
.rz[open]::details-content { opacity: 1; block-size: auto; }

/* Tresc leciutko WJEZDZA po otwarciu - osobno od wysokosci, bo samo
   rozsuniecie ramki nie daje poczucia, ze cos przyszlo. `backwards`
   trzyma stan startowy przez wstepne 40 ms zwloki. */
.rz[open] .rz-body { animation: rz-reveal .45s .04s var(--ease) backwards; }
@keyframes rz-reveal { from { opacity: 0; transform: translateY(8px); } }

/* Zgoda na interpolowanie slow kluczowych rozmiaru (`auto` -> liczba).
   Globalnie i swiadomie: jedyne przejscia po rozmiarach na tej stronie
   to rozwijana lista wyzej. Dzis rozumie to Chrome/Edge, reszta
   przegladarek ignoruje caly blok i wysokosc otwiera sie skokiem. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
}

.rz-body { padding: 0 0 22px 28px; max-width: 74ch; }
.rz-body p { font-size: 0.92rem; }
.rz-body p + p { margin-top: 10px; }

.rz-list {
  margin: 0; padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(252px, 1fr));
  gap: 9px 26px;
}
.rz-list li {
  position: relative;
  padding-left: 17px;
  font-size: 0.89rem;
  color: var(--dim);
}
.rz-list li::before {
  content: "";
  position: absolute;
  left: 0; top: .58em;
  width: 7px; height: 1.5px;
  border-radius: 1px;
  background: var(--brand);
}

/* ── Wyjazd: wiele rachunkow, jedno saldo ────────────────────────────── */
.trip {
  margin: 18px 0;
  padding: 20px;
  background: var(--void);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
}
.bills { margin: 0; padding: 0; list-style: none; }
.bills li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.89rem;
}
.bills li span { color: var(--dim); }
.bills li b { font-variant-numeric: tabular-nums; color: var(--dim); font-weight: 500; }
/* Wiersz sumy - grubsza kreska nad nim, bo to podsumowanie, nie kolejna
   pozycja. Suma jest widoczna po to, zeby kwote na osobe dalo sie sprawdzic
   w pamieci: 1720 / 4 = 430. */
.bills-sum { border-bottom: none !important; border-top: 1px solid var(--line); margin-top: 4px; padding-top: 11px !important; }
.bills-sum span { color: var(--ink) !important; font-weight: 600; }
.bills-sum b { color: var(--ink) !important; font-weight: 600; }

.trip-arrow { text-align: center; color: var(--brand); padding: 10px 0 6px; font-size: 1.1rem; }

.owes { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 8px; }
.owe {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 11px 14px;
  background: color-mix(in srgb, var(--brand) 9%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--brand) 40%, var(--line));
  border-radius: 9px;
}
.owe span { font-size: 0.82rem; color: var(--dim); }
.owe b { font-size: 0.98rem; font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  .pillars { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 620px) {
  /* Pasek ZOSTAJE paskiem: cztery segmenty w rzedzie, bo dwa rzedy po dwa
     zabilyby proporcje "jeden rachunek = cztery rowne czesci". Segmenty
     mieszcza sie po zwezeniu wypelnienia - tresc to imie i kwota. */
  .who { padding: 10px 4px; }
  .people { gap: 5px; }
  .case-row { grid-template-columns: minmax(0, 1fr) auto; padding: 15px 12px; }
  .case-why { grid-column: 1 / -1; }
  .rz-body { padding-left: 0; }
}

/* ── Twoje dane ────────────────────────────────────────────────────── */
.trust {
  padding: clamp(80px, 13vh, 150px) 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: var(--panel);
}

.trust-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(32px, 6vw, 76px);
  align-items: center;
}

.trust-list {
  margin: 0; padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}

.trust-list li {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 15px;
  row-gap: 3px;
  align-items: start;
  padding: 18px 20px;
  background: var(--panel);
  font-size: 0.88rem;
}

.trust-list b { font-size: 0.95rem; }

/* Kafelek z ikona rozpiety na oba wiersze tekstu - obietnice przestaja
   wygladac jak paragrafy regulaminu. Fiolet marki, nie kolory modulow:
   to sekcja o zaufaniu, jeden spokojny kolor. */
.trust-ic {
  grid-row: 1 / 3;
  align-self: center;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: color-mix(in srgb, var(--brand) 11%, var(--raised));
  border: 1px solid color-mix(in srgb, var(--brand) 28%, var(--line));
  color: color-mix(in srgb, var(--brand) 55%, var(--ink));
}
.trust-ic svg { width: 19px; height: 19px; }

/* ── Aplikacja na telefon ──────────────────────────────────────────── */
/* Dwie kolumny: po lewej ARGUMENTY (co ta aplikacja robi lepiej niz karta
   przegladarki), po prawej CZYNNOSC (pobierz i zainstaluj). Rozdzielone,
   bo to dwa rozne momenty czytania - jeden przekonuje, drugi prowadzi za
   reke, a zmieszane w jedna kolumne kaza czytac argumenty komus, kto juz
   sie zdecydowal. */
.mobile {
  padding: clamp(80px, 13vh, 150px) 0;
  border-top: 1px solid var(--line-soft);
}

.mobile-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

.mobile-lista {
  margin: 26px 0 0; padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.mobile-lista li {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 15px;
  row-gap: 4px;
  align-items: start;
}

.mobile-lista b { font-size: 0.95rem; }
.mobile-lista li > span:last-child { font-size: 0.88rem; color: var(--dim); line-height: 1.6; }

.mobile-ic {
  grid-row: 1 / 3;
  align-self: center;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: color-mix(in srgb, var(--spark) 11%, var(--raised));
  border: 1px solid color-mix(in srgb, var(--spark) 28%, var(--line));
  color: color-mix(in srgb, var(--spark) 60%, var(--ink));
}
.mobile-ic svg { width: 19px; height: 19px; }

/* Panel pobierania. Wypukly wzgledem sekcji, bo to jedyne miejsce na
   stronie, w ktorym cos sie POBIERA - ma byc widoczne z daleka. */
.mobile-panel {
  padding: clamp(22px, 3vw, 30px);
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--panel);
}

.mobile-btn { width: 100%; justify-content: center; }

.mobile-meta {
  margin: 12px 0 0;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.74rem;
  color: var(--faint);
  text-align: center;
}

.mobile-kroki {
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: krok;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.mobile-kroki li {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-left: 34px;
  counter-increment: krok;
}

/* Numer kroku jako pseudoelement - lista ma wlasny licznik, bo `ol` z
   domyslnymi znacznikami nie da sie ustawic w kolku bez dodatkowego
   elementu w HTML-u. */
.mobile-kroki li::before {
  content: counter(krok);
  position: absolute;
  left: 0; top: 1px;
  width: 22px; height: 22px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--spark) 32%, var(--line));
  background: color-mix(in srgb, var(--spark) 10%, var(--raised));
  color: color-mix(in srgb, var(--spark) 62%, var(--ink));
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.72rem;
}

.mobile-kroki b { font-size: 0.88rem; }
.mobile-kroki span { font-size: 0.82rem; color: var(--dim); line-height: 1.55; }

.mobile-nota {
  margin: 24px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--faint);
}

.mobile-nota a { color: var(--dim); }

@media (max-width: 900px) {
  .mobile-inner { grid-template-columns: 1fr; }
}

/* ── CTA końcowe ───────────────────────────────────────────────────── */
.final {
  position: relative;
  overflow: clip;
  padding: clamp(90px, 16vh, 180px) 0;
}

/* Poswiata domyka strone tym samym swiatlem, ktorym sie zaczela -
   `closest-side` gasnie przed krawedziami pudelka, wiec nic sie nie
   utnie (patrz poswiaty hero). */
.final::before {
  content: '';
  position: absolute;
  left: 0; top: 6%;
  width: min(46%, 78vh);
  aspect-ratio: 1;
  background: radial-gradient(circle closest-side, rgba(134, 59, 255, .13), transparent);
  pointer-events: none;
  z-index: -1;
}

/* `max-width` NIE na tym kontenerze: nosi on też `.wrap` z `margin: 0 auto`,
   więc zawężenie zamieniało całą sekcję w wyśrodkowaną kolumnę - jedyną
   wyśrodkowaną na całej stronie, w dodatku z nagłówkiem łamiącym się na
   trzy linie. Szerokość ograniczają teraz dzieci. */
.final-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.final-inner h2 { max-width: 16ch; }
.final-inner p { max-width: 44ch; }

.final h2 { font-size: clamp(2rem, 5vw, 3.4rem); }
.final p { font-size: 1.05rem; }
.final .btn { margin-top: 12px; }

/* ── Stopka ────────────────────────────────────────────────────────── */
.footer { padding: 30px 0 44px; border-top: 1px solid var(--line-soft); }

.footer-inner {
  display: flex;
  align-items: center;
  gap: 26px;
  font-size: 0.85rem;
  color: var(--faint);
}

.footer-inner a { transition: color .2s var(--ease); }
.footer-inner a:hover { color: var(--ink); }
.footer-copy { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; }

/* ═══ WĄSKI EKRAN ══════════════════════════════════════════════════════
   Przypinanie produktu wymaga dwóch kolumn obok siebie. Na telefonie ich
   nie ma, więc scena rozwija się w NORMALNĄ, pionową listę: ekran, opis,
   ekran, opis. To nie jest wersja gorsza - to ten sam materiał w układzie,
   który na tej szerokości działa.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  :root { --shell: min(1180px, 100% - 32px); }

  .topnav { display: none; }
  /* Przycisk w pasku był na telefonie prawie tak szeroki jak nazwa marki. */
  .topbar .btn-sm { padding: 8px 13px; font-size: 0.8rem; }

  .stage {
    min-height: 0;
    /* Oś czasu WYŁĄCZONA. Bez tego animacje z bloku `@supports` nadal
       działały - `--stage` istniało, więc panele siedziały w połowie
       przejścia i tekst był przygaszony niemal do niewidoczności.
       Zdjęcie osi unieważnia wszystkie animacje, które się do niej
       odwołują, jednym ruchem. */
    view-timeline-name: none;
  }
  .stage-sticky { position: static; height: auto; display: block; padding: 56px 0; }

  /* PRZEPLATANIE. `display: contents` rozpuszcza kontenery, więc panele
     i zrzuty stają się rodzeństwem w jednej kolumnie i da się je ułożyć
     przez `order`: zrzut, jego opis, następny zrzut, następny opis.
     Bez tego szły cztery obrazki, a dopiero potem cztery bloki tekstu -
     i nie było wiadomo, co do czego się odnosi. */
  .stage-grid { display: flex; flex-direction: column; gap: 0; }
  .panels,
  .device-wrap,
  .device,
  .screens { display: contents; }
  .device-bar { display: none; }
  /* Ramka jest tu rozpuszczona (`display: contents`), wiec jej poswiata
     nie ma sie czego trzymac - zdejmujemy pseudoelement w calosci. */
  .device-wrap::before { content: none; }

  .screen[data-screen="1"] { order: 1; }
  .panel[data-step="1"]    { order: 2; }
  .screen[data-screen="2"] { order: 3; }
  .panel[data-step="2"]    { order: 4; }
  .screen[data-screen="3"] { order: 5; }
  .panel[data-step="3"]    { order: 6; }
  .screen[data-screen="4"] { order: 7; }
  .panel[data-step="4"]    { order: 8; }
  .screen[data-screen="5"] { order: 9; }
  .panel[data-step="5"]    { order: 10; }

  .screen {
    /* `!important`, bo w ukladzie rozwinietym musi przebic
       `.stage-js .screen { opacity: 0 }` - klasa stage-js siedzi na
       <html> takze na telefonie i przy ograniczonym ruchu. */
    opacity: 1 !important;
    pointer-events: auto !important;
    width: 100%;
    height: auto;
    border: 1px solid var(--line);
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 18px;
    animation: none !important;
    transform: none !important;
  }

  .screen img { height: auto; object-fit: contain; }

  .panel {
    margin-bottom: 44px;
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
    animation: none !important;
  }
  .panel[data-step="5"] { margin-bottom: 0; }
  .steps { display: none; }

  .trust-inner { grid-template-columns: 1fr; }
  .hero-inner { max-width: none; }
}

/* ═══ BRAK JAVASCRIPTU: SCENA ROZWIJA SIĘ W PIONOWĄ LISTĘ ═════════════
   Scenę produktu prowadzi WSZĘDZIE stage.js (klasa `stage-js` z <head>
   wymaga działającego JS). Bez skryptów klasy nie ma - i te reguły
   rozwijają scenę do pionowej listy, dokładnie jak na telefonie. Nic się
   nie chowa, niczego nie brakuje - po prostu nic się nie rusza.
   Kiedyś blok siedział w `@supports not (animation-timeline: view())`,
   bo scenę bez JS umiał scrubbować sam CSS - tamta ścieżka odeszła
   (stany pośrednie z dwiema odsłonami naraz), więc warunek został jeden:
   jest JS albo go nie ma. ═══════════════════════════════════════════ */
  html:not(.stage-js) .stage {
    min-height: 0;
    /* Oś czasu WYŁĄCZONA. Bez tego animacje z bloku `@supports` nadal
       działały - `--stage` istniało, więc panele siedziały w połowie
       przejścia i tekst był przygaszony niemal do niewidoczności.
       Zdjęcie osi unieważnia wszystkie animacje, które się do niej
       odwołują, jednym ruchem. */
    view-timeline-name: none;
  }
  html:not(.stage-js) .stage-sticky { position: static; height: auto; display: block; padding: 56px 0; }

  /* PRZEPLATANIE. `display: contents` rozpuszcza kontenery, więc panele
     i zrzuty stają się rodzeństwem w jednej kolumnie i da się je ułożyć
     przez `order`: zrzut, jego opis, następny zrzut, następny opis.
     Bez tego szły cztery obrazki, a dopiero potem cztery bloki tekstu -
     i nie było wiadomo, co do czego się odnosi. */
  html:not(.stage-js) .stage-grid { display: flex; flex-direction: column; gap: 0; }
  html:not(.stage-js) .panels,
  html:not(.stage-js) .device-wrap,
  html:not(.stage-js) .device,
  html:not(.stage-js) .screens { display: contents; }
  html:not(.stage-js) .device-bar { display: none; }
  html:not(.stage-js) .device-wrap::before { content: none; }

  html:not(.stage-js) .screen[data-screen="1"] { order: 1; }
  html:not(.stage-js) .panel[data-step="1"]    { order: 2; }
  html:not(.stage-js) .screen[data-screen="2"] { order: 3; }
  html:not(.stage-js) .panel[data-step="2"]    { order: 4; }
  html:not(.stage-js) .screen[data-screen="3"] { order: 5; }
  html:not(.stage-js) .panel[data-step="3"]    { order: 6; }
  html:not(.stage-js) .screen[data-screen="4"] { order: 7; }
  html:not(.stage-js) .panel[data-step="4"]    { order: 8; }
  html:not(.stage-js) .screen[data-screen="5"] { order: 9; }
  html:not(.stage-js) .panel[data-step="5"]    { order: 10; }

  html:not(.stage-js) .screen {
    opacity: 1;
    width: 100%;
    height: auto;
    border: 1px solid var(--line);
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 18px;
    animation: none !important;
    transform: none !important;
  }

  html:not(.stage-js) .screen img { height: auto; object-fit: contain; }

  html:not(.stage-js) .panel {
    margin-bottom: 44px;
    opacity: 1;
    transform: none;
    animation: none !important;
  }
  html:not(.stage-js) .panel[data-step="5"] { margin-bottom: 0; }
  html:not(.stage-js) .steps { display: none; }

/* ═══ ŚCIEŻKA JS: TEN SAM EFEKT, INNY SPOSÓB LICZENIA ══════════════════
   `stage.js` wystawia na sekcji trzy liczby: `--p` (postęp przypięcia),
   `--sp` (postęp bieżącej odsłony) i `--enter` (wjazd), oraz `data-step`
   z numerem odsłony. Reszta to zwykły CSS - przełączanie idzie przejściem
   na `opacity`/`transform`, czyli po tych samych właściwościach, które
   w ścieżce natywnej liczy kompozytor.
   ═══════════════════════════════════════════════════════════════════════ */
.stage-js .screen,
.stage-js .panel {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
  /* Ukryty ekran nie może przechwytywać kliknięć leżącego pod nim. */
  pointer-events: none;
}

.stage-js .stage[data-step="1"] .screen[data-screen="1"],
.stage-js .stage[data-step="2"] .screen[data-screen="2"],
.stage-js .stage[data-step="3"] .screen[data-screen="3"],
.stage-js .stage[data-step="4"] .screen[data-screen="4"],
.stage-js .stage[data-step="5"] .screen[data-screen="5"],
.stage-js .stage[data-step="1"] .panel[data-step="1"],
.stage-js .stage[data-step="2"] .panel[data-step="2"],
.stage-js .stage[data-step="3"] .panel[data-step="3"],
.stage-js .stage[data-step="4"] .panel[data-step="4"],
.stage-js .stage[data-step="5"] .panel[data-step="5"] {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* Ramka prostuje się w miarę wjazdu - kąt liczony wprost z `--enter`.
   Mnożenie kąta przez liczbę bez jednostki jest w `calc()` poprawne. */
.stage-js .device {
  transform:
    perspective(1600px)
    rotateY(calc(-13deg * (1 - var(--enter, 1))))
    rotateX(calc(6deg * (1 - var(--enter, 1))))
    scale(calc(0.9 + 0.1 * var(--enter, 1)));
}

/* Kreska wskaźnika: odsłony przed bieżącą są pełne, bieżąca rośnie. */
.stage-js .steps span::after { transform: scaleX(0); }

.stage-js .stage[data-step="2"] .steps span[data-step="1"]::after,
.stage-js .stage[data-step="3"] .steps span[data-step="1"]::after,
.stage-js .stage[data-step="3"] .steps span[data-step="2"]::after,
.stage-js .stage[data-step="4"] .steps span[data-step="1"]::after,
.stage-js .stage[data-step="4"] .steps span[data-step="2"]::after,
.stage-js .stage[data-step="4"] .steps span[data-step="3"]::after,
.stage-js .stage[data-step="5"] .steps span[data-step="1"]::after,
.stage-js .stage[data-step="5"] .steps span[data-step="2"]::after,
.stage-js .stage[data-step="5"] .steps span[data-step="3"]::after,
.stage-js .stage[data-step="5"] .steps span[data-step="4"]::after {
  transform: scaleX(1);
}

.stage-js .stage[data-step="1"] .steps span[data-step="1"]::after,
.stage-js .stage[data-step="2"] .steps span[data-step="2"]::after,
.stage-js .stage[data-step="3"] .steps span[data-step="3"]::after,
.stage-js .stage[data-step="4"] .steps span[data-step="4"]::after,
.stage-js .stage[data-step="5"] .steps span[data-step="5"]::after {
  transform: scaleX(var(--sp, 0));
}


/* Wejscia sekcji obsluguje wspolny system obserwatora (reveal.js + blok
   "WEJSCIA SEKCJI") - dziala tez na tej sciezce, wiec nic tu nie trzeba
   odkrywac recznie. */

/* ═══ OGRANICZONY RUCH ═════════════════════════════════════════════════
   Ktoś, kto poprosił system o mniej animacji, dostaje stronę bez ruchu -
   ale Z PEŁNĄ TREŚCIĄ. Wyłączenie animacji nie może niczego ukryć, bo
   elementy startujące z `opacity: 0` zostałyby niewidoczne na zawsze.
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Samo skrócenie czasu NIE wystarcza przy animacjach sterowanych
     przewijaniem: ich zegarem jest pozycja, a nie stoper, więc animacja
     nadal by działała i zatrzymała elementy na klatce końcowej - czyli
     `opacity: 0`. Zdejmujemy więc animacje wprost. */
  *, *::before, *::after {
    animation-name: none !important;
    animation-timeline: auto !important;
    transition-duration: .001ms !important;
  }

  .stage {
    min-height: 0;
    /* Oś czasu WYŁĄCZONA. Bez tego animacje z bloku `@supports` nadal
       działały - `--stage` istniało, więc panele siedziały w połowie
       przejścia i tekst był przygaszony niemal do niewidoczności.
       Zdjęcie osi unieważnia wszystkie animacje, które się do niej
       odwołują, jednym ruchem. */
    view-timeline-name: none;
  }
  .stage-sticky { position: static; height: auto; display: block; padding: 56px 0; }

  /* PRZEPLATANIE. `display: contents` rozpuszcza kontenery, więc panele
     i zrzuty stają się rodzeństwem w jednej kolumnie i da się je ułożyć
     przez `order`: zrzut, jego opis, następny zrzut, następny opis.
     Bez tego szły cztery obrazki, a dopiero potem cztery bloki tekstu -
     i nie było wiadomo, co do czego się odnosi. */
  .stage-grid { display: flex; flex-direction: column; gap: 0; }
  .panels,
  .device-wrap,
  .device,
  .screens { display: contents; }
  .device-bar { display: none; }
  /* Ramka jest tu rozpuszczona (`display: contents`), wiec jej poswiata
     nie ma sie czego trzymac - zdejmujemy pseudoelement w calosci. */
  .device-wrap::before { content: none; }

  .screen[data-screen="1"] { order: 1; }
  .panel[data-step="1"]    { order: 2; }
  .screen[data-screen="2"] { order: 3; }
  .panel[data-step="2"]    { order: 4; }
  .screen[data-screen="3"] { order: 5; }
  .panel[data-step="3"]    { order: 6; }
  .screen[data-screen="4"] { order: 7; }
  .panel[data-step="4"]    { order: 8; }
  .screen[data-screen="5"] { order: 9; }
  .panel[data-step="5"]    { order: 10; }

  .screen {
    /* `!important`, bo w ukladzie rozwinietym musi przebic
       `.stage-js .screen { opacity: 0 }` - klasa stage-js siedzi na
       <html> takze na telefonie i przy ograniczonym ruchu. */
    opacity: 1 !important;
    pointer-events: auto !important;
    width: 100%;
    height: auto;
    border: 1px solid var(--line);
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 18px;
    animation: none !important;
    transform: none !important;
  }

  .screen img { height: auto; object-fit: contain; }

  .panel {
    margin-bottom: 44px;
    opacity: 1 !important;
    pointer-events: auto !important;
    transform: none !important;
    animation: none !important;
  }
  .panel[data-step="5"] { margin-bottom: 0; }
  .steps { display: none; }
  /* Zacheta do przewijania zyje z animacji - przy ograniczonym ruchu po
     prostu jej nie ma, tresc i tak jest w zasiegu zwyklego przewijania. */
  .scroll-nudge { display: none; }
  .hl::after { transform: scaleX(1); }
}
