/* Strona główna, druga runda (dopracowanie po uwagach Michała z 9.10).
   Kolory, kroje, nagłówek witryny, przycisk i stopka pochodzą ze wspólnej podstawy
   (../../narzedzia-warianty/css/base.css i c.css, ../../malina-kafle/css/look.css z wyglądem data-look="u").
   Ten arkusz dokłada: skalę pisma strony, odstępy góry strony (mediany z Mobbina, r4), parę przycisków pod zdaniem i ich wygląd
   (html[data-przycisk="miekki|stary"]), scenę z obrazem platformy w trzech oprawach (html[data-scena="a|b|c"]), sześć nazw na krawędziach
   obrazu (r2; od szlifu 2 z 11.10 rama 900 px, nazwy z obu stron 80 px na ramie w trzech parach na tych samych wysokościach 16 / 50 / 88%,
   kolor pisma html[data-nazwy="atrament|malina"]), poprawki paska górnego (blok do przeniesienia do podstawy), kafle 8 + 4, sekcję o autorze,
   stopkę i ruch wejścia.

   Skala pisma (1440 px): nagłówek strony 60 (dwa wiersze; do szlifu 11.10 było 64), nagłówki sekcji 44, nazwa kafla 26, zdanie 20, tekst i nazwa przy obrazie 18,
   przyciski 16 (nowy wygląd) / 17 (stary), mały 15.
   Odstępy góry (r4): pasek 70; pasek → nagłówek 96 (okno od 700 px wysokości), 64 (niższe), 56 (telefon);
   nagłówek → zdanie 20; zdanie → przyciski 28 (komputer) / 16; przyciski → scena 64 / 48 / 32. Między sekcjami 112 i 132 (głowa postaci wchodzi w ten drugi na 80 px).
   Progi: 699 px (telefon), kolumna treści 58 rem (nazwy na bocznych krawędziach obrazu; węższa: nazwy w rzędzie pod obrazem). */

:root {
  --expo: cubic-bezier(.16, 1, .3, 1);
  /* jedna krzywa wejść i powrotów na całej stronie: podstawa ma własną --ease-out (.22, 1, .36, 1) na przycisku, strzałkach i zdjęciach kafli,
     prawie taką samą jak --expo (scena, linia menu); na tej stronie obie są tą samą krzywą (R3-J4-4). Wciśnięcia 120 ms ease-out zostają. */
  --ease-out: var(--expo);
  --pen: cubic-bezier(.65, 0, .35, 1);
  --mat: 6px;                /* biały margines między ramą a obrazem */
  --home-top: 56px;          /* pasek → nagłówek (telefon) */
  --stage-gap: 32px;         /* zdanie z przyciskiem → scena (telefon) */
  --h2: clamp(1.5rem, 1rem + 2.2vw, 2.75rem);          /* 24 px do okna 485, potem 24 → 31,4 px do okna 699 (reguła niżej), 31,4 (700) → 44 px; krok do nagłówka strony 1,36 na komputerze (60 / 44) */
  --h3: clamp(1.375rem, 1.1rem + .9vw, 1.625rem);      /* 22 → 26 px */
  --lede: clamp(1.125rem, 1.03rem + .42vw, 1.25rem);   /* 18 → 20 px */
  --fs-text: clamp(1.0625rem, 1rem + .3vw, 1.125rem);  /* 17 → 18 px: akapity tak duże jak nazwy przy obrazie, małe pismo w pięciu stopniach
                                                           15 / 16 / 17 / 18 / 20 zamiast sześciu w 5 px (R2-J3-4) */
  --head-pad: 8px;           /* oddech linii pod menu (pasek komputera; telefon 4 px w bloku paska telefonu) */
}
@media (min-width: 700px) {
  :root { --mat: 8px; --home-top: 64px; --stage-gap: 48px; }
}
/* pełne mediany dopiero w oknach od 700 px wysokości (1440 × 900, 1536 × 730); niższe (1366 × 657) dostają dolny kwartyl.
   96 px daje od linii podstawowej tekstu menu do górnej krawędzi liter nagłówka 135 px przy pasku 70 px (pomiar pikseli farby w 1536 × 730
   przy gęstości 2, _zrzuty/poprawki-r3/pomiar.py; r4: mediana 141, kwartyle 106–161) */
@media (min-width: 700px) and (min-height: 700px) {
  :root { --home-top: 96px; --stage-gap: 64px; }
}
/* telefon: nagłówek sekcji 24 px do okna 485 (do 11.10 wieczorem clamp dawał 24–26,7 px: w oknie 485 krok od zmniejszonego nagłówka strony 32,9 px
   wynosił 1,23, najmniej na stronie; z 24 px jest 1,37 w 485, 1,34 w 390, w 320 bez zmian; 25 px dawało w 320 krok 1,12). Od okna 485 do 699
   rośnie liniowo do 31,4 px, czyli do wartości, którą reguła z :root daje w oknie 700: stałe 24 px w całym bloku (pierwsza wersja z 11.10 wieczorem)
   robiło skok 24 → 31,4 na progu 699 / 700, a w oknach 600–699 nagłówek był tylko 1,2 raza większy od nazwy kafla i 1,70–1,75 raza mniejszy
   od tytułu strony (krytyk szlifu 2, sedziowie/szlif2/k/h2/para_640.png); z klamrą 28,0 px w 600, 29,3 w 640, 31,4 w 699, krok do tytułu 1,34–1,46.
   Nazwa kafla 18–19 px: krok nagłówek sekcji → nazwa 1,27 w 485 i 1,33 w 390 (z 22 px było 1,09–1,21), nagłówek → akapit 1,37–1,41;
   arkusze sedziowie/szlif2/b2/kand_h2_*.png */
@media (max-width: 699px) {
  :root { --h2: clamp(1.5rem, 1.5rem + (100vw - 485px) * .0344, 1.9625rem); --h3: clamp(1.125rem, .85rem + 1.1vw, 1.25rem); }
}

/* ta strona nie ma przyklejonych pasków, więc kotwice nie potrzebują zapasu z makiety Narzędzi;
   16 px z góry i z dołu zostawia miejsce na obramowanie fokusu elementu przewiniętego do krawędzi okna */
html { scroll-padding-block: 16px; -webkit-tap-highlight-color: transparent; }
/* przewijanie do sekcji odnośnikiem w stronie („Poznaj stronę” pod zdaniem, „O mnie” w stopce) jest płynne tylko po kliknięciu i tylko ze skryptu
   (js/home.js, scrollIntoView), nie przez scroll-behavior: smooth na html: ta reguła animowała też każde przewinięcie do elementu z fokusem
   (Tab po Tab przez kafle) i przewijanie ze skryptów, a wariant html:focus-within nie działał wcale, bo Chrome zdejmuje fokus z odnośnika
   w chwili skoku (sedziowie/szlif/b2/diag_plynnosc.py, przewijanie.json). Bez skryptów zwykły skok do kotwicy.
   Sekcja, do której skrypt przeniósł punkt startu Tab (chwilowy tabindex −1), nie dostaje obrysu fokusu: obrys 3 px wokół całej sekcji
   nic nie wskazuje, a następny Tab i tak podświetla pierwszy kafel. */
.finds:focus, .about:focus { outline: 0; }
a, button { touch-action: manipulation; }
/* odnośnik „Przeskocz do treści”: schowany przesunięciem o własną wysokość, więc nie wystaje przy dużej czcionce przeglądarki */
.skip { top: 0; transform: translateY(-120%); }
.skip:focus { top: 12px; transform: none; }

/* ============ pasek górny: do przeniesienia do wspólnej podstawy (ten sam pasek dostaną Narzędzia i pozostałe strony) ============
   Wysokość 72 px (mediana wzorców 66, z linią 57–69; r4; do rundy 2 szlifu 70 px). Odnośniki 16 / 500, odstęp 28 px; najechanie i strona bieżąca:
   ciemne pismo i cienka malinowa linia pod napisem (ten sam gest, co odręczne podkreślenie na landingu), bez prostokąta tła.
   „Zaloguj się”: obrys 1 px, 44 px (pole dotyku), 600, lżejszy od jedynego przycisku strony. Koszyk: ikona optycznie zamyka kolumnę.
   Telefon: pasek 60 px, panel pod linią, napisy równo z logo, wiersze 52 px. Pod paskiem linia 1 px (reguła niżej).
   Wysokość w rem (4,5 rem = 72 px, telefon 3,75 rem = 60 px; sędziowie rundy 2 szlifu): przy ekranie skalowanym na 125% pasek 70 px kończył się
   w połowie piksela (87,5) i linia pod nim rozmywała się na dwa blade wiersze, 72 px daje 90, czyli jeden czysty wiersz; w rem pasek rośnie
   z czcionką przeglądarki, więc przy 24 px litery znaku nie dotykają linii (przy stałych 60 px „g” stało 1 px nad nią). */
.head-in { min-height: 4.5rem; gap: 12px; }
/* linia pod paskiem (Michał 11.10 wieczorem: „delikatna kreseczka oddzielająca menu od reszty”): 1 px w kolorze --line, przez całe okno, na dolnej
   krawędzi paska (72 px i 8 px oddechu, telefon 60 i 4), stoi od pierwszej klatki jak cały pasek. Wzorce z Mobbina (sedziowie/szlif2/r.md): 13 z 13 linii ma 1 px
   i biegnie przez całe okno, żadna nie kończy się na kolumnie treści; --line na kremie daje 7,8 punktu jasności, tyle co Oku, Supabase i Runway
   (mediana wzorców 6,6–7,6). Odrzucone (sedziowie/szlif2/b2/kand_linia_*.png): słabsza #F1E8E1 (4,6 pkt, Mintlify i Grain) w przeglądzie 1536
   prawie znikała, mocniejsza #DCCFC4 (12 pkt) zaczynała rysować ramkę, linia na szerokość kolumny czytała się jak podkreślenie wiersza menu.
   Ten sam kolor, co linia nad „Co tu znajdziesz”: na stronie jeden rodzaj linii. Cieniem zamiast obramowania, żeby pasek nie urósł o 1 px i odstępy
   zostały: tekst menu → linia 27–31 px (wzorce 23–42, mediana 28), linia → litery nagłówka 103–108 px w 1536 × 730 (wzorce z wyśrodkowanym
   nagłówkiem 68–214, mediana 142; 112 i 128 px dopełnienia dokładały pusty pas i chowały ramę do 228 / 212 px, kand_odstep_1536.png).
   Panel menu na telefonie ma własny border-top w tym samym miejscu i kolorze, więc po otwarciu linia jest jedna. */
