/* ============================================================
   Simple Client Mode — kreator

   Jedna decyzja zajmuje cały ekran, więc miniatury są tu treścią
   główną, a nie dodatkiem przy panelu. Stąd inne proporcje niż
   w trybie zaawansowanym: mniej elementów, większe kadry.
   ============================================================ */
/* Kreator jest własnym obszarem przewijania (`overflow-y` niżej), ale
   jako element flex nie zgodzi się zejść poniżej wysokości treści,
   dopóki nie powie mu się tego wprost. Bez `min-height: 0` rósł ponad
   okno, przez co strona dostawała własny pasek przewijania, a przyklejona
   stopka z „Dalej” lądowała pod dolną krawędzią ekranu — na telefonie
   widać było z niej trzy piksele.

   Ograniczenie wysokości `.app` robimy TYLKO tam, gdzie stoi kreator:
   ta sama klasa niesie panel administratora, który ma rosnąć swobodnie. */
.app:has(> .wizard) {
  height: 100vh;
  height: 100dvh;
}

.wizard {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;

  /* Na wysokim ekranie (4K) krok stał przyklejony do górnej krawędzi,
     a pod nim zostawał pusty pas. Treść jest tu jedna, więc należy jej
     się środek okna. `safe` znaczy: środek dopóki krok się mieści —
     gdy jest wyższy niż okno, układ wraca do góry, żeby przewijanie nie
     ucięło początku (zwykłe `center` obcina to, co wystaje ponad). */
  display: flex;
  flex-direction: column;

  /* Wyśrodkowanie przez margines, a NIE przez justify-content.

     „safe center" miało chronić przed ucinaniem treści wyższej niż okno,
     ale Safari go nie zna i cofa się do zwykłego „center" — a ten przy
     przepełnieniu obcina GÓRĘ i nie daje jej przewinąć: tytuł kroku
     zostawał nad krawędzią, a gest w górę trafiał w odświeżanie strony.
     „margin: auto" na jedynym dziecku robi to samo wyśrodkowanie
     i działa wszędzie, bo przy przepełnieniu margines po prostu znika. */
  justify-content: flex-start;

  /* Kreator jest własnym obszarem przewijania — gest na jego górnej
     krawędzi ma zatrzymać się na niej, a nie przechodzić na stronę
     i uruchamiać „pull to refresh". */
  overscroll-behavior-y: contain;

  /* Pas karuzeli jest szerszy niż okno (wszystkie ekrany w rzędzie).
     clip-path przycina go tylko wizualnie, więc bez tego kreator dawał
     się przewijać w bok. */
  overflow-x: hidden;

  /* Marginesy pionowe przez zmienne, bo powitanie musi znać ICH wartość:
     liczy swoją wysokość jako „okno minus to, co zabiera kreator", a te
     wartości zmieniają się na wąskim ekranie. Wpisane na sztywno zostawiały
     na telefonie biały pas pod powitaniem — odejmowane 72 px, gdy kreator
     zabierał tam 20. */
  --wiz-pad-top: var(--s-7);
  --wiz-pad-bottom: var(--s-8);
  padding: var(--wiz-pad-top) var(--s-6) var(--wiz-pad-bottom);
  background: var(--c-surface);
}

/* Etapy stoją po lewej, ale POZA układem: treść kroku ma być na osi
   ekranu, a nie zepchnięta w bok przez kolumnę. Stąd sidebar wyjęty
   z przepływu i główna kolumna na pełną szerokość. */
.wizard__shell {
  position: relative;
  max-width: 1240px;
  margin: 0 auto;

  /* Kreator jest kolumną flex (wyśrodkowanie w pionie), więc trzeba
     wprost zabronić kurczenia — inaczej krok wyższy niż okno zostałby
     ściśnięty zamiast wystawić pasek przewijania.

     `width: 100%` jest tu konieczne: boczne marginesy „auto" wyłączają
     rozciąganie flex itemu, więc szerokość zaczęłaby wynikać z treści —
     a treścią przeglądu jest pas karuzeli szerszy od okna (10 000 px).
     Krok wyjeżdżał wtedy poza ekran i strona wyglądała na pustą. */
  width: 100%;
  flex: 0 0 auto;

  /* Patrz .wizard: to ten margines wyśrodkowuje krok w pionie. */
  margin: auto;
}

/* Pasek etapow trzyma sie krawedzi okna i jego pionowej osi — jest
   stalym punktem odniesienia, a nie elementem plynacym z trescia.
   fixed, wiec nie odsuwa i nie przesuwa kroku. */
.wizard__side {
  position: fixed;
  left: var(--s-6);
  top: 50%;
  transform: translateY(-50%);
  width: 240px;
}

.wizard__shell--full .wizard__side { display: none; }

/* Karuzela w podsumowaniu: bez ograniczenia szerokości, żeby sąsiednie
   kadry sięgały krawędzi kolumny. Treść wewnątrz i tak jest wyśrodkowana,
   więc tytuł, zakładki i przyciski zostają na osi. */
.wizard__shell--wide { max-width: none; }
.wizard__shell--wide .wiz__step--summary { max-width: none; }

/* Kadr da się kliknąć, żeby go powiększyć (js/ui/simple.js) — kursor
   mówi o tym, zanim ktoś spróbuje.

   W trybie wskazywania miejsca nic tu nie trzeba wyłączać: klasę
   `.is-commenting` dostaje warstwa WEWNĄTRZ kadru (css/comments.css),
   a kursor dziecka i tak wygrywa z odziedziczonym — nad samą makietą
   klient widzi więc znacznik komentarza, nie lupkę.

   Pinezka otwiera swój wątek, więc zostaje przy zwykłym wskaźniku. */
.browser-fit.is-zoomable { cursor: zoom-in; }
.browser-fit.is-zoomable .pin { cursor: pointer; }

/* PAS DOCHODZI DO KRAWĘDZI OKNA ALBO DO PANELU ROZMOWY.

   Nie do marginesu kroku: sąsiednie kadry mają wyglądać jak dalszy ciąg
   rzędu, a nie jak pasek w ramce.

   O ILE WYJŚĆ POZA KROK, WIE JAVASCRIPT. Krok ma własny limit szerokości
   (1100 px), kreator — padding zależny od tego, czy panel rozmowy jest
   otwarty, zwinięty, czy nie ma go wcale. Różnica między jednym a drugim
   nie jest stała: na szerokim oknie pas kończył się kilkadziesiąt pikseli
   przed panelem, zostawiał tam pustkę, a clip-path ucinał w tym miejscu
   cień kadru. Dlatego obie strony liczy js/ui/simple.js (dopasuj)
   z rzeczywistych pomiarów — wartości niżej służą tylko pierwszej
   klatce, zanim pomiar się wykona.

   „stretch" jest tu konieczne: element wyśrodkowany w kolumnie flex
   ignoruje ujemny margines. */
.wiz__browser.wiz__slider {
  --wyciek-l: var(--s-6);
  --wyciek-r: var(--s-6);
  align-self: stretch;

  /* Obie klasy w selektorze celowo: `.wiz__browser` ma „max-width: 100%"
     i stoi w pliku NIŻEJ, więc przy równej wadze wygrywało ono — pas
     dostawał ujemny margines z lewej, ale nie rósł. Wyglądało to jak
     przesunięcie w bok: z jednej strony kadr wychodził poza krok,
     z drugiej kończył się przed panelem. */
  max-width: none;
  width: calc(100% + var(--wyciek-l) + var(--wyciek-r));
  margin-left: calc(var(--wyciek-l) * -1);
  margin-right: calc(var(--wyciek-r) * -1);
}

.wizard__main {
  display: flex;
  justify-content: center;
  min-width: 0;

  /* Układ odniesienia dla ołówka projektanta (niżej). `relative` nie
     łapie niczego, co stoi tu na `fixed` — kolumna rozmowy i powiększenie
     wiszą i tak przy korzeniu kreatora, nie w tej kolumnie. */
  position: relative;
}

/* ============================================================
   OŁÓWEK PROJEKTANTA — POWRÓT DO EDYCJI

   Widoczny tylko dla zalogowanego projektanta (js/ui/simple.js →
   sprawdźProjektanta); klient nie dostaje go nigdy i nie robi po niego
   ani jednego zapytania.

   Kolor akcentowy z czarnym znakiem w środku — ten sam, co „Publish
   configuration" w panelu (.btn--accent). `--c-accent` jest w jasnym
   motywie prawie czarny, więc czarny ołówek na nim byłby niewidoczny;
   akcentem, który maluje działanie, jest tu `--c-accent-2`.
   ============================================================ */
.wiz__edit {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 6;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;

  background: var(--c-accent-2);
  color: var(--c-accent-2-ink);
  box-shadow: var(--sh-2);
  transition: background var(--t-fast) var(--e-out),
              transform var(--t-fast) var(--e-out);
}

.wiz__edit:hover {
  background: var(--c-accent-2-hover);
  transform: translateY(-1px);
}

.wiz__edit:active { transform: none; }

/* NA WĄSKIM OKNIE OŁÓWEK IDZIE NAD PASEK PRZYCISKÓW.

   Kolumna jest wtedy niewiele szersza od samego kroku, a `.wiz__nav`
   (max 860 px) sięga jej krawędzi — ołówek w rogu siadał wprost na
   „Zatwierdź". Zmierzone: przy oknie 390 i 820 px prostokąty zachodziły
   na siebie, przy 1300 px dzieliło je 190 px.

   Granica jest ta sama, przy której kreator zwęża resztę układu. Wyżej
   niż pasek, bo pasek jest odpowiedzią klienta — ołówek należy do
   projektanta i ma nie stać mu na drodze. */
@media (max-width: 1100px) {
  .wiz__edit { bottom: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .wiz__edit { transition: none; }
  .wiz__edit:hover { transform: none; }
}

/* Krok wchodzi z lekkim podniesieniem — przejście między pytaniami ma być
   widoczne, ale nie ma zabierać czasu; 220 ms mieści się poniżej progu,
   przy którym ruch zaczyna spowalniać pracę. */
@keyframes wiz-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.wiz__step {
  width: 100%;
  max-width: 980px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-5);
}

.wiz__step--enter { animation: wiz-in 220ms var(--e-out); }

.wiz__step--intro { justify-content: center; padding-top: var(--s-9); gap: var(--s-4); }

/* ============================================================
   POWITANIE

   Pierwsze, co widzi klient. Zamiast interfejsu — jego własny projekt:
   mocno rozmyty pierwszy ekran wypełnia okno, więc kolory powitania są
   kolorami tego projektu i nie trzeba ich nigdzie ustawiać.

   Nad rozmyciem chodzą powoli trzy plamy światła. To nie jest ozdoba
   dla ozdoby: nieruchome rozmycie czyta się jak zepsuty obraz, a ruch
   mówi, że strona żyje i czeka na ruch klienta.
   ============================================================ */
.wiz__hero {
  position: relative;
  /* Dokładnie tyle, ile zostaje pod nagłówkiem po marginesach kreatora —
     powitanie ma wypełnić okno, a nie dołożyć ośmiu pikseli przewijania. */
  /* 100vh na telefonie znaczy „okno bez pasków przeglądarki", więc
     powitanie kończyło się wyżej niż widoczny ekran i pod spodem
     zostawał biały pas. dvh mierzy to, co widać naprawdę. */
  min-height: calc(100vh - var(--h-header) - var(--wiz-pad-top) - var(--wiz-pad-bottom));
  min-height: calc(100dvh - var(--h-header) - var(--wiz-pad-top) - var(--wiz-pad-bottom));
  max-width: none;
  padding: var(--s-8) var(--s-6);
  justify-content: center;
}

/* Tło wychodzi poza kolumnę kroku aż do krawędzi okna — kreator ma
   swoje marginesy, a powitanie ma ich nie mieć. */
