/* ══════════════════════════════════════════════════════════════════════════════
   A.S TCHÓRZEWSKI — wygląd strony.        Jedyne źródło prawdy: `DESIGN.md`
   ══════════════════════════════════════════════════════════════════════════════
   Kierunek B „Scena" na fundamencie Apple Premium Cinematic, z dwoma twardymi
   odstępstwami od oryginału:
   🔴 `border-radius: 0` WSZĘDZIE (polecenie K. z 07.09.2026).
      Kontrola: `grep -n "border-radius" assets/app.css | grep -v ":0"` — pusto.
   🔴 STRONA JEST JASNA, nie ciemna (droga A, decyzja K. z 07.09.2026 21:15).
      Ciemne zostało scenie, ramce wezwania i podpisom na pasach zdjęć.
      Pełne uzasadnienie przy tokenach niżej i w `DESIGN.md`.

   Mechanika i dostępność siedzą w `rdzen.css` / `rdzen.js` i NIE są tu powtarzane.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── KROJE (u siebie, bez Google Fonts → bez banera cookies) ─────────────────── */
@font-face{font-family:Jost;font-style:normal;font-weight:300;font-display:swap;
  src:url(fonty/jost-latin-ext-300-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Jost;font-style:normal;font-weight:300;font-display:swap;
  src:url(fonty/jost-latin-300-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Jost;font-style:normal;font-weight:400;font-display:swap;
  src:url(fonty/jost-latin-ext-400-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Jost;font-style:normal;font-weight:400;font-display:swap;
  src:url(fonty/jost-latin-400-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Jost;font-style:normal;font-weight:500;font-display:swap;
  src:url(fonty/jost-latin-ext-500-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Jost;font-style:normal;font-weight:500;font-display:swap;
  src:url(fonty/jost-latin-500-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;
  src:url(fonty/inter-latin-ext-400-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;
  src:url(fonty/inter-latin-400-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;
  src:url(fonty/inter-latin-ext-500-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:swap;
  src:url(fonty/inter-latin-500-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* ── TOKENY (kolory zmierzone z ich banera — `DESIGN.md`) ───────────────────── */
/* 🔴 ODWRÓCENIE 07.09.2026 (decyzja K., droga A z `DESIGN.md`): STRONA JEST JASNA.
   Powód: klient potwierdził, że aktualne jest STARE logo — czarny napis
   „TCHÓRZEWSKI" i czarne wieżowce. Na `#0F0F12` z logo zostawał biały dach
   i srebrna kielnia, reszta znikała (59 % widocznych pikseli znaku to ciemne).
   Ciemna czerń NIE ZNIKA ze strony — schodzi do roli AKCENTU: nagłówek sceny,
   ramka wezwania i podpisy na pasach zdjęć. Kierunek „Scena" żyje dalej,
   tylko scena jest teraz z papieru, a czerń jest na niej gościem.
   🔒 ZASADA, KTÓRA TO SPINA: **logo stoi WYŁĄCZNIE na jasnym** (górny pasek,
   stopka). Cokolwiek robimy z ciemnymi blokami — znak tam nie wchodzi. */
:root{
  --papier:#F3F1ED;                  /* tło główne — dawne „dzień” */
  --papier-2:#FFFFFF;                /* karty i pola na papierze */
  --papier-3:#E9E5DE;                /* stopka — papier o ton głębszy, bez linii-protezy */
  --noc:#0F0F12;                     /* akcent: scena, ramka wezwania, podpisy na pasach */
  --noc-2:#18161A;                   /* karta na ciemnym — ocieplona, żeby nie była grafitem */
  --biel:#F5F5F7;
  /* 🔴 Neutralne są CIEPŁE, nie chłodnoszare. Chłodny szary obok ciepłego pomarańczu
     to najczęstszy „domyślny" zestaw i właśnie on czyta się jak szablon. Te dwa
     odcienie są przesunięte w stronę ich #C85C13; kontrast sprawdzony (6,93 i 5,29). */
  --przyg:#A39A93;                   /* drugi plan NA CIEMNYM */
  --atrament:#1B1B1E;                /* tekst na papierze */
  --przyg-jasny:#6B6259;             /* drugi plan na papierze */
  --akcent:#C85C13;
  --akcent-ciemniej:#B0500F;
  /* 🔴 Kontrast: biel na #C85C13 daje 4,20 - poniżej progu 4,5. Przyciski i etykiety
     na jasnym tle biorą więc ciemniejsze warianty tego samego pomarańczu.
     Zmierzone bramką 07.09.2026, nie na oko. */
  --akcent-btn:#A34A0F;              /* tło przycisku - biel na tym = 5,89 */
  --akcent-btn-hover:#8F3F0A;
  --akcent-na-jasnym:#8F3F0A;        /* mały tekst akcentem na papierze = 6,4 */
  --akcent-jasny:#E2762A;            /* mały tekst akcentem na ciemnym #17171B = 5,9 */
  --wa:#25A63F;
  /* Linie: domyślne są teraz CIEMNE (na papierze). Warianty na biało obsługują
     wyłącznie bloki `.ciemna`. ⛔ Nie mieszać — jasna linia na papierze znika. */
  --linia:rgba(27,27,30,.22);
  --linia-slaba:rgba(27,27,30,.12);
  --linia-na-ciemnym:rgba(255,255,255,.16);
  --linia-slaba-na-ciemnym:rgba(255,255,255,.08);
  --rytm:clamp(5rem,9.5vw,10rem);    /* więcej powietrza między sekcjami (K. 07.09) */
  --wrap:1240px;
  --bok:32px;
  --gora:96px;                       /* wysokość górnego paska — hero liczy od niej odstęp */
  /* plakietka opinii Google (rdzeń) — gdyby weszła, ma być prostokątna jak reszta */
  --gb-promien:0;
}

*{margin:0;padding:0}
html{background:var(--papier)}
body{background:var(--papier);color:var(--atrament);
  font:400 17px/1.65 Inter,system-ui,-apple-system,sans-serif;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3,h4{font-family:Jost,Inter,sans-serif;font-weight:300;line-height:1.08;
  letter-spacing:-.015em}
a{text-decoration:none}
::selection{background:var(--akcent);color:#fff}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--bok);width:100%}
.skip{background:var(--papier);color:var(--atrament);font-weight:500;border:1px solid var(--akcent)}

/* ── BLOK CIEMNY — jedyny sposób, w jaki czerń wchodzi na tę stronę ──────────
   Wszystko, co na papierze jest ciemne, tu musi się odwrócić. Trzymamy to
   w JEDNYM miejscu, żeby nie polować po pliku za każdym razem, gdy dojdzie
   nowa sekcja. ⛔ Logo w `.ciemna` NIE wchodzi (patrz nota przy tokenach). */
.ciemna{background:var(--noc);color:var(--biel)}
.ciemna h1,.ciemna h2,.ciemna h3,.ciemna h4{color:var(--biel)}
.ciemna .pod,.ciemna .lead,.ciemna .przyciemniony,.ciemna .godziny{color:var(--przyg)}
.ciemna .etykieta,.ciemna .kod,.ciemna .licznik,.ciemna .dalej{color:var(--akcent-jasny)}
.ciemna .lata b{color:var(--akcent-jasny)}
.ciemna .lata p,.ciemna .klatka p,.ciemna .klatka figcaption,
.ciemna .dane th,.ciemna .spec{color:var(--przyg)}
.ciemna .karta,.ciemna [data-po-kliknieciu]{background:var(--noc-2);
  border-color:var(--linia-na-ciemnym)}
.ciemna .zygzak,.ciemna .grupa-tyt,.ciemna .lata li,
.ciemna .dane th,.ciemna .dane td,.ciemna .reel,.ciemna .reel figcaption,
.ciemna .wiersz-usluga,.ciemna .kafel{
  border-color:var(--linia-slaba-na-ciemnym)}
.ciemna .duch{border-color:rgba(255,255,255,.22);color:var(--biel)}
.ciemna .duch:hover{border-color:var(--biel);background:rgba(255,255,255,.09)}

/* etykieta nad nagłówkiem — jedyne miejsce na wersaliki (`DESIGN.md`) */
.etykieta{display:block;font:500 12px/1 Inter;letter-spacing:.2em;text-transform:uppercase;
  color:var(--akcent-na-jasnym);margin-bottom:22px}

/* ── PRZYCISKI ──────────────────────────────────────────────────────────────── */
.btn,.duch{display:inline-flex;align-items:center;gap:10px;border-radius:0;
  font:500 15px/1 Inter;padding:15px 24px;border:1.5px solid transparent;
  transition:background .2s ease,border-color .2s ease,transform .2s ease,box-shadow .2s ease}
.btn{background:var(--akcent-btn);color:#fff}
.btn:hover{background:var(--akcent-btn-hover)}
.duch{border-color:rgba(27,27,30,.3);color:var(--atrament);background:transparent}
.duch:hover{border-color:var(--atrament);background:rgba(27,27,30,.045)}
.btn-wa{background:var(--wa)}
.btn-wa:hover{background:#1E8A33}
.ikona-wa{flex:none}

/* ── PODŚWIETLENIE PRZYCISKU — przelot światła ───────────────────────────────
   🔴 08→10.09.2026, prośba K.: „hover ma wyglądać jak na demie, tam ładniej się
   podświetla". Sama zmiana tła o 8% czyta się jak przełącznik, nie jak reakcja.
   Bierzemy dokładnie ten sam ruch, co silnik dem (`recipes/multipage/motion.css`):
   ukośna smuga światła przelatuje przez przycisk w 0,75 s + przycisk unosi się
   o 2 px i dostaje cień pod spodem. To NIE jest „poświata" z zakazu w DESIGN.md
   (żadnej łuny dookoła krawędzi) — smuga leci WEWNĄTRZ prostokąta i jest
   przezroczysta, więc kontrast napisu (5,89 na przycisku głównym) zostaje
   nietknięty. Krawędź dalej ostra, `border-radius:0` bez zmian.
   ⚠️ `isolation:isolate` jest obowiązkowe: bez niego `z-index:-1` wypycha smugę
   POD tło przycisku i efektu nie widać wcale. */
.btn,.duch,.tel-gora,.pk-btn{position:relative;overflow:hidden;isolation:isolate}
.btn::after,.duch::after,.tel-gora::after,.pk-btn::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(100deg,transparent 32%,rgba(255,255,255,.24) 50%,transparent 68%);
  translate:-120% 0}
/* przycisk-duch stoi na papierze i jest przezroczysty — biała smuga byłaby na nim
   niewidoczna, więc bierze światło w kolorze własnego napisu (ciemne na papierze,
   jasne w bloku ciemnym, bez osobnych reguł na każdy blok) */
.duch::after{background:linear-gradient(100deg,transparent 32%,
  color-mix(in srgb,currentColor 18%,transparent) 50%,transparent 68%)}
@media (prefers-reduced-motion:no-preference){
  .btn:hover::after,.btn:focus-visible::after,
  .duch:hover::after,.duch:focus-visible::after,
  .tel-gora:hover::after,.tel-gora:focus-visible::after,
  .pk-btn:hover::after,.pk-btn:focus-visible::after{
    translate:120% 0;transition:translate .75s cubic-bezier(.16,.84,.44,1)}
  .btn:hover,.btn:focus-visible,.duch:hover,.duch:focus-visible,
  .tel-gora:hover,.tel-gora:focus-visible{
    transform:translateY(-2px);box-shadow:0 8px 20px -12px rgba(27,27,30,.55)}
  /* wciśnięcie = przycisk wraca na swoje miejsce (wcześniej `active` unosił go
     o 1 px, co po dodaniu uniesienia na hover czytałoby się odwrotnie) */
  .btn:active,.duch:active,.tel-gora:active{transform:translateY(0);box-shadow:none}
}

/* ── GÓRNY PASEK ────────────────────────────────────────────────────────────── */
/* 🔴 Pasek jest JASNY i to nie jest kwestia gustu: stoi w nim logo, a logo ma
   czarny napis. Ciemny pasek = znak znika. To ta sama decyzja co cała droga A. */
.top{position:sticky;top:0;z-index:100;background:rgba(243,241,237,.86);
  -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid var(--linia-slaba);transition:transform .3s var(--ease)}
.top .wrap{display:flex;align-items:center;gap:28px;height:var(--gora)}
.znak{flex:none;display:block}
/* 🔴 60 px, nie 34. Stare logo jest ZNAKIEM RYSUNKOWYM w proporcji 4:3, nie
   poziomym wordmarkiem 704×154 jak poprzednie. Przy 34 px napis „TCHÓRZEWSKI"
   robił się kreską 4 px wysoką - nieczytelną. Przy 60 px znak ma 81 px szerokości
   i napis ~8 px, czyli tyle, ile trzeba. Dlatego pasek urósł z 82 na 96 px. */
.znak img{height:60px;width:auto;display:block}
.nawigacja{margin-left:auto}
.nawigacja ul{list-style:none;display:flex;gap:34px}
.nawigacja a:not(.btn){font-size:14.5px;color:var(--przyg-jasny);padding:6px 0;letter-spacing:.01em}
.nawigacja a:not(.btn):hover{color:var(--atrament)}
.nawigacja a[aria-current="page"]{color:var(--atrament)}
.nawigacja a:not(.btn)::after{background:var(--akcent);height:1px;bottom:-2px}
.nawigacja .strzalka-poz{display:none}
.tel-gora{flex:none;display:inline-flex;align-items:center;gap:9px;background:var(--akcent-btn);
  color:#fff;font:500 15px/1 Inter;padding:13px 22px;border-radius:0}
.tel-gora:hover{background:var(--akcent-btn-hover)}
.tel-gora{transition:background .2s ease,transform .2s ease,box-shadow .2s ease}
.burger{display:none}

/* ── SCENA (nagłówek strony głównej) ────────────────────────────────────────── */
/* Scena ZOSTAJE CIEMNA i to jest sedno drogi A: pionowe kadry z budowy dalej stoją
   na czerni jak przedmiot w witrynie - to był drugi (i nadal ważny) powód wyboru
   tego kierunku. Zmieniło się tylko to, że czerń nie jest już tłem CAŁEJ strony,
   więc logo w pasku nad nią siedzi na papierze i jest widoczne. */
/* 🔴 08.09.2026 (decyzja K. + Marceli: pierwszy ekran „kompletnie mi się nie podoba"):
   scena jest PEŁNOEKRANOWA. Zdjęcie idzie na całą szerokość, tekst leży na nim.
   Wcześniej kadr stał w ramce OBOK tekstu - z pionowych zdjęć telefonem robiło to
   przypis, a nie pierwsze wrażenie.
   ⚠️ Zdjęcie ma być WYSOKIE (1440×1300), nie docięte do proporcji ekranu: wycinek
      dobiera `object-fit:cover`, więc ten sam plik działa i na laptopie, i na telefonie.
   🔴 Reguła K. z 07.09 („hero zawsze mieści się na każdym urządzeniu") jest tu
      spełniona z definicji - scena MA wysokość ekranu, nic z niej nie wystaje. */
/* 🔴 `svh`, NIE `dvh` (K. 30.09.2026, iPhone: „scroll dziwnie działa"). `dvh` idzie za
   paskiem przeglądarki: przy przewijaniu Chrome/Safari na iPhonie chowa pasek, okno
   rośnie o ~100 px, scena rośnie razem z nim i CAŁA treść pod nią zjeżdża pod palcem;
   przy ruchu w górę pasek wraca i treść podskakuje. Zmierzone 30.09: okno −110 px →
   scena −110 px. `svh` = ekran z widocznym paskiem, czyli dokładnie to, co widać
   po wejściu na stronę, i nie zmienia się w trakcie przewijania. `vh` = zapas dla
   przeglądarek bez `svh`. */
.scena{position:relative;overflow:hidden;min-height:calc(100vh - var(--gora,96px));
  min-height:calc(100svh - var(--gora,96px));
  display:grid;align-items:center;padding:72px 0;background:var(--noc);color:var(--biel)}
.scena-tlo{position:absolute;inset:-150px 0;width:100%;height:calc(100% + 300px);object-fit:cover;
  object-position:center 42%}
/* ⚠️ Świadome złamanie zakazu gradientów (`DESIGN.md`, odstępstwo 6): bez przyciemnienia
   biały nagłówek nie utrzyma kontrastu na zdjęciu. Ciemniej po LEWEJ, gdzie stoi tekst,
   jaśniej po prawej, żeby zdjęcia nie zabić. Bramka mierzy kontrast z pikseli. */
.scena::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,rgba(10,10,12,.92) 0%,rgba(10,10,12,.84) 34%,
    rgba(10,10,12,.50) 64%,rgba(10,10,12,.20) 100%)}
/* 🔴 14.09.2026: hero dostał JASNE zdjęcie (sypialnia po wykończeniu) i bramka wyglądu
   zmierzyła kontrast 2,17-4,48 na leadzie, etykiecie i godzinach - przy wymaganych 4,5.
   Samo przyciemnienie gradientem zabiłoby zdjęcie, więc drugą połowę roboty robi cień:
   niewidoczny na oko, a oddaje literom tło niezależnie od tego, co pod nimi leży. */
.scena .godziny{text-shadow:0 1px 4px rgba(8,8,10,.72)}
.scena h1{text-shadow:0 2px 10px rgba(8,8,10,.45)}
.scena>.wrap{position:relative;z-index:2}
/* 🔴 29.09.2026 hero to JEDNO zdanie klienta (63 znaki) zamiast krótkiego hasła z leadem
   pod spodem. Przy starych 16ch i 4,6 rem szło w pięć wierszy - teraz trzy na laptopie. */
.scena h1{font-size:clamp(2.6rem,4.8vw,4.1rem);margin-bottom:30px;max-width:20ch;
  color:var(--biel)}
.lead{color:var(--przyg-jasny);font-size:19px;max-width:46ch;margin-bottom:34px}
.scena .duch{border-color:rgba(255,255,255,.22);color:var(--biel)}
.scena .duch:hover{border-color:var(--biel);background:rgba(255,255,255,.09)}
.kontakt-linia{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.godziny{font-size:14px;color:var(--przyg-jasny)}
.scena .godziny{color:var(--przyg)}

/* ⛔ `.kadr-scena` (pionowy kadr w odsuniętej ramce OBOK tekstu) skasowany 08.09.2026
   razem z przejściem sceny na pełny ekran. Nie wracać bez decyzji K. - to był układ,
   który odrzucił. Historia i wyliczenie wysokości: `NOTATKI-BUDOWY.md`, blok E. */

/* ── SEKCJE ─────────────────────────────────────────────────────────────────── */
.sekcja{padding:var(--rytm) 0}
/* otwarcie podstrony: pełny rytm pod nagłówkiem zostawiał pół ekranu pustej płaszczyzny,
   bo zaraz pod nim zaczyna się sekcja z własnym górnym marginesem.
   ⚠️ Dolna wartość urosła z 2,5 na 5 rem, gdy otwarcie stało się blokiem CIEMNYM:
   przy 24 px z ciemnego zostawał wąski pasek doklejony pod paskiem nawigacji,
   a nie blok. Przy jasnej sekcji tego nie było widać - granicy koloru nie było. */
.otwarcie{padding:clamp(3.5rem,7vw,6rem) 0 clamp(3.5rem,6vw,5rem)}
/* Otwarcie z własnym kadrem — ta sama mechanika, co na scenie, tylko niżej i płycej. */
.otwarcie--kadr{position:relative;overflow:hidden}
.otwarcie-tlo{position:absolute;inset:-300px 0;width:100%;height:calc(100% + 600px);object-fit:cover;
  object-position:center 42%}
/* 🔴 Wartości podniesione po pomiarze bramki 08.09.2026: przy .78 na 38 % lead
   „Wszystkie z naszych budów…" leżał na niebie w oknach dachowych i dawał 4,20:1
   (próg 4,5). Zmieniasz zdjęcie w otwarciu → PRZEMIERZ bramką, nie na oko. */
.otwarcie--kadr::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,rgba(10,10,12,.93) 0%,rgba(10,10,12,.88) 44%,
    rgba(10,10,12,.52) 74%,rgba(10,10,12,.24) 100%)}
.otwarcie--kadr>.wrap{position:relative;z-index:2}
.otwarcie h1{font-size:clamp(2.3rem,4.4vw,3.6rem);margin-bottom:20px;max-width:18ch}
.sekcja h2{font-size:clamp(2rem,3.6vw,2.9rem);margin-bottom:18px}
.pod{color:var(--przyg-jasny);font-size:16.5px;max-width:52ch;margin-bottom:46px}
.naglowek-sekcji{margin-bottom:64px}
.naglowek-sekcji .pod{margin-bottom:0}

/* ── PRZED I PO ─────────────────────────────────────────────────────────────── */
.para{display:grid;grid-template-columns:1fr 1fr;gap:34px;align-items:stretch}
/* Zdjęcia „przed i po" to najmocniejszy dowód na stronie - dostają szerszy
   kontener niż tekst. 1500 px daje ~735 px na kadr przy źródle 1100 px (1,5×);
   ⛔ szerzej NIE - pełna szerokość na ekranie 1920 zeszłaby do 1,15× i zmiękła. */
.wrap--szeroki{max-width:1500px}
/* 🔴 PARA FILMÓW (blok E, 08.09.2026). `.reel` ma sufit 420 px (źródła to 540 i 720 px
   szerokości - szerzej zaczyna się rozmywać), więc w rzędzie 1fr 1fr dwa kafle stawały
   po LEWEJ, a po prawej zostawało 300 px pustki. Słupki dostają twardą szerokość
   i cała para idzie na środek. ⛔ Nie podnosić 520 px - przy 540 px źródła to już
   skala 1:1, a wyżej film mięknie. Poniżej 980 px `.reel` traci sufit (media query)
   i kafle wypełniają połówki same. */
.para--filmy{max-width:1074px;margin-inline:auto}   /* 520 + 34 przerwy + 520 */
.para--filmy .reel{max-width:none}
.klatka{position:relative}
.klatka img{width:100%;border-radius:0;box-shadow:0 2px 8px rgba(0,0,0,.08)}
.klatka p,.klatka figcaption{margin-top:16px;font-size:15px;color:var(--przyg-jasny)}
/* Para kadrów pod nagłówkiem sekcji („Poza wnętrzami"). Wężej niż `.wrap` i z własnym
   odstępem u góry: przy pełnej szerokości dwa PIONOWE kadry rosły do ~935 px wysokości,
   czyli wyżej niż ekran, i zjadały sekcję, która ma być zajawką, a nie galerią. */
.para--dowod{max-width:940px;margin-inline:auto;margin-top:clamp(34px,4.5vw,58px)}
.znacznik{position:absolute;top:18px;left:18px;background:rgba(15,15,18,.86);color:#fff;
  font:500 12px/1 Inter;letter-spacing:.16em;text-transform:uppercase;padding:9px 14px;
  border-radius:0}
.znacznik.po{background:var(--akcent-btn)}

/* ── PRZED I PO: DWA BLOKI OBOK SIEBIE ────────────────────────────────────────
   🔴 29.09.2026 klient: „po prostu dwa zdjęcia przed i po, bez opisów". Zygzak z case
   study (14.09, pomysł Marcelego) bez tekstu zostawiał pustą połowę rzędu, więc wrócił
   układ `.duety` z 14.09 (K.: „obydwa bloki obok siebie"). Poniżej 900 px jeden pod drugim.
   ⛔ Nie dokładaj trzeciej pary do rzędu - przy trzech kolumnach „przed" przestaje być
      czytelne. Trzecia para = nowy rząd. */
.duety{display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:start}
.duet{margin:0}

/* ⛔ `aspect-ratio` MUSI zgadzać się z plikami OBU par (stała `PARA` = 1500/1322
   w `przygotuj-media.py`; wszystkie cztery kadry są cięte do tej samej proporcji).
   Rozjazd uruchamia `object-fit:cover`, czyli przycięcie, którego tu nie chcemy. */
.duet-rama{position:relative;overflow:hidden;line-height:0;aspect-ratio:1500/1322;
  background:var(--noc)}
/* Taśma dwóch kadrów obok siebie. Przesuwa się o połowę własnej szerokości, więc
   przejście jest jednym ruchem w tę stronę, w którą pokazuje strzałka. */
.duet-tasma{display:flex;width:200%;height:100%;
  transition:transform .42s cubic-bezier(.4,0,.2,1);will-change:transform}
.duet-tasma img{width:50%;height:100%;object-fit:cover;display:block;border-radius:0}
.duet-rama.jest-po .duet-tasma{transform:translateX(-50%)}

/* Strzałki: koła przy krawędziach kadru, pionowo na środku. Skrajna gaśnie i przestaje
   być klikalna — przy dwóch kadrach zapętlanie tylko myli (nie ma trzeciego zdjęcia). */
.duet-strzalka{position:absolute;top:50%;transform:translateY(-50%);z-index:3;
  width:46px;height:46px;border:0;border-radius:50%;background:rgba(15,15,18,.86);
  box-shadow:0 0 0 1px rgba(255,255,255,.28);color:#fff;cursor:pointer;padding:0;
  display:flex;align-items:center;justify-content:center;
  transition:opacity .25s cubic-bezier(.4,0,.2,1),background .25s cubic-bezier(.4,0,.2,1)}
.duet-strzalka svg{display:block}
.duet-strzalka--lewo{left:14px}
.duet-strzalka--prawo{right:14px}
.duet-strzalka:hover{background:rgba(15,15,18,.96)}
.duet-strzalka:focus-visible{outline:2px solid #fff;outline-offset:3px}
.duet-strzalka[disabled]{opacity:.28;cursor:default;box-shadow:none}

/* Etykiety stoją jedna na drugiej i przenikają — widoczna jest ta, która opisuje
   kadr aktualnie na wierzchu. Kadry NIE przenikają, przenika sam napis. */
.duet-etyk{z-index:4;top:16px;left:16px;transition:opacity .3s cubic-bezier(.4,0,.2,1)}
.duet-etyk--po{opacity:0}
.duet-rama.jest-po .duet-etyk--przed{opacity:0}
.duet-rama.jest-po .duet-etyk--po{opacity:1}

@media (max-width:900px){
  .duety{grid-template-columns:1fr;gap:34px}
  .duet-strzalka{width:42px;height:42px}
  .duet-strzalka--lewo{left:10px}
  .duet-strzalka--prawo{right:10px}
  .duet-etyk{top:10px;left:10px;font-size:10px;padding:6px 9px;letter-spacing:.12em}
}
/* Bez rdzenia widać pierwszy kadr („przed") — strzałki nic by nie robiły. */
html:not(.js) .duet-strzalka{display:none}
@media (prefers-reduced-motion:reduce){
  /* kadr przeskakuje bez jazdy, sam pokaz po wejściu w widok nie rusza (`rdzen.js`) */
  .duet-tasma,.duet-etyk{transition:none}
}

/* ── OPINIE Z GOOGLE ───────────────────────────────────────────────────────── */
/* 🔴 Plakietka (`.g-badge`) siedzi w rdzeniu i wygląda tak samo na KAŻDEJ naszej
   stronie - tu tylko dobieramy tło pod papier. Liczby opinii nie ma celowo:
   sześć to za mało, żeby liczba pomagała (standard ze skilla `strona-docelowa`). */
.sekcja--opinie{overflow:hidden}
.sekcja--opinie .g-badge{--gb-tlo:var(--papier-2);--gb-obwodka:var(--linia-slaba)}
/* ⚠️ Jedyne miejsce na stronie z zaokrągleniami - `DESIGN.md` każe wszędzie
   `border-radius: 0`. Decyzja K. z 10.09.2026: plakietka Google i karty opinii mają
   wyglądać jak w silniku dem, bo tam ten klocek jest rozpoznawalny. Plakietka stoi
   POD nagłówkiem, nie obok - też jego decyzja. */
.naglowek-opinie{margin-bottom:38px}
.naglowek-opinie h2{margin:0 0 18px}
.sekcja--opinie .g-badge{border-radius:999px;padding:.55em 1.05em}

/* Taśma jedzie sama i nigdy się nie zatrzymuje na dobre - pauza tylko pod kursorem,
   żeby dało się skończyć czytanie. Długość jednego przebiegu (`--tasma`) i czas
   liczy `rdzen.js`, bo zależą od realnej szerokości kart. */
.karuzela{position:relative;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent)}
.karuzela-tor{display:flex;gap:26px;width:max-content;padding:4px var(--bok)}
.karuzela--gotowa .karuzela-tor{animation:jedzie var(--czas,30s) linear infinite}
.karuzela--gotowa:hover .karuzela-tor,
.karuzela--gotowa:focus-within .karuzela-tor{animation-play-state:paused}
@keyframes jedzie{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(-1 * var(--tasma)),0,0)}}
/* bez ruchu: zwykły, przewijalny palcem rząd */
.karuzela--stoi{overflow-x:auto;-webkit-overflow-scrolling:touch}

.opinia{flex:0 0 clamp(280px,32vw,420px);margin:0;background:var(--papier-2);
  border:1px solid var(--linia-slaba);border-radius:18px;padding:30px 30px 26px;
  display:flex;flex-direction:column;gap:16px;line-height:1.6}
.opinia-gw{flex:none;fill:var(--gb-gwiazdka,#F5A623)}
.opinia blockquote{margin:0;font-size:1.02rem;color:var(--tekst)}
.opinia figcaption{margin-top:auto;font:500 15px/1.4 Inter;color:var(--tekst)}
.opinia figcaption span{display:block;margin-top:4px;font-weight:400;font-size:13px;
  color:var(--przyg-jasny)}
@media (max-width:700px){
  .opinia{flex-basis:min(80vw,320px);padding:24px 22px}
  .naglowek-opinie{margin-bottom:26px}
}

/* ── WARSTWA RUCHU ────────────────────────────────────────────────────────── */
/* Sekwencje korzystają z obserwatora `.rv` i animacji `kaskada-wjazd` rdzenia.
   Opóźnienia należą do animacji, więc nie zostają na późniejszym hoverze. */
.para.kaskada.is-in>.klatka{animation-delay:calc(var(--i,0) * 140ms)}

/* Zygzak zaczyna się tekstem; obraz dochodzi z jego własnej strony po 120 ms. */
.zygzak.rv>.zygzak-obraz{opacity:0;transform:translateX(-24px)}
.zygzak--odwrocony.rv>.zygzak-obraz{transform:translateX(24px)}
.zygzak.rv.is-in>.zygzak-obraz{opacity:1;transform:none;
  animation:zygzak-obraz-z-lewej .55s var(--ease) backwards;animation-delay:120ms}
.zygzak--odwrocony.rv.is-in>.zygzak-obraz{animation-name:zygzak-obraz-z-prawej}
@keyframes zygzak-obraz-z-lewej{from{opacity:0;transform:translateX(-24px)}}
@keyframes zygzak-obraz-z-prawej{from{opacity:0;transform:translateX(24px)}}

/* Kadry realizacji zaczynają się od zera w każdej grupie i kończą na 240 ms. */
.grupa.rv.is-in .galeria.kaskada>figure{opacity:1;transform:none;
  animation:kaskada-wjazd .55s var(--ease) backwards;animation-delay:calc(var(--i,0) * 60ms)}

/* Liczba prowadzi opis o 80 ms; wiersze ruszają co 90 ms bez zmiany siatki. */
.lata--ruch>li b,.lata--ruch>li p{opacity:0;transform:translateY(16px)}
.lata--ruch.rv.is-in>li b,.lata--ruch.rv.is-in>li p{opacity:1;transform:none;
  animation:kaskada-wjazd .55s var(--ease) backwards;animation-delay:calc(var(--i,0) * 90ms)}
.lata--ruch.rv.is-in>li p{animation-delay:calc(var(--i,0) * 90ms + 80ms)}

/* 🔴 NA DOTYKU ŻADEN WJAZD NIE PRZESUWA — zostaje samo przenikanie (K. 11.09.2026:
   „treść podskakuje, gdy sekcja się pojawia"). To ta sama poprawka co `.rv` w rdzeniu,
   tylko dla sekwencji tej strony: na telefonie czytelnik przewija w tym samym czasie,
   w którym element dojeżdża, więc kadr rusza się pod wzrokiem i gubi się miejsce
   w tekście. Opóźnienia kaskady zostają — one same z siebie nic nie przesuwają. */
@media (pointer:coarse){
  .zygzak.rv>.zygzak-obraz,
  .lata--ruch>li b,.lata--ruch>li p{transform:none}
  .zygzak.rv.is-in>.zygzak-obraz,
  .zygzak--odwrocony.rv.is-in>.zygzak-obraz,
  .grupa.rv.is-in .galeria.kaskada>figure,
  .para.kaskada.is-in>.klatka,
  .lata--ruch.rv.is-in>li b,.lata--ruch.rv.is-in>li p{
    animation-name:wjazd-bez-ruchu}
  @keyframes wjazd-bez-ruchu{from{opacity:0}}
}

/* Bez rdzenia treść i kadry zostają widoczne w swoim docelowym miejscu. */
html:not(.js) .scena-tlo[data-paralaksa],html:not(.js) .otwarcie-tlo[data-paralaksa],
html:not(.js) .pas img[data-paralaksa],html:not(.js) .para.kaskada>.klatka,
html:not(.js) .zygzak.rv>.zygzak-obraz,html:not(.js) .galeria.kaskada>figure,
html:not(.js) .lata--ruch>li b,html:not(.js) .lata--ruch>li p{
  opacity:1!important;transform:none!important;animation:none!important}

@media (prefers-reduced-motion:reduce){
  .scena-tlo[data-paralaksa],.otwarcie-tlo[data-paralaksa],.pas img[data-paralaksa],
  .para.kaskada>.klatka,.zygzak.rv>.zygzak-obraz,.galeria.kaskada>figure,
  .lata--ruch>li b,.lata--ruch>li p{opacity:1!important;transform:none!important;animation:none!important}
}

/* ── KAFLE USŁUG ────────────────────────────────────────────────────────────── */
.kafle{display:grid;grid-template-columns:repeat(4,1fr);gap:26px}
.kafel{display:block;border:1px solid var(--linia-slaba);background:var(--papier-2);
  border-radius:0;overflow:hidden;transition:border-color .2s ease}
.kafel:hover{border-color:var(--linia)}
.kafel .obraz{overflow:hidden;aspect-ratio:2/3}
.kafel img{width:100%;height:100%;object-fit:cover;border-radius:0;
  transition:transform .55s var(--ease)}
.kafel:hover img{transform:scale(1.03)}
.kafel{display:flex;flex-direction:column}
.kafel .opis{padding:26px 24px 28px;display:flex;flex-direction:column;flex:1}
.kafel h3{font-size:1.35rem;margin-bottom:8px}
/* `spec` i `dalej` MUSZĄ być blokami: jako elementy liniowe sklejały się w jedno zdanie
   („zabudowa i podejścia. Zobacz →") i dolne krawędzie kafli rozjeżdżały się o wiersz. */
.kafel .spec{display:block;font-size:14px;color:var(--przyg-jasny);line-height:1.5}
.kafel .dalej{display:block;margin-top:auto;padding-top:16px;font:500 13px/1 Inter;
  color:var(--akcent-na-jasnym);letter-spacing:.06em}
/* 🔴 Hover kafla przewraca DOLNY blok na noc (K. 10.09.2026: „zmien tez kolor bloczku
   pod spodem… całość dalej bardzo dobrze czytelna"). Kontrast po przewrocie:
   biel #F5F5F7 na #0F0F12 = 18,3 · opis 72% bieli = 10,4 · akcent #E2762A = 5,9.
   ⛔ Nie ruszać samego obrazka - powiększenie 1.03 zostaje. */
.kafel .opis{transition:background-color .28s var(--ease)}
.kafel h3,.kafel .spec,.kafel .dalej{transition:color .28s var(--ease)}
.kafel:hover .opis,.kafel:focus-visible .opis{background:var(--noc)}
.kafel:hover h3,.kafel:focus-visible h3{color:var(--biel)}
.kafel:hover .spec,.kafel:focus-visible .spec{color:rgba(245,245,247,.74)}
.kafel:hover .dalej,.kafel:focus-visible .dalej{color:var(--akcent-jasny)}

/* wiersze usług pod kaflami (montaż drzwi i okien, podłogi) */
.wiersz-usluga{display:flex;align-items:center;gap:22px;flex-wrap:wrap;
  border:1px solid var(--linia-slaba);border-radius:0;padding:22px 24px;margin-top:22px}
.wiersz-usluga+.wiersz-usluga{margin-top:12px}
.wiersz-usluga h3{font-size:1.2rem}
.wiersz-usluga .spec{color:var(--przyg-jasny);font-size:14.5px}
.wiersz-usluga .dalej{margin-left:auto;color:var(--akcent-na-jasnym);font:500 13px/1 Inter;
  letter-spacing:.06em}

/* ── FILM (rdzeń, blok 7: rusza pod kursorem i pod przytrzymanym palcem) ─────
   Plakat stoi zawsze; film wjeżdża NAD niego, więc przy starcie nie ma mrugnięcia
   na czarne tło (przy `display:none` na plakacie kadr gasł na jedną klatkę). */
/* Oba filmy klienta mają RÓŻNE proporcje (9:16 i 3:4). Puszczone „jak są" dawały
   dwa kafle różnej wysokości i pod niższym zostawała martwa dziura — dlatego jeden
   kadr 4:5 dla wszystkich, przycięty od środka. */
.reel{max-width:420px;margin:0;border:1px solid var(--linia-slaba);cursor:pointer;
  display:flex;flex-direction:column}
.reel-media{position:relative;line-height:0;background:#000;aspect-ratio:4/5;overflow:hidden}
.reel .plakat{display:block;width:100%;height:100%;object-fit:cover}
.reel video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  background:#000;opacity:0;transition:opacity .18s ease}
.reel.gra video{opacity:1}
.reel-btn{position:absolute;inset:0;width:100%;display:flex;align-items:flex-end;
  justify-content:flex-start;gap:12px;padding:22px;background:transparent;border:0;
  color:#fff;font:500 15px/1 Inter;cursor:pointer;border-radius:0}
/* ⚠️ `.reel-napis`, NIE `.reel-btn span`: w środku siedzą jeszcze `.reel-tekst`
   i `.reel-czas`, a selektor potomka łapałby też je (podwójne tło, przezroczystość
   mnożona przez siebie). */
.reel-napis{display:inline-flex;align-items:center;gap:10px;background:rgba(15,15,18,.72);
  padding:12px 18px;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:opacity .18s ease}
.reel-napis .ikona-play{flex:none}
.reel-czas::before{content:"("}
.reel-czas::after{content:")"}
/* gra = kadr ma mówić sam za siebie, napis schodzi z drogi */
.reel.gra .reel-napis{opacity:0}
.reel.gra:hover .reel-napis{opacity:.45}
.reel-btn:focus-visible .reel-napis{outline:2px solid var(--biel);outline-offset:3px;opacity:1}
/* dotyk: „najedź" nie istnieje, więc mówimy palcem.
   🔴 K. 30.09.2026 (iPhone): „teksty na filmikach się rozjeżdżają". Tytuł, „(39 s)"
   i dopisek „· przytrzymaj" były osobnymi elementami jednego flexa — w przycisku
   ~300 px każdy łamał się sam i kropka wisiała w innym wierszu niż słowo.
   Teraz dwie linie: tytuł (nie łamie się), pod nim mniejsze „39 s · przytrzymaj". */
@media (hover:none){
  .reel-tekst{text-align:left;line-height:1.25}
  .reel-tekst .reel-czas{display:block;margin-top:4px;font-size:12.5px;font-weight:400;opacity:.75}
  .reel-czas::before{content:none}
  .reel-czas::after{content:" · przytrzymaj"}
  .reel.gra .reel-napis{opacity:0}
}
.reel figcaption{flex:1;padding:16px 18px;font-size:14px;color:var(--przyg-jasny);
  border-top:1px solid var(--linia-slaba)}
.pod-para{margin-top:34px;text-align:center}

/* ── ZYGZAK (podstrona „Co robimy") ─────────────────────────────────────────── */
.zygzak{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center;
  overflow:hidden;padding:56px 0;border-top:1px solid var(--linia-slaba)}
.zygzak:first-of-type{border-top:0;padding-top:0}
.zygzak--odwrocony .zygzak-obraz{order:-1}
.zygzak-obraz img{width:100%;border-radius:0}
.zygzak .kod{font:500 12px/1 Inter;letter-spacing:.2em;color:var(--akcent-na-jasnym);
  display:block;margin-bottom:16px}
.zygzak h2{font-size:clamp(1.7rem,3vw,2.3rem);margin-bottom:16px}
.zygzak p+p{margin-top:14px}
/* 🔴 29.09.2026 klient podyktował do każdej usługi punkty („- maszynowe / - ręczne").
   To jest TREŚĆ, nie podpis: pełny kolor tekstu i kreska jak u niego w wiadomości.
   ⛔ Nie wracać do szarej `.spec-linia` - to ją klient kazał usunąć („małe szare podpisy"). */
.zygzak .punkty{list-style:none;margin-top:22px;display:grid;gap:10px}
.zygzak .punkty li{position:relative;padding-left:28px;font-size:18px;line-height:1.45}
.zygzak .punkty li::before{content:"";position:absolute;left:0;top:.72em;width:16px;height:1px;
  background:var(--akcent-na-jasnym)}
/* Blok z DWOMA zdjęciami: kolumna zdjęć dwa razy szersza od tekstu, oba kadry 3:4 obok
   siebie. Przy 1fr 1fr każdy kadr miałby ~270 px i robił za znaczek. */
.zygzak--dwa{grid-template-columns:1fr 2fr}
.zygzak--dwa.zygzak--odwrocony{grid-template-columns:2fr 1fr}
.zygzak--dwa .zygzak-obraz{display:grid;grid-template-columns:1fr 1fr;gap:16px}

/* ── GALERIA (naturalne proporcje, bez kadrowania) ──────────────────────────── */
.galeria{columns:3;column-gap:22px}
/* 🔴 Grupa 2- i 4-zdjęciowa idzie na DWA słupki (blok E, 08.09.2026). Przy `columns:3`
   dwa kadry zostawiały pusty trzeci słupek, a cztery - dziurę na całą wysokość rzędu
   po prawej. Liczbę słupków wybiera `grupa()` w `pages.py`, nie oko. */
.galeria--2{columns:2}
.galeria figure{break-inside:avoid;margin:0 0 22px;cursor:zoom-in;position:relative}
.galeria img{width:100%;border-radius:0;display:block}
.grupa+.grupa{margin-top:var(--rytm)}
.grupa-tyt{display:flex;align-items:baseline;gap:18px;flex-wrap:wrap;margin-bottom:28px;
  padding-bottom:14px;border-bottom:1px solid var(--linia-slaba)}
.grupa-tyt h2{font-size:1.9rem;margin:0}
.grupa-tyt .licznik{font:500 12px/1 Inter;letter-spacing:.2em;color:var(--akcent-na-jasnym);
  text-transform:uppercase}

/* powiększenie zdjęcia (mechanika: `rdzen.js`, blok 5) */
/* ⚠️ Podgląd ZOSTAJE CIEMNY, mimo że strona jest jasna. Powiększone zdjęcie ma leżeć
   na czymś, co nie konkuruje z nim jasnością - to jest ta sama zasada, co ciemna
   sala kinowa. Jasna zasłona rozświetlałaby kadry z budowy. */
.lb{position:fixed;inset:0;z-index:150;background:rgba(9,9,11,.96);display:flex;
  align-items:center;justify-content:center;padding:clamp(1rem,5vw,3rem)}
.lb[hidden]{display:none}
.lb img{max-width:100%;max-height:84vh;object-fit:contain;border-radius:0}
.lb-cap{position:absolute;left:0;right:0;bottom:clamp(1rem,3vw,2rem);text-align:center;
  font-size:13.5px;color:var(--przyg);padding:0 20px}
.lb button{position:absolute;background:rgba(255,255,255,.08);
  border:1px solid var(--linia-na-ciemnym);
  color:#fff;width:46px;height:46px;font-size:24px;line-height:1;cursor:pointer;border-radius:0}
.lb button:hover{background:rgba(255,255,255,.18)}
.lb-x{top:clamp(1rem,3vw,2rem);right:clamp(1rem,3vw,2rem)}
.lb-p{left:clamp(.5rem,2vw,1.5rem);top:50%;transform:translateY(-50%)}
.lb-n{right:clamp(.5rem,2vw,1.5rem);top:50%;transform:translateY(-50%)}

/* ── PAS ZDJĘCIA NA CAŁĄ SZEROKOŚĆ ──────────────────────────────────────────── */
/* Pas na pełną szerokość dostaje własne powietrze - bez tego sąsiaduje z sekcją
   krawędź w krawędź i czyta się jak ściana zdjęć (uwaga K. 07.09.2026). */
.pas{--pas-wys:clamp(240px,34vw,420px);--zapas:195px;position:relative;line-height:0;
  height:var(--pas-wys);overflow:hidden;margin:clamp(2rem,4vw,4rem) 0}
.pas img{width:100%;height:var(--pas-wys);object-fit:cover;border-radius:0}
/* ⚠️ Wyższy pas TYLKO dla kadru z pełnego oryginału (2400 px). Pas z betonu ma
   źródło 1440 px i przy tej wysokości by zmiękł - dlatego to osobna klasa, a nie
   podniesienie wartości dla wszystkich. */
.pas--duzy{--pas-wys:clamp(320px,46vw,620px);--zapas:330px}
.pas img[data-paralaksa]{position:absolute;inset:calc(-1 * var(--zapas)) 0;width:100%;
  height:calc(100% + 2 * var(--zapas))}
/* 🔴 ZAPAS PARALAKSY TYLKO TAM, GDZIE PARALAKSA DZIAŁA (K. 30.09.2026, iPhone: „paralaksa
   jest w złym formacie zdjęcia"). `rdzen.js` (10c) rusza zdjęcia wyłącznie przy
   `innerWidth > 900`, a CSS dawał zapas ±330 px zawsze — na telefonie rama zdjęcia miała
   320 + 660 = 980 px wysokości przy 390 px szerokości, `cover` powiększał plik 21:9
   ~6× i pokazywał 17 % jego szerokości (sama lampa na tynku), przy gęstości 0,23
   (stąd miękkość). Ten sam błąd co w hero 14.09 — tam naprawiony osobno, tu dla
   wszystkich ram z paralaksą naraz. Próg 900 px MUSI zgadzać się z warunkiem w `rdzen.js`:
   poniżej niego nic się nie przesuwa, więc zapas jest samym kosztem.
   `will-change:auto` — bez ruchu warstwa graficzna tylko zjada pamięć telefonu. */
@media (max-width:900px){
  .pas img[data-paralaksa],.otwarcie-tlo[data-paralaksa]{inset:0;height:100%;transform:none!important}
  [data-paralaksa]{will-change:auto}
}
/* Telefon: rama 1:1, a `<picture>` w `pages.py` podaje do niej kwadratowy kadr
   (`pas-*-tel.jpg`, z tego samego źródła). ⛔ Próg 600 px = `media` przy `<source>`. */
@media (max-width:600px){
  .pas--duzy{--pas-wys:100vw}
}
/* 🔴 Gradient policzony pod CIEMNE zdjęcia nie wystarcza pod jasne. Pas z elewacji
   (biały tynk + niebo) dał kontrast 3,76:1 przy progu 4,5 - złapane przez bramkę
   na telefonie 07.09.2026. Mocniejszy gradient z przystankiem w połowie + cień
   pod tekstem; na ciemnym pasie z betonu nie widać różnicy.
   ⚠️ Po przejściu strony na jasną gradient jest tym bardziej potrzebny: pas jest
   teraz jedynym ciemnym akcentem w tym miejscu i nie ma się o co oprzeć. */
.pas figcaption{position:absolute;left:0;right:0;bottom:0;padding:22px var(--bok);
  font:400 14px/1.5 Inter;color:#fff;line-height:1.5;
  text-shadow:0 1px 3px rgba(0,0,0,.55);
  background:linear-gradient(to top,rgba(15,15,18,.94) 0%,rgba(15,15,18,.72) 55%,transparent 100%)}

/* ── LISTA FAKTÓW / KARTA DANYCH ────────────────────────────────────────────── */
.karta{border:1px solid var(--linia-slaba);background:var(--papier-2);padding:34px;border-radius:0}
.karta h2{font-size:1.6rem;margin-bottom:22px}
.dane{width:100%;border-collapse:collapse}
.dane th,.dane td{text-align:left;padding:14px 0 18px;border-bottom:1px solid var(--linia-slaba);
  font-size:15.5px;line-height:1.5;vertical-align:top}
.dane th{font-weight:400;color:var(--przyg-jasny);width:40%;padding-right:20px}
.dane tr:last-child th,.dane tr:last-child td{border-bottom:0}
.dane a{border-bottom:1px solid var(--akcent);padding-bottom:1px}

.dwie-kolumny{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:start}
.trzy-kolumny{display:grid;grid-template-columns:repeat(3,1fr);gap:34px}
.tekst-dlugi p{max-width:58ch}
.tekst-dlugi p+p{margin-top:18px}
.tekst-dlugi h3{font-size:1.5rem;margin:38px 0 14px}

/* oś lat (podstrona „O nas") */
.lata{list-style:none;display:grid;gap:0}
.lata li{display:grid;grid-template-columns:120px 1fr;gap:26px;padding:22px 0;
  border-top:1px solid var(--linia-slaba)}
/* rok akcentem na papierze: jasny wariant daje 2,71 - musi zostać ciemniejszy */
.lata b{font-family:Jost;font-weight:400;font-size:1.7rem;color:var(--akcent-na-jasnym);
  line-height:1}
.lata p{color:var(--przyg-jasny);font-size:16px}

/* 🔴 KADR W „O NAS" — decyzja K. z 07.09.2026 (droga A drugiego pytania).
   Powód: na telefonie kolumny `oś lat | narracja` zwijają się w jedną i człowiek
   dostaje 104 słowa bez ani jednego obrazu (bramka `sciana_tekstu`). Kadr wchodzi
   MIĘDZY oś a narrację, więc na telefonie przerywa ścianę tekstu, a na laptopie
   wypełnia pustkę pod krótką osią - tam i tak zostawało pół kolumny papieru.
   ⛔ Nie przenosić go do prawej kolumny: wtedy na telefonie ląduje na końcu
   i nie przerywa niczego. Kolejność w HTML JEST tu treścią. */
/* ⚠️ Na laptopie kadr ma LIMIT SZEROKOŚCI. Bez niego pionowe zdjęcie rozciągało się
   na całą kolumnę (494×659 px) i lewa strona wybiegała ~250 px poniżej prawej -
   zamiast wyrównać kolumny, przechylał je w drugą stronę. Zawężamy SZEROKOŚĆ,
   nie przycinamy wysokości: kadry pionowe idą bez kadrowania (`DESIGN.md`).
   Na telefonie limit jest kasowany - tam kadr ma być pełnej szerokości. */
/* ── „O nas": oś lat | narracja, a POD nimi szeroki kadr przez obie kolumny ────
   🔴 Kolejność w HTML to `oś → kadr → narracja` i MA TAKA ZOSTAĆ: na telefonie
   siatka się zwija i kadr przerywa ścianę tekstu w połowie (bramka `sciana_tekstu`).
   Na laptopie kadr wskakuje do drugiego wiersza przez `grid-row` - dlatego położenie
   robi tu SIATKA, a nie kolejność elementów. */
.uklad-o-nas{display:grid;grid-template-columns:1fr 1fr;gap:60px 70px;align-items:start}
.uklad-o-nas>.o-nas-lata{grid-column:1;grid-row:1}
.uklad-o-nas>.tekst-dlugi{grid-column:2;grid-row:1}
.uklad-o-nas>.kadr-o-nas{grid-column:1/-1;grid-row:2}
.kadr-o-nas{margin:0}
.kadr-o-nas img{width:100%;height:auto;display:block;border-radius:0}
.kadr-o-nas figcaption{margin-top:12px;font-size:13.5px;color:var(--przyg-jasny);
  line-height:1.45}

/* ── ZAMKNIĘCIE STRONY: wezwanie do kontaktu ────────────────────────────────── */
/* 🔴 Ramka wezwania jest CIEMNA i to jest drugi (obok sceny) świadomy akcent czerni.
   Na jasnej stronie sama cienka linia zniknęłaby w papierze; ciemny blok mówi
   „tu się kończy czytanie, zaczyna dzwonienie". Znaku firmowego tu nie ma,
   więc zasada „logo tylko na jasnym" jest zachowana. */
.domkniecie{background:var(--noc);color:var(--biel);border:0;
  padding:clamp(2rem,4vw,3.4rem);border-radius:0;
  display:grid;grid-template-columns:1fr auto;gap:40px;align-items:center}
.domkniecie h2{font-size:clamp(1.7rem,3vw,2.4rem);margin-bottom:12px;color:var(--biel)}
.domkniecie p{color:var(--przyg);max-width:52ch}
.domkniecie .kontakt-linia{justify-content:flex-end}
.domkniecie .duch{border-color:rgba(255,255,255,.22);color:var(--biel)}
.domkniecie .duch:hover{border-color:var(--biel);background:rgba(255,255,255,.09)}

/* ── MAPA PO KLIKNIĘCIU (rdzeń, blok 6) ─────────────────────────────────────── */
/* 🔴 08.09.2026, blok E. Zasłona była BIAŁYM prostokątem (`--papier-2`) na papierze
   `#F3F1ED` z włoskową ramką - czytała się jak element, który się nie wczytał, a nie
   jak część strony (rdzeń wprost tego zabrania: „ma wyglądać jak część strony, nie jak
   błąd"). Teraz to ciemny panel w tonie pasa wezwania, z siatką w tle udającą plan
   miasta i adresem złożonym typograficznie. ⛔ Nie wracać na biel i nie zdejmować
   siatki - to ona odróżnia „miejsce na mapę" od „dziury". */
[data-po-kliknieciu]{border:0;background:var(--noc);color:var(--biel);min-height:380px;
  position:relative;overflow:hidden;gap:6px}
[data-po-kliknieciu]::before{content:"";position:absolute;inset:0;opacity:.16;
  background-image:
    repeating-linear-gradient(0deg,transparent 0 47px,rgba(255,255,255,.55) 47px 48px),
    repeating-linear-gradient(90deg,transparent 0 47px,rgba(255,255,255,.55) 47px 48px),
    linear-gradient(112deg,transparent 0 calc(50% - 3px),rgba(255,255,255,.9) calc(50% - 3px) calc(50% + 3px),transparent calc(50% + 3px));
  pointer-events:none}
[data-po-kliknieciu]>*{position:relative}
.mapa-adres{font:500 12px/1 Inter;letter-spacing:.2em;text-transform:uppercase;
  color:var(--akcent-jasny)}
[data-po-kliknieciu] p{font-size:1.35rem;color:var(--biel);margin:0 0 12px}
.pk-btn{background:var(--akcent-btn);color:#fff;font:500 15px/1 Inter;padding:15px 24px;
  border-radius:0}
.pk-btn:hover{background:var(--akcent-btn-hover)}
[data-po-kliknieciu]+iframe,iframe{width:100%;min-height:320px;border:0}
.mapa{min-height:440px;display:block}
/* 🔴 K. 10.09.2026: „zmniejsz puste przestrzenie pod i nad mapką". Mapa to blok
   informacyjny, nie osobny rozdział - pełny rytm sekcji robił wokół niej dziurę
   na pół ekranu. ⛔ Nie zmieniać globalnego `--rytm`, bo rozjedzie się cała strona. */
.sekcja--mapa{padding-block:calc(var(--rytm) * .42)}
.sekcja--mapa .naglowek-sekcji{margin-bottom:32px}
@media (max-width:700px){.mapa{min-height:320px}}

/* ── STOPKA ─────────────────────────────────────────────────────────────────── */
/* 🔴 Stopka jest JASNA, choć na ciemnej stronie była czarna - bo stoi w niej LOGO.
   Ton głębszy od papieru (`--papier-3`) oddziela ją od treści bez rysowania kreski. */
footer{background:var(--papier-3);border-top:1px solid var(--linia-slaba);padding:70px 0 40px;
  color:var(--przyg-jasny)}
.stopka{display:grid;grid-template-columns:1.4fr 1fr 1.2fr;gap:50px}
.stopka img{height:66px;width:auto;margin-bottom:20px;display:block}
.stopka p{font-size:14.5px;line-height:1.6}
.stopka h2{font-family:Inter;font-size:12px;font-weight:500;letter-spacing:.2em;
  text-transform:uppercase;color:var(--atrament);margin-bottom:18px}
.stopka a{display:block;font-size:14.5px;padding:5px 0;color:var(--przyg-jasny)}
.stopka a:hover{color:var(--atrament)}
.stopka-dol{display:flex;gap:20px;flex-wrap:wrap;justify-content:space-between;
  margin-top:50px;padding-top:24px;border-top:1px solid var(--linia-slaba);font-size:13px}
.stopka-dol a{border-bottom:1px solid var(--linia)}

/* ── PASEK PRZY DOLNEJ KRAWĘDZI (telefon) ───────────────────────────────────── */
.pasek-dolny{display:none;position:fixed;left:0;right:0;bottom:0;z-index:120;gap:1px;
  box-shadow:0 -2px 12px rgba(0,0,0,.22)}
.pasek-dolny a{flex:1;display:flex;align-items:center;justify-content:center;gap:9px;
  padding:18px 8px;font:500 16px/1 Inter;color:#fff;border-radius:0}
.pasek-dolny .a-tel{background:#16181C}
.pasek-dolny .a-wa{background:var(--wa)}

/* ── TELEFON ────────────────────────────────────────────────────────────────── */
@media (max-width:980px){
  :root{--bok:20px;--gora:76px}
  body{padding-bottom:0}
  /* 🔴 `min-height`, NIE `height` (K. 11.09.2026: „menu się nie pokazuje").
     Rozwinięte menu wchodzi w DRUGI wiersz tego flexa (`.nawigacja{order:3;width:100%}`).
     Przy sztywnej wysokości 76 px drugi wiersz wylewał się poza pasek — a tło i rozmycie
     siedzą na `.top`, więc pozycje menu lądowały ciemnym tekstem na ciemnym zdjęciu hero
     i były PRAKTYCZNIE NIEWIDOCZNE. Widać było tylko pomarańczowe strzałki.
     ⚠️ Samo `min-height` tu NIE WYSTARCZA i to jest pułapka: regułа bazowa
     `.top .wrap` (wyżej) ma `height:var(--gora)`, a media query jej nie zdejmuje.
     Kontener zostawał na 76 px, a menu (271 px) po prostu z niego wychodziło.
     Dlatego jest tu JAWNE `height:auto` przed `min-height`. Zmierzone 11.09.2026.
     ⛔ Nie wracaj do `height` — pasek MUSI móc urosnąć pod otwarte menu. */
  .top .wrap{height:auto;min-height:var(--gora);flex-wrap:wrap;gap:16px}
  /* 46 px zamiast 60: pasek na telefonie jest niższy, a znak nadal czytelny
     (62 px szerokości, napis ~6 px - na gęstym ekranie telefonu wystarcza). */
  .znak img{height:46px}
  .tel-gora{display:none}          /* numer stoi na pasku przy kciuku, nie dublujemy */
  .burger{display:inline-flex;align-items:center;gap:10px;margin-left:auto;
    background:transparent;color:var(--atrament);border:1.5px solid rgba(27,27,30,.3);
    border-radius:0;padding:11px 16px;font:500 15px/1 Inter;cursor:pointer}
  .burger-kreski{display:inline-flex;flex-direction:column;gap:3px}
  .burger-kreski i{display:block;width:16px;height:1.5px;background:currentColor}
  .nawigacja{margin-left:0;width:100%;order:3}
  html.js .nawigacja{display:none}
  html.js .nawigacja.is-open{display:block}
  .nawigacja ul{display:block;padding:6px 0 14px}
  .nawigacja a:not(.btn){display:flex;justify-content:space-between;align-items:center;
    width:100%;padding:16px 0;font-size:17px;color:var(--atrament);
    border-bottom:1px solid var(--linia-slaba)}
  .nawigacja a:not(.btn)::after{display:none}
  .nawigacja .strzalka-poz{display:inline;color:var(--akcent-na-jasnym);font-size:18px}
  .nawigacja a[aria-current="page"]{color:var(--akcent-na-jasnym)}

  .scena{padding:56px 0;min-height:calc(100vh - var(--gora,96px));min-height:calc(100svh - var(--gora,96px))}
  /* 🔴 Telefon jest WĘŻSZY niż kadr, więc `cover` obcina boki i zostaje sam materac.
     Dwie rzeczy naraz (K. 14.09.2026: „przesuń w lewo, żeby okno po prawej było widać;
     jeżeli da się oddalić - też"):
     1. `object-position` w prawo - widoczny wycinek idzie na okno dachowe nad łóżkiem.
     2. ZERO zapasu na paralaksę. Na komputerze zapas ±150 px kosztuje trochę kadru, ale
        na telefonie kontener robił się o 300 px wyższy niż ekran (tj. +40 %), więc `cover`
        skalowało zdjęcie i pokazywało ~33 % jego szerokości. Bez zapasu widać ~47 % -
        to jest to „oddalenie". Cena: paralaksa hero na telefonie nie działa (bez zapasu
        tło odsłoniłoby krawędź), dlatego `transform:none`. */
  .scena-tlo{inset:0;height:100%;transform:none !important;object-position:80% 38%}
  .scena h1{font-size:clamp(2.2rem,8vw,2.9rem);max-width:none}
  /* 🔴 Na telefonie kadr idzie PRZED tekstem: decyzja z etapu 2 - pierwszy ekran ma
     rozstrzygnąć jednym zdjęciem prawdziwej roboty, a nie samym nagłówkiem.
     Numery i tak są pod kciukiem, na przyklejonym pasku przy dolnej krawędzi. */
  /* Na telefonie scena zostaje pełnoekranowa: przyciemnienie idzie z góry na dół,
     bo tekst leży NAD zdjęciem, a nie obok niego. */
  /* ⚠️ .80/.64/.50 dawało etykiecie nad nagłówkiem 4,49:1 przy progu 4,5 — bramka
     to złapała. Nie rozjaśniać poniżej tych wartości bez ponownego pomiaru. */
  .scena::after{background:linear-gradient(180deg,rgba(10,10,12,.85) 0%,
    rgba(10,10,12,.70) 46%,rgba(10,10,12,.56) 100%)}
  .otwarcie--kadr::after{background:linear-gradient(180deg,rgba(10,10,12,.90) 0%,
    rgba(10,10,12,.86) 100%)}
  .kafle{grid-template-columns:1fr 1fr;gap:16px}
  .galeria{columns:2;column-gap:16px}
  .galeria figure{margin-bottom:16px}
  .zygzak,.dwie-kolumny{grid-template-columns:1fr;gap:32px}
  /* 🔴 Te selektory MUSZĄ być tak samo szczegółowe jak reguły z laptopa
     (`.uklad-o-nas>.kadr-o-nas`), inaczej `grid-row:2` wygrywa mimo media query,
     kadr ląduje POD tekstem i bramka znów zgłasza `sciana_tekstu`. */
  .uklad-o-nas{grid-template-columns:1fr;gap:32px}
  .uklad-o-nas>.o-nas-lata,.uklad-o-nas>.kadr-o-nas,
  .uklad-o-nas>.tekst-dlugi{grid-column:1;grid-row:auto}
  .zygzak{padding:38px 0}
  .zygzak--dwa,.zygzak--dwa.zygzak--odwrocony{grid-template-columns:1fr}
  .zygzak--odwrocony .zygzak-obraz{order:0}
  /* Jedna kolumna nie czyta się już jak zygzak — zostaje wspólny fade `.rv`. */
  .zygzak.rv>.zygzak-obraz,.zygzak.rv.is-in>.zygzak-obraz{
    opacity:1;transform:none;animation:none}
  .trzy-kolumny{grid-template-columns:1fr;gap:26px}
  .domkniecie{grid-template-columns:1fr;gap:26px}
  .domkniecie .kontakt-linia{justify-content:flex-start}
  .stopka{grid-template-columns:1fr;gap:36px}
  .reel{max-width:none}
  .pasek-dolny{display:flex}
  body{padding-bottom:70px}
}

@media (max-width:600px){
  .para{grid-template-columns:1fr;gap:22px}
  /* Dwa kadry obok siebie w 326 px to po ~155 px - za mało, żeby coś na nich zobaczyć. */
  .zygzak--dwa .zygzak-obraz{grid-template-columns:1fr;gap:14px}
  .kafle{grid-template-columns:1fr}
  .galeria{columns:1}
  .lata li{grid-template-columns:1fr;gap:6px;padding:18px 0}
  .karta{padding:24px 20px}
  .dane th{width:44%}
}

/* ── DRUK: klient drukuje kontakt i zakres ──────────────────────────────────── */
@media print{
  body{background:#fff;color:#000}
  .pasek-dolny,.reel-btn,.lb{display:none!important}
  .scena-tlo[data-paralaksa],.otwarcie-tlo[data-paralaksa],.pas img[data-paralaksa],
  .para.kaskada>.klatka,.zygzak.rv>.zygzak-obraz,.galeria.kaskada>figure,
  .lata--ruch>li b,.lata--ruch>li p{opacity:1!important;transform:none!important;animation:none!important}
  .karta{background:#fff;color:#000}
  /* Ciemne akcenty na papierze zjadają toner i wychodzą szarą plamą. */
  .scena,.domkniecie,.ciemna{background:#fff!important;color:#000!important}
  .scena h1,.domkniecie h2,.ciemna h1,.ciemna h2,.ciemna h3{color:#000!important}
  .scena .lead,.domkniecie p,.ciemna .pod{color:#333!important}
}

/* odstęp między tekstem sekcji a ramką wezwania na stronie głównej */
.odstep-domkniecie{margin-top:clamp(2.5rem,5vw,4.5rem)}


/* ── ZNACZKI SOCIAL (prawy dolny róg) ────────────────────────────────────────
   🔴 BEZ KAFELKA - polecenie K. z 08.09.2026: „w okrągłych dymkach, bez tego
   białego, tylko same logo i ładnie podświetlone, z efektem hovera".
   Wcześniej znaki siedziały w kwadratowych płytkach z obrysem; na papierze
   czytało się to jak baner doklejony do strony.

   ⚠️ OKRĄGŁOŚĆ ROBI SAM ZNAK, nie `border-radius`. Facebook jest wypełnionym
   kołem z natury, Instagram dostał koło w swoim gradiencie (`pages.py`).
   Dzięki temu zasada `border-radius: 0` z `DESIGN.md` zostaje nienaruszona -
   nie ma płytki, więc nie ma czego zaokrąglać. ⛔ Nie wracać tu do `border-radius`.

   🔴 PODŚWIETLENIE JEST FUNKCJĄ, NIE OZDOBĄ. Znak bez tła leży wprost na tym,
   co akurat jest pod spodem - a przewijając stronę przejeżdża i po papierze,
   i po ciemnej scenie, i po zdjęciach. Biała poświata trzyma go czytelnym na
   ciemnym, ciemna - na jasnym. Dlatego są DWIE, obie słabe; razem dają obrys
   widoczny na każdym tle, którego samo się nie widzi jako ramki. */
.social-dymki{position:fixed;right:24px;bottom:24px;z-index:110;
  display:flex;flex-direction:column;gap:14px}
.social-dymki a{display:grid;place-items:center;width:48px;height:48px;
  background:none;border:0;
  filter:drop-shadow(0 0 0 rgba(255,255,255,0)) drop-shadow(0 3px 8px rgba(15,15,18,.28));
  transition:transform .22s var(--ease),filter .22s ease}
.social-dymki svg{width:48px;height:48px;display:block}
.social-dymki .s-fb svg path{fill:#1877F2}
.social-dymki .ig-kolo{fill:url(#ig-grad)}
/* ⚠️ Lista filtrów MUSI mieć te same funkcje w obu stanach, inaczej przejście
   nie animuje się, tylko przeskakuje. Dlatego stan spoczynku ma poświatę
   o zerowym promieniu i zerowej alfie, a nie brak poświaty. */
.social-dymki a:hover,.social-dymki a:focus-visible{transform:translateY(-3px) scale(1.06);
  filter:drop-shadow(0 0 12px rgba(255,255,255,.55)) drop-shadow(0 6px 14px rgba(15,15,18,.4))}
.social-dymki a:active{transform:translateY(-1px) scale(1.02)}

/* 🔴 NA TELEFONIE ZNACZKÓW W ROGU NIE MA. Dolny róg należy do „Zadzwoń” i „WhatsApp” -
   one przynoszą telefony, social nie. Przy `bottom:84px` zasłaniały H1 o 37 px
   (złapane przez bramkę 07.09.2026), a niżej wchodziły na przyklejony pasek.
   Zamiast kombinować z pozycją: na telefonie social siedzi w STOPCE, tam gdzie
   człowiek go szuka i gdzie niczego nie przykrywa. */
@media (max-width:900px){
  .social-dymki{display:none}
}

/* Te same znaczki w stopce - na telefonie jedyne, na laptopie drugie obok rogu.
   Stopka jest jasna, więc poświata jest tu ciemniejsza niż w rogu. */
.stopka-social{display:flex;gap:14px;margin-top:20px}
.stopka-social a{display:grid;place-items:center;width:40px;height:40px;
  background:none;border:0;
  filter:drop-shadow(0 0 0 rgba(27,27,30,0)) drop-shadow(0 2px 5px rgba(27,27,30,.18));
  transition:transform .22s var(--ease),filter .22s ease}
.stopka-social svg{width:40px;height:40px;display:block}
.stopka-social .s-fb svg path{fill:#1877F2}
.stopka-social .ig-kolo{fill:url(#ig-grad-stopka)}
.stopka-social a:hover,.stopka-social a:focus-visible{transform:translateY(-3px) scale(1.06);
  filter:drop-shadow(0 0 10px rgba(27,27,30,.28)) drop-shadow(0 5px 12px rgba(27,27,30,.3))}
@media print{.social-dymki{display:none}}


/* ══════════════════════════════════════════════════════════════════════════════
   WEJŚCIE NA STRONĘ — kurtyna z logo         (skill `wejscie-na-strone`, 08.09.2026)
   ══════════════════════════════════════════════════════════════════════════════
   CO OPOWIADA (reguła 1 skilla: wejście ma opowiadać PRODUKT klienta, bo zwykły
   fade z logo umie zrobić każdy szablon): ekran jest świeżo wykończoną ŚCIANĄ
   w kolorze papieru. Spod pociągnięcia wychodzi znak firmy, pod nim zostaje ślad
   w kolorze akcentu, a potem ściana odsłania gotowe wnętrze. To jest dosłownie to,
   co ta firma robi: gładź, malowanie, wnętrze pod klucz.

   🔴 DLACZEGO KURTYNA JEST JASNA, A NIE CIEMNA: cały efekt to KONTRAST między
   zasłoną a tym, co spod niej wychodzi. Nasza scena jest ciemna (`#0F0F12`),
   więc zasłona musi być papierowa - to jest ten sam układ, który K. ocenił jako
   najlepszy przy MEBLE FRONT. ⛔ Ciemna zasłona na ciemnej scenie nie odsłania
   niczego: obie warstwy mają ten sam kolor i widz nie widzi ruchu.

   🔴 ZASŁONA SCHODZI W DÓŁ, nie w górę. Znak leci do paska NA GÓRZE, a pasek jest
   jasny - musi być odsłonięty PIERWSZY, żeby znak wylądował na papierze.

   🔴🔴 NAJPIERW LECI ZNAK, DOPIERO POTEM SCHODZI ŚCIANA (opóźnienie .42s).
   Zmierzone 08.09.2026 na stopklatce: przy jednoczesnym starcie ściana wygrywa
   wyścig (0,62 s kontra 0,72 s znaku), odsłania ciemną scenę pod lecącym znakiem
   i czarny napis „TCHÓRZEWSKI" ZNIKA w czerni jak naklejka - dokładnie pułapka
   z reguły 7 skilla. Sama krzywa z wolnym startem tego NIE ratowała.
   Przy tym opóźnieniu znak jedzie po papierze aż do paska, a ściana rusza dopiero,
   gdy on jest już prawie na miejscu. ⛔ Nie zdejmować tego opóźnienia i nie skracać
   go poniżej ~0,4 s bez ponownego sprawdzenia na stopklatce (`_makiety/wejscie/`).

   ⛔ ZERO zwykłego `opacity`+`scale` na logo - to jest znamię taniej roboty.
   Znak wchodzi MASKĄ (`clip-path`) z rozmycia do ostrości, jak spod wałka.

   Bezpieczniki (wszystkie obowiązkowe): zasłona jest `display:none`, dopóki nie
   włączy jej skrypt · twardy limit czasu ją zdejmuje niezależnie od wszystkiego ·
   klik/scroll/dotyk/klawisz przerywa · `prefers-reduced-motion` pomija całość. */

.wejscie{display:none}
.intro-on .wejscie{display:block;position:fixed;inset:0;z-index:200;pointer-events:none}

/* PŁYTA — to ona zasłania i to ona ma `clip-path`. Znak jest jej RODZEŃSTWEM,
   nie dzieckiem: dziecko zostałoby przycięte razem z nią i zniknęłoby w trakcie
   odsłony, zamiast lecieć do paska. */
.wejscie-plyta{position:absolute;inset:0;background:var(--papier);
  clip-path:inset(0 0 0 0)}
.intro-on.intro-out .wejscie-plyta{clip-path:inset(100% 0 0 0);
  transition:clip-path .62s cubic-bezier(.66,0,.24,1) .42s}

.wejscie-znak-box{position:fixed;left:50%;top:50%;z-index:201;
  transform:translate(-50%,-50%);display:grid;justify-items:center;gap:18px}
.intro-on.intro-out .wejscie-znak-box{
  transform:translate(calc(-50% + var(--i-px)),calc(-50% + var(--i-py)))
            scale(var(--i-zmniejsz));
  transition:transform .72s cubic-bezier(.16,.84,.44,1)}

/* TAKT 1 — znak wychodzi spod pociągnięcia: maska w prawo + z rozmycia do ostrości.
   ⚠️ Skala idzie 1,045 → 1, a NIE „mały → duży": docelowy rozmiar znaku robi
   `width`/`height` z pomiaru (reguła 8 skilla), bo powiększanie `transform`em
   rasteryzuje warstwę w rozmiarze bazowym i na telefonie daje rozmyty znak. */
/* 🔴 ⛔ ŻADNEGO `drop-shadow` NA ZNAKU — w ŻADNYM stanie, nawet z alfą 0.
   iOS (Safari i Chrome na iPhonie to ten sam silnik) rysuje go jako jasny PROSTOKĄT
   całego znaku, a nie jako łunę wokół liter. To jest dokładnie „białe pole na logo",
   które K. zgłosił z telefonu przy STOLMARZE (08.09.2026, lekcja 2026-09-08-005)
   i drugi raz TUTAJ (11.09.2026) — bo tu stała poświata z alfą .9 w stanie `intro-out`,
   wpisana jako „ubezpieczenie" wbrew regule 7 skilla `wejscie-na-strone`.
   ⚠️ Na Chrome/Macu tego NIE WIDAĆ, także w emulacji WebKita. Widać tylko na iPhonie.
   ⚠️ Lista filtrów MUSI mieć te same funkcje we wszystkich stanach, inaczej przeglądarka
   nie animuje przejścia, tylko przeskakuje — dlatego wszędzie jest samo `blur`. */
.wejscie-znak{display:block;width:var(--i-w);height:var(--i-h);max-width:none;
  clip-path:inset(0 100% 0 0);transform:scale(1.045);
  filter:blur(14px)}
.intro-on.intro-gra .wejscie-znak{clip-path:inset(0 0 0 0);transform:scale(1);
  filter:blur(0);
  transition:clip-path .52s cubic-bezier(.16,1,.3,1),
             filter .52s cubic-bezier(.16,1,.3,1),
             transform .52s cubic-bezier(.16,1,.3,1)}
/* ⛔ Nie dokładaj tu reguły `.intro-on.intro-out .wejscie-znak` z filtrem. Stała tu
   i robiła wyłącznie tę poświatę; lot znaku do paska prowadzi `.wejscie-znak-box`. */

/* Drugi bezpiecznik z tej samej lekcji: na czas wejścia pasek BEZ `backdrop-filter`.
   WebKit potrafi narysować warstwę rozmycia rodzica NAD dzieckiem z własnym
   `filter`/`transform`, czyli nad lecącym znakiem. Po zejściu kurtyny klasa
   `intro-on` znika i rozmycie paska wraca samo. */
.intro-on .top{-webkit-backdrop-filter:none;backdrop-filter:none}

/* TAKT 2 — ślad po pociągnięciu. Rusza 0,14 s PO znaku; bez tego opóźnienia
   wszystko startuje naraz i czyta się jak jeden płaski fade (reguła 4 skilla). */
.wejscie-kreska{display:block;width:var(--i-w);height:2px;background:var(--akcent);
  transform:scaleX(0);transform-origin:left center}
.intro-on.intro-gra .wejscie-kreska{transform:scaleX(1);
  transition:transform .46s cubic-bezier(.16,1,.3,1) .14s}
.intro-on.intro-out .wejscie-kreska{opacity:0;transition:opacity .3s ease}

/* Znak w pasku czeka schowany i odsłania się dokładnie wtedy, gdy lecący znak
   ląduje na jego miejscu. Bez tego przez pół sekundy widać DWA loga naraz.
   ⚠️ `visibility`, nie `display` - miejsce w nagłówku ma zostać zajęte, inaczej
   pasek zapada się na czas wejścia i podskakuje po zdjęciu kurtyny. */
.intro-on .znak img{visibility:hidden}

/* 🔴 Reguła 5b skilla: animacje wejściowe pierwszego ekranu grają POD zasłoną
   i kończą się już PO odsłonie - hero wychodzi spod kurtyny wyblakłe. Gasimy je
   klasą TRWAŁĄ, której nigdy nie zdejmujemy; gdyby wisiała na `intro-on`,
   zdjęcie tamtej klasy puściłoby je drugi raz, tym razem na widoku. */
.bez-wejscia-tla .scena .rv{opacity:1;transform:none;transition:none}

@media (prefers-reduced-motion:reduce){
  .wejscie,.intro-on .wejscie{display:none}
  .intro-on .znak img{visibility:visible}
}
@media print{.wejscie{display:none!important}}