/* Oddech linii (Michał 17.10: „a jakby dać kreseczce z 10 px oddechu?”): dopełnienie pod paskiem, menu zostaje na miejscu, linia schodzi
   o 8 px (34 px pod tekstem menu zamiast 26; wzorce 23–42), na telefonie o 4 px pod znakiem. 8, nie 10: pasek 80 px przy skali 125% kończy się
   na pełnym pikselu (100), 82 px wypadałoby na pół piksela i linia znów by się rozmyła. Odstęp nad nagłówkiem strony jest pomniejszony
   o to samo (.home), więc nagłówek, przyciski i rama stoją tam, gdzie stały. */
.site-head { box-shadow: 0 1px 0 var(--line); padding-bottom: var(--head-pad); }
.main-nav { gap: 16px; }
.main-nav ul { gap: 0; }
.main-nav li a { position: relative; padding: 0 14px; border-radius: 0; }
.main-nav li a::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: 9px; height: 2px; border-radius: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: 0 50%; transition: transform .22s var(--expo); }
.main-nav li a[aria-current] { box-shadow: none; border-radius: 0; color: var(--ink); font-weight: 600; }
.main-nav li a[aria-current]::after { transform: none; }
/* obrys fokusu odnośnika menu z zaokrąglonymi narożnikami jak u „Zaloguj się” i ikon (odnośnik ma promień 0 ze względu na linię pod napisem;
   przy promieniu 0 obrys 3 px był ostrym prostokątem obok zaokrąglonych sąsiadów, R3-J3-5) */
.main-nav li a:focus-visible { border-radius: 8px; }
.btn-line { min-height: 44px; padding: 0 16px; box-shadow: inset 0 0 0 1px var(--ink); }
.icon-btn { border-radius: 999px; }
@media (hover: hover) and (pointer: fine) {
  .main-nav li a:hover { background: none; color: var(--ink); }
  .main-nav li a:hover::after { transform: none; }
}
/* Próg przycisku menu: 64 em (1024 px), nie 75 em jak w podstawie: pełny pasek (znak 142 + menu 702 + koszyk 44 = 902 px z odstępami)
   mieści się w kolumnie 976 px okna 1024 × 768. Podstawy (base.css, look.css) tu nie edytujemy, więc blok 64–74,99 em przywraca
   w tym zakresie wartości komputera; przy przenoszeniu do podstawy wystarczy zmienić tam próg i ten blok usunąć.
   Drugi warunek (K-V2-2): pełny pasek tylko tam, gdzie mieści się w kolumnie treści. Pasek rośnie z czcionką przeglądarki (znak, odnośniki
   i „Zaloguj się” w rem; ikony i odstępy w px): 351 px + 34,5 em (Chromium: 902 / 1040 / 1144 / 1178 px przy 16 / 20 / 23 / 24 px,
   po odjęciu 10 px ujemnego marginesu koszyka), a kolumna ma najwyżej 1152 px, więc od czcionki 23,3 px pasek nie mieści się w żadnym oknie
   (przy 24 px koszyk kończył się 26 px za kolumną w oknach od 1536 px, a od 1800 px, czyli 75 em, dawała to podstawa). Zapytanie o media
   nie zna szerokości kolumny, więc warunek jest zapisany w szerokości okna: pasek telefonu do 63,99 em ALBO do „pasek + 2 × 24 px odstępu”,
   gdzie człon max() odsuwa tę granicę poza każde okno, gdy pasek przekracza 1152 px. Przy 16 px granica to 951 px, przy 20 px 1089 px,
   obie poniżej 64 em, więc przy zwykłej i dużej czcionce nic się nie zmienia. Drugi człon powtarza wartości telefonu z podstawy (base.css,
   look.css), bo ponad 64 em obowiązują tam wartości komputera; przeglądarka bez max() w zapytaniu o media pomija tylko ten człon. */
@media (min-width: 64em) {
  .cart { margin-right: -10px; }
}
@media (min-width: 64em) and (max-width: 74.99em) {
  .head-in { flex-wrap: nowrap; min-height: 4.5rem; gap: 12px; }
  .logo { margin-right: 0; font-size: 1.1875rem; }
  html[data-look="u"] .logo-new { gap: 10px; }
  html[data-look="u"] .logo-mark { height: 36px; }
  html[data-look="u"] .logo-word { font-size: 1.1875rem; }
  .burger { display: none; }
  .main-nav, .site-head[data-open] .main-nav { order: 1; display: flex; position: static; flex-direction: row; flex-basis: auto; align-items: center; gap: 16px;
    margin: 0 0 0 auto; padding: 0; border-top: 0; background: none; box-shadow: none; clip-path: none; transition: none; }
  .main-nav ul { flex-direction: row; align-items: center; gap: 0; }
  .main-nav li { padding: 0; }
  .main-nav li + li { border-top: 0; }
  .main-nav li a { display: inline-flex; min-height: 44px; padding: 0 14px; font-size: 1rem; }
  .main-nav li a::after { display: block; }
  .main-nav li a[aria-current] { color: var(--ink); }
  .btn-line { justify-content: normal; min-height: 44px; }
}
/* panel menu w oknach 620–1023 px: „Zaloguj się” nie rozciąga się na całą kolumnę (720 × 48 px w 768 × 1024, napis sam na środku);
   stoi od lewej, na osi odnośników i znaku, 200 px (R2-J3-5) */
@media (min-width: 620px) and (max-width: 63.99em), (min-width: 620px) and (max-width: calc(399px + 34.5em + max(0px, (34.5em - 801px) * 1000) - .02px)) {
  .main-nav .btn-line { align-self: flex-start; min-width: 12.5rem; }
}
@media (max-width: 63.99em), (max-width: calc(399px + 34.5em + max(0px, (34.5em - 801px) * 1000) - .02px)) {
  /* wartości telefonu z podstawy (base.css, look.css), potrzebne ponad 64 em przy dużej czcionce; do 63,99 em powtarzają to, co już obowiązuje */
  .logo { margin-right: auto; font-size: clamp(.9375rem, 4.7vw, 1.0625rem); }
  html[data-look="u"] .logo-new { gap: 9px; }
  html[data-look="u"] .logo-mark { height: 34px; }
  html[data-look="u"] .logo-word { font-size: 1.09375rem; }
  .burger { display: inline-grid; }
  .cart { margin-right: 0; }
  .main-nav, .site-head[data-open] .main-nav { order: 1; position: absolute; left: 0; right: 0; top: 100%; flex-direction: column; align-items: stretch; flex-basis: auto; margin: 0; background: var(--bg);
    transition: clip-path .15s var(--expo), display .15s allow-discrete; }
  .main-nav { display: none; }
  .site-head[data-open] .main-nav { display: flex; }
  .main-nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .main-nav li + li { border-top: 1px solid var(--line); }
  .main-nav li a { display: flex; font-size: 1.0625rem; border-radius: 0; }
  .main-nav li a[aria-current] { box-shadow: none; }
  .btn-line { justify-content: center; }
  /* wartości tej strony */
  .head-in { min-height: 3.75rem; gap: 2px; }
  :root { --head-pad: 4px; }
  /* kreski ikony menu kończą się na krawędzi kolumny, jak koszyk na komputerze: pole dotyku wysunięte o 10 px */
  .burger { margin-right: -10px; }
  /* panel leży nad treścią, więc ma krawędź i cień jak rama: linia 1 px na dolnej krawędzi (pierścień) i miękka warstwa do 28 px pod panelem
     (R3-J1-4: cień 0 24px 32px −24px był ledwie widoczny, panel kończył się samą cienką linią nad makietą); stan otwarty przycina 48 px pod panelem */
  .main-nav, .site-head[data-open] .main-nav { gap: 12px; padding: 4px var(--gutter) 20px; border-top: 1px solid var(--line); box-shadow: 0 1px 0 var(--line), 0 20px 44px -14px rgba(45, 42, 38, .26); }
  .main-nav li { padding: 0; }
  .main-nav li a { min-height: 52px; padding: 0; }
  .main-nav li a::after { display: none; }
  .main-nav li a[aria-current] { color: var(--accent-dark); }
  .btn-line { min-height: 48px; }
}
/* przyklejony pasek (STICKY = True w build.py): zostaje u góry, chowa się przy przewijaniu w dół (klasa head-away ze skryptu)
   i wraca przy ruchu w górę; skok do sekcji omija pasek. Linia pod paskiem jest ta sama w spoczynku i po odklejeniu (reguła wyżej), więc klasa
   head-stuck ze skryptu nie ma dziś własnej reguły (do 11.10 linia pojawiała się dopiero po przyklejeniu, jak u Notion i Duolingo) */
html[data-sticky] { scroll-padding-top: 86px; }
html[data-sticky] .site-head { position: sticky; top: 0; z-index: 20; transition: transform .3s var(--expo); }
/* chowanie szybsze (200 ms) niż powrót (300 ms): wyjście krótsze niż wejście. Fokus klawiatury w pasku trzyma go w oknie
   (R2-J5-4: po Escape w menu pasek odjeżdżał z fokusem na y −52); fokus po dotknięciu i kliknięciu (bez :focus-visible) nie trzyma */
html[data-sticky] .site-head.head-away:not([data-open]):not(:has(:focus-visible)) { transform: translateY(-100%); transition-duration: .2s; }
/* przy przyklejonym pasku panel menu nie może wyjść pod dolną krawędź niskiego okna (768 × 365 przy powiększeniu 200%):
   ogranicza go wysokość okna bez paska (100% = wysokość paska, bloku zawierającego panel) i przewija się sam */
@media (max-width: 63.99em), (max-width: calc(399px + 34.5em + max(0px, (34.5em - 801px) * 1000) - .02px)) {
  html[data-sticky] .site-head[data-open] .main-nav { max-height: calc(100vh - 100%); max-height: calc(100dvh - 100%); overflow-y: auto; overscroll-behavior: contain; }
}

/* ============ góra: nagłówek, pod nim zdanie i przycisk na jednej osi, niżej obraz platformy z nazwami na krawędziach ============ */
/* overflow-x: clip: w oprawie b i c pole wychodzi poza kolumnę; przycięcie chroni przed przewijaniem w bok o szerokość paska przewijania */
.home { padding-block: calc(var(--home-top) - var(--head-pad)) 0; overflow-x: clip; }
/* O układzie decyduje szerokość kolumny treści liczona w rem (zapytanie o kontener), więc przy powiększonej czcionce
   przeglądarki strona sama przechodzi w układ wąski, zanim cokolwiek na siebie najedzie. */
.home .wrap { container-type: inline-size; }

/* Stopień nagłówka liczy się z szerokości kolumny; dolna granica w vw chroni przed łamaniem w środku słowa przy czcionce przeglądarki 32 px.
   Jeden stopień na komputerze, bez ścinania w niskich oknach: obraz może zejść pod pierwszy ekran (15 z 15 wzorców, r4).
   Szlif 11.10 (Michał: „troszkę mniejszy”): każdy próg o około 6% mniejszy, na komputerze 64 → 60 px; krok do nagłówków sekcji 1,31–1,42
   w całym zakresie okien. Najdłuższy wiersz stoi wyraźnie obok krawędzi ramy i nazw, nie „prawie równo” (próby: sedziowie/szlif/b/kand_*.png).
   1536 × 730: wiersz 1024 px, 49 px za krawędzią ramy z każdej strony, 64 px przed krawędzią nazw (56 px dawało 15 px za ramą, 54 px stawało na niej). */