.wiz__hero-bg {
  position: fixed;
  inset: var(--h-header) 0 0 0;
  z-index: 0;
  overflow: hidden;
  /* Ta sama biel co strona: rozmycie repliki sięga poza jej krawędzie
     i gdyby pod spodem było ciemno, wzdłuż okna szłaby ciemna obwódka. */
  background: var(--c-surface);
  pointer-events: none;
}

.wiz__hero-shot {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* Replika pierwszego kroku w tle powitania. Kadr repliki pokrywa się
   DOKŁADNIE z oknem (.wiz__hero-bg jest fixed na całym oknie), bo na
   końcu przejścia strona ma usiąść tam, gdzie stanie prawdziwy krok —
   inaczej podmiana byłaby przeskokiem o kilkanaście pikseli.

   Rozmycie i lekkie powiększenie siedzą więc na SAMEJ stronie, nie na
   kadrze: to one się animują, a kadr trzyma układ. Powiększenie jest
   przy okazji potrzebne, żeby rozmycie nie zostawiło jasnej obwódki
   przy krawędziach okna.

   Nic tu nie klikamy — to zapowiedź, a nie druga kopia kreatora. */
.wiz__hero-page {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--c-surface);

  /* ŻADNEGO TRANSFORMU — i to jest decyzja, nie przeoczenie.

     Replika liczy swoje wymiary tak samo jak prawdziwy krok, przez
     getBoundingClientRect, a ten idzie za transformem przodków. Nawet
     lekkie powiększenie przesuwało więc karuzelę przeglądu o kilkadziesiąt
     pikseli i kadr doskakiwał przy podmianie. Zostaje samo rozmycie —
     wchodzenie w ostrość i tak niesie całe przejście. */
  filter: blur(24px);
}

/* Strona zaczyna się POD nagłówkiem — dokładnie tak jak prawdziwy krok.

   Przewijanie jest tu takie samo jak w prawdziwym kreatorze (overflow-y:
   auto), bo kadr dopasowuje swoją wysokość do NADMIARU: mierzy
   scrollHeight − clientHeight i oddaje różnicę. Przy „overflow: hidden"
   nadmiaru nie widać, więc replika zostawiała kadr o kilkanaście pikseli
   za duży i przy podmianie wszystko pod nim podskakiwało. Paska nie
   pokazujemy — to tło, nie miejsce do przewijania. */
.wiz__hero-wizard {
  position: absolute;
  inset: var(--h-header) 0 0 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}

.wiz__hero-wizard::-webkit-scrollbar { display: none; }

/* Płótno gradientu leży NA rozmytym ekranie i jest przez niego mnożone:
   kolory shadera prowadzą światło, a barwa zostaje ta z projektu. Bez
   WebGL2 płótna nie ma wcale i zostaje samo rozmycie (js/ui/gradient.js). */
.gradient-canvas {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    display: block;
    mix-blend-mode: color-burn;
    /* mix-blend-mode: overlay; */
    filter: blur(1px);
    opacity: 0.7;
    transform: scale(1.01);
}

/* Trzy plamy światła w powolnym, niesynchronicznym ruchu. Kolory biorą
   się z tego, co świeci pod spodem — same są tylko rozjaśnieniem. */
.wiz__hero-glow {
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(38% 42% at 22% 32%, rgba(255, 255, 255, 0.20), transparent 70%),
    radial-gradient(32% 38% at 74% 24%, rgba(255, 255, 255, 0.14), transparent 72%),
    radial-gradient(46% 50% at 58% 78%, rgba(255, 255, 255, 0.12), transparent 70%);
  mix-blend-mode: soft-light;
  animation: hero-drift 34s ease-in-out infinite alternate;
}

@keyframes hero-drift {
  from { transform: translate3d(-4%, -3%, 0) scale(1); }
  50%  { transform: translate3d(3%, 2%, 0) scale(1.12); }
  to   { transform: translate3d(-2%, 4%, 0) scale(1.05); }
}

/* Przyciemnienie pod tekstem — biały napis musi się trzymać niezależnie
   od tego, jak jasny jest projekt pod spodem. */
.wiz__hero-veil {
  position: absolute;
  inset: 0;
  /* Nad gradientem: płótno dochodzi później (czeka na obraz do próbkowania),
     więc bez tego przykryłoby przyciemnienie i tekst zostałby na jaskrawym tle. */
  z-index: 1;
  /* Ciemno TAM, GDZIE STOI TEKST, jaśniej przy krawędziach — odwrotnie
     niż zwykła winieta. Biały napis ma się trzymać niezależnie od tego,
     jak jasny jest projekt, a kolor ma zostać widoczny po bokach. */
  /* Strona kroku jest w większości BIAŁA, więc przyciemnienie musi być
     mocne i sięgać daleko. W przejściu welon gaśnie i strona wraca do
     swoich barw. */
  background: radial-gradient(76% 66% at 50% 48%, rgb(8 8 10 / 78%), rgba(8, 8, 10, 0.34) 100%);
}

/* ============================================================
   WEJŚCIE POWITANIA

   Elementy nie pojawiają się naraz, tylko po kolei, z dołu i z rozmycia —
   oko dostaje kolejność czytania: znak, czyj to projekt, co się stało,
   co dalej, gdzie kliknąć. Całość trwa niecałą sekundę, bo to ma być
   wrażenie płynnego wejścia, a nie pokaz animacji.

   Tło wchodzi osobno i wolniej: jest scenografią, więc ma się rozjaśnić
   pod tekstem, a nie z nim konkurować.
   ============================================================ */
@keyframes hero-in {
  from {
    opacity: 0;
    transform: translateY(18px);
    filter: blur(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

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

/* To samo wejście, ale bez rozmycia — dla elementów, które mają WŁASNY
   filtr. Animacja ustawia `filter` na twardo, więc wersja z blur-em
   skasowałaby odwrócenie ciemnego znaku i logo zniknęłoby w tle. */
@keyframes hero-in-soft {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Krok ma własne wejście dla całej sekcji (wiz-in) — na powitaniu byłoby
   drugą animacją nałożoną na te poniżej. */
.wiz__hero.wiz__step--enter { animation: none; }

.wiz__hero-bg { animation: hero-bg-in 1200ms var(--e-out) both; }

.wiz__hero-project,
.wiz__hero-title span,
.wiz__hero-title b,
.wiz__hero-lead,
.wiz__hero-start,
.made-with--hero {
  animation: hero-in 760ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

/* Znak nad nazwą projektu — pierwszy w kolumnie powitania. Wysokość
   z ustawień projektanta tu NIE obowiązuje: w nagłówku znak dzieli miejsce
   z nazwą i statusem, a tu stoi sam i może być większy. */
.wiz__hero-mark {
  display: flex;
  justify-content: center;
  margin-bottom: var(--s-3);
}

.wiz__hero-mark img {
  height: 40px;
  width: auto;
}

/* W powitaniu nagłówek jest pusty — znak przeszedł do treści. Wraca na
   swoje miejsce dopiero po przejściu, razem z całym nagłówkiem. */
body.is-hero .header .brand { display: none; }

/* Kolejność czytania, nie kolejność w kodzie: znak wchodzi pierwszy,
   napis nad tytułem przed tytułem, a podpis narzędzia na samym końcu. */
.wiz__hero-mark {
  animation: hero-in-soft 760ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: 120ms;
}
.wiz__hero-project        { animation-delay: 200ms; }
.wiz__hero-title span     { animation-delay: 300ms; }
.wiz__hero-title b        { animation-delay: 400ms; }
.wiz__hero-lead           { animation-delay: 520ms; }
.wiz__hero-start          { animation-delay: 640ms; }
.made-with--hero          { animation-delay: 820ms; }

/* Dwa człony nagłówka wchodzą osobno, więc muszą być własnymi pudełkami —
   inaczej translateY nie ma czego przesuwać. */
.wiz__hero-title span,
.wiz__hero-title b { display: inline-block; }

/* ---------------- wyjście z powitania ----------------

   Treść odjeżdża w górę i gaśnie, tło zostaje o chwilę dłużej i dopiero
   wtedy ustępuje — dzięki temu przegląd wyłania się spod obrazu, zamiast
   go zastępować. Czas przejścia jest powtórzony w js/ui/simple.js, bo to
   ono decyduje, KIEDY przerysować krok. */
@keyframes hero-out {
  from { opacity: 1; transform: translateY(0); filter: blur(0); }
  to   { opacity: 0; transform: translateY(-16px); filter: blur(6px); }
}

.wiz__hero.is-leaving .wiz__hero-content,
.wiz__hero.is-leaving .made-with--hero {
  animation: hero-out 320ms cubic-bezier(0.55, 0, 0.7, 0.2) both;
}

/* ---------------- powitanie WCHODZI w krok ----------------

   Z repliką w tle powitanie nie znika jak osobna strona: zdejmujemy
   z niej po kolei to, co należy do powitania (teksty, światła, płótno
   gradientu), a strona wchodzi w ostrość i siada w swoim rozmiarze.
   Podmiana repliki na prawdziwy krok wypada dopiero po tym — obie są
   zbudowane tymi samymi funkcjami, więc jej nie widać.

   Sumarycznie ok. 0,94 s; ta sama liczba stoi w js/ui/simple.js. */
@keyframes hero-focus {
  from { filter: blur(24px); }
  to   { filter: blur(0); }
}

@keyframes hero-layer-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

.wiz__hero.is-leaving .wiz__hero-page {
  /* Wyostrzanie idzie tą samą krzywą co wejście powitania — ruch ma być
     jednym gestem, a nie dwoma różnymi. */
  animation: hero-focus 820ms cubic-bezier(0.22, 0.61, 0.36, 1) 100ms both;
}

/* Gradient WebGL i światła wygaszamy WCZEŚNIEJ niż kończy się ostrzenie:
   ruch ma ucichnąć, zanim strona stanie się sobą. Samo płótno zatrzymuje
   dopiero render() (js/ui/simple.js) — tu tylko gaśnie. */
.wiz__hero.is-leaving .wiz__hero-veil,
.wiz__hero.is-leaving .wiz__hero-glow,
.wiz__hero.is-leaving .gradient-canvas {
  animation: hero-layer-out 620ms cubic-bezier(0.4, 0, 0.2, 1) 60ms both;
}

/* Nagłówek powitania jest biały i wyśrodkowany, a krok ma zwykły, ciemny.
   Zamiana w locie byłaby skokiem, więc znak gaśnie w drugiej połowie
   przejścia i wraca — już w swojej zwykłej postaci — po podmianie. */
body.is-hero-leaving .header {
  animation: hero-layer-out 300ms cubic-bezier(0.4, 0, 0.2, 1) 320ms both;
}

/* ---------------- co wyłania się PO stronie ----------------

   Strona wchodzi w ostrość jako całość, ale dwie rzeczy dołączają do niej
   osobno i po kolei: najpierw kolumna etapów (to ona mówi, gdzie klient
   jest i ile go czeka), potem nagłówek. Jednoczesne pojawienie się obu
   czytałoby się jak mrugnięcie interfejsu; kolejność robi z tego zdanie:
   „oto twoja droga — a oto narzędzia".

   Obie wychodzą z rozmycia, tak samo jak strona pod nimi — ruch ma być
   jednym gestem, a nie trzema różnymi pomysłami. */
/* Y MUSI zostać na -50%: kolumna jest wyśrodkowana w pionie własnym
   transformem (reguła .wizard__side), a klatki nadpisują całą własność.
   Sam translateX zrzucał ją o pół wysokości w dół, skąd wskakiwała na
   miejsce dopiero po animacji. */
@keyframes hero-side-in {
  from { opacity: 0; transform: translate(-14px, -50%); filter: blur(10px); }
  to   { opacity: 1; transform: translate(0, -50%);     filter: blur(0); }
}

@keyframes hero-header-in {
  from { opacity: 0; transform: translateY(-10px); filter: blur(8px); }
  to   { opacity: 1; transform: translateY(0);     filter: blur(0); }
}

/* W tle powitania kolumny etapów nie ma — stoi tam sam projekt. Obie
   rzeczy, które dochodzą do gotowej już strony, wchodzą PO podmianie
   repliki i jedna po drugiej. */
.wiz__hero-wizard .wizard__side { display: none; }

/* Wyostrzona replika zostaje na wierzchu jeszcze chwilę PO podmianie
   i gaśnie — pod nią stoi już prawdziwy krok. Kryje to kilka pikseli
   różnicy, których nie da się uzgodnić (js/ui/simple.js). Pod nagłówkiem
   (z-index 20), nad treścią kroku. */
.wiz__hero-bg--fading {
  position: fixed;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  animation: hero-layer-out 260ms cubic-bezier(0.4, 0, 0.2, 1) both;
}

/* Najpierw NAGŁÓWEK — znak wraca z powitania na swoje miejsce. */
body.is-hero-arrive .header {
  animation: hero-header-in 420ms cubic-bezier(0.22, 0.61, 0.36, 1) 60ms both;
}

/* WJAZD PANELU: MIEJSCE ROBI SIĘ POD NIM, A NIE PRZED NIM.

   Rezerwa na panel to padding kreatora (400 px, przy zwiniętym pasku 72).
   Jeśli jest od pierwszej klatki, klient patrzy najpierw na pusty biały
   pas, a dopiero potem wjeżdża w niego panel — i to widać.

   Animujemy więc OBA elementy naraz i dokładnie te, o które chodzi:
   padding rośnie od zera do rezerwy, a panel jedzie od swojej szerokości
   do zera. Strona zaczyna jako pełnej szerokości i zwęża się dokładnie
   pod nadjeżdżającym panelem — pustka nie ma kiedy istnieć.

   Stan startowy nakłada klasa `is-panel-away`, zdejmowana w następnej
   klatce (js/ui/simple.js) — przejściem zajmuje się transition, więc nie
   ma tu zabawy z fill-mode ani z opóźnieniami klatek kluczowych. */
.wizard--panel,
.wizard--panel-rail {
  transition: padding-right 440ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.wizard--panel.is-panel-away,
.wizard--panel-rail.is-panel-away {
  padding-right: var(--s-6);
}

.wiz__sidebar {
  transition:
    transform 440ms cubic-bezier(0.22, 0.61, 0.36, 1),
    opacity 440ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* DROGA PANELU = ZMIANA REZERWY.

   Panel przesuwa się dokładnie o tyle, o ile zmienia się padding kreatora
   (`--panel-shift` nadaje js/ui/simple.js). Przy translateX(100%) obie
   animacje miały ten sam czas, ale różne drogi — panel 380 px, rezerwa
   328 px — więc ich krawędzie rozjeżdżały się w połowie ruchu i padding
   wyglądał, jakby nie nadążał. Ta sama droga i ta sama krzywa znaczą
   jedną prędkość: krawędź panelu i krawędź treści idą sklejone.

   Krycie gaśnie razem z ruchem, więc panel znika, zanim zdąży się
   zatrzymać w połowie drogi. */
.wiz__sidebar.is-panel-away {
  transform: translateX(var(--panel-shift, 100%));
  opacity: 0;
}

/* Panel, który właśnie ustępuje miejsca (zwinięcie albo rozwinięcie).
   Stoi już poza kreatorem, w <body>, więc niczego nie zasłania i nie
   łapie kursora — ma tylko dojechać za krawędź i zniknąć. */
.wiz__sidebar.is-panel-leaving {
  pointer-events: none;
}

/* Powitanie: w tle stoi strona BEZ rezerwy — dokładnie tak, jak wygląda
   pierwsza klatka po podmianie. */
.wiz__hero-wizard.wizard--panel,
.wiz__hero-wizard.wizard--panel-rail {
  padding-right: var(--s-6);
  transition: none;
}

/* Potem KOLUMNA ETAPÓW — droga, którą klient ma przed sobą. Odstęp jest
   na tyle duży, żeby dało się je rozróżnić, i na tyle mały, żeby całość
   dalej czytała się jak jeden ruch. */
body.is-hero-arrive .wizard__side {
  animation: hero-side-in 440ms cubic-bezier(0.22, 0.61, 0.36, 1) 220ms both;
}

/* Znak w nagłówku gaśnie razem z treścią, ale zostaje na swoim miejscu —
   w przeglądzie stoi w tym samym rogu, tylko w innym kolorze. */
.wiz__hero.is-leaving ~ * .brand__logo,
body.is-hero .wiz__hero.is-leaving .brand__logo { opacity: 1; }

/* Przegląd wchodzący po powitaniu ma się WYŁONIĆ, a nie mrugnąć —
   stąd dłuższe wejście niż przy zwykłej zmianie kroku. */
.wiz__step--summary.wiz__step--enter {
  animation: wiz-in 520ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  .wiz__hero-glow { animation: none; }

  /* Bez ruchu nie ma czego wyłaniać ani czym wjeżdżać. */
  .wizard--panel,
  .wizard--panel-rail,
  .wiz__sidebar { transition: none; }

  /* Bez ruchu nie ma czego wyłaniać — kolumna etapów po prostu jest. */
  .wiz__hero-wizard .wizard__side { opacity: 1; }

  .wiz__hero.is-leaving .wiz__hero-content,
  .wiz__hero.is-leaving .made-with--hero,
  .wiz__hero.is-leaving .wiz__hero-page,
  .wiz__hero.is-leaving .wiz__hero-veil,
  .wiz__hero.is-leaving .wiz__hero-glow,
  .wiz__hero.is-leaving .gradient-canvas,
  body.is-hero-leaving .header,
  body.is-hero-arrive .header,
  body.is-hero-arrive .wizard__side,
  body.is-hero-arrive .wiz__sidebar,
  .wiz__hero-mark,
  .wiz__step--summary.wiz__step--enter { animation: none; }

  /* Ruch wyłączony w systemie znaczy „bez ruchu", a nie „bez treści" —
     elementy zostają widoczne, znika samo wejście. */
  .wiz__hero-bg,
  body.is-hero .brand__logo,
  .wiz__hero-project,
  .wiz__hero-title span,
  .wiz__hero-title b,
  .wiz__hero-lead,
  .wiz__hero-start,
  .made-with--hero {
    animation: none;
  }
}

.wiz__hero-content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-4);
  max-width: 760px;
  text-align: center;
  color: #ffffff;
}

.wiz__hero-project {
  margin: 0;
  font-size: var(--fs-16);
  color: rgba(255, 255, 255, 0.82);
}

.wiz__hero-project b { font-weight: 700; color: #ffffff; }

.wiz__hero-title {
  margin: 0;
  font-size: clamp(32px, 5.4vw, 60px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-weight: 400;
  color: #ffffff;
}

.wiz__hero-title b { font-weight: 700; }

.wiz__hero-lead {
  margin: 0;
  max-width: 560px;
  font-size: var(--fs-18);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}

/* Jedyny przycisk na ekranie — biały, żeby nie było wątpliwości, gdzie
   klient ma kliknąć. */
.wiz__hero-start {
  margin-top: var(--s-4);
  height: 48px;
  gap: var(--s-2);
  padding: 0 var(--s-6);
  background: #ffffff;
  color: var(--c-black);
  font-weight: 600;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}

.wiz__hero-start:hover { background: rgba(255, 255, 255, 0.9); }
.wiz__hero-start svg { display: block; }

/* Podpis narzędzia przy dolnej krawędzi, w kolorze tła powitania. */
.made-with--hero {
  position: relative;
  z-index: 1;
  margin-top: auto;
  padding-top: var(--s-8);
  color: rgba(255, 255, 255, 0.65);
}

.made-with--hero .made-with__mark { filter: invert(1); opacity: 0.8; }
.wiz__step--summary { max-width: 1100px; }

/* ---------------- Pasek etapów (pionowy) ---------------- */
.stepper {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

/* Wiersz jest przyciskiem — patrz js/ui/simple.js. Wygląd przycisku
   zdejmujemy do zera: klikalne ma być pole, a nie ramka wokół niego. */
.stepper__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.stepper__item[aria-current="true"] { cursor: default; }

/* Łącznik biegnie od kółka do kółka — rysuje go górna połowa każdego
   elementu, więc nie trzeba znać ich liczby. */
.stepper__item::before {
  content: "";
  position: absolute;
  /* Oś kółka: 26 px / 2 minus połowa grubości linii. Krok bieżący jest
     większy, ale przesunięty o -2 px, więc jego środek wypada tam samo. */
  left: 12.25px;
  bottom: 100%;
  height: var(--s-5);
  width: 1.5px;
  background: var(--c-line);
}

.stepper__item:first-child::before { display: none; }

/* Droga już przebyta jest czarna aż do bieżącego kroku; to, co przed
   klientem, zostaje szare. Odcinek NAD krokiem należy do tego kroku,
   więc wystarczy pomalować kroki zrobione i bieżący. */
.stepper__item.is-done::before,
.stepper__item.is-current::before { background: var(--c-ink); }

.stepper__dot {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px solid var(--c-line);
  background: var(--c-surface);
  font-size: var(--fs-12);
  font-weight: 650;
  color: var(--c-ink-muted);
  transition: background var(--t-fast) var(--e-out),
              border-color var(--t-fast) var(--e-out),
              color var(--t-fast) var(--e-out);
}

.stepper__dot svg { display: block; }

.stepper__item:hover .stepper__dot { border-color: var(--c-ink-muted); }
.stepper__item:hover .stepper__label { color: var(--c-ink); }

/* Zrobione — błękitne kółko z czarnym haczykiem i czarnym obrysem. */
.is-done .stepper__dot {
  border-color: var(--c-ink);
  background: var(--c-done);
  color: var(--c-done-ink);
}

.is-done .stepper__dot,
.is-current .stepper__dot { border-width: 1.5px; }

.stepper__item.is-done:hover .stepper__dot { border-color: var(--c-ink); }

/* Bieżący krok: czarne koło, biała cyfra — i o kilka pikseli większe,
   żeby oko znalazło je bez czytania. */
.is-current .stepper__dot {
  width: 30px;
  height: 30px;
  /* Ujemny margines ze wszystkich stron: koło rośnie na zewnątrz swojego
     miejsca, więc podpis obok zostaje w tej samej osi co pozostałe. */
  margin: -2px;
  border-color: var(--c-accent);
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

.stepper__item.is-current:hover .stepper__dot { border-color: var(--c-accent); }

.stepper__label {
  font-size: var(--fs-13);
  line-height: 1.35;
  color: var(--c-ink-muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color var(--t-fast) var(--e-out);
}

.is-current .stepper__label { color: var(--c-ink); font-weight: 600; }
.is-done .stepper__label { color: var(--c-ink); }

/* ---------------- Nagłówki ---------------- */
.wiz__title {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: var(--ls-tight);
  text-align: center;
  color: var(--c-ink);
}

.wiz__hint {
  font-size: var(--fs-14);
  color: var(--c-ink-muted);
  text-align: center;
  margin-top: calc(var(--s-3) * -1);
}

/* Skrót „Same as Desktop” — pod podpowiedzią, nad pasem wariantów.
   Cichy, bo to boczne wyjście z kroku, a nie odpowiedź na pytanie:
   odpowiedzi stoją w pasie, decyzję przyjmuje przycisk pod nim. */
.wiz__same {
  align-self: center;
  margin-top: calc(var(--s-2) * -1);

  /* Niższy od przycisków decyzji (44 px) — pod nagłówkiem kroku pełna
     pigułka ważyłaby tyle, co „Zatwierdź” pod pasem wariantów. */
  height: 32px;
  padding: 0 var(--s-4);
  font-size: var(--fs-13);
}

.wiz__lead {
  font-size: var(--fs-16);
  line-height: 1.6;
  color: var(--c-ink-soft);
  text-align: center;
  max-width: 520px;
}

.wiz__start { min-width: 200px; margin-top: var(--s-4); }

/* ---------------- Opcje ---------------- */
/* Opcje stoją obok siebie i są wyśrodkowane niezależnie od tego, ile
   ich jest — siatka o stałej liczbie kolumn rozstawiała dwa telefony
   na krańce ekranu. */
.wiz__options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-6);
  width: 100%;
}

/* Ekrany są tu treścią do porównania, więc żaden nie może być
   przygaszony — wybór poznaje się po obwódce i haczyku, nie po sile
   koloru. Przygaszona opcja czyta się jak niedostępna. */
/* Selektor musi być mocniejszy niż `.thumb:hover:not(:disabled)`
   z panelu bocznego, które przygaszało kadr do 0.8 przy najechaniu.
   Zamiast przygaszania ekran delikatnie się powiększa — reakcja jest
   widoczna, a podgląd nie traci na czytelności. */
.wiz__option.thumb,
.wiz__option.thumb:hover,
.wiz__option.thumb:hover:not(:disabled) { gap: var(--s-3); opacity: 1; }

.wiz__option.thumb .thumb__frame {
  transition: transform var(--t-fast) var(--e-out),
              border-color var(--t-mid) var(--e-out),
              box-shadow var(--t-mid) var(--e-out);
}

/* Wybrany ekran zostaje powiększony — widać go z drugiego końca stołu,
   a stan „wybrane" nie znika po zjechaniu kursorem. */
.wiz__option.thumb:hover .thumb__frame,
.wiz__option.thumb[aria-pressed="true"] .thumb__frame { transform: scale(1.02); }

.wiz__option.thumb:active .thumb__frame { transform: scale(0.995); }

/* Kadr trzyma proporcje telefonu i nie przekracza wysokości okna —
   krok musi mieścić się na ekranie razem z tytułem i nawigacją. */
.wiz__option .thumb__frame {
  display: block;               /* wysokość i proporcja działają tylko na bloku */
  /* Wysokość musi być konkretna, żeby proporcja wyliczyła szerokość —
     samo max-height zostawiłoby kadr bez wymiaru. */
  --wiz-thumb-h: min(52vh, 560px);
  height: var(--wiz-thumb-h);
  border-radius: var(--r-lg) !important;
  /* Szerokość liczymy sami z proporcji telefonu. Safari nie wyprowadza
     szerokości z `aspect-ratio`, gdy element jest pozycją flexa
     w kolumnie o nieokreślonej szerokości — kadr robił się wąski,
     a `object-fit: cover` przycinał ekran po bokach. Chrome i Firefox
     liczyły to poprawnie, więc usterka była widoczna tylko w Safari. */
  width: calc(var(--wiz-thumb-h) * 390 / 844);
  max-width: 100%;
  aspect-ratio: 390 / 844;
  margin: 0 auto;
  border-radius: var(--r-lg);
  box-shadow: var(--sh-2);
}

.wiz__option .thumb__image { height: 100%; }

/* Kadr strony: proporcje okna przeglądarki i ograniczenie SZEROKOŚCIĄ,
   nie wysokością — leżący kadr wyczerpuje szerokość dużo wcześniej niż
   wysokość okna. Szerokość bierzemy z komórki, a nie z okna: kolumna
   kreatora jest węższa niż ekran i sztywne 620 px mieściło tylko jeden
   kadr w rzędzie. */
.wiz__options--web { gap: var(--s-5); }

.wiz__options--web .wiz__option {
  flex: 0 1 calc(50% - var(--s-5));
  min-width: 260px;
  max-width: 620px;
}

.wiz__option--web .thumb__frame {
  height: auto;
  width: 100%;
  aspect-ratio: 1440 / 900;
}

.wiz__option[aria-pressed="true"] .thumb__frame {
  border-color: var(--c-accent);
  box-shadow: 0 0 0 2px var(--c-accent), var(--sh-2);
}

.wiz__option .thumb__check {
  top: var(--s-3);
  right: var(--s-3);
  width: 26px;
  height: 26px;
  border-width: 0;
}

.wiz__name {
  font-size: var(--fs-16);
  font-weight: 600;
  color: var(--c-ink);
  text-align: center;
}

.wiz__option[aria-pressed="false"] .wiz__name { color: var(--c-ink-muted); font-weight: 500; }

/* ---------------- Nawigacja kroków ---------------- */
/* „Continue" jest teraz głównym ruchem w kroku, więc ma wagę przycisku
   akcji, a nie linku obok. */
.wiz__next { min-width: 160px; }

.wiz__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  width: 100%;
  max-width: 860px;
  margin-top: var(--s-4);
}

/* ---------------- Podsumowanie ---------------- */
/* Kadr potrzebuje powietrza z obu stron: nad nim kończy się tekst kroku,
   pod nim zaczyna nawigacja. Przy ciasnym odstępie przełącznik ekranów
   czytał się jak część makiety, a nie jak sposób poruszania się po niej. */
.wiz__stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-7);
  margin-top: var(--s-3);
}

/* ZAKŁADKI EKRANÓW — JEDEN RZĄD W OKNIE.

   Przy kilkunastu ekranach łamały się na kilka rzędów i nawigacja
   ważyła więcej niż projekt, który opisuje. Teraz to okno, a pas
   z przyciskami przesuwa pod nim karuzela (js/ui/simple.js): aktywna
   zakładka stoi na osi, reszta czeka po bokach.

   Maska wygasza krawędzie, żeby rząd nie urywał się w pół słowa — ale
   tylko wtedy, gdy naprawdę jest co przewijać. Przy trzech ekranach
   przygaszone brzegi kłamałyby, że dalej coś jeszcze jest. */
.wiz__screens {
  max-width: 100%;
  overflow: hidden;
}

.wiz__screens.is-przewijalny {
  -webkit-mask-image: linear-gradient(90deg,
    transparent, #000 var(--s-7), #000 calc(100% - var(--s-7)), transparent);
  mask-image: linear-gradient(90deg,
    transparent, #000 var(--s-7), #000 calc(100% - var(--s-7)), transparent);
}

.wiz__screens__tor {
  display: flex;
  gap: var(--s-2);
  width: max-content;
  margin: 0 auto;                /* mieszczący się komplet zostaje na środku */
}

.wiz__screen {
  height: 32px;
  padding: 0 var(--s-4);
  /* W pasie zakładka trzyma swoją szerokość: ściśnięta nazwa ekranu
     łamałaby się na dwa wiersze i rozpychała rząd w pionie. */
  flex: 0 0 auto;
  white-space: nowrap;
  border-radius: var(--r-pill);
  font-size: var(--fs-13);
  color: var(--c-ink-muted);
  background: transparent;
  /* Zmiana tła i koloru pod kursorem ma być zauważalna, a nie nagła. */
  transition: background var(--t-fast) var(--e-out),
              color var(--t-fast) var(--e-out);
}

.wiz__screen:hover { background: var(--c-surface-hover); color: var(--c-ink); }

.wiz__screen[aria-pressed="true"] {
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

/* Telefon w podsumowaniu jest klonem podglądu, więc przejmujemy nad nim
   skalowanie: pudełko rezerwuje miejsce, a sam telefon się kurczy. */
.wiz__phone {
  /* Wartość wyjściowa; realną skalę liczy js/ui/simple.js z wysokości,
     jaka faktycznie zostaje pod telefonem (CSS nie umie tego wyrazić —
     min() z lengthem i liczbą to nieprawidłowa wartość). */
  --wiz-scale: 0.5;
  position: relative;
  width: calc(412px * var(--wiz-scale));
  height: calc(866px * var(--wiz-scale));
}

.wiz__phone .phone {
  position: absolute;
  top: 0;
  left: 0;
  transform: scale(var(--wiz-scale));
  transform-origin: top left;
}

.wiz__download { align-self: center; }

/* Okno przeglądarki zamiast telefonu — projekt typu Website / Web App.
   Ramka skaluje się sama (js/ui/frame.js), więc kolumna daje jej tylko
   szerokość i punkt odniesienia dla pinów komentarzy. */
.wiz__browser {
  width: 100%;
  display: flex;
  justify-content: center;
}

/* Lista komentarzy w kreatorze — ta sama treść co w panelu widoku
   zaawansowanego, tylko w kolumnie obok kadru. */
.wiz__comments {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  max-height: 100vh;
  overflow-y: auto;
  padding: 82px var(--s-4) var(--s-4);
}

/* Kolumna jest przewijana, więc jej zawartość ma zachować swoją wysokość.
   Bez tego flex ściskał wszystko po kolei — przycisk „Add comment" miał
   42 px w regule i 23 px na ekranie. */
.wiz__comments > * { flex: 0 0 auto; }

/* Duży przycisk w aplikacji ma 42 px — tak samo tutaj. */
.wiz__comment-add { height: 42px; }

.wiz__comment-add[aria-pressed="true"] {
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

/* ============================================================
   KOLUMNA KONFIGURACJI — LEWA KRAWĘDŹ PODSUMOWANIA

   Lustro panelu rozmowy z prawej: ta sama szerokość, ta sama krawędź,
   ten sam sposób trzymania się okna. Leży POZA krokiem (`fixed`), więc
   nie zabiera szerokości pasowi ekranów.

   Wcześniej ta lista stała paskiem POD kadrem i rosła w dół: przy pięciu
   warstwach spychała pas ekranów o dwieście pikseli i zmieniała jego
   skalę przy każdym przejściu na inny ekran. Z boku ma stałą szerokość
   i własne przewijanie, więc kadr stoi nieruchomo niezależnie od tego,
   ile warstw ma ekran.
   ============================================================ */
/* KOLUMNA NIE ZABIERA MIEJSCA PASOWI.

   Panel rozmowy po prawej odsuwa treść paddingiem, bo klient czyta
   w nim wątki i kadr ma mu nie wchodzić pod rękę. Tutaj jest odwrotnie:
   to lista do zerknięcia, a pas ekranów jest tym, po co klient tu
   przyszedł. Rezerwacja miejsca zwężałaby kolumnę kreatora, a z nią —
   przy projekcie webowym — same kadry stron (`skalujKadry` liczy skalę
   z jej szerokości). Kolumna leży więc NA treści, a sąsiedni slajd
   kończy się na jej krawędzi (js/ui/simple.js → `ustawWyciek`).

   Dzięki temu kadr stoi w tym samym miejscu i ma ten sam rozmiar
   niezależnie od tego, czy oglądany ekran ma warianty. */

.wiz__config {
  position: fixed;
  top: var(--h-header);
  left: 0;
  bottom: 0;
  width: var(--w-wiz-config);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-5) var(--s-4);
  border-right: 1px solid var(--c-line);
  background: var(--c-surface);
  z-index: 30;
}

/* Nagłówek: znaczek, nazwa oglądanego ekranu i podpis pod nią. */
.wiz__config-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex: 0 0 auto;
}

/* Pełne czarne koło z białą ikoną — jedyny mocny akcent w tej kolumnie.
   Reszta jest wyciszona, bo to lista do zerknięcia; gdyby wszystko
   krzyczało, nie byłoby wiadomo, od czego zacząć. */
.wiz__config-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

.wiz__config-badge svg { display: block; }

.wiz__config-titles {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.wiz__config-screen {
  font-size: var(--fs-16);
  font-weight: 700;
  color: var(--c-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wiz__config-sub {
  font-size: var(--fs-13);
  color: var(--c-ink-soft);
}

/* LISTA PRZEWIJA SIĘ SAMA.

   `min-height: 0` jest tu konieczne: element flex domyślnie nie kurczy
   się poniżej swojej treści, więc bez tego lista rozpychałaby kolumnę
   zamiast dostać własny pasek przewijania. Ujemne marginesy oddają
   kartom pełną szerokość kolumny, a padding zostawia miejsce na obrys
   ogniskowania i na sam pasek. */
.wiz__config-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin: 0 calc(var(--s-1) * -1);
  padding: 2px var(--s-1);
}

/* Karta: nazwa warstwy u góry, wybrany wariant pod nią. Biała, z cienkim
   obrysem — kolumna ma być spisem, a nie rzędem kolorowych plakietek. */
/* Nagłówek sekcji zestawu (Desktop / Tablet / Mobile). Cichy i mały —
   rozdziela karty, a nie konkuruje z nimi o uwagę. Pierwszy w kolumnie
   nie odsuwa się od nagłówka, bo lista ma już nad sobą odstęp. */
.wiz__config-group {
  flex: 0 0 auto;
  margin: var(--s-2) 0 0;
  font-size: var(--fs-12);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;

  /* Mierzone, nie na oko: `--c-ink-faint` (nazwa wariantu w karcie niżej)
     daje na białym 2.0:1, `--c-ink-muted` 2.6:1 — przy 12 px
     i wersalikach nagłówek byłby nie do przeczytania. `--c-ink-soft` to
     ten sam token, co podpis „Your configuration" w nagłówku kolumny. */
  color: var(--c-ink-soft);
}

.wiz__config-group:first-child { margin-top: 0; }

.wiz__config-row {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-3);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-card);
}

.wiz__config-name {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.wiz__config-icon {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--c-ink);
}

.wiz__config-icon svg { display: block; }

.wiz__config-layer {
  font-size: var(--fs-14);
  font-weight: 650;
  color: var(--c-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Wariant i ołówek w jednym rzędzie: nazwa bierze wolne miejsce
   i ucina się wielokropkiem, ikona trzyma się prawej krawędzi. */
.wiz__config-bottom {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

.wiz__config-variant {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-14);

  /* To jest ODPOWIEDŹ — co klient wybrał — więc nie może być
     najjaśniejszym tekstem na karcie. `--c-ink-faint` dawał na bieli
     1.98:1 (norma dla zwykłego tekstu to 4.5:1); ten sam token, co
     podpis „Your configuration" w nagłówku kolumny, daje 7.2:1.
     Nazwa warstwy zostaje mocniejsza, bo jest czarna i pogrubiona. */
  color: var(--c-ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Ołówek jest widoczny zawsze — przy jednej karcie na ekran chowanie go
   pod kursor znaczyłoby, że trzeba się domyślić, że da się coś zmienić. */
.wiz__config-edit {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--c-ink-faint);
  cursor: pointer;
  transition: color var(--t-fast) var(--e-out),
              background var(--t-fast) var(--e-out);
}

.wiz__config-edit svg { display: block; }

.wiz__config-edit:hover {
  background: var(--c-surface-hover);
  color: var(--c-ink);
}

/* Przycisk powrotu zamyka kolumnę od dołu: pełna szerokość, ciemny —
   to jedyna akcja w tej kolumnie, więc ma wyglądać jak akcja. */
.wiz__config > .wiz__summary-back {
  flex: 0 0 auto;
  width: 100%;
  justify-content: center;
  background: var(--c-accent);
  color: var(--c-accent-ink);
  border-color: var(--c-accent);
}

.wiz__config > .wiz__summary-back:hover { background: var(--c-black-hover); }

/* Wąskie okno: kolumna schodzi nad treść i przestaje być przyklejona —
   dwie kolumny boczne i kadr pośrodku nie mieszczą się naraz. */
@media (max-width: 1100px) {
  .wiz__config {
    position: static;
    width: auto;
    max-height: 40vh;
    margin-bottom: var(--s-5);
    border-right: 0;
    border-bottom: 1px solid var(--c-line);
    padding: 0 0 var(--s-4);
  }
}

/* POWRÓT W LEWYM GÓRNYM ROGU.

   Krok jest kolumną flex z `align-items: center`, więc sam przycisk
   dosuwamy do lewej krawędzi. `order: -1` stawia go przed wszystkim
   innym niezależnie od tego, w której kolejności trafił do drzewa —
   plakietka zatwierdzenia dochodzi przed nim tylko czasem.

   Ujemny margines dolny zabiera mu własną wysokość z układu: przycisk
   ma leżeć NA wysokości tytułu, a nie odsuwać kadr w dół. */
/* PRZYCISK W ROGU JEST POZA PRZEPŁYWEM — I TO JEST KONIECZNE.

   Ujemny margines nie wystarczał. Wysokość kadru liczy się z bilansu
   kroku (js/ui/simple.js → `miejsceDlaPasa`): sumujemy wysokości
   POZOSTAŁYCH dzieci i odejmujemy je od wysokości kreatora. Przycisk
   stojący w przepływie dokładał do tej sumy swoje 44 px plus odstęp —
   a pojawia się tylko na ekranach BEZ wariantów (na pozostałych siedzi
   w kolumnie konfiguracji). Kadr rósł i malał przy każdym przejściu
   między takimi ekranami: 0.471 kontra 0.522 skali, czyli skok o 44 px.

   Poza przepływem nie wchodzi do bilansu w ogóle, więc kadr ma ten sam
   rozmiar niezależnie od tego, gdzie akurat mieszka przycisk. */
.wiz__step--summary { position: relative; }

.wiz__step .wiz__summary-back {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  gap: var(--s-2);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  color: var(--c-ink);
}

.wiz__step .wiz__summary-back:hover { background: var(--c-surface-hover); }

.wiz__summary-back { gap: var(--s-2); }

/* Strzałka w lewo — ten sam chevron co wszędzie, obrócony. */
.wiz__summary-back svg { transform: rotate(90deg); }

@media (max-width: 900px) {
  /* Na wąskim ekranie nie ma z czego zabierać wysokości — przycisk
     wraca do normalnego przepływu. */
  .wiz__summary-back { margin-bottom: 0; }
}

@media (max-width: 620px) {
  .wiz__picked-row { flex-wrap: wrap; }
  .wiz__picked-change { margin-left: auto; }
}

.wiz__approve { height: 52px; font-size: var(--fs-16); }

/* ---------------- Okno zatwierdzenia ---------------- */
/* Imię pytamy dopiero w oknie po kliknięciu w zatwierdzenie (simple.js,
   zatwierdź) — na ekranie zostaje sam przycisk decyzji.

   Okno korzysta z .cms-confirm, ale układ ma własny: wszystko w osi,
   od znaku na górze po parę przycisków na dole. To ostatnia decyzja
   w całej wizycie i jedyne miejsce, gdzie okno mówi „popatrz tutaj". */
.wiz__approve-box {
  max-width: 360px;
  align-items: center;
  gap: var(--s-3);
  text-align: center;
  padding: var(--s-6) var(--s-7) var(--s-7);

  /* Mleczna szyba: okno przepuszcza projekt, który klient właśnie
     zatwierdza. Rozmycie działa tylko przy przezroczystym tle, więc
     jedno bez drugiego nie ma sensu. Starsze przeglądarki dostają
     pełne tło z pierwszej deklaracji. */
  background: var(--c-surface);
  background: color-mix(in srgb, var(--c-surface) 92%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.wiz__approve-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-pill);
  background: var(--c-brand);
  color: var(--c-brand-ink);
}

.wiz__approve-mark svg { display: block; }

/* Pieczęć w oknie sukcesu wchodzi w kadr: koło najpierw, znak chwilę
   po nim. Jeden spokojny ruch — potwierdzenie, nie fajerwerki. */
@keyframes wiz-mark-in {
  from { opacity: 0; transform: scale(0.86); }
  to   { opacity: 1; transform: none; }
}

.wiz__approve-mark--in { animation: wiz-mark-in var(--t-mid) var(--e-out) both; }

.wiz__approve-mark--in svg {
  animation: wiz-mark-in var(--t-slow) var(--e-out) both;
  animation-delay: 90ms;
}

@media (prefers-reduced-motion: reduce) {
  .wiz__approve-mark--in,
  .wiz__approve-mark--in svg { animation: none; }
}

/* Kto i kiedy zatwierdził — w oknie sukcesu pod tekstem. */
.wiz__approve-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: var(--s-3);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-surface-sunk);
}

.wiz__approve-meta-name {
  font-size: var(--fs-14);
  letter-spacing: var(--ls-tight);
  color: var(--c-ink);
}

.wiz__approve-meta-date {
  font-size: var(--fs-12);
  color: var(--c-ink-muted);
}

/* Ten sam fakt w podsumowaniu — stan, który klient zastaje po powrocie. */
.wiz__approved {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  align-self: center;
  /* Siedzi tuż nad tytułem kroku — ujemny margines ściąga ją bliżej
     niż wynosi odstęp między elementami kroku. */
  margin: 0 auto calc(-1 * var(--s-3));
  padding: 6px var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-brand-tint);
  font-size: var(--fs-13);
  color: var(--c-brand);
}

.wiz__approved svg { display: block; }

.wiz__approve-box .np-confirm__title { margin: var(--s-1) 0; font-size: var(--fs-18); }

/* Podpis pod pytaniem trzyma się jego szerokości — pełny wiersz
   rozjeżdżałby się na dwie różne osie z resztą okna. */
.wiz__approve-box .wiz__approve-field { margin-top: var(--s-1); }

.wiz__approve-field {
  position: relative;
  width: 100%;
}

.wiz__approve-field-icon {
  position: absolute;
  top: 50%;
  left: 14px;
  transform: translateY(-50%);
  display: inline-flex;
  color: var(--c-brand);
  pointer-events: none;
}

.wiz__approve-field-icon svg { display: block; }

.wiz__approve-field .cms-input {
  height: 48px;
  padding-left: 42px;
  border-radius: var(--r-pill);
  font-size: var(--fs-14);
}

.wiz__approve-actions {
  width: 100%;
  justify-content: center;
  gap: var(--s-3);
}

.wiz__approve-actions .btn { flex: 1 1 0; min-width: 0; }

/* ---------------- Przełącznik trybów ---------------- */
/* Wyjście do trybu zaawansowanego to jedyna alternatywa dla kreatora,
   więc musi być widoczne jak przycisk, a nie jak szary podpis. */
.mode-link {
  height: 34px;
  padding: 0 var(--s-4);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-pill);
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--c-ink);
  background: var(--c-surface);
  white-space: nowrap;
  transition: background var(--t-fast) var(--e-out),
              border-color var(--t-fast) var(--e-out);
}

.mode-link:hover { background: var(--c-surface-hover); border-color: var(--c-accent); }

/* ---------------- Wąskie ekrany ---------------- */
/* ============================================================
   NAWIGACJA KARUZELI WARIANTÓW

   Kropki mówią, ile jest opcji i przy której jesteśmy; strzałki dają
   wyjście tym, którzy nie przesuwają palcem. Na desktopie wszystkie
   kadry są widoczne naraz, więc pasek jest ukryty (display: none) —
   pokazuje go dopiero reguła w media query dla telefonu.
   ============================================================ */
.wiz__carousel {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  padding: 0 var(--s-4);
}

.wiz__dots {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.wiz__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--c-line-strong);
  cursor: pointer;
  transition: background var(--t-fast) var(--e-out),
              transform var(--t-fast) var(--e-out);
}

.wiz__dot[aria-current="true"] {
  background: var(--c-accent-2);
  transform: scale(1.35);
}

/* Pole dotyku ma mieć 44 px, a kropka 8 — powiększamy je przezroczystym
   obrysem zamiast samej kropki, żeby nie rozpychać paska. */
.wiz__dot::after {
  content: "";
  position: absolute;
  inset: -18px;
}

.wiz__dot { position: relative; }

.wiz__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border: 1px solid var(--c-line);
  border-radius: 50%;
  background: var(--c-surface);
  color: var(--c-ink);
  cursor: pointer;
}

.wiz__arrow:disabled { opacity: 0.35; cursor: default; }

.wiz__arrow--prev svg { transform: rotate(90deg); }
.wiz__arrow--next svg { transform: rotate(-90deg); }

@media (max-width: 900px) {
  /* Nie ma miejsca na kolumnę — etapy wracają nad treść jako rząd kółek */
  .wizard__side {
    position: static;
    transform: none;
    width: auto;
    margin-bottom: var(--s-5);
  }

  .stepper { flex-direction: row; justify-content: center; gap: var(--s-4); }
  .stepper__item::before {
    left: auto;
    right: 100%;
    bottom: auto;
    top: 12.5px;
    width: var(--s-4);
    height: 1.5px;
  }

  .stepper__label { display: none; }

  .wiz__options { gap: var(--s-4); }
  .wizard {
    --wiz-pad-top: var(--s-6);
    padding: var(--wiz-pad-top) var(--s-4) var(--wiz-pad-bottom);
  }
  .wiz__title { font-size: 22px; }
}

/* ---------------- Postęp ---------------- */
/* Nad paskiem etapów: kropki mówią „gdzie jestem", licznik „ile zostało". */
.wiz__progress {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: var(--s-5);
}

.wiz__progress-text {
  margin: 0;
  font-size: var(--fs-12);
  font-weight: 600;
  letter-spacing: var(--ls-tight);
  color: var(--c-ink-muted);
}

.wiz__progress-track {
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--c-line);
  overflow: hidden;
}

.wiz__progress-fill {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--c-accent-2);
  transition: width var(--t-mid) var(--e-out);
}

/* ---------------- Termin akceptacji ---------------- */
.wiz__due {
  margin: 0;
  font-size: var(--fs-13);
  color: var(--c-ink-muted);
  text-align: center;
}

.wiz__due--soon { color: var(--c-ink); font-weight: 600; }
.wiz__due--overdue { color: var(--c-danger-text); font-weight: 600; }

/* ============================================================
   TELEFON (≤ 600 px)

   Na telefonie klient ogląda projekt telefonu — kadr musi więc zostać
   duży, a wszystko dookoła zejść z drogi. Trzy decyzje:

   1. Warianty jadą w POZIOMIE, jeden ekran naraz, z przyciąganiem.
      Ułożone w kolumnie dawały stronę na 1900 px: klient przewijał
      trzy telefony w dół, żeby dojść do przycisku, i nie widział
      dwóch wariantów obok siebie — czyli traciło sens porównywanie.
   2. Przyciski kroku siedzą na dole ekranu i nie odjeżdżają z treścią.
   3. Kropki etapów znikają — pasek postępu z licznikiem mówi to samo,
      a zajmuje jeden wiersz zamiast trzech.
   ============================================================ */
@media (max-width: 600px) {
  .wizard {
    --wiz-pad-top: var(--s-5);
    --wiz-pad-bottom: 0px;
    padding: var(--wiz-pad-top) 0 var(--wiz-pad-bottom);
  }

  .wizard__side { margin-bottom: var(--s-4); padding: 0 var(--s-4); }
  .stepper { display: none; }
  .wiz__progress { margin-bottom: 0; }

  /* Margines trzyma sam krok, a nie kreator: karuzela wariantów musi
     sięgać krawędzi ekranu, więc marginesu nie da się dać wyżej. */
  .wiz__step { gap: var(--s-4); }
  .wiz__step--intro { padding: 0 var(--s-4); }
  .wiz__title { font-size: 20px; padding: 0 var(--s-4); }
  .wiz__hint,
  .wiz__lead,
  .wiz__due { padding: 0 var(--s-4); }

  /* Karuzela: kadr sąsiada wystaje zza krawędzi, więc od razu widać,
     że jest więcej opcji i w którą stronę przewijać. */
  .wiz__options {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: var(--s-3);
    padding: 0 var(--s-4) var(--s-2);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .wiz__options::-webkit-scrollbar { display: none; }

  .wiz__options .wiz__option {
    flex: 0 0 78%;
    max-width: 78%;
    scroll-snap-align: center;
  }

  .wiz__option .thumb__frame { height: min(52vh, 460px); }

  /* Nawigacja karuzeli pokazuje się dopiero tam, gdzie kadry nie mieszczą
     się obok siebie — na szerokim ekranie nie ma czego przesuwać. */
  .wiz__carousel { display: flex; }
  .wiz__options--web .wiz__option { flex: 0 0 88%; max-width: 88%; min-width: 0; }

  /* Przyciski zawsze pod ręką — inaczej „Continue" ucieka pod kadry. */
  .wiz__nav {
    position: sticky;
    bottom: 0;
    max-width: none;
    margin-top: var(--s-3);
    padding: var(--s-3) var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom, 0px));
    background: var(--c-surface);
    border-top: 1px solid var(--c-line);
    gap: var(--s-3);
  }

  .wiz__nav .btn { flex: 1 1 0; min-width: 0; }
  .wiz__next { min-width: 0; }

  /* Podsumowanie: zakładki zostają jednym pasem — na wąskim ekranie tym
     bardziej, bo rzędów przycisków zmieściłoby się tu jeszcze mniej. */
}