/* nagłówek, zdanie i przycisk na osi ramy z obrazem (Michał, 11.10: „wyśrodkować napis dla zachowania harmonii”) */
/* telefon do 469 px: cztery wiersze („Wszystko, czego / potrzebuje nauczyciel / angielskiego / w przedszkolu”), najdłuższy 88% kolumny
   (390: 32 px, 315 px w kolumnie 357, 21 px od krawędzi ramy; z 9,7cqw było 34,65 px i 340 px, 9 px od krawędzi). Trzy wiersze wymagałyby
   tu 29,6 px, czyli 1,2 nagłówka sekcji; za mało. Do 345 px dolna granica 28 px (320: wiersz 274 w kolumnie 288, 7 px od krawędzi,
   jak dotąd; 23 px zapasu wymagałoby 25 px, mniej niż nagłówek sekcji). */
.title { --h1: clamp(min(1.75rem, 10.5vw), 9cqw, 2.75rem); text-align: center; }
/* okna 470–699 px (w tym 485 px, w którym właściciel ogląda „mobilkę”): trzy wiersze „Wszystko, czego potrzebuje / nauczyciel angielskiego /
   w przedszkolu”, najdłuższy 89% kolumny, przy 485 px 33 px i 397 px w ramie 444, 23 px od jej krawędzi (36 px z propozycji sędziego dawało
   435 px, 5 px od krawędzi; 43 px i cztery wiersze z „angielskiego” samo w trzecim: było). Próg 470, nie 460: dolna granica 32 px dawała
   przy 460 wiersz 387 px w kolumnie 421, 17 px od krawędzi. Sufit 42 px zrównuje stopień z tabletem przy 700 px. */
@media (min-width: 470px) {
  .title { --h1: clamp(2rem, 7.4cqw, 2.625rem); }
}
/* kolumna 700–927 px (tablet pionowo): trzy wiersze, 42–49 px, krok do nagłówków sekcji 1,31–1,42; od 58 rem kolumny stopień komputera:
   49 px przy kolumnie 928 (ciągłość z tabletem), 60 px od kolumny 1143 (okna od około 1190 px) */
@media (min-width: 700px) {
  .title { --h1: clamp(2.625rem, 6.5cqw, 3.0625rem); }
}
@container (min-width: 58rem) {
  .title { --h1: clamp(2.5rem, 5.25cqw, 3.75rem); }
}
/* łamanie zachłanne (wrap, nie balance z podstawy) w każdym oknie: skrypt wejścia mierzy wiersze po owinięciu słów w spany, a balance w Chromie
   łamie tekst ze spanami inaczej niż bez nich (485 i 768: ze spanami „Wszystko, czego / potrzebuje nauczyciel / angielskiego w przedszkolu”,
   bez spanów „Wszystko, czego potrzebuje / nauczyciel angielskiego / w przedszkolu”), więc po wejściu nagłówek przeskakiwał na inne wiersze
   (sedziowie/szlif/b/diag_wejscie.py). Zachłanne łamanie nie zależy od spanów, a przy tej treści daje w 320–1920 px te same wiersze, co balance
   (przemiatanie co 20 px). */
.home .title h1 { position: relative; z-index: 0; max-width: none; font-size: var(--h1); line-height: 1.08; letter-spacing: -.02em; text-wrap: wrap; }
/* tablet (700 px do kolumny 58 rem, nazwy w rzędzie pod ramą na całą kolumnę): zawsze trzy wiersze. Bez ograniczenia od kolumny 837 px
   (okna 885–975) mieściły się dwa wiersze po 837 px, czyli 8–18 px od krawędzi ramy; 15 em przepuszcza trzy wiersze (najdłuższy 12,06 em),
   a dwa (17,08 em) już nie. Pudełko węższe od kolumny, więc na osi przez margines. */
@media (min-width: 700px) {
  .home .title h1 { max-width: 15em; margin-inline: auto; }
}
/* układ komputera: pełna szerokość kolumny, dwa wiersze. Łamanie zachłanne było tu już wcześniej (R2-J5-3: balance rozstrzygał remis dwóch
   połówek po 26 znaków inaczej w kroju zastępczym niż w Brygadzie, „nauczyciel” raz w pierwszym, raz w drugim wierszu, i podmiana kroju
   przesuwała ramę: CLS 0,078 na wolnym 4G → 0,002); od szlifu 11.10 obowiązuje w każdym oknie (reguła wyżej). */
@container (min-width: 58rem) {
  .home .title h1 { max-width: none; }
}
/* „nauczyciel”: malina, grubsze o 200 od reszty wiersza, odręczne podkreślenie z landingu (UNDERLINE w build.py).
   Podkreślenie leży pod pismem, tuż pod linią podstawową: ogonek „y” przechodzi przez nie jak przez pociągnięcie pisaka. */
.home .title h1 .name { color: var(--accent); font-weight: 600; white-space: nowrap; }
/* słowo z kreską zostaje zwykłym inline (podstawa daje .scribble inline-block): atomowy inline-block łamał nagłówek z text-wrap: balance
   inaczej niż bez kreski w 17 z 81 szerokości (600–920 px; K-V2-1), a inline łamie się tak samo, bo dla łamania jest tym samym słowem.
   Kreska leży względem pudełka inline (pole znaków 1,17 em zamiast wiersza 1,08 em, dolna krawędź 0,045 em niżej), stąd bottom
   .015em zamiast −.03em: kreska stoi tam, gdzie z inline-block (1536: co do 0,01 px; 485: 0,5 px wyżej). */
.home .title h1 .scribble { display: inline; }
.home .title h1 .scribble::after { z-index: -1; left: -.05em; right: -.07em; bottom: .015em; height: .19em; }
/* zdanie, pod nim przycisk, oba na osi ramy w każdym oknie. W rzędzie (do 11.10) środek grupy stał na osi, ale środek przycisku 249 px
   na prawo od niej, a 21 z 21 wzorców z tekstem na środku stawia przycisk pod zdaniem, żaden w rzędzie (sedziowie/srodek/j1.md–j3.md).
   Zdanie i przycisk to jedna grupa, od nagłówka oddziela ją większy odstęp, od ramy jeszcze większy (64 px). Pomiar pikseli farby w 1536 × 730
   (gęstość 2, sedziowie/szlif/b/pion_px.py), liczony jak r4 od linii podstawowej wyżej do liter albo pudełka niżej, przy nagłówku 60 px
   (wysokość x 28 px): nagłówek → litery zdania 39 px (1,39×; r4 mediana 38, kwartyle 33–43), zdanie → przycisk 31 px (1,09×; mediana 38,
   kwartyle 29–45). Z 24 / 24 px było 43 i 27 px (górny kwartyl i pod dolnym); 20 / 28 przesuwa zdanie o 4 px w górę, rama stoi w tym samym miejscu.
   Telefon: 20 / 16 px, czyli 25 i 19 px od linii pisma (zdanie → przycisk 1,25 wysokości x, mediana r4). */
.pitch { display: flex; flex-direction: column; align-items: center; gap: 16px; margin-top: 20px; }
@container (min-width: 58rem) { .pitch { gap: 28px; } }
.home .lede { max-width: 26em; margin: 0; font-size: var(--lede); line-height: 1.4; text-wrap: balance; }
/* do 559 px zdanie w dwóch wierszach („Drukujesz wieczorem, / rano prowadzisz zajęcia. Tyle.”): w jednym wierszu miało 431 px przy ramie 444
   (okno 485), 7 px od jej krawędzi; od 560 px jeden wiersz 438 px ma do ramy 37 px i więcej */
@media (max-width: 559px) {
  .home .lede { max-width: 18em; }
}
/* --- para przycisków pod zdaniem (Michał 11.10: „buttony były dwa: Poznaj platformę i Poznaj stronę, który będzie kierować do tego, co jest poniżej”) ---
   Główny prowadzi do platformy, drugi przewija do sekcji „Co tu znajdziesz” (href="#co-znajdziesz"; bez skryptów zwykły skok).
   Para w rzędzie na osi ramy, główny z lewej, oba tej samej wysokości, odstęp 14 px: tak robi 16 z 16 wzorców z dwoma przyciskami pod zdaniem
   (sedziowie/srodek/j3.md „pod zdaniem (2)”; odstęp mediana 18 px w obrazie 1920, kwartyle 15–21, czyli 14 px w oknie 1536; drugi przycisk
   z obrysem albo cichym wypełnieniem, nigdy sam napis; pomiar sedziowie/szlif/b2/wzorce_pomiar.json i wycinki wzorce_zoom_*.png).
   Do 469 px (ten sam próg, od którego nagłówek ma cztery wiersze) jeden pod drugim, równej szerokości, odstęp 12 px: w rzędzie para ma 346 px
   (stary wygląd 376), czyli w telefonie 390 nie mieści się w kolumnie 357 px, a w oknie 485 stoi w ramie 444 px z zapasem 49 px z każdej strony
   (rama zaczyna się 62 px wyżej niż z kolumną i widać 4 nazwy zamiast 0). Właściciel w 485 zobaczy więc rząd, nauczycielka w telefonie kolumnę.
   Pola dotyku 50 px (nowy wygląd) i 54 px (stary). Wejście strony: para wchodzi razem ze zdaniem (.pitch > *), bez zmian.
   Próg w em (29,3125 em = 469 px), bo przyciski rosną z czcionką przeglądarki: przy 20 px rząd w oknie 485 stawał 6 px od krawędzi ramy,
   a przy 24 px łamał się na dwa wiersze o różnych szerokościach; z progiem w em okno 485 dostaje wtedy kolumnę równych przycisków. */
.home .actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 12px 14px; margin: 0; }
@media (max-width: 29.3125em) {
  .home .actions { display: inline-grid; justify-items: stretch; gap: 12px; }
  .home .actions .btn { justify-content: center; }
}
/* przycisk przesuwa się przy najechaniu i wciśnięciu; niewidoczne pole pod nim stoi w miejscu, więc kliknięcie przy samej krawędzi nie przepada.
   max-width: przy bardzo dużej czcionce przeglądarki napis przycisku łamie się, zamiast wychodzić poza ekran */
.home .btn { position: relative; max-width: 100%; }
.home .btn::after { content: ""; position: absolute; inset: -4px 0 -7px; }
/* drugi przycisk: przejścia tła i pisma (podstawa przechodzi tylko transform i cień), bo przy najechaniu wypełnia się kolorem pisma jak „Zaloguj się” */
.home .btn-2 { transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), background-color .15s ease, color .15s ease; }