/* ============================================================
   TRYB STRONY: ETAPY — EKRAN — ROZMOWA

   Trzy kolumny, z których dwie skrajne stoją poza przepływem:
   etapy przy lewej krawędzi, rozmowa przy prawej. Treść kroku
   zostaje na osi okna i to ona dostaje całą resztę miejsca.
   ============================================================ */

/* SZEROKOŚĆ ROZMOWY JEST REGULOWANA.

   Jedna liczba w dwóch miejscach: kolumna ma ją jako szerokość, a kreator
   jako rezerwę po prawej (szerokość plus odstęp). Trzyma ją zmienna, bo
   przeciąganie krawędzi zmienia obie naraz — i ta sama wartość musi
   trafić do rachunku drogi panelu w js/ui/simple.js. */
:root { --w-wiz-side: 380px; }

.wizard--panel { padding-right: calc(var(--w-wiz-side) + 20px); }
.wizard--panel-rail { padding-right: 72px; }

.wiz__sidebar {
  position: fixed;
  top: var(--h-header);
  right: 0;
  bottom: 0;
  width: var(--w-wiz-side);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: 0;
  border-left: 1px solid var(--c-line);
  background: var(--c-surface);
  z-index: 30;
}

/* W trakcie ciągnięcia nic się nie animuje i nic nie zaznacza — kolumna
   ma iść dokładnie za kursorem, a nie doganiać go przejściem. */
.is-resizing-side,
.is-resizing-side .wizard--panel,
.is-resizing-side .wizard--panel-rail,
.is-resizing-side .wiz__zoom-side,
.is-resizing-side .wiz__zoom-side__inner,
.is-resizing-side .wiz__sidebar { transition: none !important; }

.is-resizing-side { cursor: col-resize; user-select: none; }

/* Podpis narzędzia zamyka kolumnę rozmowy — pod listą wątków, przy
   dolnej krawędzi panelu. Lista przewija się nad nim. */
.wiz__sidebar .made-with {
  flex: 0 0 auto;
  margin: 0;
  padding-top: var(--s-3);
  border-top: 1px solid var(--c-line);
}

/* --- panel zwinięty: wąski pasek z pionową etykietą --- */
.wiz__sidebar.is-collapsed {
  width: 56px;          /* pasek nie jest regulowany — nie ma w nim czego szerzyć */
  align-items: center;
  padding: var(--s-4) 0;
  gap: var(--s-5);
}

/* --- kadr strony --- */

/* Obrys ramki w kreatorze jest ledwie widoczny: ma zamykać kadr, a nie
   obwodzić go jasną linią, która czyta się jak zaznaczenie. */
.wiz__browser .browser { border-color: var(--c-line); }

/* BIEL MAKIETY ZOSTAJE POD GRAFIKĄ, NIE NA KRAWĘDZI.

   Makieta przeglądarki ma własne, białe tło (css/browser.css) — pod nim
   leży projekt, więc normalnie biel jest niewidoczna. Ale ramka jest
   zaokrąglona i przycięta („overflow: hidden"), a pas przesuwa się
   transformem: przy ułamkowych pozycjach pikseli krawędź przycięcia
   wygładza się z tłem SPOD spodu i biel prześwituje na obwodzie. W jasnym
   motywie tego nie widać, w ciemnym Firefoksie to mrugający jasny obrys.

   W kadrach kreatora tłem jest więc powierzchnia motywu: w ciemnym
   ciemna, w jasnym ta sama biel co dotąd. Powiększenie i panel zostają
   bez zmian — tam nic się nie przesuwa. */