/* --- nowy wygląd pary (PRZYCISK = "miekki" w build.py; Michał 11.10: „button za ostry? powinien być bardziej delikatny?”) ---
   Pasek 5 px ciemnej maliny bez rozmycia był jedyną twardą krawędzią strony (rama i nazwy mają miękkie, rozmyte cienie). Główny: ta sama malina,
   cień z rodziny cienia ramy i nazw (barwa pisma, przesunięcie i rozmycie: 0 1px 2px i 0 6px 16px −6px), 50 px zamiast 54 (mediana wysokości
   we wzorcach 61 px w obrazie 1920 = 49 px w oknie 1536, kwartyle 40–55), pismo 16/600 zamiast 17/600, promień 12 (--r-s) jak „Zaloguj się”
   i nazwy przy obrazie: jeden promień wszystkich kontrolek. Drugi: obrys 1 px w kolorze pisma na kremie, czyli „Zaloguj się” z paska o stopień
   większe; przy najechaniu wypełnia się kolorem pisma tak samo. Arkusz kandydatów sedziowie/szlif/b2/kand_*.png i kand2_*.png: 54 px z drugim
   jako białą kartą (drugi wyglądał jak nazwa przy obrazie, a te nie są klikalne), 48 px i 500 z obrysem w malinie (za lekki napis, podwójny
   akcent), bez cienia (płaski obok ramy z cieniem), strzałka w dół na drugim (konkurowała ze strzałką głównego; 0 z 16 wzorców ma znak na drugim).
   Stany: najechanie unosi o 1 px i wydłuża cień (300 ms, powrót 200 ms); wciśnięcie: skala .97 w 120 ms, sąsiad stoi w miejscu; fokus klawiatury:
   obrys 3 px z podstawy bez zmian; dotyk: to samo wciśnięcie. Kontrast: biel na #CC3366 4,96:1, #2D2A26 na kremie 14,5:1.
   Cień o stopień mniejszy od 11.10 wieczorem (Michał: „delikatniejszy button zostaje […] może trochę mniejszy cień”): 0 4px 12px −5px .22 zamiast
   0 6px 16px −6px .30 (zasięg pod krawędzią 9 px zamiast 14,5; sedziowie/szlif2/b2/kand_cien_*.png: 5/14/−6/.26 prawie nie różnił się od
   dzisiejszego, 3/10/−4/.18 był już niemal płaski obok ramy z cieniem). Najechanie i wciśnięcie przeliczone w tej samej proporcji. */
html[data-przycisk="miekki"] .home .btn { min-height: 50px; padding: .7rem 1.4rem; border-radius: var(--r-s); font-size: 1rem;
  box-shadow: 0 1px 2px rgba(45, 42, 38, .08), 0 4px 12px -5px rgba(45, 42, 38, .22); }
html[data-przycisk="miekki"] .home .btn:active { transform: scale(.97); box-shadow: 0 1px 2px rgba(45, 42, 38, .08), 0 2px 6px -3px rgba(45, 42, 38, .16); transition-duration: .12s; }
html[data-przycisk="miekki"] .home .btn-2 { background: none; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
html[data-przycisk="miekki"] .home .btn-2:active { box-shadow: inset 0 0 0 1px var(--ink); }
/* pole pod przyciskiem: bez paska i z uniesieniem 1 px wystarczy 3 px z góry i 4 px z dołu przy najechaniu */
html[data-przycisk="miekki"] .home .btn::after { inset: -3px 0; }
@media (hover: hover) and (pointer: fine) {
  html[data-przycisk="miekki"] .home .btn:hover:not(:active) { transform: translateY(-1px); box-shadow: 0 1px 2px rgba(45, 42, 38, .08), 0 8px 18px -7px rgba(45, 42, 38, .28); transition-duration: .3s; }
  html[data-przycisk="miekki"] .home .btn:hover::after { inset: -3px 0 -4px; }
  html[data-przycisk="miekki"] .home .btn-2:hover:not(:active) { transform: none; background: var(--ink); color: var(--bg); box-shadow: inset 0 0 0 1px var(--ink); }
}

/* --- stary wygląd pary (PRZYCISK = "stary"): główny bez żadnej zmiany (podstawa i look.css: 54 px, 17/600, promień 16, pasek 5 px ciemnej maliny,
   uniesienie 2 px, wciśnięcie 4 px w dół). Drugi w tej samej wypukłej postaci: biały, obrys 1,5 px i pasek 5 px w kolorze pisma, te same ruchy.
   Arkusz kand2_*.png: pasek w ciemnej malinie pod białym robił z drugiego odmianę głównego, a płaski obrys obok wypukłego to dwa języki. */
html[data-przycisk="stary"] .home .btn-2 { background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink), 0 5px 0 var(--ink); }
html[data-przycisk="stary"] .home .btn-2:active { box-shadow: inset 0 0 0 1.5px var(--ink), 0 1px 0 var(--ink); }
@media (hover: hover) and (pointer: fine) {
  html[data-przycisk="stary"] .home .btn-2:hover:not(:active) { box-shadow: inset 0 0 0 1.5px var(--ink), 0 7px 0 var(--ink); }
}

/* --- scena: obraz platformy w białej ramie i sześć nazw ---
   Rama (.shot) i siatka nazw (.caps) leżą w tej samej komórce siatki i mają tę samą szerokość, więc procenty nazw liczą się od ramy.
   Szerokość ramy w układzie krawędziowym: 78,125% kolumny treści, czyli 900 px przy kolumnie 1152 (Michał 11.10 wieczorem: „zrób te 900”;
   reguła w @container niżej). --cap-pad: dopełnienie boczne nazwy w układzie krawędziowym, 22 px przy kolumnie 1152 (okna od 1200 px),
   16 px przy kolumnie 976 (okno 1024) i mniejszych, liniowo między nimi (6 px na 176 px kolumny). --cap-max: szerokość najdłuższej nazwy,
   „Karty prezentacyjne”: pismo 161,81 px przy czcionce 16 px (Chromium, Brygada 1918 kursywa 18 px) plus dwa dopełnienia, 205,81 px przy
   kolumnie 1152, 193,81 przy 976 (w rem, bo nazwa rośnie z czcionką przeglądarki). --in: ile każda nazwa leży na ramie: tyle, żeby zewnętrzna
   krawędź najdłuższej nazwy stanęła na krawędzi kolumny, czyli --cap-max minus połowa tego, co zostaje z kolumny obok ramy (10,9375% kolumny):
   79,8 px przy kolumnie 1152 (8 px białego marginesu i 72 px obrazu), 87 px w oknie 1024 (kolumna 976). W oknach od 1600 px koniec nazwy
   przesuwa się w głąb ramy proporcjonalnie do jej wzrostu (0,1773 × --grow, czyli 2 × 79,8 / 900), więc leży na tym samym miejscu makiety
   co w 1536: 96,8 px przy ramie 1092; bez tego członu w 1920 × 1080 nazwa znów przecinała słowa panelu (zostawało „rt” ze „Start”).
   Dopełnienie 22 zamiast 16 px (krytyk szlifu 2, sedziowie/szlif2/k.md zarzut 1): przy 67,8 px na ramie koniec nazwy padał w środku słów
   panelu makiety („Start” kończy się 76,3 px od krawędzi ramy, „działy” 77,2, „Pory roku” 96,7) i spod lewych nazw wystawało „rt”, „ały”,
   „ry roku”; z 79,8 px słowa górnych dwóch par są zakryte w całości (3,5 i 2,5 px zapasu), a dolna para zeszła na 88% (build.py), w pusty
   panel pod „Pory roku”. Większe dopełnienie zamiast większego --in, bo zewnętrzne krawędzie mają zostać na linii znaku i koszyka; w kolumnie
   976 dopełnienie wraca do 16, bo tam makieta jest mniejsza i 87 px już zakrywa całe słowa, a po prawej 99 px wchodziłoby na rysunek sukienki.
   Przed szlifem 2 było 18 px (koniec nazwy przed kolumną ikon panelu makiety); Michał: „pastylki niech troszkę wejdą mocniej na makietę”,
   a kandydaci 28 / 40 / 54 / 68 / 104 px są w sedziowie/szlif2/b1/arkusz_zach_*.png: 28 i 40 stawiały krawędzie nazw 40 i 28 px poza kolumną
   (nazwy najszerszą rzeczą na stronie), 54 trzynaście px poza nią („prawie równo”), 104 zasłaniało różowe ramki kart makiety po prawej.
   W oknach od 1600 px scena oprawy a wychodzi poza kolumnę o --grow z każdej strony (do 6 rem = 96 px), żeby rama nie malała wobec okna:
   bez tego 1920 × 1080 dawałoby 900 px = 47% okna; z 96 px rama ma 1092 px (57%; w 1536 58,6%) od okna 1792 px. Granica 96, nie 112
   jak przy ramie 800: pierwszy wiersz nagłówka (1024,5 px) stoi wtedy 34 px w głąb ramy z każdej strony, wyraźnie, a dolna para nazw
   w 1920 × 1080 kończy się 1 px nad krawędzią okna (ze 112 px: pod nią). Przy wzroście rama mija szerokość wiersza w oknie około 1725 px;
   koniec wiersza stoi 3–24 px od krawędzi ramy tylko w oknach 1677–1718 i 1731–1772 (szerokości bez paska przewijania 1583, 1663 i 1903
   są poza tym zakresem). Granica w rem, bo z granicą w px przy czcionce przeglądarki 17–19 px rama stała 7–21 px obok osi (R3-J3-2).
   W 1536 i 1440 --grow = 0. --room: miejsce na wystającą część nazwy w oprawach b i c (126 px plus 24 px odstępu od krawędzi pola).
   W wąskiej kolumnie rama ma całą szerokość kolumny. */
.stage { --bleed: clamp(0px, (100vw - var(--wrap)) / 2 - 16px, 56px); --grow: clamp(0px, (100vw - 1600px) / 2, 6rem);
  --cap-pad: clamp(1rem, 1rem + (100cqw - 61rem) * 6 / 176, 1.375rem); --cap-max: calc(10.113rem + 2 * var(--cap-pad));
  --in: calc(var(--cap-max) - 10.9375cqw + var(--grow) * .1773);
  --room: calc(var(--cap-max) - var(--in) + 24px); --shot-w: 100%;
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr); margin-top: var(--stage-gap); }
.shot { grid-area: 1 / 1; position: relative; z-index: 1; width: var(--shot-w); margin-inline: auto; min-width: 0; }
/* obrys ramy przy najechaniu leży na pseudoelemencie i przenika (opacity), bo przejście box-shadow na 1000 × 600 px z rozmyciem 39 px
   to malowanie dużej powierzchni (RUCH.md: tylko transform, opacity, clip-path); na odnośniku zostaje samo wciśnięcie */