.wiz__browser {
  /* Kolor liczony TU, poza makietą: wewnątrz `.browser__page` tokeny
     wracają do motywu jasnego (css/tokens.css), bo tam zaczyna się
     projekt klienta i ciemny motyw nie ma prawa go przemalować. */
  --kadr-tło: var(--c-surface);
}

.wiz__browser .browser {
  background: var(--kadr-tło);
  background-clip: padding-box;
}

/* Korpus urządzenia zostaje korpusem: biel, przed którą broni
   `--kadr-tło`, jest tu zakryta ekranem (css/browser.css). */
.wiz__browser .browser--device { background: var(--phone-frame); }

/* Stronę przemalowujemy TYLKO wtedy, gdy ekran jest JEDNĄ GRAFIKĄ
   (`.layer--page` — import z Figmy). Wtedy tło i tak jest zakryte
   w całości, więc jego kolor widać wyłącznie na wygładzanej krawędzi.
   Ekranów złożonych z sekcji to nie dotyczy: tam tło strony jest częścią
   projektu i zostaje białe w każdym motywie. */
.wiz__browser .browser__page:has(.layer--page) {
  background: var(--kadr-tło);
}

/* Ramka strony ma 1440 px w naturze i kurczy się transformem. Żeby
   wiedzieć, DO ILU ma się skurczyć, kolumna musi umieć zmaleć poniżej
   swojej zawartości — bez „min-width: 0" element flex trzyma szerokość
   treści, kadr mierzył 1440 px jako „dostępne miejsce" i zostawał
   w skali 1:1, wychodząc poza ekran. */
.wizard__main > * { min-width: 0; }

.wiz__step--summary .wiz__stage {
  width: 100%;
  min-width: 0;
}

.wiz__browser {
  position: relative;
  max-width: 100%;
}

/* Powiększenie ma własny przycisk w rogu ramki — z dala od środka, gdzie
   lądują piny komentarzy. Widoczny zawsze, nie dopiero po najechaniu:
   kontrolka, której nie widać, dla klienta nie istnieje. */
.wiz__zoom {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 5;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  /* `--c-card`, nie `--c-surface`: w ciemnym motywie powierzchnia jest
     prawie kanwą i kółko znikało; karta ma własny, jaśniejszy odcień.
     W jasnym to ta sama biel. Token cienia był kiedyś `--sh-sm` — nigdy
     nie istniał, więc zawsze szedł zapasowy, jasny cień. */
  border: 1px solid var(--c-line-strong);
  background: var(--c-card);
  color: var(--c-ink-muted);
  box-shadow: var(--sh-1);
}

.wiz__zoom:hover {
  color: var(--c-ink);
  border-color: var(--c-line-strong);
}

/* --- karuzela ekranów w podsumowaniu --- */

/* Trzy kadry w rzędzie, środek na osi kolumny. Sąsiedzi mają tę samą
   szerokość co środek, więc wystają symetrycznie i przycina ich krawędź
   — to ten sam sygnał co kadr sąsiada w karuzeli wariantów: „jest tego
   więcej, przesuń się". */