.shot a { position: relative; display: block; padding: var(--mat); border-radius: var(--r-l); background: var(--card); transition: transform .12s ease-out; }
/* obrys w ciepłej linii o stopień ciemniejszej od #E9DDD3, nie w szarości pisma: szary #6B655F na miękkiej ramie czytał się jak obramowanie fokusu (R2-J1-3) */
.shot a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 0 1px #D6C8BC; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
.shot img { width: 100%; aspect-ratio: 27 / 16; border-radius: calc(var(--r-l) - var(--mat)); background: #FBF7F3; }
.shot a:active { transform: scale(.995); }
/* 19.10, Michał: „do obrazka platformy na mainie też możemy zrobić badge »wkrótce otwarcie«”. Pigułka stanu w akcencie na środku górnej
   krawędzi ramy (Mobbin: Webflow „BETA” na środku nad produktem, Superpower „BETA” przy nazwie). Pełna malina odróżnia stan od białych
   nazw na ramie; biały pierścień 3 px w kolorze strony odcina ją od krawędzi ramy. Biały na #CC3366 = 4,9:1. Leży w figure.shot,
   więc wchodzi i unosi się razem z ramą. */
.shot .soon { position: absolute; top: 0; left: 50%; z-index: 2; transform: translate(-50%, -50%); display: inline-flex; align-items: center;
  height: 2rem; padding: 0 .875rem .0625rem; border-radius: 999px; background: var(--accent); color: #fff;
  font: 600 .9375rem/1 var(--font-body); letter-spacing: .01em; white-space: nowrap; pointer-events: none;
  box-shadow: 0 0 0 3px var(--bg), 0 2px 6px rgba(45, 42, 38, .16); }
@media (forced-colors: active) { .shot .soon { border: 1px solid CanvasText; } }
@media (hover: hover) and (pointer: fine) {
  .shot a:hover::after { opacity: 1; }
}

/* nazwy: pastylka z Canny (oba końce zaokrąglone, biel, cienki obrys, cień do 4 px), pismo nagłówków w kursywie,
   bez ikon, strzałek i obrotu; nie są przyciskami (pointer-events: none, poza kolejnością Tab).
   Układ wąski (domyślny): rzędy pod obrazem, każdy wyśrodkowany pod ramą (incident.io: nazwy w rzędzie pod polem; R2-J3-1: samo
   wyśrodkowane pudełko z rzędami od lewej dawało wcięcie od ramy 0–147 px zależne od okna i poszarpaną prawą stronę); pierwszy rząd leży
   na dolnej krawędzi ramy połową wysokości (ta sama reguła, co na komputerze: nazwa na krawędzi obrazu, częścią na nim, częścią poza nim),
   więc rząd należy do ramy, a nie stoi luzem pod nią. Rzędy nad cieniem ramy (z-index), żeby nazwy były białe, nie szare.
   Szerokość rzędu ogranicza łamanie (sześć nazw od szlifu 2 z 11.10; z siedmioma było 2 + 2 + 3 do 660 px i 4 + 3 wyżej): do 36 em okna
   (575 px przy zwykłej czcionce) 2 + 2 + 2 w kolejności z zamówienia (rzędy 285 / 268 / 186 px: „Karty prezentacyjne” z „Karty pracy”,
   „Książki metodyczne” ze „Szkolenia”, „Zabawy” z „Metodyka”), od 576 px 3 + 3 (459 / 288 px) aż do układu krawędziowego. 19 rem mieści
   285 px i nie mieści trzeciej nazwy (459); 30 rem mieści 459 i nie mieści czwartej (561); 36 em, bo w oknie 576 rząd 459 px stoi 34 px od
   krawędzi ramy 528 px, a przy 512 px stałby 5 px od niej. R2-J3-3: próg w em trzyma podział także przy czcionce przeglądarki 20 i 24 px
   (3 + 3 potrzebuje kolumny 459 px przy 16 px, 574 przy 20, 688 przy 24; 36 em daje 672, 720 i 816). Bez ograniczenia podział zmieniał się
   wiele razy między 320 a 975 px i zostawiał samotną nazwę w ostatnim rzędzie. */
.caps { grid-area: 2 / 1; position: relative; z-index: 2; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; width: var(--shot-w); max-width: 19rem; margin: -1rem auto 0; pointer-events: none; }
@media (min-width: 36em) { .caps { max-width: 30rem; } }
.caps li { display: block; }
.caps li span { display: inline-flex; align-items: center; height: 2rem; padding: 0 .75rem .0625rem; border-radius: 999px; background: var(--card);
  box-shadow: 0 0 0 1px var(--line), 0 1px 2px rgba(45, 42, 38, .08), 0 2px 4px rgba(45, 42, 38, .06);
  color: var(--accent-deep); font: italic 500 1rem/1 var(--font-display); letter-spacing: .005em; white-space: nowrap; }
/* kolor pisma nazw (NAZWY_KOLOR w build.py; Michał 11.10 wieczorem: „czy czarny, ten co w nagłówkach, byłby lepszy, by nie było za dużo
   kolorów”): "atrament" = kolor pisma nagłówków sekcji (14,3:1 na białej karcie), "malina" = ciemna malina z reguły wyżej (8,8:1).
   W obu układach (na krawędziach obrazu i w rzędach pod nim). Z atramentem malina zostaje na „nauczyciel”, głównym przycisku i w makiecie. */
html[data-nazwy="atrament"] .caps li span { color: var(--ink); }
/* 320 px: pierwszy rząd (Karty prezentacyjne, Karty pracy) potrzebuje 285 px, kolumna ma 288; węższe dopełnienie daje 11 px zapasu
   (277 px, 5 px od krawędzi ramy z każdej strony; tyle samo miał ten rząd z siedmioma nazwami) */
@media (max-width: 339px) { .caps li span { padding-inline: .625rem; } }

/* kolumna treści od 58 rem (928 px przy zwykłej czcionce): nazwy na bocznych krawędziach obrazu.
   Każda nazwa to punkt (li bez wymiarów) na --y wysokości ramy, --in (79,8 px przy kolumnie 1152) w głąb ramy od jej krawędzi; pastylka (span)
   stoi końcem na tym punkcie (siatka 0 × 0, bez transformacji, więc transform zostaje wolny dla ruchu). Z obu stron ta sama reguła: nazwa
   leży na ramie 79,8 px (8 px białego marginesu i 72 px obrazu), reszta poza nią (szlif 2 z 11.10, po krytyku; budowniczy szlifu 2 dał 67,8,
   w szlifie 1 było 18 px i rama 800, przed nim lewe leżały końcem 2% w głąb, prawe środkiem 2% poza krawędzią). Wysokości: trzy pary na 16, 50
   i 88% (margines od góry ramy 68 px, od dołu 47 w oknie 1536), dobrane do wierszy panelu makiety, żeby nazwa zakrywała wiersz w całości albo
   stała obok niego, a nie przecinała go: 16 zakrywa „Start” (logo panelu 9 px wyżej, podświetlony „Działy” 4 px niżej, awatar po prawej 27 px
   wyżej), 50 zakrywa nagłówek „Twoje działy” („Forum” 10 px wyżej, „Zwierzęta” 2 px niżej), 88 stoi w pustym panelu 9 px pod wierszem
   „Pory roku” (na 84 nazwa przecinała ten wiersz: słońce wystawało 1 px nad nią, a „roku” zostawało obok; pomiar sedziowie/szlif2/f/pomiar.txt).
   W poziomie nazwa zakrywa ikonę i całe słowo wiersza (słowa kończą się 76–77 px od krawędzi ramy, nazwa 79,8); po prawej zakrywa krawędź
   i biały margines kart, różowa ramka obrazka zaczyna się 12 px („Zabawy”) i 8,5 px („Metodyka”) za końcem nazwy. Strony i wysokości
   w CAPS w _build/build.py (kolejność w DOM = kolejność z zamówienia, BRIEF.md punkt 4). Nazwa wyśrodkowana na krawędzi (Asana, 40–44%
   na obrazie) odpada z lewej: przecinała ikony panelu makiety na pół (próby sedziowie/szlif/b3/kand_B.png, K5). */
@container (min-width: 58rem) {
  /* rama 900 px przy kolumnie 1152 (78,125% kolumny; 58,6% okna 1536, 62,5% okna 1440, 70,3% okna 1280; przed szlifem 2: 800, 52% okna 1536;
     wzorce Mobbina 63–76% okna). Ta sama proporcja w węższych kolumnach: 762,5 px w oknie 1024 (74,5% okna), 725 w 976. Zewnętrzne
     krawędzie dwóch najdłuższych nazw, stojących naprzeciw siebie na tej samej wysokości („Karty prezentacyjne” 205,81 px z lewej,
     „Książki metodyczne” 203,47 px z prawej, przy dopełnieniu 22 px), stoją na krawędziach kolumny (oś znaku, nagłówka, kafli i stopki)
     w każdej szerokości kolumny, bo --in liczy się z tej samej proporcji (cqw); „Książki metodyczne” są o 2,3 px krótsze, więc ich
     zewnętrzna krawędź stoi 2,3 px w głąb kolumny. W oknach 976–1200 px nazwy stoją 24 px od krawędzi okna. Rama stoi na osi, więc obie
     strony mogą sięgać krawędzi kolumny tylko wtedy, gdy najdłuższa nazwa z lewej i z prawej wystają o tyle samo (sedziowie/szlif/b3/kand_A.png).
     Drugi wzór, odrzucony (sedziowie/szlif2/b1/arkusz_wzor_1024.png): stałe 7,5% ramy na nazwę i rama z tego wyliczana dawała w 1024
     ramę 693 px (68% okna) i nazwy 52 px na ramie; przy 762 px nazwy (dopełnienie 16) leżą 87 px na ramie i zakrywają w panelu całe słowa,
     ale po prawej koniec nazwy leży na różowej ramce karty (7 px w głąb jej prawej krawędzi, rysunek sukienki 7 px dalej); to samo w oknach
     do około 1120 px. W oprawie a scena rośnie poza kolumnę o 2 × --grow (okna od 1600 px). */
  .stage { --shot-w: calc(78.125cqw + 2 * var(--grow)); }
  html[data-scena="a"] .stage { margin-inline: calc(-1 * var(--grow)); }
  .caps { grid-area: 1 / 1; display: block; max-width: none; margin: 0 auto; height: 100%; }
  /* ścieżki siatki 0 × 0: pastylka wystaje z nich w stronę przeciwną do ramy (justify-items), więc jej koniec leży na punkcie */
  .caps li { position: absolute; top: var(--y); width: 0; height: 0; display: grid; grid-template: 0 / 0; place-items: center; }
  /* lewe nazwy: koniec nazwy --in w głąb ramy od lewej krawędzi, pastylka rośnie w lewo; prawe: koniec --in w głąb od prawej krawędzi, pastylka
     rośnie w prawo. Koniec 72 px na obrazie (okno 1536) zakrywa kolumnę ikon panelu makiety (20–35 px od krawędzi obrazu) i całe słowo
     wiersza (słowa kończą się 68–69 px od krawędzi obrazu); po prawej zakrywa krawędź i biały margines kart (21–72 px), nie dochodzi do
     różowych ramek (84–92 px) ani do pola szukania (62 px od prawej krawędzi, wyżej niż górna para). Podświetlone wiersze „Działy”
     (19–23% wysokości) i „Ubrania” (70–74%) wysokości w CAPS omijają. */
  .caps li[data-side="l"] { left: var(--in); justify-items: end; }
  .caps li[data-side="r"] { left: calc(100% - var(--in)); justify-items: start; }
  /* na komputerze nazwa jest kartą (promień 12, sam cień: Asana), nie pastylką: pastylka z obrysem miała tę samą sylwetkę,
     co rząd filtrów makiety („Karty pracy 17”), a dwie nazwy powtarzają się na ekranie. W rzędzie pod ramą zostaje pastylka. */
  /* pierścień 1 px o kryciu 7% domyka górną krawędź białej karty na kremie (1,09:1 → ok. 1,2:1; R2-J2-4); to nie obrys w barwie linii,
     żeby karta nie wróciła do sylwetki filtrów makiety */
  .caps li span { height: 2.25rem; padding: 0 var(--cap-pad) .0625rem; border-radius: var(--r-s); box-shadow: 0 0 0 1px rgba(45, 42, 38, .07), 0 2px 6px rgba(45, 42, 38, .16); font-size: 1.125rem; }
}

/* --- oprawa a: rama wprost na kremie, z cieniem (Craft na stronie #FEF9F3, Mural, Flighty, Calm) ---
   Cień Crafta w dwóch warstwach, przeliczony na naszą ramę i ociepliony (r1); linia 1 px domyka biały margines ramy na kremie
   (biel różni się od kremu jasnością tylko o 0,018). Rozmycia i przesunięcie przeliczone na ramę 927 px (R3-J2-2: 14 / 21 / 39 px liczono
   dla ramy 834 px): 16 / 23 / 43 px. */
/* 17.10, Michał: „troszkę za duży cień pod screenem platformy”, potem „zmniejszyłeś spread cienia tego?”: cień leży pod ramą, nie wokół niej.
   Mała warstwa 4 px zamiast 16 (prawie nic nad ramą), duża z ujemnym rozlaniem −10 px, więc nie wychodzi na boki. Zasięg mierzony w 1536:
   pod ramą 62 → 29 px, z boku 39 → 15 px, nad ramą 9 → 1 px (sedziowie/autor/arkusz_cien2.png, N1); dalej największy cień na stronie */
html[data-scena="a"] .shot a { box-shadow: 0 0 0 1px var(--line), 0 1px 4px rgba(45, 42, 38, .06), 0 14px 28px -10px rgba(45, 42, 38, .16); }
/* w wąskiej kolumnie rama ma 290–720 px, a cień 39 px to 13–20% jej szerokości (komputer 5,6%, Craft 5,1%) i malował się na rzędzie nazw:
   krótszy cień, zasięg 27 px, tło pod ramą najwyżej 2% ciemniejsze od kremu */
@container not (min-width: 58rem) {
  html[data-scena="a"] .shot a { box-shadow: 0 0 0 1px var(--line), 0 1px 8px rgba(45, 42, 38, .08), 0 10px 20px rgba(45, 42, 38, .12); }
}

/* --- oprawa b: zdjęcie z sali jako tło sceny (Cursor zmierzony; Craft, V7, Granola) ---
   Pole 21:9 ze zdjęciem (jasność pasów ok. 52–60%), promień 24, wychodzi poza kolumnę o --bleed, zostaje 16 px od krawędzi okna.
   Rama na zdjęciu bez długiego cienia, z jasną linią 1 px jak u Cursora; margines górny 32 px (Cursor 3,1% szerokości ramy).
   W wąskiej kolumnie pole dochodzi do krawędzi okna, rama i rząd nazw stoją na nim z marginesem 16 px. */
html[data-scena="b"] .stage { margin-inline: calc(-1 * var(--gutter)); padding: 28px var(--gutter); border-radius: 0; background: #8C8174; overflow: hidden; isolation: isolate; }
html[data-scena="b"] .scene-bg { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 62%; }
html[data-scena="b"] .shot a { box-shadow: 0 0 0 1px rgba(255, 255, 255, .55), 0 2px 6px rgba(45, 42, 38, .18); }
html[data-scena="b"] .shot a::after { box-shadow: 0 0 0 1px #fff; }
/* w wąskiej kolumnie widać ze zdjęcia tylko wąskie pasy (jasność 58%): przyciemnione do 51%, żeby różnica do obrazu platformy
   wyniosła co najmniej 42 punkty (r3: 42–47), z podbiciem nasycenia, bo samo przyciemnienie je gasi (14% → 17%) */
@container not (min-width: 58rem) {
  html[data-scena="b"] .scene-bg { filter: brightness(.88) saturate(1.5); }
}
/* w układzie szerokim zdjęcie (po retuszu prawej ćwiartki pliku, R2-J2-2) jest przyciemnione o 6%, żeby górny pas zszedł z 63,7 do 60 (r3: 52–60) */
@container (min-width: 58rem) {
  html[data-scena="b"] .scene-bg { filter: brightness(.94); }
}
html[data-scena="b"] .caps li span { box-shadow: 0 0 0 1px rgba(255, 255, 255, .5), 0 1px 3px rgba(45, 42, 38, .18), 0 2px 4px rgba(45, 42, 38, .1); }
@container (min-width: 58rem) {
  html[data-scena="b"] .stage { --shot-w: min(66vw, 1100px, 100% - 2 * var(--room)); margin-inline: calc(-1 * var(--bleed)); padding: 32px 0; border-radius: var(--r-l); }
  html[data-scena="b"] .caps { margin: 0 auto; }
}

/* --- oprawa c: pole w odcieniu kremu (incident.io #F9F4F0, Notion #F8F5F0, Aave; krok jasności 0,030 OKLCH) ---
   Pole #F7EDE6 (krem ciemniejszy o 0,030, odcień 58°), promień 24, margines górny i dolny 48 px (5,8% szerokości ramy: Front, Uxcel);
   rama bez cienia dłuższego niż 6 px (Whereby, Front, Airtable). W wąskiej kolumnie pole dochodzi do krawędzi okna. */
html[data-scena="c"] .stage { margin-inline: calc(-1 * var(--gutter)); padding: 20px var(--gutter); border-radius: 0; background: #F7EDE6; }
html[data-scena="c"] .shot a { box-shadow: 0 0 0 1px var(--line), 0 2px 6px rgba(45, 42, 38, .07); }
@container (min-width: 58rem) {
  html[data-scena="c"] .stage { --shot-w: min(66vw, 1100px, 100% - 2 * var(--room)); margin-inline: calc(-1 * var(--bleed)); padding: 48px 0; border-radius: var(--r-l); }
}

/* ============ co tu znajdziesz: duży kafel Narzędzi i pięć kafli 4:3 na siatce dwunastu kolumn (8 + 4, 4 + 4 + 4) ============ */
.finds { padding-block: clamp(64px, 7.6vw, 112px) clamp(40px, 3.6vw, 52px); }
/* cel przycisku „Poznaj stronę” (id="co-znajdziesz" na sekcji): sekcja zaczyna się dopełnieniem 64–112 px, więc bez korekty linia nad nagłówkiem
   stawała 80–128 px pod górną krawędzią okna; ujemny margines przewijania zjada dopełnienie, zostaje 16 px z scroll-padding i 32 px tutaj:
   linia 48 px od góry okna, pismo nagłówka 80 px (z przyklejonym paskiem o 70 px niżej). Po skoku następny Tab trafia w pierwszy kafel
   (bez skryptów przeglądarka przenosi punkt startu Tab na cel odnośnika, ze skryptem robi to fokus na sekcji, js/home.js). */
.finds { scroll-margin-top: calc(32px - clamp(64px, 7.6vw, 112px)); }
/* linia nad nagłówkiem zamyka górę strony i otwiera spis; nagłówek wisi tuż pod nią, blisko kafli */
.finds h2 { padding-top: clamp(20px, 2.2vw, 32px); border-top: 1px solid var(--line); font-size: var(--h2); line-height: 1.08; }
.home-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 12px; padding-top: 0; margin-top: clamp(24px, 2.8vw, 40px); }
.home-tiles li { display: flex; min-width: 0; }
/* telefon: pierwszy i ostatni kafel na całą szerokość, cztery środkowe parami, wszystkie zdjęcia 4:3 poza ostatnim (3:2:
   przy 16:9 kadr pokazywał 75% wysokości zdjęcia, nad kartą w dłoni zostawało 8 px, dolne karty były ucięte; 3:2 pokazuje 89%) */
.home-tiles li:first-child, .home-tiles li:last-child { grid-column: span 2; }
.home-tiles li:last-child .tile-photo img { aspect-ratio: 3 / 2; }
/* kafel kurczy się przy wciśnięciu; pole pod nim jest o 4 px większe, więc kliknięcie przy krawędzi nie przepada */
.home-tiles .tile { position: relative; display: flex; flex-direction: column; flex: 1; min-width: 0; transition: transform .12s ease-out; }
.home-tiles .tile::after { content: ""; position: absolute; inset: -4px; }
.home-tiles .tile:active { transform: scale(.985); }
.home-tiles .tile-photo { position: relative; }
/* zdjęcie przybliża się przy najechaniu w 300 ms i wraca szybciej, w 200 ms */
.home-tiles .tile-photo img { transition: transform .2s var(--ease-out); }
.tile-name { margin-top: 12px; }
/* strzałka stoi przy nazwie, jak na Narzędziach; przy najechaniu rusza się w stronę, w którą prowadzi kafel */
.finds .home-tiles .tile h3 { display: flex; align-items: center; gap: .35em; margin: 0; min-width: 0; font-size: var(--h3); font-weight: 500; line-height: 1.15; letter-spacing: -.01em; overflow-wrap: anywhere; }
.tile h3 svg { flex: none; width: .8em; height: .8em; color: var(--muted); transition: transform .2s var(--ease-out), color .15s ease; }
@media (hover: hover) and (pointer: fine) {
  .home-tiles .tile:hover .tile-photo img { transform: scale(1.035); transition-duration: .3s; }
  .home-tiles .tile:hover h3 svg { transform: translateX(4px); color: var(--accent-dark); }
}
@media (min-width: 700px) {
  .home-tiles { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(32px, 3.4vw, 44px) 24px; }
  .home-tiles li, .home-tiles li:last-child { grid-column: span 4; }
  .home-tiles li:first-child { grid-column: span 8; grid-row: span 2; }
  /* duży kafel wypełnia dwa rzędy małych: zdjęcie bierze całą wysokość nad nazwą */
  .home-tiles li:first-child .tile-photo { flex: 1; }
  .home-tiles li:first-child .tile-photo img { position: absolute; inset: 0; height: 100%; aspect-ratio: auto; }
  .home-tiles li:last-child .tile-photo img { aspect-ratio: 4 / 3; }
  .tile-name { margin-top: 14px; }
}

/* ============ o autorze: tekst po lewej, po prawej pole w kolorze strony, z którego wychodzi postać; głowa wychodzi ponad pas ============ */
/* pas jest malowany pseudoelementem od --up w dół, więc głowa postaci wychodzi ponad jego krawędź zawsze o tyle samo,
   niezależnie od tego, czy wiersz siatki wyznacza tekst, czy postać */
.about { --up: clamp(40px, 5.5vw, 80px); position: relative; isolation: isolate; }
/* pas sekcji o autorze w kolorze blatu ze zdjęć kafli (Michał 17.10: „tło do tekstu o Michale bardziej brązowe, jak kolor stołów z powyższych zdjęć”):
   blat w kaflach Blog, Sklep, Metodyka to OKLCH około 0,81 / 0,048 / 64° (#D8BCA4). Pas: #E4D3BE (0,875 / 0,034 / 72°; wcześniej #F5EDE7 z podstawy).
   Jaśniej niż blat, żeby pismo zostało czytelne (9,8:1); odcień o 8° w stronę żółci, bo w tej jasności sam odcień blatu (64°, #E9D1BB)
   czytał się jak brzoskwinia, a ten pod zdjęciami ze stołami czyta się jak jasny dąb (sedziowie/autor/arkusz_pas2.png). Pole za postacią
   jest w kolorze strony, więc na pasie czyta się jak okno w krem (jasność 0,982 wobec 0,875). */
.about::before { content: ""; position: absolute; inset: var(--up) 0 0; z-index: -1; background: #E4D3BE; }
.about-in { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; align-items: end; }
.about-text { align-self: center; max-width: 31rem; margin-top: var(--up); padding-block: clamp(40px, 4.8vw, 72px); }
.about h2 { font-size: var(--h2); line-height: 1.08; }
.about h2 span { display: block; }
.about-text p { margin-top: 14px; font-size: var(--fs-text); line-height: 1.55; }
.about-text h2 + p { margin-top: clamp(20px, 2.2vw, 32px); }
/* podpis: --muted #6B655F na pasie #E9D1BB miał 3,9:1 (poniżej 4,5:1), więc o stopień ciemniej: 4,9:1, tyle co dawniej na jaśniejszym pasie */
/* postać stoi na dolnej krawędzi pasa, a głową wychodzi ponad jego górną krawędź o --up, w odstęp po kaflach;
   pole za postacią zaczyna się na wysokości ramion (44% szerokości postaci od jej góry), czyli poniżej krawędzi pasa.
   --about-tint: kolor pola. Do 17.10 jasna malina (Michał: „ten różowy nie pasuje do chłopa”), potem przez chwilę jasna szałwia #D8E0D0
   (sedziowie/autor/arkusz_1536.png, sedzia.md); na koniec, na jego słowo („a jakby to tło za Michałem było normalnym tłem naszej stronki”),
   kolor strony: na pasie w jasnym dębie zostają same ciepłe neutralne tła, jedynym kolorem w sekcji jest zielony sweter na zdjęciu
   (sedziowie/autor/arkusz_pole_krem.png, wariant 3). */
.about-photo { --w: min(440px, 38vw); --about-tint: var(--bg); position: relative; display: flex; justify-content: center; align-items: flex-end; }
.about-photo::before { content: ""; position: absolute; inset: calc(var(--w) * .44) 0 0; border-radius: var(--r-l) var(--r-l) 0 0; background: var(--about-tint); }
.about-photo img { position: relative; width: var(--w); }
/* poniżej 1024 px postać stoi w całości na pasie (głowa nie wychodzi ponad jego krawędź). Kolumna tekstu jest wyższa od postaci tylko do ok. 810 px;
   w 820–1023 px to postać wyznacza wysokość wiersza i czubek głowy stykał się z górną krawędzią pasa (R3-J3-1), więc figura dostaje 40 px od góry
   jak na telefonie: postać stoi 40 px w głąb pasa, pole za nią zaczyna się na wysokości ramion liczonej od góry postaci; w 700–790 px (tekst wyższy)
   i od 1024 px bez zmian */
@media (max-width: 1023px) {
  .about { --up: 0px; }
  .about-photo { padding-top: 40px; }
  .about-photo::before { inset: calc(40px + var(--w) * .44) 0 0; }
  /* bez głowy nad pasem odstęp kafle → pas to sam padding sekcji: 64 px, tyle co scena → linia (R2-J1-2: 40 px stawiało pas tuż pod „Sklep”) */
  .finds { padding-bottom: 64px; }
}
@media (max-width: 699px) {
  .about-in { grid-template-columns: minmax(0, 1fr); }
  .about-text { padding-bottom: 0; }
  .about-photo { --w: min(300px, 80vw); }
}

/* ============ stopka: zaczyna się zaraz za pasem ============ */
main + .site-foot { padding-top: 48px; }
/* odnośnik logo w stopce jest tak szeroki, jak znak z napisem (142 px), a nie jak cała komórka siatki (598 px):
   puste pole obok logo nie prowadzi na stronę główną, a obrys fokusu obejmuje sam znak */
.site-foot .logo { justify-self: start; }
/* w wąskiej stopce odnośniki stoją przy samej krawędzi kolumny: obramowanie fokusu bez odsunięcia mieści się w całości */
@media (max-width: 899px) {
  .foot-nav a:focus-visible { outline-offset: 0; }
  .foot-end { gap: 16px 24px; }
}
/* od 900 px zdanie o prawach i odnośniki prawne stoją w jednym rzędzie: w 900–1078 px zdanie łamie się na dwa wiersze i oddaje miejsce odnośnikom,
   które kończą się na krawędzi kolumny jak menu stopki (R3-J3-3: wcześniej schodziły tam do osobnego rzędu od lewej, a menu stopki stało przy prawej,
   czyli dwa wyrównania w jednej stopce; naniesione bez zmian z poprawką R1-J3-7, która wyrównywała ten osobny rząd do osi ©: −12 px dopełnienia
   odnośnika zostaje na wypadek łamania przy dużej czcionce przeglądarki) */
@media (min-width: 900px) {
  .foot-end { column-gap: 36px; }
  .foot-end .foot-nav { margin-left: -12px; }
  /* kolumna znaku na jego szerokość, odnośniki w reszcie (wyrównane do prawej jak dotąd): przy czcionce przeglądarki 32 px znak nie kurczył się
     do zera i zachodził na „Narzędzia” (R2-J5-5) */
  .foot-in { grid-template-columns: auto minmax(0, 1fr); }
}
@media (min-width: 900px) and (max-width: 1078px) {
  .foot-end { flex-wrap: nowrap; }
  .foot-end p { flex: 1 1 0; min-width: 0; }
  .foot-end .foot-nav { flex: none; flex-wrap: nowrap; }
}
/* telefon: siedem odnośników w dwóch kolumnach zamiast łamanego rzędu z samotnym „O mnie”; kolumny po połowie pudełka
   (kolumna treści + 12 px wyrównania z podstawy), a dopełnienie odnośnika 12 px stawia napis drugiej kolumny tam, gdzie drugi kafel
   (485: 248,7 px, 390: 201 px; R2-J3-7: kolumny max-content zaczynały drugą na 135 / 131 px i zostawiały prawą połowę stopki pustą);
   lewa krawędź równo z logo. Wypełnianie kolumnami, 4 + 3 (Narzędzia, Piosenki, Blog, Sklep | Platforma, Gry, O mnie): wypełnianie rzędami
   zostawiało „O mnie” samo w czwartym rzędzie (R3-J1-5) */
@media (max-width: 699px) {
  .foot-in > .foot-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(4, auto); grid-auto-flow: column; column-gap: 0; }
}
/* do 379 px odnośniki prawne bez bocznego dopełnienia, odstęp 12 px: trzy mieszczą się w jednym rzędzie (napisy 260 + 24 = 284 px w kolumnie 288)
   zamiast łamania 2 + 1 z samotnym „Kontakt” (R2-J3-6) */
@media (max-width: 379px) {
  .foot-end .foot-nav { gap: 0 12px; margin-left: 0; }
  .foot-end .foot-nav a { padding-inline: 0; }
}

/* ============ ruch (RUCH.md; choreografia w js/home.js na GSAP) ============
   Jedna krzywa na całej stronie: --expo (expo-out) w CSS, expo.out w GSAP. Wejścia dużych elementów 600–800 ms, nazwy 600, stagger 60 ms;
   reakcje 200–300 ms (wyjście krótsze niż wejście), wciśnięcie 100–120 ms. Animowane są tylko transform, opacity i clip-path.
   Wejście góry strony przy każdym otwarciu: stan początkowy daje klasa „anim” na <html> (skrypt w <head>, tylko bez ograniczonego ruchu,
   bezpiecznik 300 ms od pierwszej klatki, jeżeli skrypt ruchu jeszcze nie przejął stanu), skrypt przejmuje go stylami inline
   i po wejściu zdejmuje klasę. Gdy bezpiecznik zadziała, klasa „anim-off” daje 200 ms przenikania zamiast skoku krycia 0 → 1 w jednej klatce,
   a skrypt, który dojdzie później, rejestruje sam ruch przewijania. Bez skryptów i przy ograniczonym ruchu żaden z tych selektorów nie działa:
   cała strona stoi w stanie końcowym. */
html.anim .home .title h1, html.anim .pitch > *, html.anim .shot, html.anim .caps li span { opacity: 0; }
html.anim-off .home .title h1, html.anim-off .pitch > *, html.anim-off .stage .shot, html.anim-off .caps li span { transition: opacity .2s ease; }
.home .title h1 .ln { display: block; }
/* odręczna kreska (UNDERLINE = True w build.py): schowana do chwili, gdy skrypt doda klasę „pen” (wiersz ze słowem już stoi), potem ciągnie się od lewej */
@keyframes pen-stroke { from { clip-path: inset(-20% 100% -20% 0); } to { clip-path: inset(-20% 0 -20% 0); } }
html.anim .home .title h1 .scribble::after { clip-path: inset(-20% 100% -20% 0); }
html.anim .home .title h1 .scribble.pen::after { animation: pen-stroke .5s var(--pen) forwards; }

/* rama i sześć nazw unoszą się razem przy najechaniu na obraz: jeden przedmiot, nazwy należą do niego. Unosi się cała scena (.stage)
   w każdej oprawie, także w b i c razem z polem pod ramą: uniesienie na samej ramie (.shot) zderzało się z wejściem, bo GSAP trzyma na niej
   transform do końca wejścia i dopiero po zdjęciu stylu rama dojeżdżała 3 px w górę, gdy wskaźnik stał nad nią od otwarcia (K-V3-5);
   .stage nie jest animowana, więc stan najechania jest na niej od pierwszej klatki. Wejście 300 ms, powrót 200 ms. */
@media (hover: hover) and (pointer: fine) {
  .stage { transition: transform .2s var(--expo); }
  .stage:has(.shot a:hover) { transform: translateY(-3px); transition-duration: .3s; }
  /* pole najechania ramy wydłuża się o 3 px w dół dopiero w stanie najechania, czyli o tyle, o ile rama się unosi: pole uniesione zawiera
     całe pole spoczynkowe, więc stan nie przełącza się, gdy wskaźnik stoi przy dolnej krawędzi ramy (R2-J4-1 / R2-J5-2: scena drgała
     0 ↔ −3 px, 38 zmian kierunku w 1,6 s → 0). ::before jest wolny (::after trzyma obrys); w spoczynku pseudoelementu nie ma. */
  .stage:has(.shot a:hover) .shot a::before { content: ""; position: absolute; inset: 0 0 -3px; border-radius: inherit; }
  /* to samo dla przycisku uniesionego o 2 px: pole pod nim o 2 px dłuższe tylko przy najechaniu (wskaźnik 5–7 px pod przyciskiem przełączał stan 20 razy na sekundę) */
  .home .btn:hover::after { inset: -4px 0 -9px; }
}

/* „Co tu znajdziesz”: linia nad nagłówkiem jest pseudoelementem kolumny (ta sama geometria, co border-top nagłówka: 1 px u góry kolumny);
   nagłówek zachowuje 1 px przezroczystej krawędzi dla układu. Linia stoi: rysowanie od lewej (900 ms) 1 px #E9DDD3 na kremie przy kontraście
   1,27:1 było ruchem bez widza, widocznym dopiero w powiększeniu (R2-J4-5). */
.finds .wrap { position: relative; }
.finds .wrap::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; background: var(--line); }
.finds h2 { border-top-color: transparent; }

/* o autorze: postać unosi się ze przewijaniem (w skrypcie) spod dolnej krawędzi pasa, więc figura przycina to, co wystaje pod nią */
.about-photo { overflow: clip; }
/* kolor pola za postacią do porównania (AUTOR_CIEPLY = True w build.py): brzoskwinia Whereby #F3DCD6 w odcieniu pasa zamiast zimnego różu */
html[data-autor="cieply"] .about-photo { --about-tint: #F3DCD6; }
/* kafel, do którego doszedł fokus klawiatury spod pierwszego ekranu, jest widoczny od pierwszej klatki, a jego zdjęcie bez skali wejścia */
.home-tiles li:focus-within, .home-tiles li:focus-within .tile-photo img { opacity: 1 !important; transform: none !important; }

/* reakcje na wskaźnik i wciśnięcie poza przyciskiem i kaflami (te są w podstawie i wyżej): koszyk i przycisk menu kurczą się przy wciśnięciu,
   „Zaloguj się” też; odnośniki stopki dostają podkreślenie przenikaniem zamiast skoku */
.icon-btn { transition: background-color .15s ease, transform .12s ease-out; }
.icon-btn:active { transform: scale(.92); }
.btn-line { transition: background-color .15s ease, color .15s ease, transform .12s ease-out; }
.btn-line:active { transform: scale(.97); }
.foot-nav a { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: .22em; transition: color .15s ease, text-decoration-color .2s ease; }
/* podświetlenie dotyku przeglądarki jest wyłączone (tap-highlight u góry pliku), więc odnośniki menu, stopki i znak mają własną odpowiedź
   na wciśnięcie: pismo ciemnieje, znak lekko gaśnie; 100 ms, żeby reakcja była natychmiastowa (R2-J5-6) */
.main-nav li a:active { color: var(--accent-dark); transition-duration: .1s; }
.foot-nav a:active { color: var(--ink); text-decoration-color: currentColor; transition-duration: .1s; }
.logo { transition: opacity .1s ease; }
.logo:active { opacity: .7; }
@media (hover: hover) and (pointer: fine) {
  .foot-nav a:hover { text-decoration-color: currentColor; }
  /* linia pod odnośnikiem menu: rysuje się 260 ms, cofa 180 ms, zawsze od lewej (wchodzi i wychodzi tą samą drogą) */
  .main-nav li a::after { transition-duration: .18s; }
  .main-nav li a:hover::after { transition-duration: .26s; }
}

/* menu na telefonie: panel odsłania się spod paska od góry (clip-path, 240 ms) i chowa tą samą drogą szybciej (150 ms); bez przenikania,
   więc pod panelem nie prześwituje treść. W przeglądarce bez przejść dyskretnych otwiera się i zamyka od razu, jak dotąd. */
@media (max-width: 63.99em), (max-width: calc(399px + 34.5em + max(0px, (34.5em - 801px) * 1000) - .02px)) {
  .main-nav { clip-path: inset(0 0 100% 0); transition: clip-path .15s var(--expo), display .15s allow-discrete; }
  /* stan otwarty: przycięcie sięga 48 px pod panel, żeby nie obcinało jego cienia (pas cienia 28 px pod panelem; bez niego panel
     kończył się bez krawędzi, a obraz platformy pod nim wyglądał na ucięty); reguła musi stać przed @starting-style */
  .site-head[data-open] .main-nav { clip-path: inset(0 0 -48px 0); transition-duration: .24s, .24s; }
  @starting-style { .site-head[data-open] .main-nav { clip-path: inset(0 0 100% 0); } }
}
/* bez skryptów podstawa rozwija menu na stałe, a przycięcie z warstwy ruchu je zasłaniało (pasek 501 px pustki, 0 z 8 odnośników):
   bez przycięcia, bez wyglądu rozwijanego panelu (odnośniki równo z logo); przyklejony pasek z rozwiniętym menu nie może się przyklejać */
@media (scripting: none) and (max-width: 63.99em), (scripting: none) and (max-width: calc(399px + 34.5em + max(0px, (34.5em - 801px) * 1000) - .02px)) {
  .burger { display: none; }
  .head-in { flex-wrap: wrap; }
  .main-nav, .site-head[data-open] .main-nav { order: 4; display: flex; position: static; flex-basis: 100%; clip-path: none; transition: none; padding: 0 0 16px; border-top: 0; box-shadow: none; }
  html[data-sticky] .site-head { position: relative; }
}

/* Ograniczony ruch: klasy „anim” nie ma, skrypt ruchu nie startuje, nic się nie przesuwa; wspólna podstawa skraca przejścia do zera.
   Gdyby klasa jednak trafiła na stronę, treść i tak jest widoczna. Mniej i łagodniej, nie zero (Emil, impeccable): zmiany koloru
   i podkreślenia przy najechaniu zostają z przenikaniem 150 ms, bez przesunięć i skali. */
@media (prefers-reduced-motion: reduce) {
  html.anim .home .title h1, html.anim .pitch > *, html.anim .shot, html.anim .caps li span { opacity: 1; }
  html.anim .home .title h1 .scribble::after { clip-path: none; animation: none; }
  .site-head[data-open] .main-nav { clip-path: none; }
  /* stany najechania bez przesunięcia i skali (kolor nazwy i strzałki zostaje): przy przejściu 0,01 ms skala 1,035 zdjęcia kafla,
     4 px strzałki i 3 px sceny były skokiem, nie ruchem (R2-J4-3) */
  .home-tiles .tile:hover .tile-photo img, .home-tiles .tile:hover h3 svg, .stage:has(.shot a:hover) { transform: none !important; }
  /* przyciski przy najechaniu bez skoku o −2 / −1 px i strzałka bez 3 px (R3-J4-3); cień, kolor i wciśnięcie zostają (oba wyglądy, oba przyciski) */
  .home .btn:hover:not(:active), .home .btn:hover svg { transform: none !important; }
  .btn-line, .icon-btn, .main-nav li a, .foot-nav a, .tile h3 svg { transition-property: color, background-color, text-decoration-color !important; transition-duration: .15s !important; transition-timing-function: ease !important; }
}
/* druk: wszystko widoczne (także nazwy czekające na wjazd w okno, postać związana z przewijaniem i zdjęcia kafli bez skali wejścia), bez cieni pod ramą,
   bez zdjęcia pod sceną, bez ikon menu i koszyka; nagłówek spisu nie zostaje sam na dole strony. Przycisk bez tła: przy druku bez grafiki tła
   (ustawienie domyślne przeglądarki) biały napis na białym był nieczytelny (R3-J5-4), więc napis w ciemnej malinie z obrysem 1 px */
@media print {
  .home-tiles li, .about-text > *, .finds h2, .caps li span, .about-photo img, .home-tiles .tile-photo img { opacity: 1 !important; transform: none !important; }
  html[data-look] .home .btn { background: none; color: var(--accent-dark); box-shadow: inset 0 0 0 1px currentColor; }
  html[data-look] .home .btn-2 { color: var(--ink); }
  .finds h2 { break-after: avoid; }
  .shot a { box-shadow: 0 0 0 1px var(--line) !important; }
  .scene-bg, .burger, .cart { display: none; }
  html[data-scena="b"] .stage { background: none; }
}

/* tryb wymuszonych kolorów usuwa tła i cienie: przycisk, rama, nazwy i pola dostają obrys; podkreślenie zostaje nad tłem */
@media (forced-colors: active) {
  .btn, .btn-line { border: 2px solid ButtonText; }
  .shot a, .caps li span, .about::before, .about-photo::before, html[data-scena="b"] .stage, html[data-scena="c"] .stage { border: 1px solid CanvasText; }
  .main-nav li a::after { background: CanvasText; }
  .home .title h1 .scribble::after { z-index: 0; }
  .finds h2 { border-top-color: CanvasText; }
  .finds .wrap::before { display: none; }
  /* linia pod paskiem jest cieniem, a tryb usuwa cienie: obramowanie w kolorze systemu, jak linia nad „Co tu znajdziesz” */
  .site-head { border-bottom: 1px solid CanvasText; }
}
/* wymuszone kolory w motywie ciemnym: ciemne kreski znaku (#2D2A26 w pliku SVG) ginęły na czarnym tle i zostawało samo malinowe siedzisko (R3-J5-5);
   odwrócenie jasności z obrotem barwy o 180° robi kreski jasnymi, a malinę zostawia maliną. Napis obok jest tekstem i dostaje kolor systemu sam. */
@media (forced-colors: active) and (prefers-color-scheme: dark) {
  .logo-mark { filter: invert(1) hue-rotate(180deg); }
}