.wiz__slider {
  display: flex;
  align-items: center;

  /* Pas ustawia się transformem, więc zaczyna się od lewej — wyśrodkowanie
     robi przesunięcie, nie układ. */
  justify-content: flex-start;

  /* Przycinamy WYŁĄCZNIE w poziomie. „overflow: hidden" ucinał też
     w pionie, a cień kadru sięga 180 px w dół (--sh-phone) — stąd widoczna
     krawędź pod pasem. clip-path z ujemną górą i dołem obcina po bokach
     i puszcza cień. */
  overflow: visible;
  clip-path: inset(-240px 0 -240px 0);

  /* Pas da się chwycić — kursor mówi o tym, zanim ktoś spróbuje. */
  cursor: grab;
  user-select: none;
}

/* Klasa NIE nazywa się „is-dragging": tak nazywa się przeciągana karta
   w panelu (css/cms.css) i ta reguła dokładała pasowi cień, obrys oraz
   własną przezroczystość. Karuzela ma swoją nazwę i swoje zasady. */
.wiz__slider.is-swiping { cursor: grabbing; }

/* Cieni sąsiadów w ruchu NIE gasimy, choć nakładają się na siebie:
   zmiana box-shadow to przerysowanie całego kadru, a w Safari widać je
   jako białe mrugnięcie (patrz .wiz__slide wyżej). Smuga pod pasem jest
   mniejszym złem niż mrugający projekt. */

/* Kadr ekranu to obrazy: bez tego przeglądarka zaczyna własne
   przeciąganie obrazka zamiast przesuwać karuzelę. */
.wiz__slider img { -webkit-user-drag: none; user-drag: none; }

/* Firefox nie zna „user-drag" i zaczyna natywne przeciąganie obrazka —
   pas przestaje wtedy dostawać zdarzenia ruchu i w ogóle nie jedzie.
   Atrybut draggable="false" nadaje js/ui/simple.js (przygotujObrazy),
   a to poniżej wyłącza jeszcze zaznaczanie tekstu w kadrach. */
.wiz__slider, .wiz__slider * { -moz-user-select: none; }

.wiz__track {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  touch-action: pan-y;          /* pion zostaje przewijaniem strony */
}

/* BEZ „will-change" — I TO JEST DECYZJA, NIE PRZEOCZENIE.

   Podpowiedź o własnej warstwie graficznej miała pomóc płynności, ale
   kosztowała więcej, niż dawała. Przeglądarka rasteryzuje wtedy cały pas
   osobno i na krawędziach zaokrąglonej makiety prześwituje jej własne,
   BIAŁE tło (.browser w css/browser.css) — w ciemnym motywie Firefoksa
   widać to jako mrugający jasny obrys w trakcie przewijania.

   Przesunięcie transformem i tak jedzie po stronie kompozytora, więc
   płynności nie tracimy. Pamięć kadrów rozwiązały lekkie kopie obrazów
   (js/ui/simple.js), a nie ta podpowiedź. */

.wiz__slide {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: transparent;
  /* Przycisk centruje tekst po swojemu — kadr w środku ma wyglądać
     dokładnie tak samo jak ten na środku karuzeli. */
  text-align: initial;
  font: inherit;
  color: inherit;
  opacity: 0.32;
  cursor: pointer;

  /* BEZ „filter" I BEZ ZMIENNEGO CIENIA — to Safari.

     Sąsiad miał tu delikatne odbarwienie (saturate 0.9), a na czas
     przeciągania gasł mu cień. Jedno i drugie każe Safari rysować kadr
     do osobnego bufora i przerysowywać go od zera, gdy efekt się zmienia:
     przy grafikach wysokich na 2880 px kadr bielał na ułamek sekundy.
     Przygaszenie samym kryciem robi kompozytor — nic nie trzeba
     przerysowywać, a różnicy w wyglądzie nie widać.

     Środkowy kadr nie jest .wiz__slide, więc nigdy tego nie miał — stąd
     mrugały wyłącznie kadry po bokach. */
}

/* WIELKOŚĆ MÓWI, KTÓRY KADR JEST TERAZ OGLĄDANY.

   Kadr na osi zostaje w swojej skali (to ona wyznacza wysokość kroku),
   a sąsiedzi są od niego o dziesiątą część mniejsi. Skalujemy transformem,
   więc miejsce w pasie zostaje TO SAMO dla każdego slajdu — inaczej
   trzeba by przeliczać krok karuzeli osobno dla każdej pary sąsiadów. */
.wiz__slide { --slajd: 0.9; }
.wiz__track > .browser-fit,
.wiz__track > .wiz__phone { --slajd: 1; }

/* Kadr na osi to prawdziwy podgląd, a nie .wiz__slide — pełne krycie
   i skalę ma z samego CSS. Gdy karuzela zostawi go z boku (klasę nadaje
   js/ui/simple.js), musi wyglądać jak każdy inny sąsiad. Bez tego
   przy szybkim przewijaniu rozbłyskiwał na 100%, choć był już drugi
   albo trzeci w kolejce. */
.wiz__track > .browser-fit.is-obok,
.wiz__track > .wiz__phone.is-obok { opacity: 0.32; --slajd: 0.9; }

.wiz__slide,
.wiz__track > .browser-fit,
.wiz__track > .wiz__phone {
  transform: scale(var(--slajd, 1));
  transform-origin: center center;
}

/* Jasność i wielkość zmieniają się w tym samym rytmie co ruch pasa —
   kadr wjeżdżający na środek rozjaśnia się i rośnie po drodze, a nie
   dopiero na miejscu. */
.wiz__slide,
.wiz__track > .browser-fit,
.wiz__track > .wiz__phone {
  transition: opacity 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* W trakcie przeciągania jedno i drugie ma nadążać za palcem, nie za zegarem. */
.wiz__slider.is-swiping .wiz__slide,
.wiz__slider.is-swiping .wiz__track > .browser-fit,
.wiz__slider.is-swiping .wiz__track > .wiz__phone { transition: none; }

/* SLAJD NA OSI W PASIE WARIANTÓW.

   W podsumowaniu kadr na osi jest gołym `.browser-fit` i pozna go po
   budowie. W kroku wyboru wszystkie slajdy są przyciskami (bo pas nie
   przebudowuje kroku po dojeździe — js/ui/simple.js → `wariantyPas`),
   więc oś wyróżnia klasa. Krycia ani skali tu NIE ustawiamy: nadaje je
   karuzela stylem w linii, a ten i tak wygrywa. */
.wiz__slide.is-na-osi {
  cursor: zoom-in;                 /* klik powiększa, nie przewija */
}

/* Sąsiad rozjaśnia się pod kursorem — to zaproszenie do przesunięcia.
   Slajd na osi nie: jego krycie trzyma karuzela stylem w linii, a sam
   nie jest „następny do obejrzenia". */
.wiz__slide:not(.is-na-osi):hover { opacity: 0.55; }

/* Nazwa wariantu pod pasem — jedna, dla tego, co stoi na osi. */
.wiz__slide-name {
  margin: 0;
  min-height: 1.5em;               /* miejsce trzyma się przy zmianie nazwy */
}

/* Sąsiad jest podglądem, nie makietą do klikania — całe kliknięcie
   należy do przycisku, który go niesie. */
.wiz__slide .browser { pointer-events: none; }

/* ============================================================
   PAS WARIANTÓW W PROJEKCIE MOBILNYM

   Ta sama karuzela co przy stronach, tylko slajdem jest telefon.
   Pas strony niesie klasę `.wiz__browser` i razem z nią reguły wyjścia
   poza krok (--wyciek): kadr strony bywa szerszy od kolumny, więc musi
   sięgać krawędzi okna. Telefon jest wąski — trzy mieszczą się
   w kolumnie kroku w całości, więc pasowi wystarczy jej szerokość.
   ============================================================ */
.wiz__slider--phone {
  /* Krok jest kolumną flex z „align-items: center", a w niej element
     bez własnej szerokości kurczy się do treści — pas musiałby wtedy
     stać w miejscu wyznaczonym przez sumę slajdów, a nie przez kolumnę,
     i oś (środek `.wizard__main`) wypadłaby poza nim. */
  align-self: stretch;
  width: 100%;
}

/* Telefon w slajdzie skaluje się tak samo jak ten w podsumowaniu —
   pudełko rezerwuje miejsce, a sam telefon się kurczy (.wiz__phone
   wyżej). Liczbę podaje js/ui/simple.js → skalujTelefony. */
.wiz__slide .wiz__phone { flex: 0 0 auto; }

/* To samo, co `.wiz__slide .browser`: makieta jest podglądem, całe
   kliknięcie należy do przycisku slajdu. Bez tego klik w warstwę
   telefonu nie dochodził do niego i slajd nie dawał się przesunąć. */
.wiz__slide .phone { pointer-events: none; }

/* Pas telefonów — odpowiednik `.wiz__browser` dla projektu mobilnego.
   Telefony są wąskie, więc pas bierze szerokość kolumny i nie wychodzi
   poza krok; wyjście poza krawędź (--wyciek) należy do kadrów stron,
   które bywają szersze od kolumny. */
.wiz__phones {
  width: 100%;
  display: flex;
  justify-content: center;
}

/* W PASIE POZYCJĘ PROWADZI TRANSFORM, NIE UKŁAD.

   `.wiz__phones` wyśrodkowuje pojedynczy telefon — ale gdy jest pasem,
   wyśrodkowanie dokłada się do przesunięcia karuzeli i telefon ucieka
   w bok o pół szerokości kolumny. Pas zaczyna się od lewej, a na oś
   dowozi go `translateX`. Dwie klasy w selektorze celowo: musi wygrać
   z regułą wyżej. */
.wiz__phones.wiz__slider {
  align-self: stretch;
  justify-content: flex-start;
}


/* NAWIGACJA PASA JEST WIDOCZNA ZAWSZE.

   Pasek pod siatką miniatur (`.wiz__carousel`) ma sens tylko na wąskim
   ekranie — na szerokim wszystkie kadry siatki widać naraz i nie ma
   czego przesuwać, więc reguła wyżej trzyma go schowanego do media
   query. W pasie jest odwrotnie: zawsze jedna opcja stoi na osi,
   a sąsiedzi są przygaszeni i przycięci krawędzią — kropki są wtedy
   jedynym miejscem, w którym widać, ile tych opcji jest. */
.wiz__carousel--pas { display: flex; }

/* ============================================================
   STOS KARTEK POD KADREM

   Pod ekranem, który ma warianty, leżą dwie podsunięte kartki — to samo,
   co w świecie papieru mówi „tych wersji jest więcej". Ekran bez wyboru
   stosu nie dostaje (klasę nadaje js/ui/simple.js), bo obiecywałby
   głębię, której tam nie ma.

   Rysują go pseudo-elementy SAMEGO kadru, a nie osobne węzły: karuzela
   mierzy slajdy przez `offsetWidth` i każdy dodatkowy element w pasie
   musiałaby wliczyć w pozycję. Pseudo-element leży poza układem, więc
   nie rusza niczego.

   Ujemny `z-index` chowa kartki pod makietą; kadr ma własny kontekst
   nakładania (`position: relative`), więc nie wypadają pod tło kroku.
   Bliższa kartka leży na -1, dalsza na -2 — patrz niżej.
   ============================================================ */
.is-stacked::before,
.is-stacked::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: -7px;
  width: 94%;
  height: 40px;
  transform: translateX(-50%);
  border-radius: 0 0 14px 14px;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-top: 0;
  box-shadow: 0 10px 24px rgba(16, 17, 26, 0.06);
}

/* Druga kartka jest węższa i leży głębiej — dwie równe wyglądałyby jak
   gruba ramka, a nie jak stos.

   `z-index: -2` jest tu konieczne, a nie kosmetyczne: przy równym
   z-indeksie o kolejności rozstrzyga porządek w drzewie, więc `::after`
   rysował się NAD `::before` — dalsza kartka zachodziła na bliższą
   i stos wyglądał odwrotnie, niż leży. */
.is-stacked::after {
  z-index: -2;
  bottom: -14px;
  width: 88%;
  box-shadow: 0 12px 28px rgba(16, 17, 26, 0.05);
}

/* Sąsiedzi stosu nie dostają: stoją przygaszeni i przycięci krawędzią
   pasa, więc kartki pod nimi byłyby szumem. Klasę i tak dostaje tylko
   kadr na osi — to jest zabezpieczenie na wypadek przebudowy pasa. */
.wiz__slide .is-stacked::before,
.wiz__slide .is-stacked::after { display: none; }

/* --- powiększenie --- */
.wiz__zoomer .wiz__zoom { display: none; }

/* NAKŁADKA POWIĘKSZENIA — PODGLĄD I ROZMOWA OBOK SIEBIE.

   Dwie kolumny, razem cała szerokość okna: rozmowa nie kładzie się na
   ekranie, tylko odbiera mu część miejsca, a kadr zmniejsza się o tyle
   samo (js/ui/simple.js przelicza skalę obserwatorem rozmiaru).

   Bez rozmowy druga kolumna ma zero szerokości, więc podgląd dostaje
   wszystko — dokładnie jak przedtem. */
.wiz__zoomer {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;

  /* Tor bierze szerokość Z KOLUMNY, a nie odwrotnie — to ona jest
     animowana (patrz `.wiz__zoom-side`). `grid-template-columns` nie
     nadaje się do przejścia: wartość z `var()` nie uruchamia go wcale,
     a bez tego zwijanie nie zwalniało ani piksela miejsca. Szerokość
     zwykłego bloku animuje się bez niespodzianek, a tor „auto" idzie
     za nią klatka w klatkę. */
  grid-template-columns: minmax(0, 1fr) auto;

  /* Rozmowa wyjeżdża poza prawą krawędź — nakładka ją tam przycina,
     żeby nie dołożyła paska przewijania stronie pod spodem. */
  overflow: hidden;
  background: rgba(10, 11, 12, 0.86);
}

/* Dwie szerokości kolumny: pełna rozmowa albo sam pasek (js/ui/simple.js
   → pokażRozmowę). Bez paska siatka zwinęłaby ją do zera i nie byłoby
   czym rozmowy otworzyć. */
.wiz__zoomer.has-side .wiz__zoom-side { width: var(--w-zoom-side, 380px); }
.wiz__zoomer.has-side-rail .wiz__zoom-side { width: 56px; }

/* PASEK LEŻY POD ROZMOWĄ, W TYM SAMYM MIEJSCU KOLUMNY.

   Oba stany są w jednym drzewie i oba są WIDOCZNE — nie przełączamy
   `display`, bo z niego nie da się animować. Rozmowa zjeżdża w prawo,
   kolumna zwęża się razem z nią, a spod spodu wyłania się pasek.
   Sam pasek maluje `.wiz__sidebar-railbox` w css/comments.css, wspólnie
   z panelem; tutaj zostaje tylko to, co u klienta własne. */
.wiz__zoomer .wiz__sidebar-railbox {
  display: flex;
  position: absolute;
  top: 0;
  right: 0;
  width: 56px;
  opacity: 0;

  /* `visibility` schodzi DOPIERO po ruchu (i wraca od razu), więc pasek
     nie łapie kliknięć i czytników ekranu, kiedy go nie widać. */
  visibility: hidden;
  transition: opacity var(--t-mid) var(--e-out),
              visibility 0s linear var(--t-mid);
}

.wiz__zoomer.has-side-rail .wiz__sidebar-railbox {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--t-mid) var(--e-out);
}

.wiz__zoom-main {
  position: relative;          /* kotwica dla przycisków nakładki */
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-6);
}

/* Kolumna rozmowy. Jasna, bo to zwykła lista wątków — ciemne jest tło
   pod ekranem, nie sama rozmowa.

   Sama kolumna jest tylko okienkiem: całe wnętrze ma stałą szerokość
   i zostaje przycięte, dopóki kolumna się nie rozsunie. */
.wiz__zoom-side {
  position: relative;          /* kotwica dla rozmowy i paska */
  min-width: 0;
  overflow: hidden;
  width: 0;
  transition: width var(--t-mid) var(--e-out);
}

/* Wsuwa się z prawej krawędzi. Wnętrze ma STAŁĄ szerokość i jedzie
   transformem — gdyby zwężało się razem z kolumną, cała rozmowa
   przelewałaby się w trakcie ruchu. Leży poza układem (`absolute`),
   więc zwężanie kolumny go nie dotyczy; kadr obok przelicza skalę przez
   czas przejścia (js/ui/simple.js goni go przez 420 ms). */
.wiz__zoom-side__inner {
  box-sizing: border-box;
  position: absolute;
  top: 0;
  right: 0;
  width: var(--w-zoom-side, 380px);
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: 0;
  background: var(--c-surface);
  border-left: 1px solid var(--c-line);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--t-mid) var(--e-out),
              visibility 0s linear var(--t-mid);
}

.wiz__zoomer.has-side .wiz__zoom-side__inner {
  transform: none;
  visibility: visible;
  transition: transform var(--t-mid) var(--e-out);
}

/* Przy otwartej rozmowie przycisk nad kadrem znika: swoje zrobił, a taki
   sam stoi już na górze kolumny. Dwa jednakowe napisy obok siebie kazałyby
   zgadywać, czym się różnią. */
.wiz__zoomer.has-side .wiz__zoom-comment { display: none; }

.wiz__zoom-side .wiz__comments {
  flex: 1 1 auto;
  max-height: none;            /* kolumna ma całą wysokość okna */
}

/* Strzałka zwijania celuje w prawo — kolumna chowa się za krawędź. */
.wiz__zoom-side .wiz__sidebar-collapse { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
  .wiz__zoom-side,
  .wiz__zoomer .wiz__sidebar-railbox,
  .wiz__zoom-side__inner { transition: none; }
}

/* Przełącznik rozmiarów stoi NAD kadrem, na osi nakładki — tak samo jak
   w panelu projektanta. Poza przepływem, bo kolumna podglądu układa
   dzieci w rzędzie i pasek stanąłby obok ekranu zamiast nad nim. */
.viewports--zoom {
  position: absolute;
  top: var(--s-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}

/* Pasek rozdzielczości pod kadrem w KROKU (nie w powiększeniu).

   Kadr jest kolumną flex z własnym `gap`, a wyśrodkowanie bierze
   z `align-items` rodzica — bazowy `.viewports` dokłada jednak
   `margin-bottom`, który podwajałby odstęp do zakładek ekranów. */
.viewports--stage { margin-bottom: 0; }

.wiz__zoom-stage { display: flex; }

/* Powiększony telefon — projekt mobilny. Pudełko rezerwuje miejsce, a sam
   telefon się kurczy; skalę liczy js/ui/simple.js z tego, ile zostało
   w kolumnie podglądu (openZoom → dopasuj), tak samo jak przy kadrze
   strony. `margin: auto` trzyma go na środku nakładki, bo w odróżnieniu
   od ramki okna nie rozciąga się na całą jej szerokość. */
.wiz__zoom-phone { margin: auto; }

/* Pin w powiększeniu pokazuje, gdzie już jest uwaga — ale go nie chwytamy. */
.wiz__zoomer .pin { cursor: default; }

/* Podpis pod kadrem, nie nad nim: powiększenie ma oddać ekranowi całą
   górę okna, a nazwa i tak jest w tytule kroku. */
.wiz__zoom-label {
  position: absolute;
  bottom: var(--s-3);
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-size: var(--fs-13);
  color: rgba(255, 255, 255, 0.7);
}

.wiz__zoom-close {
  position: absolute;
  top: var(--s-4);
  right: var(--s-5);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  font-size: 16px;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
}

.wiz__zoom-close:hover { background: rgba(255, 255, 255, 0.22); }

/* Komentowanie w powiększeniu. Przycisk stoi po przeciwnej stronie niż
   zamknięcie — dwa różne wyjścia z nakładki nie mogą leżeć obok siebie. */
.wiz__zoom-comment {
  position: absolute;
  top: var(--s-4);
  left: var(--s-5);
  height: 36px;
  gap: var(--s-2);
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
}

.wiz__zoom-comment:hover { background: rgba(255, 255, 255, 0.22); }

/* Włączony tryb wskazywania: ten sam akcent co obrys kadru, żeby było
   widać, że kolejne kliknięcie postawi pin. */
.wiz__zoom-comment[aria-pressed="true"] {
  color: var(--c-ink);
  background: var(--c-accent-2);
}

/* Lista wyborów w podsumowaniu strony leży pod ekranem, nie obok. */
/* Wąskie okno: panel rozmowy schodzi pod treść, etapy się chowają. */
@media (max-width: 1100px) {
  .wizard--panel,
  .wizard--panel-rail { padding-right: var(--s-6); }

  .wiz__sidebar {
    position: static;
    width: auto;
    max-height: 60vh;
    margin-top: var(--s-6);
    border-left: 0;
    border-top: 1px solid var(--c-line);
    /* Panel nie stoi już przy krawędzi, tylko pod treścią — nie ma skąd
       wjeżdżać. */
    animation: none;
  }

  .wiz__sidebar.is-collapsed { width: auto; flex-direction: row; }
  .wiz__sidebar-rail { writing-mode: horizontal-tb; }
}

/* ============================================================
   TELEFON — PANEL ROZMOWY POD TREŚCIĄ

   Blok stoi PO regule z 1100 px celowo: tamta zostawia rezerwę
   `padding-right` na panel stojący obok, a tutaj panel jest już pod
   treścią. Bez tego kreator miał 24 px z prawej i zero z lewej, więc
   cała strona wyglądała na przesuniętą w bok — a rezerwowała miejsce
   na panel, którego tam nie ma.
   ============================================================ */
@media (max-width: 600px) {
  .wizard--panel,
  .wizard--panel-rail,
  .wiz__hero-wizard.wizard--panel,
  .wiz__hero-wizard.wizard--panel-rail {
    padding-right: 0;
    padding-left: 0;
  }
}

/* Zwijanie panelu to sprawa układu dwukolumnowego. Pod treścią rozmowa
   nikomu nie zabiera miejsca, więc pasek i chevron znikają, a panel
   zostaje otwarty (js/ui/simple.js, panelOtwarty). */
@media (max-width: 900px) {
  .wiz__sidebar-collapse,
  .wiz__sidebar-open,
  .wiz__sidebar-rail { display: none; }

  /* Otwarta rozmowa nie przewija się już w swoim okienku: na telefonie
     przewija się cała strona, a wewnętrzny pasek zamykał listę w ramce
     wysokiej na pół ekranu. */
  .wiz__sidebar { max-height: none; }

  /* iOS powiększa widok przy wejściu w pole mniejsze niż 16 px i nie
     wraca do poprzedniej skali po wyjściu. */
  .comment__field,
  .comment .cms-input,
  .composer .cms-input { font-size: var(--fs-16); }
}

/* ============================================================
   ZESTAWY EKRANÓW U KLIENTA (Desktop / Tablet / Mobile)

   Przełącznik nad listą etapów — zestaw jest kontekstem, nie etapem.
   Lista braków w oknie „jeszcze nie wszystko" przed zatwierdzeniem.
   ============================================================ */
.viewports--steps {
  display: flex;
  margin: 0 0 14px;
}

.viewports--steps .viewports__btn {
  flex: 1 1 auto;
  justify-content: center;
  padding: 0 10px;
}

.wiz__missing {
  list-style: none;
  margin: 4px 0 12px;
  padding: 0;
  text-align: left;
  font-size: var(--fs-13);
  color: var(--c-ink-soft);
}

.wiz__missing-row + .wiz__missing-row { margin-top: 6px; }
.wiz__missing-row strong { color: var(--c-ink); }
