/* Kotwice — warstwa wizualna „Classical".
 *
 * Wartości pochodzą z systemu projektowego Classical
 * (design_handoff_speedread_classical/). Tokeny `:root` są przeniesione
 * z `classical-styles.css` — hexy wpisujemy tutaj i nigdzie indziej.
 *
 * Kroje siedzą w assets/fonts/fonts.css — osadzone lokalnie, bez CDN, bo
 * aplikacja ma działać offline i po otwarciu z dysku. Każdy krój do składu
 * książki ma prawdziwe odmiany 600 i 700; syntezowane pogrubienie rozmywa
 * litery i zabija efekt kotwicy, który stoi wyłącznie na kontraście wagi.
 * Odświeżenie listy: node tools/fetch-fonts.js
 *
 * Zasada wagi w tym systemie: pogrubienie jest oszczędne. Nagłówki interfejsu
 * kończą się na 600, duże napisy schodzą do 400. Waga 700 zostaje wyłącznie
 * kotwicom — i tylko wtedy, gdy użytkownik ją wybierze.
 */

/* --- Tokeny ------------------------------------------------------------- */

:root {
  /* Barwy podawane parami: chłodna podstawa i ciepły papier. Suwak „ciepło
     tła" miesza je w przestrzeni oklab, żeby po drodze nie robiło się szaro —
     mieszanie w sRGB przy takich jasnych tonach potrafi zszarzeć w środku. */
  --warmth: 0;
  --mix: calc(var(--warmth) * 1%);

  --bg-cool: #f7f5f2;
  --bg-warm: #fbefe2;
  --surface-cool: #f1ede8;
  --surface-warm: #f5e6d9;
  --neutral-200-cool: #efeae4;
  --neutral-200-warm: #f3e4d6;
  --neutral-300-cool: #e0dbd5;
  --neutral-300-warm: #e4d3c4;

  --color-bg: color-mix(in oklab, var(--bg-cool), var(--bg-warm) var(--mix));
  --color-surface: color-mix(in oklab, var(--surface-cool), var(--surface-warm) var(--mix));
  --color-neutral-200: color-mix(in oklab, var(--neutral-200-cool), var(--neutral-200-warm) var(--mix));
  --color-neutral-300: color-mix(in oklab, var(--neutral-300-cool), var(--neutral-300-warm) var(--mix));

  --color-text: #1a1a1a;
  --color-neutral-400: #c6c0b9;
  /*
   * Cichy tusz drobnego pisma. Wartość NIE jest wybrana okiem: to najjaśniejszy
   * odcień tego samego szarego, który na tle strony daje 4,5:1 — próg WCAG AA
   * dla pisma poniżej 18,7 px. Poprzednie `#9b9797` dawało 2,59:1, czyli mniej
   * niż połowę wymaganego, i tak wyglądały wszystkie podpisy w panelach
   * tablicy, liczniki i puste stany.
   *
   * „Najjaśniejszy, który przechodzi" to reguła, a nie kompromis: hierarchia
   * ma być zachowana wszędzie tam, gdzie nie kosztuje czytelności.
   */
  --color-neutral-500: #6e6e6e;

  /* Złoto. `--color-accent` to obrys, kreska i drobny znak — na papierze daje
     około 3:1, więc wystarcza na ikony, duże napisy i chrom, ale NIE na tekst
     akapitowy. Do złotego tekstu w zwykłym rozmiarze służy `--color-accent-700`. */
  /*
   * RAMPA AKCENTU. Cztery stopnie, wszystkie z jednej rodziny paczki:
   *   300  brzoskwinia — wypełnienia paneli i podkreślenia
   *   400  jaśniejszy — górny stop gradientów
   *   ---  podstawowy #FF7A00 — kreski, obrysy, znak; NIGDY pod tekstem
   *   700  głęboki — dolny stop gradientów i pismo w akcencie
   * Poza tymi czterema nie ma w interfejsie ani jednego innego pomarańczu.
   */
  --color-accent: #ff7a00;
  --color-accent-300: #ffe2cc;
  --color-accent-400: #ff8a1a;
  /*
   * GŁĘBOKI POMARAŃCZ — JEDEN NA CAŁĄ APLIKACJĘ.
   *
   * Ten sam #D96200, który jest dolnym stopniem gradientu przycisków. Miał
   * przez chwilę własną, ciemniejszą wartość dobraną pod próg czytelności
   * pisma — i było to widać od razu: odnośnik „Zacznij od przykładu" stał
   * obok przycisku i wyglądał jak inna barwa, bo nią był. Dwa pomarańcze
   * obok siebie czytają się jak usterka, nawet gdy każdy z osobna ma powód.
   *
   * Cena jest zapisana i pilnowana: ten kolor daje na papierze 3,39:1, czyli
   * próg dla pisma pogrubionego od 14 px, a nie dla zwykłego. Napisy, które
   * go niosą, są więc pogrubione — sprawdza to `check-kontrast-ui`.
   */
  --color-accent-700: #d96200;

  /*
   * PRZYCISK PEŁNY — para barw, nie jedna.
   *
   * Osobne tokeny, bo w ciemnym motywie ta para SIĘ ODWRACA: `--color-accent-700`
   * idzie tam w drugą stronę i robi się jasny. Napisany na sztywno jasny tusz
   * byłby więc bielą na jasnym bursztynie, czyli poprawką czytelności, która
   * czytelność psuje — dokładnie po zmianie motywu, gdzie nikt jej nie szuka.
   */
  /*
   * PRZYCISK PEŁNY: POMARAŃCZ ZE ZNAKU, TUSZ ATRAMENTOWY.
   *
   * Wypełnienie jest dokładnie tym #FF7A00, który stoi w nawiasach logo —
   * przycisk i znak mają być tą samą barwą i to była decyzja wprost.
   *
   * Etykieta jest BIAŁA — tak stoi w zaakceptowanym projekcie i tak zostaje.
   * Odnotowane, bo liczba jest znana i nie zniknie przez przemilczenie:
   * biel na tym gradiencie daje od 2,61:1 u góry do 3,69:1 u dołu, przy progu
   * 4,5:1 dla pisma tej wielkości. Wyjątek jest wpisany imiennie w
   * `check-kontrast-ui`, żeby był widoczny, a nie rozpuszczony w obniżonym
   * progu dla całego interfejsu.
   */
  --klawisz-pelny-tlo: #d96200;
  --klawisz-pelny-tusz: #ffffff;
  --klawisz-pelny-grad: linear-gradient(180deg, #ff8a1a 0%, #d96200 100%);
  --klawisz-pelny-obwodka: 1px solid rgba(168, 76, 0, .45);
  --klawisz-pelny-swiatlo:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    0 6px 12px -7px rgba(168, 76, 0, .6);

  --color-divider: color-mix(in srgb, var(--color-text) 16%, transparent);

  --error-ink: #7f1d1d;
  --error-bg: #fef2f2;
  --error-line: #fecaca;

  /*
   * KRÓJ INTERFEJSU — jeden, Atkinson Hyperlegible, w nagłówkach i w tekście.
   *
   * Dwie zmienne zostają, bo nazywają rolę, a nie krój: gdyby nagłówki dostały
   * kiedyś inny krój, zmiana zajmie jeden wiersz. Tekst czytanej książki NIE
   * bierze kroju stąd — ma własny `--reader-font`, zasilany z listy „Krój
   * pisma" w ustawieniach. Złączenie tych dwóch dróg odebrałoby czytelnikowi
   * wybór bez żadnego komunikatu.
   *
   * Grubości wyłącznie 400 i 700. Ten krój nie ma pośrednich, więc zapisane
   * 500 albo 600 przeglądarka dopasowałaby do najbliższej istniejącej — i liczba
   * w arkuszu mówiłaby co innego niż ekran.
   */
  --font-heading: "Atkinson Hyperlegible", system-ui, sans-serif;
  --font-body: "Atkinson Hyperlegible", system-ui, sans-serif;

  --space-1: 4.6px;
  --space-2: 9.2px;
  --space-3: 13.8px;
  --space-4: 18.4px;
  /*
   * Piąty stopień skali BYŁ UŻYWANY, ale nigdy zdefiniowany — w sześciu
   * miejscach, w tym w odstępach szuflady sprawdzianu. Nieznana zmienna
   * unieważnia CAŁĄ deklarację, więc `padding` z takim odstępem po prostu
   * znikał i treść dotykała krawędzi ekranu. Nic nie krzyczy, nic nie pada —
   * po prostu nie ma marginesu, a wygląda to na decyzję projektową.
   */
  --space-5: 23px;
  --space-6: 27.6px;
  --space-8: 36.8px;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;

  --shadow-lg: 0 12px 32px color-mix(in srgb, #1a1a1a 22%, transparent);

  /* Ustawienia czytnika — nadpisywane z JS. */
  --anchor-weight: 600;

  /* Waga zwykłego tekstu w czytniku. Na papierze zwykłe 400.
     W ciemnym motywie schodzi niżej — powód przy nadpisaniu. */
  --text-weight: 400;
  /* Zakreślacze. Jasne i niskonasycone, żeby litery na wierzchu zostały
     czytelne — to je się czyta, barwa ma je tylko otaczać. */
  --mark-zolty: #f6e7a8;
  --mark-rozowy: #f3ccd6;
  --mark-zielony: #cfe6c8;
  --mark-niebieski: #cadcee;
  --reader-font: 'Literata', Georgia, 'Times New Roman', serif;
  --reader-size: 19px;
  --reader-measure: 36rem;
  --reader-leading: 1.65;

  /* Faktura papieru — nadpisywana z JS. */
  --paper-tex: none;
  --paper-size: auto;
  --paper-blend: multiply;
  --paper-amt: 0;

  /*
   * Płótno tablicy zostaje JASNE także w ciemnym motywie — i jest to
   * wymuszone, nie przeoczone.
   *
   * Barwy kształtów siedzą w modelu i idą stamtąd wprost do pliku SVG:
   * karteczka jest jasnożółta, napis prawie czarny, i takie zostają wszędzie,
   * gdzie ten plik trafi. Do tego element typu „tekst" nie ma pod sobą żadnego
   * kształtu — leży wprost na płótnie. Ciemne płótno dawałoby więc ciemny napis
   * na ciemnym tle, a po zapisaniu plik i tak wróciłby jasny: byłby to podgląd
   * czegoś, czego nie ma.
   *
   * Diagram jest tu tym, czym w czytniku jest strona — rzeczą na papierze,
   * oglądaną w aplikacji, a nie częścią jej skóry.
   *
   * W ciemnym motywie papier schodzi o ton niżej. Biel pełną mocą obok
   * ciemnego paska narzędzi razi i wygląda jak niedokończony motyw; ton niżej
   * czyta się jako kartka położona na ciemnym blacie. Różnica względem bieli
   * w zapisanym pliku jest przy tym mniejsza niż między dwoma monitorami.
   */
  --board-plotno: #fcfbf9;
  --board-siatka: #211d15;

  /*
   * Prowadnica. Barwa CELOWO spoza palety kształtów.
   *
   * Złoto odpada, choć jest barwą chromu tablicy: obrys kształtu jest złoty,
   * więc złota prowadnica biegnąca wzdłuż krawędzi zlewa się z nią dokładnie
   * tam, gdzie ma być najlepiej widoczna. Ta sama pomyłka, którą zrobiła
   * pierwsza ramka zaznaczenia. Róż jest w palecie jako barwa karteczki, więc
   * nie kłóci się z resztą, a jako włosowa linia w trakcie ruchu nie da się
   * pomylić z obrysem — bo obrysy nie bywają różowe i proste naraz.
   */
  --board-prowadnica: #c2506e;

  /* ==================================================================
   * KARTECZKI I PASEK TABLICY — odświeżony wygląd
   *
   * Wartości pochodzą z projektu (`design_handoff_boards_warm_ui`) i są tu
   * WYŁĄCZNIE nazwane. Żaden z tych hexów nie ma prawa pojawić się w regule
   * komponentu — po to ta sekcja istnieje i po to jest w jednym miejscu.
   *
   * NAZWY RODZIN IDĄ ZA MODELEM, nie za projektem. Projekt mówi „bursztyn,
   * brzoskwinia, szałwia, róż, błękit"; model zapisuje przy kształcie
   * `kolor: 'zolty' | 'rozowy' | 'zielony' | 'niebieski'`. Gdyby tokeny
   * nazwać po projektowemu, każdy komponent musiałby wozić ze sobą tablicę
   * tłumaczącą jedno na drugie — a taka tablica to miejsce, w którym piąta
   * barwa dopisana w jednym miejscu, a nie w drugim, znika po cichu.
   * Nazwy projektowe zostają w komentarzach przy każdej rodzinie.
   *
   * DLACZEGO WERSJE CIEMNE SĄ OSOBNYMI NAZWAMI, a nie nadpisaniem w bloku
   * motywu ciemnego: płótno tablicy zostaje jasne także w motywie ciemnym
   * (powód wyżej, przy `--board-plotno`). Karteczka na jasnym płótnie ma więc
   * zostać jasna, choćby reszta aplikacji pociemniała — automatyczne
   * przełączenie dałoby ciemną karteczkę na jasnym papierze. Chrom paska
   * przeciwnie: on jest częścią aplikacji, więc jego tokeny SĄ nadpisywane
   * w blokach motywu niżej.
   * ================================================================== */

  /* Bursztyn — rodzina domyślna. */
  --karteczka-zolty-od: #fff2ce;
  --karteczka-zolty-do: #f7c766;
  --karteczka-zolty-tlo: linear-gradient(160deg, #fff2ce, #f7c766);
  --karteczka-zolty-tekst: #5c4413;
  --karteczka-zolty-tlo-ciemny: linear-gradient(160deg, #6e5117, #45300d);
  --karteczka-zolty-tekst-ciemny: #f6e4b8;

  /* Brzoskwinia — rodzina, której model jeszcze nie zna. */
  --karteczka-brzoskwiniowy-od: #ffe4cb;
  --karteczka-brzoskwiniowy-do: #f6b384;
  --karteczka-brzoskwiniowy-tlo: linear-gradient(160deg, #ffe4cb, #f6b384);
  --karteczka-brzoskwiniowy-tekst: #6b3f2c;
  --karteczka-brzoskwiniowy-tlo-ciemny: linear-gradient(160deg, #6a3a22, #42210f);
  --karteczka-brzoskwiniowy-tekst-ciemny: #f6dcc8;

  /* Szałwia. */
  --karteczka-zielony-od: #edf6d3;
  --karteczka-zielony-do: #c3dd92;
  --karteczka-zielony-tlo: linear-gradient(160deg, #edf6d3, #c3dd92);
  --karteczka-zielony-tekst: #3f4f22;
  --karteczka-zielony-tlo-ciemny: linear-gradient(160deg, #405621, #283715);
  --karteczka-zielony-tekst-ciemny: #ddecc0;

  /* Róż. */
  --karteczka-rozowy-od: #fce2ed;
  --karteczka-rozowy-do: #f0a6c6;
  --karteczka-rozowy-tlo: linear-gradient(160deg, #fce2ed, #f0a6c6);
  --karteczka-rozowy-tekst: #5f2b42;
  --karteczka-rozowy-tlo-ciemny: linear-gradient(160deg, #5e2e44, #3c1c2c);
  --karteczka-rozowy-tekst-ciemny: #f6d2e1;

  /* Błękit. */
  --karteczka-niebieski-od: #dcebf9;
  --karteczka-niebieski-do: #a5cbee;
  --karteczka-niebieski-tlo: linear-gradient(160deg, #dcebf9, #a5cbee);
  --karteczka-niebieski-tekst: #24455c;
  --karteczka-niebieski-tlo-ciemny: linear-gradient(160deg, #244b65, #16303f);
  --karteczka-niebieski-tekst-ciemny: #d2e7f6;

  /*
   * Bazy cieni rodzin — jako TRÓJKI SKŁADOWYCH, nie gotowe barwy.
   *
   * Projekt każe tej samej barwie wystąpić przy czterech różnych kryciach
   * (cień spoczynkowy, cień przy przeciąganiu, próbka wybrana, niewybrana).
   * Zapisana jako `rgba(...)` musiałaby zostać przepisana cztery razy z ręki
   * i za czwartym razem ktoś pomyli jedną cyfrę. Trójka składowych wchodzi
   * do `rgb(... / krycie)` i krycie zostaje jedyną rzeczą, która się zmienia.
   */
  --karteczka-zolty-cien: 146 101 22;
  --karteczka-brzoskwiniowy-cien: 150 86 44;
  --karteczka-zielony-cien: 94 120 44;
  --karteczka-rozowy-cien: 146 54 92;
  --karteczka-niebieski-cien: 35 84 120;

  /*
   * Cienie karteczki — OSOBNO DLA KAŻDEJ RODZINY, i to nie z lenistwa.
   *
   * Pierwsza wersja miała jeden cień z barwą braną przez `--cien-baza`, którą
   * miał ustawiać sam element. Nie działa: zmienne podstawiają się w miejscu
   * DEKLARACJI, nie użycia. Token stojący na `:root` rozwiązuje `var()` bazą
   * korzenia i dziedziczy w dół już rozwiązany, więc karteczka różowa dostawała
   * cień bursztynowy. Zmierzone, nie wywnioskowane — `check-tokeny.js` złapał
   * to przy pierwszym uruchomieniu.
   *
   * Liczby i tak nie są przepisywane: składowe barwy przychodzą z trójek wyżej,
   * a te leżą na tym samym poziomie, więc podstawienie działa.
   *
   * Warstwa `inset` u góry to nie ozdoba: bez niej gradient wygląda płasko,
   * bo nic nie mówi, z której strony pada światło. Projekt zaznacza to wprost.
   */
  --cien-karteczka-zolty:
    0 1px 1px rgba(32, 31, 29, .1),
    0 12px 20px -10px rgb(var(--karteczka-zolty-cien) / 50%),
    inset 0 1px 0 rgba(255, 255, 255, .65);
  --cien-karteczka-brzoskwiniowy:
    0 1px 1px rgba(32, 31, 29, .1),
    0 12px 20px -10px rgb(var(--karteczka-brzoskwiniowy-cien) / 50%),
    inset 0 1px 0 rgba(255, 255, 255, .65);
  --cien-karteczka-zielony:
    0 1px 1px rgba(32, 31, 29, .1),
    0 12px 20px -10px rgb(var(--karteczka-zielony-cien) / 50%),
    inset 0 1px 0 rgba(255, 255, 255, .65);
  --cien-karteczka-rozowy:
    0 1px 1px rgba(32, 31, 29, .1),
    0 12px 20px -10px rgb(var(--karteczka-rozowy-cien) / 50%),
    inset 0 1px 0 rgba(255, 255, 255, .65);
  --cien-karteczka-niebieski:
    0 1px 1px rgba(32, 31, 29, .1),
    0 12px 20px -10px rgb(var(--karteczka-niebieski-cien) / 50%),
    inset 0 1px 0 rgba(255, 255, 255, .65);

  /* Przy przeciąganiu karteczka się unosi: cień dłuższy i mocniejszy. */
  --cien-ciagniona-zolty: 0 18px 28px -12px rgb(var(--karteczka-zolty-cien) / 60%);
  --cien-ciagniona-brzoskwiniowy: 0 18px 28px -12px rgb(var(--karteczka-brzoskwiniowy-cien) / 60%);
  --cien-ciagniona-zielony: 0 18px 28px -12px rgb(var(--karteczka-zielony-cien) / 60%);
  --cien-ciagniona-rozowy: 0 18px 28px -12px rgb(var(--karteczka-rozowy-cien) / 60%);
  --cien-ciagniona-niebieski: 0 18px 28px -12px rgb(var(--karteczka-niebieski-cien) / 60%);

  /* Wersja ciemna jest jedna dla wszystkich rodzin: na ciemnym tle barwa
     rodziny w cieniu i tak nie jest widoczna, a czerń pod spodem tak. */
  --cien-karteczka-ciemny:
    inset 0 1px 0 rgba(255, 255, 255, .1),
    0 14px 22px -12px rgba(0, 0, 0, .9);

  /* Pastylka paska i klawisze. Te tokeny SĄ nadpisywane w motywie ciemnym. */
  --pasek-tlo: linear-gradient(180deg, #ffffff 0%, #ffffff 100%);
  --pasek-obwodka: #e7e2dc;
  --pasek-cien:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 2px 3px rgba(26, 26, 26, .06),
    0 14px 26px -14px rgba(168, 76, 0, .55);
  --pasek-separator: #e7e2dc;

  --klawisz-znak: #6e6e6e;
  --klawisz-znak-wylaczony: rgba(26, 26, 26, .4);
  --klawisz-hover-tlo: linear-gradient(170deg,
    rgba(255, 226, 204, .85) 0%, rgba(255, 138, 26, .5) 100%);
  --klawisz-hover-cien: inset 0 1px 0 rgba(255, 255, 255, .7);
  --klawisz-aktywny-tlo: linear-gradient(180deg, #ff8a1a 0%, #d96200 100%);
  --klawisz-aktywny-znak: #ffffff;
  --klawisz-aktywny-cien:
    inset 0 1px 0 rgba(255, 255, 255, .75),
    0 4px 8px -3px rgba(168, 76, 0, .65);
  /* Wciśnięty: ten sam gradient, cień skrócony — palec dociska klawisz do tła. */
  --klawisz-wcisniety-cien: 0 2px 4px -2px rgba(168, 76, 0, .65);

  --papier-pole-tlo: linear-gradient(180deg, #ffffff, #ffe2cc);
  --papier-pole-obwodka: rgba(168, 76, 0, .3);
  --papier-pole-tekst: #1a1a1a;

  /* Próbki pisaka. Własne wartości, mocniejsze niż gradient karteczki — kółko
     o średnicy dwudziestu paru pikseli niesie barwę na dużo mniejszej
     powierzchni, więc dolny przystanek musi być nasycony. */
  --probka-zolty: linear-gradient(170deg, #fff3d2, #f0be60);
  --probka-brzoskwiniowy: linear-gradient(170deg, #ffd9c4, #ee9c6c);
  --probka-zielony: linear-gradient(170deg, #e4f1c8, #a8c878);
  --probka-rozowy: linear-gradient(170deg, #f8d2e1, #e091b4);
  --probka-niebieski: linear-gradient(170deg, #d3e6f7, #8fbbe0);
  --probka-cien-zolty:
    inset 0 1px 0 rgba(255, 255, 255, .7),
    0 3px 6px -3px rgb(var(--karteczka-zolty-cien));
  --probka-cien-brzoskwiniowy:
    inset 0 1px 0 rgba(255, 255, 255, .7),
    0 3px 6px -3px rgb(var(--karteczka-brzoskwiniowy-cien));
  --probka-cien-zielony:
    inset 0 1px 0 rgba(255, 255, 255, .7),
    0 3px 6px -3px rgb(var(--karteczka-zielony-cien));
  --probka-cien-rozowy:
    inset 0 1px 0 rgba(255, 255, 255, .7),
    0 3px 6px -3px rgb(var(--karteczka-rozowy-cien));
  --probka-cien-niebieski:
    inset 0 1px 0 rgba(255, 255, 255, .7),
    0 3px 6px -3px rgb(var(--karteczka-niebieski-cien));
  --probka-wybrana-cien:
    0 0 0 2px rgba(168, 76, 0, .9),
    0 3px 6px -2px rgba(168, 76, 0, .6);

  /*
   * Panel „więcej" na telefonie. Projekt podaje wyłącznie wersję jasną;
   * wartości ciemne (w blokach motywu niżej) są WYPROWADZONE z pastylki,
   * bo to ta sama powierzchnia widziana z bliska — nie ma ich na żadnym
   * zrzucie i nie ma się do czego porównać.
   */
  --panel-wiecej-tlo: linear-gradient(180deg, #ffffff 0%, #faf7f4 100%);
  --panel-wiecej-obwodka: rgba(168, 76, 0, .26);
  --panel-wiecej-cien:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 20px 32px -18px rgba(168, 76, 0, .65);
  --panel-hairline: rgba(168, 76, 0, .22);
  --panel-kafel-tlo: linear-gradient(170deg,
    rgba(255, 255, 255, .9), rgba(250, 247, 244, .6));
  --panel-kafel-cien:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 4px 8px -6px rgba(168, 76, 0, .7);

  /* Promienie. Zagięcie ma większy promień w jednym rogu — w tym, w którym
     papier się odwija. */
  /*
   * Spod uchwytu zaznaczenia. Bialy na papierze, ciemny w motywie ciemnym:
   * uchwyt musi odcinac sie i od jasnej karteczki, i od ciemnego chromu,
   * a jednolicie zloty ginie na zoltej karteczce.
   */
  /* Plakietka pod napisem lacznika. Jasna kartka na kresce, zeby napis
     dalo sie przeczytac takze wtedy, gdy lacznik biegnie przez ksztalt. */
  /* ==================================================================
   * BIBLIOTEKA — wyciszona wersja stylistyki tablicy
   *
   * Karta jest papierowa: gradient prawie bez barwy, cień neutralny,
   * bursztyn wyłącznie jako akcent. Pełny kolor zostaje na tablicy i
   * w miniaturach tablic, gdzie pastele mówią o kategorii notatki.
   * ================================================================== */
  --karta-tlo: linear-gradient(180deg, #ffffff 0%, #faf7f4 100%);
  --karta-obwodka: rgba(26, 26, 26, .12);
  --karta-cien:
    0 1px 1px rgba(26, 26, 26, .06),
    0 14px 24px -16px rgba(26, 26, 26, .35);
  --karta-obwodka-aktywna: rgba(168, 76, 0, .42);
  --karta-cien-aktywna: 0 14px 24px -16px rgba(168, 76, 0, .5);

  --okladka-tlo: linear-gradient(180deg, #ffffff 0%, #faf7f4 100%);
  --okladka-kreska: rgba(168, 76, 0, .2);

  /* Pasek postępu. Wypełnienie idzie w poziomie, bo mierzy drogę w tekście,
     a nie głębokość czegokolwiek. */
  /* Strona powitalna: os krokow, stopka i FAQ. */
  /* Naglowek czytelni (8a) i segment trybu. */
  --czytelnia-tlo: linear-gradient(180deg, #ffffff 0%, #fbf8f5 100%);
  --czytelnia-cien:
    0 1px 1px rgba(26, 26, 26, .05),
    0 12px 22px -16px rgba(26, 26, 26, .35);
  --czytelnia-wlos: rgba(26, 26, 26, .09);
  --czytelnia-narzedzie: #6e6e6e;
  --czytelnia-narzedzie-hover: rgba(168, 76, 0, .07);
  /*
   * STAN WŁĄCZONY JEST POMARAŃCZOWY — wszędzie tak samo: w przełączniku
   * trybu, w pasku czytelni i w przyborniku tablicy.
   *
   * Przekazanie projektu rozdzielało te stany: czarna plama dla narzędzia,
   * pomarańczowa dla trybu. Decyzja po obejrzeniu tego na ekranie jest inna
   * i wiąże: czarny klawisz na jasnym pasku czytał się jak wyłączony albo
   * zepsuty, a nie jak włączony. Jeden stan włączony, jedna barwa.
   */
  --czytelnia-wlaczony-obwodka: rgba(168, 76, 0, .45);
  --czytelnia-wlaczony-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
  --czytelnia-wlaczony-tekst: #ffffff;
  --czytelnia-wlaczony-cien:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 3px 6px -4px rgba(168, 76, 0, .6);
  /* Przycisk zwykly 6a — bialy gradient, uzywany takze w naglowku czytelni. */
  --przycisk-zwykly-tlo: linear-gradient(180deg, #ffffff, #faf7f4);
  --segment-tlo: linear-gradient(180deg, #ffffff, #ffffff);
  --segment-cien: inset 0 1px 2px rgba(26, 26, 26, .05);

  /* Panel ustawien (8b). */
  --ust-cien: 0 16px 26px -18px rgba(26, 26, 26, .4);
  --ust-obwodka-zywa: rgba(168, 76, 0, .24);
  --ust-tlo-zywe: linear-gradient(180deg, #ffffff 0%, #faf7f4 100%);
  --ust-cien-zywy: 0 16px 26px -18px rgba(168, 76, 0, .45);
  --ust-tor: rgba(26, 26, 26, .2);
  --ust-tor-przebyty: rgba(168, 76, 0, .5);
  --ust-uchwyt-obwodka: rgba(168, 76, 0, .75);
  --ust-uchwyt-tlo: linear-gradient(180deg, #ffffff, #ffe2cc);
  --ust-uchwyt-cien:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 2px 5px -2px rgba(168, 76, 0, .65);
  --ust-pole-obwodka: rgba(26, 26, 26, .22);
  --ust-pole-tlo: linear-gradient(180deg, #ffffff, #f1ede8);
  --ust-pole-cien: inset 0 1px 2px rgba(26, 26, 26, .06);
  --ust-pole-wl-tlo: linear-gradient(160deg, #ff8a1a, #d96200);
  --ust-pole-wl-znak: #ffffff;
  --ust-select-obwodka: rgba(26, 26, 26, .16);
  --ust-select-obwodka-zywa: rgba(168, 76, 0, .4);
  --ust-karta-obwodka: rgba(168, 76, 0, .2);
  --ust-karta-tlo: linear-gradient(180deg, #ffffff, #faf7f4);
  --ust-karta-cien: inset 0 1px 0 rgba(255, 255, 255, .85);
  --ust-zamknij-obwodka: rgba(168, 76, 0, .5);
  --ust-zamknij-tlo: linear-gradient(180deg, #fffcf2, #ffe2cc);
  /* Znacznik pola wyboru mieszka w tokenie, bo barwa kreski siedzi
     wewnatrz adresu danych i nie da sie jej podmienic zmienna. */
  --ust-pole-znak: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M4.4 9.2 7.5 12.3 13.6 5.9' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  --os-kreska: rgba(168, 76, 0, .32);
  --os-kolko-obwodka: rgba(168, 76, 0, .55);
  --os-kolko-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
  --os-kolko-tusz: #ffffff;
  /* Pas zamykający stronę jest brzoskwiniowy — tak stoi w projekcie.
     Ta sama para barw co panele wyróżnione, więc nie dokłada koloru. */
  --stopka-tlo: linear-gradient(180deg, #fff3e8 0%, #ffe2cc 100%);
  --stopka-obwodka: rgba(168, 76, 0, .24);
  --faq-kreska: rgba(26, 26, 26, .09);
  --faq-hover: rgba(168, 76, 0, .05);

  --tor-tlo: rgba(26, 26, 26, .09);
  --tor-wypelnienie: linear-gradient(90deg, #ff8a1a, #ff7a00);
  --tor-najdalej: rgba(168, 76, 0, .55);

  --tabela-pas: #faf7f4;
  --plakietka-tlo: #f1ede8;
  --plakietka-obwodka: rgba(168, 76, 0, .22);

  --uchwyt-spod: #ffffff;

  --promien-karteczka: 11px;
  --promien-karteczka-dol: 11px 11px 16px 11px;
  --promien-karteczka-gora: 11px 16px 11px 11px;
  --promien-platek: 16px;
  --promien-pastylka: 999px;
  --promien-panel: 18px;
  --promien-kafel: 12px;
  --promien-pole: 10px;

  /* Ruch. Klawisz odpowiada natychmiast, panel wjeżdża — różnica jest
     zamierzona: klawisz potwierdza dotknięcie, panel pokazuje, skąd przyszedł. */
  --ruch-klawisz: 120ms ease-out;
  --ruch-panel: 180ms cubic-bezier(.2, .8, .25, 1);
}

/* Deklaracja schematu barw musi być JEDNOZNACZNA tam, gdzie motyw jest
   wymuszony. Przy `light dark` i motywie ciemnym przeglądarka rysowała listę
   rozwijaną `<select>` w wersji jasnej — biały spód — a tekst opcji brał kolor
   z naszego motywu, czyli kremowy. Efekt: rozwinięta lista była nie do
   odczytania. To samo dotyczy pól wyboru i pasków przewijania. */
:root[data-theme='light'] { color-scheme: light; }
:root[data-theme='dark'] { color-scheme: dark; }
:root[data-theme='system'] { color-scheme: light dark; }

/* Motyw ciemny: albo z wyboru użytkownika, albo z ustawienia systemu, gdy
   użytkownik nie wybrał nic konkretnego. Te same tokeny, inne wartości —
   nigdzie poza tymi dwoma blokami barwy się nie rozjeżdżają. */
@media (prefers-color-scheme: dark) {
  :root[data-theme='system'] {
    --bg-cool: #141414;
    --bg-warm: #241c14;
    --surface-cool: #1f1f1f;
    --surface-warm: #2a2118;
    --neutral-200-cool: #2e2e2e;
    --neutral-200-warm: #33291e;
    --neutral-300-cool: #3a3a3a;
    --neutral-300-warm: #443829;

    --color-text: #f3f0ec;
    --color-neutral-400: #4f4f4f;
    --color-neutral-500: #a3a3a3;  /* patrz motyw jasny: 4,5:1 także na tle panelu */
    /* Ta sama rampa, odwrócona: na ciemnym tle jaśniejsze stopnie idą tam,
       gdzie na papierze szły ciemniejsze. Wartości nadal z tej samej rodziny. */
    --color-accent: #ff8a1a;
    --color-accent-300: #c25700;
    --color-accent-400: #e06600;
    --color-accent-700: #ff9433;
    /* Odwrócone: jasny bursztyn pod spodem, ciemny tusz na nim. */
    --klawisz-pelny-tlo: #d96200;
    --klawisz-pelny-tusz: #ffffff;
    --color-divider: color-mix(in srgb, #f3f0ec 18%, transparent);

    --error-ink: #fca5a5;
    --error-bg: #2a1717;
    --error-line: #5b2626;

    /* Jasny tekst na ciemnym tle rozlewa się optycznie: cienkie kreski wydają
       się grubsze, niż są, więc różnica między zwykłym pismem a kotwicą
       kurczy się. Pomiar to potwierdza — ta sama para wag daje na ciemnym
       tle o kilka procent mniej widocznej różnicy niż na papierze.
       Odpowiedzią jest CIEŃSZE pismo zwykłe, nie grubsza kotwica: kotwica
       zostaje dokładnie taka, jaką wybrał użytkownik, a rośnie odstęp
       do reszty wyrazu. Kroje bez tak niskiej wagi (Lora zaczyna się od 400)
       przeglądarka i tak przytnie do swojego minimum. */
    --text-weight: 300;
    /* Zakreślacze w ciemnym motywie: ciemniejsze i mniej nasycone, żeby jasny
       tekst na nich pozostał czytelny. Nie te same barwy przygaszone —
       przygaszona żółć na czarnym tle robi się brudnozielona. */
    --mark-zolty: #4a4223;
    --mark-rozowy: #4a2f38;
    --mark-zielony: #2e4630;
    --mark-niebieski: #2b3c4d;

    /* Papier tablicy o ton niżej — powód przy wartości jasnej. */
    --board-plotno: #efece6;

    /*
     * Chrom tablicy w motywie ciemnym — pastylka paska, klawisze, panel „więcej".
     *
     * Karteczek tu nie ma i to nie jest przeoczenie: płótno zostaje jasne, więc
     * karteczka też. Jej wersja ciemna czeka pod własnymi nazwami w bloku jasnym.
     *
     * Wartości panelu „więcej" są WYPROWADZONE z pastylki — projekt podaje dla
     * niego wyłącznie wersję jasną. To ta sama powierzchnia widziana z bliska.
     */
    /*
 * Biblioteka w motywie ciemnym. Projekt nie zawiera tego ekranu w wersji
 * ciemnej — wartości są WYPROWADZONE z zasad ogólnych: karta o ton jaśniejsza
 * od tła, obwódka z bieli o niskim kryciu, cień głębszy, bo na ciemnym tle
 * rozmycie ginie szybciej.
 */
--karta-tlo: linear-gradient(180deg, #1f1f1f 0%, #171717 100%);
--karta-obwodka: rgba(255, 255, 255, .1);
--karta-cien:
  0 1px 1px rgba(0, 0, 0, .5),
  0 14px 24px -16px rgba(0, 0, 0, .9);
--karta-obwodka-aktywna: rgba(255, 122, 0, .4);
--karta-cien-aktywna: 0 14px 24px -16px rgba(255, 122, 0, .3);

--okladka-tlo: linear-gradient(180deg, #252525 0%, #1c1c1c 100%);
--okladka-kreska: rgba(255, 122, 0, .18);

/* Strona powitalna w motywie ciemnym — wyprowadzone, projekt jej nie ma. */
/* Naglowek czytelni w motywie ciemnym — wyprowadzone, projekt go nie ma. */
--czytelnia-tlo: linear-gradient(180deg, #1f1f1f 0%, #171717 100%);
--czytelnia-cien:
  0 1px 1px rgba(0, 0, 0, .5),
  0 12px 22px -16px rgba(0, 0, 0, .9);
--czytelnia-wlos: rgba(255, 255, 255, .09);
--czytelnia-narzedzie: #e8e4df;
--czytelnia-narzedzie-hover: rgba(255, 122, 0, .1);
--czytelnia-wlaczony-obwodka: rgba(168, 76, 0, .45);
--czytelnia-wlaczony-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
--czytelnia-wlaczony-tekst: #ffffff;
--czytelnia-wlaczony-cien:
  inset 0 1px 0 rgba(255, 255, 255, .08),
  0 3px 6px -4px rgba(0, 0, 0, .8);
--przycisk-zwykly-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--segment-tlo: linear-gradient(180deg, #171717, #131313);
--segment-cien: inset 0 1px 2px rgba(0, 0, 0, .5);

/* Panel ustawien w motywie ciemnym — wyprowadzone, projekt go nie ma. */
--ust-cien: 0 16px 26px -18px rgba(0, 0, 0, .85);
--ust-obwodka-zywa: rgba(255, 122, 0, .26);
--ust-tlo-zywe: linear-gradient(180deg, #242424 0%, #1a1a1a 100%);
--ust-cien-zywy: 0 16px 26px -18px rgba(0, 0, 0, .9);
--ust-tor: rgba(255, 255, 255, .22);
--ust-tor-przebyty: rgba(255, 122, 0, .55);
--ust-uchwyt-obwodka: rgba(255, 122, 0, .7);
--ust-uchwyt-tlo: linear-gradient(180deg, #2e2e2e, #242424);
--ust-uchwyt-cien:
  inset 0 1px 0 rgba(255, 255, 255, .12),
  0 2px 5px -2px rgba(0, 0, 0, .8);
--ust-pole-obwodka: rgba(255, 255, 255, .24);
--ust-pole-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--ust-pole-cien: inset 0 1px 2px rgba(0, 0, 0, .5);
--ust-pole-wl-tlo: linear-gradient(160deg, #ff8a1a, #d96200);
--ust-pole-wl-znak: #ffffff;
--ust-select-obwodka: rgba(255, 255, 255, .16);
--ust-select-obwodka-zywa: rgba(255, 122, 0, .42);
--ust-karta-obwodka: rgba(255, 122, 0, .18);
--ust-karta-tlo: linear-gradient(180deg, #242424, #1c1c1c);
--ust-karta-cien: inset 0 1px 0 rgba(255, 255, 255, .06);
--ust-zamknij-obwodka: rgba(255, 122, 0, .45);
--ust-zamknij-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--ust-pole-znak: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M4.4 9.2 7.5 12.3 13.6 5.9' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

--os-kreska: rgba(255, 122, 0, .28);
--os-kolko-obwodka: rgba(255, 122, 0, .45);
--os-kolko-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
--os-kolko-tusz: #ffffff;
--stopka-tlo: linear-gradient(180deg, #242424 0%, #1a1a1a 100%);
--stopka-obwodka: rgba(255, 122, 0, .22);
--faq-kreska: rgba(255, 255, 255, .09);
--faq-hover: rgba(255, 122, 0, .07);

--tor-tlo: rgba(255, 255, 255, .1);
--tor-wypelnienie: linear-gradient(90deg, #ff8a1a, #c25700);
--tor-najdalej: rgba(255, 122, 0, .55);

--tabela-pas: #1c1c1c;
--plakietka-tlo: #252525;
--plakietka-obwodka: rgba(255, 122, 0, .24);
--uchwyt-spod: #1a1a1a;
--pasek-tlo: linear-gradient(180deg, #252525 0%, #181818 100%);
    --pasek-obwodka: rgba(255, 122, 0, .22);
    --pasek-cien:
      inset 0 1px 0 rgba(255, 255, 255, .07),
      0 16px 28px -16px rgba(0, 0, 0, .95);
    --pasek-separator: rgba(255, 122, 0, .24);

    --klawisz-znak: #e8e4df;
    --klawisz-znak-wylaczony: rgba(232, 228, 223, .35);
    --klawisz-hover-tlo: linear-gradient(170deg,
      rgba(255, 122, 0, .3), rgba(217, 98, 0, .18));
    /* Na ciemnym tle światło u góry klawisza nie ma czego rozjaśnić — biała
       kreska na brązie czyta się jak rysa, nie jak połysk. */
    --klawisz-hover-cien: none;
    --klawisz-aktywny-tlo: linear-gradient(180deg, #ff8a1a 0%, #d96200 100%);
    --klawisz-aktywny-znak: #ffffff;
    --klawisz-aktywny-cien:
      inset 0 1px 0 rgba(255, 255, 255, .35),
      0 4px 10px -3px rgba(0, 0, 0, .8);
    --klawisz-wcisniety-cien: 0 2px 4px -2px rgba(0, 0, 0, .8);

    --papier-pole-tlo: linear-gradient(180deg, #2e2a23, #1c1c1c);
    --papier-pole-obwodka: rgba(255, 122, 0, .28);
    --papier-pole-tekst: #f3f0ec;

    --probka-wybrana-cien:
      0 0 0 2px rgba(255, 122, 0, .85),
      0 3px 7px -2px rgba(0, 0, 0, .8);

    --panel-wiecej-tlo: linear-gradient(180deg, #252525 0%, #181818 100%);
    --panel-wiecej-obwodka: rgba(255, 122, 0, .22);
    --panel-wiecej-cien:
      inset 0 1px 0 rgba(255, 255, 255, .07),
      0 20px 32px -18px rgba(0, 0, 0, .95);
    --panel-hairline: rgba(255, 122, 0, .18);
    --panel-kafel-tlo: linear-gradient(170deg,
      rgba(255, 255, 255, .06), rgba(255, 255, 255, .02));
    --panel-kafel-cien:
      inset 0 1px 0 rgba(255, 255, 255, .08),
      0 4px 8px -6px rgba(0, 0, 0, .8);
  }
}

:root[data-theme='dark'] {
  --bg-cool: #141414;
  --bg-warm: #241c14;
  --surface-cool: #1f1f1f;
  --surface-warm: #2a2118;
  --neutral-200-cool: #2e2e2e;
  --neutral-200-warm: #33291e;
  --neutral-300-cool: #3a3a3a;
  --neutral-300-warm: #443829;

  --color-text: #f3f0ec;
  --color-neutral-400: #4f4f4f;
  --color-neutral-500: #a3a3a3;  /* patrz motyw jasny: 4,5:1 także na tle panelu */
  --color-accent: #ff8a1a;
  --color-accent-300: #c25700;
  --color-accent-400: #e06600;
  --color-accent-700: #ff9433;
  /* Odwrócone: jasny bursztyn pod spodem, ciemny tusz na nim. */
  --klawisz-pelny-tlo: #d96200;
  --klawisz-pelny-tusz: #ffffff;
  --color-divider: color-mix(in srgb, #f3f0ec 18%, transparent);

  --error-ink: #fca5a5;
  --error-bg: #2a1717;
  --error-line: #5b2626;

  /* Powód przy tym samym nadpisaniu w bloku „jak w systemie" wyżej. */
  --text-weight: 300;

  /*
   * Zakreślacze — powód przy tych samych wartościach w bloku „jak w systemie".
   *
   * DLACZEGO TO TU JEST, skoro wygląda na przepisane: bo wcześniej tego tu NIE
   * BYŁO. Cztery barwy stały wyłącznie w bloku systemowym, w dodatku wklejone
   * tam dwa razy, więc kto WYBRAŁ motyw ciemny, dostawał jasnożółte zakreślenie
   * pod jasnym pismem, a kto zostawił „jak w systemie" — poprawione. Pomiar:
   * przy `data-theme='dark'` wszystkie cztery tokeny zwracały wartości jasne.
   *
   * Że te dwa bloki muszą trzymać ten sam komplet nazw, pilnuje teraz
   * `test/check-tokeny.js` — komentarz o tym, że „barwy nigdzie się nie
   * rozjeżdżają", okazał się obietnicą bez pokrycia.
   */
  --mark-zolty: #4a4223;
  --mark-rozowy: #4a2f38;
  --mark-zielony: #2e4630;
  --mark-niebieski: #2b3c4d;

  /* Papier tablicy o ton niżej — powód przy wartości jasnej. */
  --board-plotno: #efece6;

  /*
   * Chrom tablicy w motywie ciemnym — pastylka paska, klawisze, panel „więcej".
   *
   * Karteczek tu nie ma i to nie jest przeoczenie: płótno zostaje jasne, więc
   * karteczka też. Jej wersja ciemna czeka pod własnymi nazwami w bloku jasnym.
   *
   * Wartości panelu „więcej" są WYPROWADZONE z pastylki — projekt podaje dla
   * niego wyłącznie wersję jasną. To ta sama powierzchnia widziana z bliska.
   */
  /*
 * Biblioteka w motywie ciemnym. Projekt nie zawiera tego ekranu w wersji
 * ciemnej — wartości są WYPROWADZONE z zasad ogólnych: karta o ton jaśniejsza
 * od tła, obwódka z bieli o niskim kryciu, cień głębszy, bo na ciemnym tle
 * rozmycie ginie szybciej.
 */
--karta-tlo: linear-gradient(180deg, #1f1f1f 0%, #171717 100%);
--karta-obwodka: rgba(255, 255, 255, .1);
--karta-cien:
  0 1px 1px rgba(0, 0, 0, .5),
  0 14px 24px -16px rgba(0, 0, 0, .9);
--karta-obwodka-aktywna: rgba(255, 122, 0, .4);
--karta-cien-aktywna: 0 14px 24px -16px rgba(255, 122, 0, .3);

--okladka-tlo: linear-gradient(180deg, #252525 0%, #1c1c1c 100%);
--okladka-kreska: rgba(255, 122, 0, .18);

/* Strona powitalna w motywie ciemnym — wyprowadzone, projekt jej nie ma. */
/* Naglowek czytelni w motywie ciemnym — wyprowadzone, projekt go nie ma. */
--czytelnia-tlo: linear-gradient(180deg, #1f1f1f 0%, #171717 100%);
--czytelnia-cien:
  0 1px 1px rgba(0, 0, 0, .5),
  0 12px 22px -16px rgba(0, 0, 0, .9);
--czytelnia-wlos: rgba(255, 255, 255, .09);
--czytelnia-narzedzie: #e8e4df;
--czytelnia-narzedzie-hover: rgba(255, 122, 0, .1);
--czytelnia-wlaczony-obwodka: rgba(168, 76, 0, .45);
--czytelnia-wlaczony-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
--czytelnia-wlaczony-tekst: #ffffff;
--czytelnia-wlaczony-cien:
  inset 0 1px 0 rgba(255, 255, 255, .08),
  0 3px 6px -4px rgba(0, 0, 0, .8);
--przycisk-zwykly-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--segment-tlo: linear-gradient(180deg, #171717, #131313);
--segment-cien: inset 0 1px 2px rgba(0, 0, 0, .5);

/* Panel ustawien w motywie ciemnym — wyprowadzone, projekt go nie ma. */
--ust-cien: 0 16px 26px -18px rgba(0, 0, 0, .85);
--ust-obwodka-zywa: rgba(255, 122, 0, .26);
--ust-tlo-zywe: linear-gradient(180deg, #242424 0%, #1a1a1a 100%);
--ust-cien-zywy: 0 16px 26px -18px rgba(0, 0, 0, .9);
--ust-tor: rgba(255, 255, 255, .22);
--ust-tor-przebyty: rgba(255, 122, 0, .55);
--ust-uchwyt-obwodka: rgba(255, 122, 0, .7);
--ust-uchwyt-tlo: linear-gradient(180deg, #2e2e2e, #242424);
--ust-uchwyt-cien:
  inset 0 1px 0 rgba(255, 255, 255, .12),
  0 2px 5px -2px rgba(0, 0, 0, .8);
--ust-pole-obwodka: rgba(255, 255, 255, .24);
--ust-pole-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--ust-pole-cien: inset 0 1px 2px rgba(0, 0, 0, .5);
--ust-pole-wl-tlo: linear-gradient(160deg, #ff8a1a, #d96200);
--ust-pole-wl-znak: #ffffff;
--ust-select-obwodka: rgba(255, 255, 255, .16);
--ust-select-obwodka-zywa: rgba(255, 122, 0, .42);
--ust-karta-obwodka: rgba(255, 122, 0, .18);
--ust-karta-tlo: linear-gradient(180deg, #242424, #1c1c1c);
--ust-karta-cien: inset 0 1px 0 rgba(255, 255, 255, .06);
--ust-zamknij-obwodka: rgba(255, 122, 0, .45);
--ust-zamknij-tlo: linear-gradient(180deg, #2e2e2e, #1f1f1f);
--ust-pole-znak: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M4.4 9.2 7.5 12.3 13.6 5.9' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

--os-kreska: rgba(255, 122, 0, .28);
--os-kolko-obwodka: rgba(255, 122, 0, .45);
--os-kolko-tlo: linear-gradient(180deg, #ff8a1a, #d96200);
--os-kolko-tusz: #ffffff;
--stopka-tlo: linear-gradient(180deg, #242424 0%, #1a1a1a 100%);
--stopka-obwodka: rgba(255, 122, 0, .22);
--faq-kreska: rgba(255, 255, 255, .09);
--faq-hover: rgba(255, 122, 0, .07);

--tor-tlo: rgba(255, 255, 255, .1);
--tor-wypelnienie: linear-gradient(90deg, #ff8a1a, #c25700);
--tor-najdalej: rgba(255, 122, 0, .55);

--tabela-pas: #1c1c1c;
--plakietka-tlo: #252525;
--plakietka-obwodka: rgba(255, 122, 0, .24);
--uchwyt-spod: #1a1a1a;
--pasek-tlo: linear-gradient(180deg, #252525 0%, #181818 100%);
  --pasek-obwodka: rgba(255, 122, 0, .22);
  --pasek-cien:
    inset 0 1px 0 rgba(255, 255, 255, .07),
    0 16px 28px -16px rgba(0, 0, 0, .95);
  --pasek-separator: rgba(255, 122, 0, .24);

  --klawisz-znak: #e8e4df;
  --klawisz-znak-wylaczony: rgba(232, 228, 223, .35);
  --klawisz-hover-tlo: linear-gradient(170deg,
    rgba(255, 122, 0, .3), rgba(217, 98, 0, .18));
  /* Na ciemnym tle światło u góry klawisza nie ma czego rozjaśnić — biała
     kreska na brązie czyta się jak rysa, nie jak połysk. */
  --klawisz-hover-cien: none;
  --klawisz-aktywny-tlo: linear-gradient(180deg, #ff8a1a 0%, #d96200 100%);
  --klawisz-aktywny-znak: #ffffff;
  --klawisz-aktywny-cien:
    inset 0 1px 0 rgba(255, 255, 255, .35),
    0 4px 10px -3px rgba(0, 0, 0, .8);
  --klawisz-wcisniety-cien: 0 2px 4px -2px rgba(0, 0, 0, .8);

  --papier-pole-tlo: linear-gradient(180deg, #2e2a23, #1c1c1c);
  --papier-pole-obwodka: rgba(255, 122, 0, .28);
  --papier-pole-tekst: #f3f0ec;

  --probka-wybrana-cien:
    0 0 0 2px rgba(255, 122, 0, .85),
    0 3px 7px -2px rgba(0, 0, 0, .8);

  --panel-wiecej-tlo: linear-gradient(180deg, #252525 0%, #181818 100%);
  --panel-wiecej-obwodka: rgba(255, 122, 0, .22);
  --panel-wiecej-cien:
    inset 0 1px 0 rgba(255, 255, 255, .07),
    0 20px 32px -18px rgba(0, 0, 0, .95);
  --panel-hairline: rgba(255, 122, 0, .18);
  --panel-kafel-tlo: linear-gradient(170deg,
    rgba(255, 255, 255, .06), rgba(255, 255, 255, .02));
  --panel-kafel-cien:
    inset 0 1px 0 rgba(255, 255, 255, .08),
    0 4px 8px -6px rgba(0, 0, 0, .8);
}

/* --- Podstawy ----------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* Reguła, bez której połowa interfejsu pokazuje się mimo `hidden`.
   Przeglądarka nadaje ukrytym elementom `display: none` we własnym arkuszu,
   a ten przegrywa z każdą regułą autora — więc `.button { display: inline-flex }`
   odsłaniało przyciski Dysku i eksportu, choć kod ustawiał im `hidden`. */
[hidden] { display: none !important; }

html, body { height: 100%; margin: 0; }

body {
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.55;
  overflow: hidden;
}

:focus { outline: none; }

/* Nigdy domyślny niebieski pierścień — złoto jest tu jedynym kolorem stanu. */
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
input[type='range']:focus-visible { outline-offset: 4px; }

::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* Liczba, która jest liczbą, ma mieć równe cyfry — inaczej licznik stron
   drga przy każdym przewróceniu. W prozie książki tego NIE stosujemy. */
.tnum, .num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum'; }

/*
 * PRÓG CICHEGO PISMA: 65% tuszu na tle strony.
 *
 * Nie jest to liczba dobrana okiem, tylko najniższa, przy której drobne pismo
 * sięga 4,5:1 — progu WCAG AA. Wcześniej stały tu wartości od 42 do 62
 * procent, rozsypane po trzydziestu regułach, i wszystkie dawały od 2,5 do
 * 4,2:1. Napis „Formaty: EPUB · MOBI…" na stronie startowej miał 2,55:1,
 * czyli niewiele ponad połowę wymaganego.
 *
 * Wartości POWYŻEJ 65% zostają takie, jakie były: przechodzą, więc nie ma
 * powodu odbierać im miejsca w hierarchii. Spłaszczamy tylko to, co i tak
 * było nieczytelne.
 */
.muted { color: color-mix(in srgb, var(--color-text) 65%, transparent); }

/* Nadkreślenie sekcji: wersaliki, rozstrzelone, złote. Powtarza się w całym
   interfejsie jako jedyny sposób nazywania grup. */
/*
 * NADTYTUŁY SĄ CICHYM TUSZEM, NIE POMARAŃCZEM — i to jest wniosek z pomiaru,
 * nie zmiana upodobania.
 *
 * Głęboki pomarańcz marki daje na papierze 3,39:1. Wystarcza to pismu
 * pogrubionemu od 14 px i nie wystarcza nadtytułom, które mają 11–12 px.
 * Wyjścia były trzy: powiększyć je, dołożyć czwarty, ciemniejszy pomarańcz
 * albo zdjąć z nich barwę. Pierwsze psuje skalę, drugie mnoży pomarańcze —
 * a właśnie ich mnożenie było usterką, którą to ujednolicenie usuwa.
 *
 * Akcent zostaje tam, gdzie księga go stawia: na kreskach, obrysach, znaku
 * i wypełnieniach. Ikona przy nadtytule dalej jest pomarańczowa, bo jest
 * rysunkiem, a nie pismem.
 */
.kicker {
  font-size: 0.6875rem;
  font-weight: 700;
  /* Odstęp wersalików o jedną trzecią mniejszy niż przy dawnym kroju
     szeryfowym: Atkinson ma szersze litery i ten sam odstęp je rozrywał.
     Ta sama proporcja we wszystkich wersalikach interfejsu. */
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
  font-family: var(--font-body);
}

.rule { height: 1px; border: 0; background: var(--color-divider); margin: 0; }

/* --- Przyciski ---------------------------------------------------------- */

/*
 * PRZYCISKI W 400, a nie w 700 — po próbie obu grubości na zrzutach.
 *
 * Dawne 600 było podkreśleniem w lekkim kroju szeryfowym. W Atkinsonie 700
 * jest wyraźnie ciężkie: pasek czytelni, nagłówek biblioteki i tablicy
 * składały się wtedy z samych pogrubień i tytuł nad nimi przestawał się
 * wyróżniać. Zwykły przycisk jest „resztą", nie podkreśleniem; ten krój jest
 * czytelny w 400 i przy tej wielkości. Pogrubienie zostaje tam, gdzie ma coś
 * znaczyć — w przycisku głównym, niżej.
 */
.button, .link {
  appearance: none;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 0.875rem;
  line-height: 1.2;
  color: var(--color-text);
  cursor: pointer;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: transparent;
  padding: 7px 16px;
  white-space: nowrap;
}

.button svg { display: block; flex: none; }
.button:hover:not(:disabled) { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.button:active:not(:disabled) { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.button:disabled { opacity: 0.45; cursor: not-allowed; }

/*
 * GŁÓWNY: wypukła pomarańczowa plama z BIAŁĄ etykietą.
 *
 * Do zmiany marki obowiązywała tu reguła odwrotna — „akcent jest zawsze
 * kreską, wypełnień w tym systemie nie ma" — i była słuszna przy złocie,
 * które jako plama robiło się tłem, a nie przyciskiem. Lectano rozstrzyga
 * inaczej i rozstrzyga to wprost w przekazaniu projektu: główna czynność
 * panelu ma być wypełniona.
 *
 * Nie zalewa to interfejsu pomarańczem, bo `.primary` jest z założenia
 * JEDYNY w swoim panelu — reszta klawiszy stoi na obrysie albo bez niego.
 * Biel wolno położyć tylko na ciemniejszym z dwóch pomarańczy: na jasnym
 * daje 2,6:1, na `--klawisz-pelny-tlo` — 4,6:1.
 */
.button.primary {
  background-color: var(--klawisz-pelny-tlo);
  background-image: var(--klawisz-pelny-grad);
  border: var(--klawisz-pelny-obwodka);
  box-shadow: var(--klawisz-pelny-swiatlo);
  color: var(--klawisz-pelny-tusz);
}
.button.primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #ff9433 0%, #e56800 100%);
}
.button.primary:active:not(:disabled) {
  background: linear-gradient(180deg, #e06600 0%, #c25700 100%);
  box-shadow: inset 0 2px 4px rgba(120, 54, 0, .4);
}
.button.primary svg { color: inherit; }

/*
 * PRZYCISK PEŁNY: ciemny bursztyn i jasny tusz.
 *
 * Do tej pory najważniejszy przycisk strony był bursztynowy z CIEMNYM tuszem
 * — czytelnie, ale wyglądał jak podświetlony, nie jak przycisk. Jasny tusz
 * wymaga ciemniejszego tła: biel na `--color-accent` daje 3,36:1, czyli pod
 * progiem, a na `--color-accent-700` — 6,5:1. Dlatego zmieniamy JEDNO i drugie
 * naraz; sam jaśniejszy tusz na tym samym tle byłby regresem czytelności
 * podanym jako poprawka wyglądu.
 *
 * Papier zamiast czystej bieli, bo cała aplikacja jest ciepła i biel świeci
 * na niej jak dziura.
 */
.button.pelny {
  background-color: var(--klawisz-pelny-tlo);
  background-image: var(--klawisz-pelny-grad);
  border: var(--klawisz-pelny-obwodka);
  box-shadow: var(--klawisz-pelny-swiatlo);
  color: var(--klawisz-pelny-tusz);
}

.button.pelny:hover:not(:disabled) {
  background: linear-gradient(180deg, #ff9433 0%, #e56800 100%);
}

.button.pelny:active:not(:disabled) {
  background: linear-gradient(180deg, #e06600 0%, #c25700 100%);
  box-shadow: inset 0 2px 4px rgba(120, 54, 0, .4);
}

.button.pelny svg { color: inherit; }

/* Przycisk główny jest podkreśleniem — jedyny w swoim panelu, więc jego
   pogrubienie nie konkuruje z niczym obok. */
.button.primary, .button.pelny { font-weight: 700; }

.button.ghost { border-color: transparent; padding-inline: 10px; }
.button.ghost:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

/*
 * Przycisk włączony — soczewka kotwic.
 *
 * Znak stanu jest tu ważniejszy niż zwykle: po naciśnięciu zmienia się CAŁY
 * tekst na stronie, więc czytelnik musi widzieć w pasku, w którym trybie
 * jest, bez porównywania z pamięcią. Złoto jako obrys, nie jako wypełnienie —
 * tak księga znaku traktuje akcent wszędzie indziej.
 */
.button[aria-pressed='true'] {
  color: var(--color-accent-700);
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.button.ghost[aria-pressed='true'] { border-color: var(--color-accent); }

.button[aria-pressed='true']:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
}

/*
 * Ustawienia kotwic przy zgaszonej soczewce. Nie wyłączamy ich — ruszenie
 * suwaka ma soczewkę włączyć, a wyłączona kontrolka nie da się ruszyć.
 * Przygaszenie mówi „to teraz nie działa", nie „to jest zepsute".
 */
.section.is-dormant .control { opacity: 0.55; }
.dormant-note { display: none; }

.section.is-dormant .dormant-note {
  display: block;
  margin: 0 0 var(--space-3);
  font-style: italic;
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.button.danger:hover:not(:disabled) {
  color: var(--error-ink);
  border-color: color-mix(in srgb, var(--error-ink) 45%, transparent);
  background: color-mix(in srgb, var(--error-ink) 8%, transparent);
}

.button.icon { width: 34px; padding: 0; flex: none; }

.link {
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--color-accent-700);
  text-decoration: underline;
  text-decoration-color: var(--color-accent-300);
  text-underline-offset: 3px;
}

.link:hover { text-decoration-color: var(--color-accent); }

/* --- Pasek górny -------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 0 0 auto;
  padding: 11px max(var(--space-6), env(safe-area-inset-left))
           11px max(var(--space-6), env(safe-area-inset-right));
  border-bottom: 1px solid var(--color-divider);
}

.topbar[hidden] { display: none; }

.brand {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  border: 0;
  background: none;
  padding: 0;
  margin-right: auto;
  cursor: pointer;
  color: inherit;
}

/* Sygnet [L] — wariant na miejsca bez widocznej nazwy. W pasku aplikacji
   i na powitaniu stoi znak podstawowy, czyli `.brand-lockup` niżej. */
.brand-mark { flex: none; display: block; }

/*
 * ZNAK PODSTAWOWY: nawias, nazwa, nawias.
 *
 * Stopień pisma stoi TUTAJ, a nie przy nazwie, i to jest cała mechanika tego
 * zestawu: nawiasy mają wysokość w `em`, więc idą za nazwą przy każdej zmianie
 * rozmiaru — także w regułach dla wąskich ekranów. Wystarczy jedna liczba
 * w jednym miejscu i znak nie ma jak się rozjechać.
 */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  /*
   * Odstępy są RÓŻNE po obu stronach i tak każe księga: z lewej 0,170 H,
   * z prawej 0,145 H, bo po prawej stoi okrągłe „o" i przy równych odstępach
   * wygląda na odsunięte dalej, niż jest. H to wysokość wielkiej litery,
   * czyli około 0,73 stopnia pisma — stąd 0,22 em i 0,19 em.
   */
  gap: 0;
  font-size: 1.75rem;
  line-height: 1;
}

.brand-nawias {
  flex: none;
  display: block;
  height: 1.05em;
  width: auto;
  color: var(--color-accent);
}

.brand-lockup > .brand-nawias:first-child { margin-right: 0.22em; }
.brand-lockup > .brand-nawias:last-child { margin-left: 0.19em; }

.brand-words {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
}

/* Waga 700 jest wymogiem księgi: „logo zawsze wykorzystuje oryginalny
   Atkinson Hyperlegible Bold 700". Stopień dziedziczy z zestawu. */
.brand-name {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1em;
  line-height: 1;
  letter-spacing: -0.015em;
}

.brand-strapline {
  margin-top: 4px;
  font-family: var(--font-body);
  font-size: 0.5rem;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.brand {
  padding: 4px 8px;
  margin-left: -8px;
  border-radius: var(--radius-md);
}

.brand:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

.topbar-actions { display: flex; align-items: center; gap: var(--space-2); }

.lang-switch {
  appearance: none;
  border: 0;
  background: none;
  padding: 6px 4px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.6875rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.lang-switch .on { color: var(--color-text); font-weight: 700; }
.lang-switch:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

.topbar .hair {
  width: 1px;
  height: 18px;
  background: var(--color-divider);
  margin: 0 var(--space-1);
}

/* --- Widoki ------------------------------------------------------------- */

.views { flex: 1 1 auto; min-height: 0; position: relative; }

.view { height: 100%; }
.view[hidden] { display: none; }
.view-scroll { overflow-y: auto; }

/* --- Obok siebie: źródło i tablica naraz -------------------------------- */

/*
 * KIERUNEK PODZIAŁU WYBIERA EKRAN, NIE UŻYTKOWNIK.
 *
 * Ekran wysoki dzieli się w poprzek: źródło na górze, tablica na dole —
 * bo dzielenie wąskiego ekranu wzdłuż dałoby dwie kolumny po sto pięćdziesiąt
 * pikseli, w których nie mieści się ani wiersz tekstu, ani kartka. Ekran
 * szeroki dzieli się wzdłuż: źródło po lewej, tablica po prawej — bo dzielenie
 * go w poprzek zabrałoby stronie wysokość, której w czytaniu brakuje
 * najbardziej.
 *
 * Dlatego nie ma przełącznika „pion/poziom". Byłby to wybór między układem,
 * który się mieści, a takim, który się nie mieści — a taki wybór nie jest
 * wyborem, tylko pułapką.
 */
.views.podzial { display: flex; min-height: 0; }
.views.podzial > .view { flex: 1 1 50%; height: auto; min-width: 0; min-height: 0; }

/*
 * PROPORCJĘ USTAWIA CZYTELNIA, tablica bierze resztę.
 *
 * Jedna liczba zamiast dwóch: gdyby obie połówki miały własną podstawę, przy
 * każdym zaokrągleniu zostawałby albo prześwit, albo piksel nadmiaru — a przy
 * ciągnięciu widać by to było jako drganie krawędzi.
 */
.views.podzial > .view-reader { flex: 0 0 var(--podzial, 50%); }
.views.podzial > .view-board { flex: 1 1 0; }

/*
 * UCHWYT JEST SZERSZY OD KRESKI, KTÓRĄ WIDAĆ.
 *
 * Widać włos, chwyta się siedem pikseli. Kreska szerokości jednego piksela
 * jest celem, w który trudno trafić myszą i praktycznie niemożliwie palcem;
 * pole chwytu musi być większe od tego, co rysujemy, i to jest tu cała
 * sztuczka — reszta to zwykły `flex: 0 0 auto`.
 */
.podzial-uchwyt { display: none; }

.views.podzial > .podzial-uchwyt {
  display: block;
  flex: 0 0 7px;
  align-self: stretch;
  position: relative;
  background: none;
  border: 0;
  padding: 0;
  cursor: row-resize;
  touch-action: none;
}

@media (min-width: 900px) {
  .views.podzial > .podzial-uchwyt { cursor: col-resize; }
}

/* Włos rysuje pseudoelement, żeby pole chwytu zostało niewidoczne. */
.views.podzial > .podzial-uchwyt::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 100%;
  height: 1px;
  background: color-mix(in srgb, var(--color-text) 16%, transparent);
}

@media (min-width: 900px) {
  .views.podzial > .podzial-uchwyt::before { width: 1px; height: 100%; }
}

/* Pod palcem i w trakcie ciągnięcia włos ciemnieje — jedyny sygnał, że to
   jest rzecz do złapania, a nie krawędź układu. */
.views.podzial > .podzial-uchwyt:hover::before,
.views.podzial > .podzial-uchwyt.jest-ciagniety::before {
  background: var(--color-accent);
}

.views.podzial > .podzial-uchwyt:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -1px;
}

/*
 * Krawędź rysuje teraz uchwyt, więc obramowania połówek schodzą — inaczej
 * byłyby dwie kreski obok siebie.
 */
.views.podzial > .view-board { border-top: 0; }

@media (min-width: 900px) {
  .views.podzial > .view-board { border-left: 0; }
}

/* Domyślnie — i na każdym wąskim ekranie — jedno nad drugim. */
.views.podzial { flex-direction: column; }
.views.podzial > .view-board {
  height: auto;
  border-top: 1px solid color-mix(in srgb, var(--color-text) 16%, transparent);
}

@media (min-width: 900px) {
  .views.podzial { flex-direction: row; }
  .views.podzial > .view-board {
    border-top: 0;
    border-left: 1px solid color-mix(in srgb, var(--color-text) 16%, transparent);
  }
}

/*
 * W podziale tablica jest DODATKIEM, więc oddaje wysokość pierwsza: jej pasek
 * narzędzi zwija się do jednego rzędu z przewijaniem w bok, zamiast łamać się
 * na trzy i zjeść połowę swojej własnej połowy ekranu.
 */
.views.podzial .board-tools {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: thin;
}

/*
 * „WIĘCEJ" NIE ODJEŻDŻA Z PASKIEM.
 *
 * Przewijanie w bok zrobiło z klawisza wyjścia awaryjnego rzecz schowaną za
 * przewijaniem: to właśnie w nim leży wszystko, co się w pasku nie zmieściło,
 * a sam wyjeżdżał za prawą krawędź razem z resztą. Trzeba było przewinąć
 * pasek, żeby dowiedzieć się, że jest co przewijać.
 *
 * `sticky` trzyma go przy prawej krawędzi widocznego wycinka. Własne tło jest
 * konieczne, bo narzędzia przejeżdżają POD nim — bez tła widać by było, jak
 * mu się wsuwają pod spód.
 */
.views.podzial .board-menu {
  position: sticky;
  right: 0;
  z-index: 2;
  padding-left: 6px;
  background: linear-gradient(90deg,
    transparent 0, var(--pasek-tlo) 6px, var(--pasek-tlo) 100%);
}

/*
 * LISTA WYCHODZI POZA PASEK, i to jest tu sedno usterki.
 *
 * Pasek jest kotwicą listy (`position: relative`) i jednocześnie — w podziale
 * — pojemnikiem z przewijaniem. A element przewijany w jednej osi przycina
 * też w drugiej: `overflow-y` liczy się wtedy jako `auto`, nie `visible`,
 * choć nikt go tak nie napisał. Lista wisząca POD paskiem lądowała więc poza
 * jego pudełkiem i była obcinana do zera. Menu „nie rozwijało się" —
 * a rozwijało się dokładnie tak jak zawsze, tylko w niewidocznym miejscu.
 *
 * `fixed` wyjmuje ją z tego pudełka. Miejsce liczy skrypt przy otwarciu,
 * bo współrzędne okna nie da się wyprowadzić z samego stylu — patrz
 * `ustawMiejsceMenuPaska` w app.js.
 */
.views.podzial .board-menu-lista {
  position: fixed;
  right: auto;
}

/* Tytuł tablicy i wyjście zostają, ale bez zapasu na tytuł książki. */
.views.podzial .board-head { padding-top: 4px; padding-bottom: 4px; }

/*
 * Na wąskim ekranie GŁOWA TABLICY SCHODZI CAŁKIEM.
 *
 * Zmierzone na telefonie 430×930: tytuł z mikrofonem i trzema przyciskami
 * łamał się na dwa rzędy i zabierał sto pięćdziesiąt z czterystu pięćdziesięciu
 * pikseli tablicy — jedną trzecią jej połowy ekranu na rzeczy, po które
 * sięga się raz na sesję. Zapisanie SVG, PNG i tytuł zostają tam, gdzie mają
 * sens: na pełnej tablicy, o jedno kliknięcie „Tablicy" dalej. Wyjście z
 * podziału nie ginie — stoi w pasku czytnika, tuż nad tablicą.
 */
@media (max-width: 899px) {
  .views.podzial .board-head { display: none; }
}

/*
 * Pasek kontekstowy mierzy się POŁÓWKĄ, a nie oknem.
 *
 * Reguła telefonowa łamie go przy `100vw`, bo tam tablica zajmuje całe okno.
 * W podziale okno jest dwa razy szersze niż tablica, więc ten sam pasek
 * wyjeżdżałby poza jej krawędź — na szerokim ekranie, czyli tam, gdzie nikt
 * by się tego nie spodziewał. Stoi w warstwie sceny, więc sto procent znaczy
 * tu dokładnie tyle, ile tablica ma naprawdę.
 */
.views.podzial .board-kontekst {
  max-width: calc(100% - var(--space-4));
  flex-wrap: wrap;
}

.wrap {
  max-width: 1000px;
  margin: 0 auto;
  padding: 46px var(--space-6) 92px;
}

/* Drobny druk: informacja dla kogoś, kto jej szuka. Ma być ledwo widoczna. */
.fineprint {
  margin: 0;
  padding: 0 0 var(--space-4);
  text-align: center;
  border-bottom: 1px solid var(--color-divider);
  font-size: 0.7188rem;
  line-height: 1.7;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

/* --- Biblioteka: wczytywanie -------------------------------------------- */

.drop {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding: 22px var(--space-6);
  border: 1px dashed var(--color-neutral-400);
  border-radius: var(--radius-md);
  transition: border-color .15s;
}

.drop.is-over { border-color: var(--color-accent); border-style: solid; }
.drop .hint { font-style: italic; font-size: 0.8125rem; color: color-mix(in srgb, var(--color-text) 65%, transparent); }

.drop input[type='file'] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Stan wczytywania — prostokąt nad półką z paskiem postępu. */
.loading {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--color-neutral-200);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}

.loading[hidden] { display: none; }

.loading-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: 0.8125rem;
}

.loading-pct {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--color-accent-700);
  font-variant-numeric: tabular-nums;
}

/* Pasek postępu niesie DWIE liczby: bledsza warstwa to najdalsze miejsce,
   do którego czytelnik dotarł, mocniejsza — miejsce, w którym jest teraz.
   Obie leżą na sobie, więc obie są bezwzględne; bez tego druga zeszłaby pod
   pierwszą i pasek zrobiłby się dwa razy wyższy. */
.track {
  position: relative;
  height: 3px;
  border-radius: var(--promien-pastylka);
  background: var(--tor-tlo);
  margin-top: var(--space-2);
}

.track > span {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  border-radius: var(--promien-pastylka);
  background: var(--tor-wypelnienie);
}

/* Nie własny odcień, tylko ten sam kolor ciszej: zasięg i miejsce bieżące to
   ta sama wielkość mierzona inaczej, a nie dwie różne rzeczy. */
/*
 * Znacznik „najdalej" — kreska, nie wypełnienie.
 *
 * Wcześniej był to ten sam pasek przy trzydziestu setnych krycia, czyli
 * blady cień właściwego. Mówił przez to „przeczytane, ale słabiej", a ma
 * mówić „tu już kiedyś byłeś". Pionowa kreska na końcu zasięgu jest
 * znacznikiem, a nie drugim paskiem.
 */
.track > .zasieg {
  height: 9px;
  top: -3px;
  bottom: auto;
  border-radius: 0;
  background: none;
  border-right: 1.5px solid var(--tor-najdalej);
  opacity: 1;
}

.error {
  margin-top: var(--space-4);
  padding: var(--space-2) var(--space-3);
  font-size: 0.8125rem;
  color: var(--error-ink);
  background: var(--error-bg);
  border: 1px solid var(--error-line);
  border-radius: var(--radius-md);
}

.error[hidden] { display: none; }

/* --- Biblioteka: półka -------------------------------------------------- */

.shelf-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin: var(--space-8) 0 var(--space-4);
}

.shelf-head h2 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 1.875rem;
  margin: 0;
}

.shelf-head .rule { flex: 1; }

.shelf-count {
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  font-variant-numeric: tabular-nums;
}

.books {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* 280, nie 290: przy szerokości okna 1200 px różnica dziesięciu
     pikseli decyduje o tym, czy w rzędzie stoją trzy karty czy dwie. */
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-4);
}

/*
 * KARTA KSIĄŻKI — wyciszona wersja stylistyki tablicy.
 *
 * Kolor pojawia się tu tylko jako akcent i w miniaturach tablic; sama karta
 * jest papierowa. To celowa różnica: na tablicy barwa niesie kategorię,
 * a w bibliotece nie ma czego kategoryzować — są książki, jedna po drugiej.
 */
.book {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--karta-obwodka);
  border-radius: 12px;
  background: var(--karta-tlo);
  box-shadow: var(--karta-cien);
  overflow: hidden;
}

.book:hover { border-color: var(--karta-obwodka-aktywna); }

/*
 * Wskazana książka — cel skrótów E i Delete. Obwódka i cień w bursztynie
 * zamiast obrysu: obrys rysował się POZA kartą i przy sąsiadujących kartach
 * wyglądał, jakby należał do przerwy między nimi.
 */
.book.current {
  border-color: var(--karta-obwodka-aktywna);
  box-shadow: var(--karta-cien-aktywna);
}

/* Okładka jest typograficzna — żadnych obrazków. */
.book-cover {
  padding: var(--space-6) 22px 22px;
  background: var(--okladka-tlo);
  border-bottom: 1px solid var(--okladka-kreska);
  text-align: center;
}

.book-format {
  /* Jedenaście pikseli i odstęp 0,18 em z projektu. */
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.book-title {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 1.5625rem;
  line-height: 1.15;
  text-wrap: balance;
  margin: var(--space-2) 0;
}

.book-dash { width: 34px; height: 1px; background: var(--color-accent); margin: var(--space-3) auto; }

.book-author {
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

/*
 * Stopka przypięta do dołu. Karty w rzędzie i tak mają równą wysokość, bo
 * siatka je rozciąga — ale bez tego przyciski wisiały tuż pod tekstem i rząd
 * kart z tytułami różnej długości miał je na czterech różnych wysokościach.
 */
.book-foot { margin-top: auto; padding: var(--space-3) var(--space-4); }

.book-stats {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  font-variant-numeric: tabular-nums;
}

.book-foot .track { height: 1px; margin: var(--space-2) 0 var(--space-3); }
/*
 * Rząd akcji ZAWIJA. Bez tego przy pięciu przyciskach ostatni był ucięty
 * krawędzią karty — a ucięty przycisk wygląda na usterkę i nie da się go
 * kliknąć w całości. Zawinięty rząd jest wyższy, ale kompletny.
 */
.book-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.book-actions .grow { flex: 1; }

/* --- Biblioteka: pusto i stopka ----------------------------------------- */

.empty {
  padding: 64px var(--space-6);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  text-align: center;
}

.empty[hidden] { display: none; }

.empty strong {
  display: block;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 1.625rem;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

.empty span {
  display: block;
  margin-top: var(--space-2);
  font-style: italic;
  font-size: 0.875rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.library-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-top: var(--space-8);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-divider);
}

/* Podpis autora — ten sam ton co obietnica obok: 12 px, połowa krycia. */
.byline {
  margin: var(--space-3) 0 0;
  text-align: center;
  font-style: italic;
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

/* --- Ślady czytania ------------------------------------------------------ */

.traces-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-6) var(--space-8);
  overflow-y: auto;
}

/* Ostrzeżenie na wierzchu, nie w stopce: dotyczy decyzji, którą czytelnik
   właśnie podejmuje, a nie tego, co już zrobił. */
.traces-warn {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-left: 2px solid var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
  font-size: 0.8125rem;
  line-height: 1.55;
}

.traces-empty { margin: 0; font-style: italic; color: color-mix(in srgb, var(--color-text) 65%, transparent); }

.traces-group { display: flex; flex-direction: column; gap: var(--space-2); }

.traces { list-style: none; margin: 0; padding: 0; }

.trace { border-bottom: 1px solid var(--color-divider); }

.trace label {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  cursor: pointer;
}

.trace-text { font-size: 0.8125rem; line-height: 1.5; }

.traces-toggle { display: flex; align-items: center; gap: var(--space-2); font-size: 0.8125rem; }

/* Wyłączone wyniki zostają widoczne, ale przygaszone — żeby było jasne, że
   są, a nie wychodzą; ukrycie ich wyglądałoby jak brak wyników. */
.traces-group.is-off .traces { opacity: 0.4; pointer-events: none; }

.traces-summary {
  margin: 0;
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.traces-preview {
  margin: 0;
  max-height: 20rem;
  overflow: auto;
  padding: var(--space-3);
  border: 1px solid var(--color-divider);
  background: var(--color-surface);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.75rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.traces-actions { display: flex; gap: var(--space-2); justify-content: flex-end; }

/* --- Okienko na krótki tekst --------------------------------------------- */

.ask-panel {
  position: fixed;
  z-index: 40;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: min(30rem, calc(100vw - 2 * var(--space-5)));
  padding: var(--space-5);
  border: 1px solid var(--color-divider);
  border-radius: 2px;
  background: var(--color-bg);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.28);
}

.ask-panel strong { font-family: var(--font-heading); font-size: 1.1875rem; }

/* Podgląd kopii jest szerszy od okienka na krótki tekst i ma listę, która może
   nie zmieścić się na ekranie — stąd własna szerokość i przewijanie w środku,
   a nie na całej stronie. */
.kopia-panel { width: min(38rem, calc(100vw - 2 * var(--space-5))); }

/*
 * Panel propozycji. Każda karta ma widoczną krawędź i podpis rodzaju, bo to
 * NIE SĄ jeszcze notatki — mają wyglądać na coś, co się rozważa, a nie na
 * coś, co już jest w książce.
 */
.sugestie-panel { width: min(34rem, calc(100vw - 2 * var(--space-5))); }

/* --- powtórki -------------------------------------------------------------- */

.powtorki { margin-bottom: var(--space-6); }

.powtorki-lista { list-style: none; margin: 0; padding: 0; }

.powtorka {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-divider);
}

.powtorka-tresc { margin: 0; flex: 1 1 18rem; min-width: 0; }

/* Zaległość podana jako fakt, nie jako wyrzut: ten sam cichy szary co reszta
   drobnego pisma, bez czerwieni. Lista ma pomagać wrócić, a nie rozliczać. */
.powtorka-zalegla {
  font-size: 0.75rem;
  color: var(--color-neutral-500);
}

.powtorka-oceny {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.powtorka-zrodlo, .powtorka-odloz, .powtorka-usun {
  font-size: 0.8125rem;
  color: var(--color-neutral-500);
}

.powtorka-zrodlo:hover, .powtorka-odloz:hover { color: var(--color-text); }
.powtorka-usun:hover { color: var(--error-ink); }

.sugestie-lista {
  max-height: min(52vh, 26rem);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.sugestia {
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  padding: var(--space-3);
  background: var(--color-surface);
}

.sugestia-rodzaj {
  font-size: 0.6875rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.sugestia-tresc { margin: var(--space-2) 0; }

/* Cytat pod propozycją i cichszy od niej: to jest jej POKRYCIE, nie treść. */
.sugestia-swiadek {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-3);
  border-left: 2px solid var(--color-accent);
  font-size: 0.8125rem;
  color: var(--color-neutral-500);
}

.kopia-lista {
  max-height: min(46vh, 24rem);
  overflow-y: auto;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
}

.kopia-wiersz {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-3) 0;
}

.kopia-wiersz + .kopia-wiersz { border-top: 1px solid var(--color-divider); }
.kopia-wiersz-tytul { font-weight: 700; }

.kopia-wiersz-co {
  font-size: 0.8125rem;
  color: var(--color-neutral-500);
}

/* Wybór przy duplikacie. Stoi w wierszu tej książki, bo decyzja dotyczy jej
   jednej — wspólny przełącznik na górze kazałby rozstrzygać wszystko naraz. */
.kopia-wiersz select {
  font: inherit;
  font-size: 0.8125rem;
  padding: 2px 6px;
  border: 1px solid var(--color-divider);
  border-radius: 2px;
  background: var(--color-surface);
  color: var(--color-text);
}

.kopia-rzad {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-3);
}

.kopia-rzad input[type='file'] { display: none; }

.ask-hint {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.ask-input {
  padding: 10px 12px;
  border: 1px solid var(--color-divider);
  border-radius: 2px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.9375rem;
}

.ask-input:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }

/*
 * Pole na transkrypcję. Wysokie, bo wkleja się do niego tysiąc wierszy, i to
 * jedyna postać okna pytania, w której warto zobaczyć więcej niż to, co się
 * właśnie pisze. Bez zawijania w prawo — wiersz „0:12 tekst" ma być wierszem,
 * a nie akapitem, i po to, żeby dało się jednym rzutem oka sprawdzić, czy
 * znaczniki czasu w ogóle się wkleiły.
 */
.ask-area {
  min-height: 180px;
  max-height: 46vh;
  resize: vertical;
  font-size: 0.875rem;
  line-height: 1.5;
  white-space: pre;
  overflow: auto;
}
.ask-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

/* --- Tagi i wyszukiwanie ------------------------------------------------- */

.search-bar {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.search-input {
  flex: 1;
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid var(--color-divider);
  border-radius: 2px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.9375rem;
}

.search-input:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }

.search-info {
  flex: none;
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.tag-filter { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--space-4); }

/*
 * Tag jako chip. Klikalny wszędzie, gdzie się pojawia — i na karcie książki,
 * i na pasku filtrów — bo tag, którego nie da się użyć do zawężenia, jest
 * tylko napisem.
 */
.tag-chip {
  padding: 3px 10px;
  border: 1px solid var(--color-divider);
  border-radius: 999px;
  background: none;
  color: color-mix(in srgb, var(--color-text) 75%, transparent);
  font-family: var(--font-ui, inherit);
  font-size: 0.75rem;
  cursor: pointer;
}

.tag-chip:hover { border-color: var(--color-accent); color: var(--color-accent-700); }

.tag-chip[aria-pressed='true'] {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  color: var(--color-accent-700);
}

.tag-edit { border-style: dashed; }

.book-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--space-3); }

.results { list-style: none; margin: 0 0 var(--space-6); padding: 0; }

.result { border-bottom: 1px solid var(--color-divider); }

.result-jump {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 100%;
  padding: var(--space-3) var(--space-2);
  border: 0;
  border-left: 3px solid transparent;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.result-jump:hover { background: color-mix(in srgb, var(--color-text) 5%, transparent); }

.result-note.mark-zolty     .result-jump { border-left-color: var(--mark-zolty); }
.result-note.mark-rozowy    .result-jump { border-left-color: var(--mark-rozowy); }
.result-note.mark-zielony   .result-jump { border-left-color: var(--mark-zielony); }
.result-note.mark-niebieski .result-jump { border-left-color: var(--mark-niebieski); }

/* Wynik z tablicy. Ta sama karta co reszta, z jednym znakiem różnicy: kreska
   z boku — w tym samym miejscu, w którym uwaga nosi swoją barwę — mówi, że skok
   prowadzi na płaszczyznę, a nie do książki. Osobny układ kazałby czytać listę
   wyników dwa razy. */
.result-board .result-jump { border-left-color: var(--color-accent); }

.result-where {
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.result-text { font-family: var(--reader-font); font-size: 0.9375rem; line-height: 1.55; }

.result-text mark {
  background: color-mix(in srgb, var(--color-accent) 26%, transparent);
  color: inherit;
  font-weight: 700;
}

/* --- Sprawdzian z luk ---------------------------------------------------- */

/* Szersza szuflada: tu czyta się zdania, a nie klika pozycje listy. */
.quiz-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6) var(--space-8);
  overflow-y: auto;
}

/*
 * Naglowek sekcji: nazwa cwiczenia po lewej, jego liczby po prawej.
 * Zlota wlosowka pod spodem dzieli dwa cwiczenia bez rysowania ramek.
 */
.quiz-sekcja-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2px var(--space-3);
  margin-bottom: var(--space-2);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent);
}

.quiz-sekcja-head h3 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.1875rem;
  font-weight: 700;
  line-height: 1.2;
}

.quiz-sekcja { display: flex; flex-direction: column; gap: var(--space-3); }

/*
 * Wiersz danych, a nie etykieta.
 *
 * Byly tu wersaliki i rozstrzelenie, co jest dobre dla dwoch slow, a zle dla
 * zdania: komunikat „przeczytany fragment jest za krotki na sprawdzian"
 * wychodzil krzykiem i czytalo sie go najgorzej z calej szuflady. Wersaliki
 * pasuja do etykiet, nie do zdan.
 */
/*
 * Siedemdziesiąt procent, nie pięćdziesiąt osiem — poprawka po POMIARZE,
 * nie po oględzinach. Przy 58% ta linia miała w jasnym motywie kontrast
 * poniżej 4,5:1, czyli poniżej progu czytelności dla pisma tej wielkości.
 * Wyglądała delikatnie i była po prostu za jasna.
 */
.quiz-range {
  margin: 0;
  font-size: 0.7812rem;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

/* Komunikat zamiast liczb: pelne zdanie, wiec zwykla szerokosc wiersza. */
.quiz-range.is-uwaga {
  flex-basis: 100%;
  font-size: 0.8438rem;
  line-height: 1.5;
  font-style: italic;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
}

.quiz-text {
  font-family: var(--reader-font);
  font-size: 1.0625rem;
  line-height: 1.7;
}

/*
 * Luka ma zajmować tyle miejsca, ile zajmie odpowiedź — inaczej tekst
 * przeskakuje przy każdym wyborze i czyta się go od nowa.
 */
.luka {
  display: inline-block;
  min-width: 4.5em;
  padding: 0 0.35em;
  border: 0;
  border-bottom: 2px solid var(--color-accent);
  background: none;
  font: inherit;
  color: var(--color-text);
  text-align: center;
  cursor: pointer;
}

.luka:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }

.luka.is-current {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
  border-bottom-width: 3px;
}

.luka.is-wrong {
  color: var(--error-ink);
  border-bottom-color: var(--error-ink);
  text-decoration: line-through;
}

.luka.is-right { border-bottom-color: color-mix(in srgb, var(--color-text) 40%, transparent); }

.luka-poprawka {
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
  font-style: italic;
}

.quiz-ask {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-divider);
}

.quiz-step {
  margin: 0;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.quiz-options { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.quiz-options .button { font-family: var(--reader-font); font-size: 1rem; }

.quiz-result {
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-divider);
}

.quiz-score {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-size: 1.625rem;
  font-weight: 700;
}

.quiz-note {
  margin: 0;
  font-size: 0.8125rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

/* --- Tablica -------------------------------------------------------------- */

/*
 * Kanwa ma KSZTAŁT STRONY i nie jest nieskończona. Znika przez to przesuwanie
 * widoku, minimapa i pytanie „co właściwie wyeksportować z nieskończonej
 * płaszczyzny": wynik ma trafić do PDF-a i pójść dalej, a to znaczy kartkę.
 *
 * Kartka jest BIAŁA także w ciemnym motywie — z tego samego powodu, dla którego
 * biała jest kartka z notatkami. Diagram idzie na papier albo do cudzego
 * programu i ma tam wyglądać tak samo jak tutaj.
 */
.view-board {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
}

.board-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
}

.board-title {
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 6px;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-heading);
  font-size: 1.375rem;
}

.board-title:focus {
  outline: none;
  border-bottom-color: var(--color-accent);
}

.board-tools {
  /*
   * Pasek jest KOTWICĄ dla menu „Więcej" — patrz `.board-menu-lista`. Jego
   * prawa krawędź to zawsze prawa krawędź okna, a krawędź samego przycisku
   * już nie: przy wąskim ekranie pasek łamie się na kilka rzędów i przycisk
   * ląduje gdzieś w środku ostatniego.
   */
  position: relative;
  display: flex;
  /*
   * JEDEN RZĄD — pastylka z definicji, nie z oszczędności miejsca.
   *
   * Zawijanie wróciło było tu na chwilę jako zabezpieczenie na wąskie okno
   * i od razu pokazało, dlaczego nie działa: przy 1280 px zawartość mierzyła
   * 958 px w kontenerze o 960, czyli mieściła się — a mimo to ostatni klawisz
   * spadał do drugiego rzędu, bo zawijanie w kontenerze flex rozstrzyga się
   * na ułamkach piksela. Rząd „prawie pełny" wygląda wtedy jak usterka,
   * i słusznie, bo nią jest.
   *
   * Węższe okna obsłuży ZWIJANIE (warianty 3a i 3b), czyli wypadanie
   * elementów do menu — nie łamanie rzędu. Do tego czasu poniżej progu
   * zostaje zawijanie, żeby na wąskim ekranie nic nie zniknęło za krawędzią.
   */
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px;
  /*
   * `max-content`, nie `fit-content`. To drugie nie doliczało marginesów
   * poziomych separatorów i pastylka zawijała się na trzy rzędy przy oknie,
   * na którym wszystko mieściło się w jednym. Zmierzone przy 1280 px:
   * zawartość potrzebuje 988 px, a fit-content dawało kontenerowi 960.
   */
  width: max-content;
  max-width: 100%;
  margin: var(--space-2) auto;
  padding: 6px;
  border: 1px solid var(--pasek-obwodka);
  border-radius: var(--promien-pastylka);
  background: var(--pasek-tlo);
  box-shadow: var(--pasek-cien);
}

/*
 * Obwódka skupienia z KLAWIATURY, nie z myszy — `:focus-visible`, nie `:focus`.
 * Bursztyn, nie systemowy błękit: niebieski pierścień na ciepłej pastylce jest
 * jedyną zimną rzeczą na całym pasku i widać wyłącznie jego.
 */
.board-tools :focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}


/*
 * Kreska między grupami. Nie `border` sąsiada, bo grupy bywają ukrywane
 * i wtedy zostawałaby krawędź bez niczego po drugiej stronie.
 *
 * Odstęp siedzi w SZEROKOŚCI elementu, a kreska jest rysowana tłem pośrodku —
 * nie w marginesie, choć margines byłby prostszy do napisania. Powód jest
 * zmierzony: szerokość `max-content` kontenera flex NIE DOLICZA marginesów
 * elementów. Trzy separatory po dziesięć pikseli marginesu to trzydzieści
 * pikseli, o które pastylka była za wąska dla własnej zawartości — klawisze
 * ściskały się z trzydziestu czterech pikseli do trzydziestu dwóch, czyli
 * poniżej rozmiaru z projektu, i nie było po czym poznać dlaczego.
 */
.board-sep {
  flex: 0 0 auto;
  width: 11px;
  /* `min-width` obok `width`, bo pusty element o samej szerokosci nie
     wnosi sie do szerokosci samoistnej kontenera: pastylka wychodzila
     o 30 px za waska, czyli dokladnie o trzy separatory. */
  min-width: 11px;
  height: 22px;
  background:
    linear-gradient(var(--pasek-separator), var(--pasek-separator))
    center / 1px 100% no-repeat;
}

/*
 * Nic w pastylce się nie ściska. Klawisz ma trzydzieści cztery piksele
 * z projektu, a nie tyle, ile zostanie — ściśnięty klawisz przestaje być
 * kwadratem i celem dotykowym o zadanym rozmiarze naraz.
 *
 * ŻADEN TEST TEGO DZIŚ NIE PILNUJE i to jest sprawdzone: usunięcie tej reguły
 * nie wywraca niczego, bo przy obecnych progach nie ma szerokości, na której
 * pastylka byłaby ściśnięta — powyżej 1100 px zawartość mieści się z zapasem,
 * poniżej włącza się zawijanie. Reguła jest zabezpieczeniem na ZWIJANIE
 * (warianty 3a i 3b), gdzie miejsca zabraknie naprawdę. Nie kasować jako
 * martwej: zacznie działać razem z tamtym etapem.
 */
.board-tools > * { flex: 0 0 auto; }

/* Osiem, nie dziesięć: przy dziewiętnastu pozycjach dwa piksele z każdej
   strony przycisku to sześćdziesiąt pikseli w pasku — dokładnie tyle, ile
   brakowało, żeby zmieścił się w jednym rzędzie na węższym ekranie. */
.board-tool {
  padding: 5px 8px;
  border: 0;
  border-radius: var(--promien-pastylka);
  background: transparent;
  color: var(--klawisz-znak);
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
  transition: background var(--ruch-klawisz), box-shadow var(--ruch-klawisz);
}

/* Wspólny styl znaków paska: kreska włosowa, bez wypełnień. Zapisany raz,
   przy `use`, a nie przy każdej definicji — inaczej piętnaście rysunków
   niosłoby piętnaście kopii tej samej deklaracji. */
.board-tool-znak svg,
.board-menu-pozycja svg {
  fill: none;
  stroke: currentColor;
  /* Kreska włosowa ZOSTAJE także pod aktywnym klawiszem: o tym, że narzędzie
     jest wybrane, mówi bursztynowe tło, a nie grubsza kreska. */
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Przycisk ze znakiem zamiast napisu — kwadratowy, żeby nie udawał napisu
   o jednej literze. */
.board-tool-znak {
  display: inline-flex;
  width: 34px;
  height: 34px;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.board-tool-znak svg { width: 19px; height: 19px; }

/* Wskaźnik i znak „więcej" są jedynymi wypełnionymi: strzałka kursora
   z samego obrysu czyta się jak chorągiewka, a trzy puste kółka jak zero. */
.board-tool-znak use[href="#t-wskaznik"],
.board-tool-znak use[href="#t-wiecej"] { fill: currentColor; }

.board-tool:hover:not(:disabled):not([aria-pressed="true"]) {
  background: var(--klawisz-hover-tlo);
  box-shadow: var(--klawisz-hover-cien);
}

.board-tool[aria-pressed="true"] {
  background: var(--klawisz-aktywny-tlo);
  color: var(--klawisz-aktywny-znak);
  box-shadow: var(--klawisz-aktywny-cien);
}

/* Wciśnięcie skraca cień: klawisz dosiada do tła, zamiast zmieniać barwę. */
.board-tool[aria-pressed="true"]:active { box-shadow: var(--klawisz-wcisniety-cien); }

/*
 * Wyblakły, nie przezroczysty. `opacity` przygasza CAŁY klawisz razem z jego
 * tłem i cieniem, więc cofnij bez historii wyglądał jak dziura w pastylce.
 * Przygasza się sam znak — klawisz zostaje na swoim miejscu i widać, że jest,
 * tylko nie ma czego cofać.
 */
.board-tool:disabled { color: var(--klawisz-znak-wylaczony); cursor: default; }

/* Łącznik odróżnia graf od malowanki, więc odróżnia się i w pasku. */
/* Łącznik nie jest już wyróżniony barwą. Wyróżnienie miało sens, kiedy pasek
   był listą napisów i jeden z nich trzeba było wskazać jako „ten do łączenia";
   wśród znaków złota ikona wśród szarych czyta się jak WYBRANA, czyli mówi coś
   nieprawdziwego. */

.board-colors {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

/*
 * Próbka barwy. Tło i obrys przychodzą z JS, z palety tablicy — tutaj zostaje
 * sam kształt i sposób pokazania wyboru.
 */
/*
 * Próbka pokazuje BARWĘ Z MODELU, nie z tokenów wyglądu, i to zostaje.
 * Wypełnienie i obrys wstawia JS z tego samego miejsca, z którego bierze je
 * rysowanie i zapis do pliku — próbka ma mówić, co narysuje kliknięcie.
 * Z tokenów przychodzi tylko kształt, rozmiar i cień.
 */
.board-color {
  position: relative;
  width: 21px;
  height: 21px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

/*
 * Kółko rysuje WARSTWA, a nie sam przycisk — bo na telefonie przycisk musi być
 * większy od kółka. Projekt mówi „25 px w polu 44 px": barwna plamka ma zostać
 * drobna, a palec ma trafiać w czterdzieści cztery piksele. Gdyby kółkiem był
 * sam przycisk, jedno wykluczałoby drugie.
 *
 * Barwy przychodzą ze zmiennych ustawianych przy budowaniu paska. Wpisane
 * wprost w styl przycisku biłyby każdą regułę arkusza i nie dałoby się ich
 * przenieść z przycisku na warstwę.
 */
.board-color::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--probka-obrys, currentColor);
  border-radius: var(--promien-pastylka);
  background: var(--probka-tlo, transparent);
  box-shadow: var(--probka-cien-zolty);
  transition: box-shadow var(--ruch-klawisz);
}

/*
 * Wybraną próbkę obwodzimy PIERŚCIENIEM NA ZEWNĄTRZ, a nie grubszym obrysem.
 *
 * Obrys rysuje się do środka i zjada z próbki tyle, ile ma grubości — przy
 * osiemnastu pikselach średnicy widać wtedy głównie obwódkę, a nie barwę,
 * po którą się sięga. Pierścień odsunięty o piksel zostawia próbkę w całości.
 */
/* Wybrana próbka nosi pierścień w akcencie — nie systemowy błękit i nie czerń,
   bo czerń na ciemnej próbce znika, a błękit jest barwą z innej palety. */
.board-color[aria-pressed="true"]::before {
  box-shadow: var(--probka-wybrana-cien);
}

.board-grupa {
  display: inline-flex;
  gap: 3px;
  margin: 0 3px;
  padding-left: 6px;
  border-left: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
}

/*
 * Kanwa wypełnia okno w całości i nie ma już kształtu kartki.
 *
 * Zniknął `aspect-ratio` i zniknęło wyśrodkowanie — płaszczyzna bez brzegów
 * nie ma czego środkować. Zostało `touch-action: none`, i to nie jest ozdoba:
 * bez tego przeglądarka na dotyku przechwytuje przeciąganie na własne
 * przewijanie i połowa gestów nigdy nie dochodzi do edytora.
 */
.board-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: var(--board-plotno, #ffffff);
}

/* Kanwa w trakcie przeciągania pliku — żeby było widać, że upuszczenie
   tutaj coś zrobi. */
.board-stage.is-upuszczanie {
  outline: 2px dashed var(--color-accent);
  outline-offset: -8px;
}

.board-svg {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: default;
}

/*
 * `display: block` wyżej BIJE regułę przeglądarki dla atrybutu `hidden`, więc
 * bez tej linijki schowanie kanwy nic nie robi. Zmierzone: schowana kanwa
 * tablicy nadal miała 639×817, a kanwa marginesu obok niej dostawała zero na
 * zero i nie rysowała niczego — przy czym zapis działał, więc dopisek
 * powstawał i znikał.
 *
 * Ta sama pułapka, co przy kroju pisma: własność podana w regule zawsze wygra
 * z domyślną, choćby ta druga wyglądała na wbudowaną w język.
 */
.board-svg[hidden] { display: none; }

/* Wybór papieru w pasku narzędzi — wygląda jak reszta pól wyboru w tym pasku
   (`.board-preset`), bo robi to samo: wybiera jedną rzecz z krótkiej listy. */
/*
 * Pole papieru. Dwie deklaracje decydują o tym, czy etykieta się złamie:
 * `white-space: nowrap` i `flex: 0 0 auto`. Bez nich pole jako element flexa
 * zwija się PONIŻEJ szerokości własnego tekstu i napis „papier: biały"
 * wychodzi poza pastylkę — zawijanie w kontenerze flex następuje przed
 * ściskaniem, więc skrócenie tekstu wielokropkiem nigdy się nie włącza.
 */
.board-papier {
  flex: 0 0 auto;
  height: 30px;
  /* Bez ograniczenia szerokości lista wyboru z wyłączonym wyglądem systemowym
     rozdyma się do prawie tysiąca pikseli i sama rozpycha pastylkę na trzy
     rzędy. Zmierzone: 946 px przy oknie 1280. */
  /*
   * Szerokosc STALA, nie z tresci. Lista wyboru z wylaczonym wygladem
   * systemowym nie wlicza wciecia do swojej szerokosci samoistnej, wiec
   * kontener liczyl ja o 30 px za waska — dokladnie o miejsce na chevron —
   * i ostatni klawisz wypadal z pastylki. Zmierzone: potrzeba 990 px,
   * szerokosc samoistna dawala 960.
   */
  min-width: 11rem;
  max-width: 11rem;
  padding: 0 30px 0 12px;
  border: 1px solid var(--papier-pole-obwodka);
  border-radius: var(--promien-pastylka);
  color: var(--papier-pole-tekst);
  font: inherit;
  font-size: 0.8125rem;
  white-space: nowrap;
  appearance: none;
  /* Chevron rysujemy sami, bo strzałka listy wyboru wygląda w każdej
     przeglądarce inaczej i w żadnej nie ma trzynastu pikseli. */
  background-image:
    url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb(92,68,19)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E"),
    var(--papier-pole-tlo);
  background-repeat: no-repeat, no-repeat;
  background-position: right 9px center, 0 0;
  background-size: 13px 13px, auto;
}

/* --- siatka ---------------------------------------------------------------- */

/*
 * Siatka jest bardzo cicha i taka ma zostać. Ma odpowiadać na pytanie „czy to
 * stoi równo", a nie brać udziału w rysunku — więc obie gęstości różnią się
 * wyłącznie mocą, nie barwą i nie grubością. Dwie różne barwy linii dają
 * wrażenie kratki w zeszycie i zaczynają konkurować z treścią.
 */
.board-siatka path {
  fill: none;
  stroke: var(--board-siatka);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

.board-siatka-cienka { opacity: 0.055; }
.board-siatka-gruba { opacity: 0.1; }

/* --- zawartość ------------------------------------------------------------- */

.board-ksztalt { cursor: inherit; }

/* Obraz bez bajtów — po wczytaniu uszkodzonego pliku. Lepiej, żeby było widać,
   że coś tu miało być, niż żeby element zniknął bez śladu. */
.board-obraz-brak {
  fill: color-mix(in srgb, #201f1d 6%, transparent);
  stroke: color-mix(in srgb, #201f1d 28%, transparent);
  stroke-width: 1;
  stroke-dasharray: 6 4;
}

/*
 * MIEJSCE PO RYCINIE, KTÓREJ NIE MA — widoczne, ale ciche.
 *
 * Rycina bywa nieobecna z dwóch normalnych powodów: kategoria jeszcze się nie
 * wczytała albo tablica przyszła od kogoś z innym zestawem. Element musi
 * zostać widoczny i chwytny, bo inaczej w diagramie robi się dziura, której
 * nie da się ani skasować, ani przesunąć — a strzałki dochodzą do pustego
 * miejsca bez wyjaśnienia.
 *
 * Ciszej niż brakujący obraz i bez wypełnienia: rycina jest rysunkiem, nie
 * prostokątem, więc szara płachta udawałaby, że coś tam narysowano.
 */
.board-rycina-brak .board-ksztalt {
  fill: none;
  stroke: color-mix(in srgb, #201f1d 30%, transparent);
  stroke-width: 1.5;
}

.board-rycina-brak path {
  stroke: color-mix(in srgb, #201f1d 22%, transparent);
  stroke-width: 1;
}

/* Rycina nie przechwytuje wskaźnika własnymi kreskami — trafianie liczy model
   z pudełka, a setki ścieżek serca w przekroju kradłyby zdarzenia kształtowi,
   do którego należą. */
.board-rycina { pointer-events: none; }

.board-tekst {
  font-family: "Atkinson Hyperlegible", system-ui, sans-serif;
  fill: #1d1c1a;
  pointer-events: none;
  user-select: none;
}

/* Podpis źródła pod cytatem. Odcień ten sam, co w tytule ramki i w pliku SVG:
   trzy miejsca, jeden cichy tusz — różnica odcienia czytałaby się jako
   znacząca, a nie jest. */
.board-zrodlo {
  fill: #6f6960;
}

.board-klodka {
  fill: #1d1c1a;
  stroke: #1d1c1a;
  stroke-width: 0.9;
  opacity: 0.42;
  pointer-events: none;
}

/* --- chrom ----------------------------------------------------------------- */

/*
 * Warstwa chromu leży POZA przemianą kamery, więc wszystkie grubości niżej są
 * w pikselach ekranu i zostają takie same przy każdym powiększeniu. Jest
 * przezroczysta dla wskaźnika w całości: uchwyty są sprawdzane rachunkiem
 * w `edytor.js`, nie trafieniem w kształt, i gdyby łapały zdarzenia same,
 * kliknięcie w uchwyt nie doszłoby do obsługi kanwy.
 */
.board-chrom { pointer-events: none; }

/*
 * Ramka zaznaczenia — PRZERYWANA i w barwie tuszu, nie w akcencie.
 *
 * Akcent zostaje uchwytom. Gdy ramka i uchwyt są tej samej barwy, zaznaczona
 * karteczka czyta się jak jeden złoty prostokąt z guzkami; przerywana kreska
 * w barwie pisma mówi „to jest zaznaczenie", a nie „to jest obrys kształtu".
 */
.board-wybor {
  fill: none;
  stroke: var(--color-text);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
}

/* Obrys pojedynczego kształtu w zaznaczeniu wielu — cieńszy i przygaszony,
   bo główną ramką jest ta wspólna. */
.board-wybor-jeden {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 1;
  opacity: 0.5;
}

.board-wybor-grupa.is-zamkniete .board-wybor {
  stroke: color-mix(in srgb, var(--color-text) 45%, transparent);
  stroke-dasharray: 5 3;
}

/*
 * Uchwyt: biały spód, złoty obrys, delikatny cień.
 *
 * Biały spód, bo uchwyt musi być widoczny i na ciemnym kształcie, i na jasnym
 * papierze — jednolicie złoty ginie na żółtej karteczce, a jednolicie czarny
 * wygląda jak brud na rysunku. Cień odkleja go od zawartości; bez niego
 * uchwyt na obrysie tej samej grubości zlewa się z nim w jedną plamę.
 */
.board-uchwyt {
  fill: var(--uchwyt-spod);
  stroke: var(--color-accent);
  stroke-width: 1.5;
  filter: drop-shadow(0 1px 1.5px rgb(0 0 0 / 0.16));
}

.board-uchwyt-obrot { fill: var(--color-accent); stroke: #ffffff; }

/* Krzyżyk kasujący własny szablon — w rogu karty, widoczny dopiero pod
   wskaźnikiem. Stały byłby czwartym elementem na karcie, która ma pokazywać
   układ, a nie przyciski. */
.board-szablon { position: relative; }

.board-szablon-usun {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  opacity: 0;
  background: color-mix(in srgb, var(--color-surface) 92%, transparent);
  color: var(--color-text);
  font: inherit;
  font-size: 0.875rem;
  line-height: 1;
  cursor: pointer;
  transition: opacity 120ms ease;
}

.board-szablon:hover .board-szablon-usun,
.board-szablon-usun:focus-visible { opacity: 1; }

.board-szablon-usun:hover {
  background: color-mix(in srgb, var(--board-prowadnica) 22%, var(--color-surface));
}

/* Napis wyłącznie dla czytnika ekranu: poza widokiem, ale nie `display: none`
   ani `visibility: hidden` — jedno i drugie usuwa go także z odczytu. */
.tylko-dla-czytnika {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Ognisko na kanwie musi być widoczne — inaczej idąc Tabem po stronie nie
   wiadomo, że się na nią weszło. Obwódka do środka, bo kanwa dotyka krawędzi. */
.board-svg:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

/* --- pisanie na kanwie -------------------------------------------------------
   Pole udaje napis, więc nie ma po sobie zostawić ani ramki, ani tła: widać
   ma być kształt, na którym się pisze. Zostaje sam kursor i zaznaczenie. */
.board-pisanie {
  position: absolute;
  z-index: 5;
  display: flex;
  padding: 6px;
  border: 0;
  margin: 0;
  background: transparent;
  text-align: center;
  resize: none;
  /* Ogólna reguła `textarea` daje sto czterdzieści pikselów najmniejszej
     wysokości — sensownej przy polu w oknie dialogowym, ale nie tutaj. Pole
     na kanwie ma być dokładnie tak wysokie jak kształt, na którym stoi;
     w komórce tabeli wysokiej na trzydzieści punktów tamten spód wystawał
     na cztery wiersze poniżej tabeli. */
  min-height: 0;
  overflow: hidden;
  outline: none;
  /* Napis kształtu jest wyśrodkowany w pionie; `textarea` tego nie umie,
     więc dosuwamy go dopełnieniem liczonym w JS — a tu zostaje sam środek
     w poziomie i brak zawijania na siłę. */
  white-space: pre-wrap;
  word-break: break-word;
}

.board-pisanie::selection {
  background: color-mix(in srgb, var(--color-accent) 45%, transparent);
}

/* --- menu paska --------------------------------------------------------------
   Lista wychodzi spod przycisku i leży NAD kanwą, więc musi mieć własne tło —
   przezroczysta czytałaby się przez rysunek pod spodem. */
.board-menu { display: inline-flex; }

/*
 * Lista wisi pod PASKIEM i trzyma się jego prawej krawędzi — nie krawędzi
 * przycisku, od którego ją otwarto.
 *
 * Pierwsza wersja kotwiczyła ją do przycisku i otwierała w lewo, z rozumowania
 * „«Więcej» stoi na końcu paska, czyli przy prawej krawędzi okna". Zdanie jest
 * prawdziwe dokładnie tak długo, jak długo pasek mieści się w jednym rzędzie.
 * Na telefonie łamie się na trzy, przycisk ląduje w środku ostatniego —
 * i menu o szerokości dwustu pikseli wyjeżdżało dwadzieścia pięć pikseli
 * ZA LEWĄ KRAWĘDŹ EKRANU, ucinając nazwy pozycji. Widać to było dopiero na
 * prawdziwym telefonie.
 *
 * Pasek ma tę własność, której przycisk nie ma: jego prawa krawędź jest prawą
 * krawędzią okna zawsze, bez względu na to, w ilu rzędach się ułożył.
 */
.board-menu-lista {
  position: absolute;
  top: calc(100% + 4px);
  right: var(--space-4);
  z-index: 8;
  display: flex;
  min-width: 168px;
  flex-direction: column;
  padding: 4px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-bg) 97%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow-lg);
}

.board-menu-pozycja {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 0.8125rem;
  text-align: left;
  cursor: pointer;
}

.board-menu-pozycja svg { width: 15px; height: 15px; flex: 0 0 auto; }

.board-menu-pozycja:hover {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
}

/* Otwarty panel wyróżnia swoją pozycję — inaczej menu nie odpowiada na
   pytanie, co jest teraz otwarte, a to pierwsze pytanie po jego rozwinięciu. */
.board-menu-pozycja[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 24%, transparent);
}

/* Kropka przy „Więcej": w środku czeka nierozwiązany komentarz. Nie mówi ile —
   od tego jest pozycja w menu — mówi, że jest po co je otworzyć. */
.board-tool.ma-znak { position: relative; }

.board-tool.ma-znak::after {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--board-prowadnica);
  content: '';
}

/* --- minimapa ----------------------------------------------------------------
   Tło półprzezroczyste: mapa leży NA kanwie i ma pokazywać, co pod nią jest,
   dopóki się na nią nie patrzy. Nieprzezroczysta byłaby dziurą w rysunku. */
.board-mapa-tlo {
  fill: color-mix(in srgb, var(--color-surface) 88%, transparent);
  stroke: color-mix(in srgb, var(--color-text) 14%, transparent);
  stroke-width: 1;
}

/* Pudełka rysujemy przygaszone, bo mapa ma być tłem dla prostokąta widoku,
   a nie drugim rysunkiem konkurującym z pierwszym. */
.board-mapa-ksztalt { opacity: 0.5; }
.board-mapa-ksztalt.is-ramka { opacity: 0.16; }

.board-mapa-widok {
  fill: color-mix(in srgb, var(--color-accent) 16%, transparent);
  stroke: var(--color-accent);
  stroke-width: 1.25;
}

.board-mapa { pointer-events: none; }

/* --- historia wersji ---------------------------------------------------------
   Pasek podglądu stoi na kanwie, u góry: to, co pod nim, NIE jest bieżącym
   stanem tablicy, więc ostrzeżenie musi być tam, gdzie wzrok, a nie w rogu. */
.board-podglad-wersji {
  position: absolute;
  top: var(--space-3);
  left: 50%;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 8px 6px var(--space-3);
  transform: translateX(-50%);
  border: 1px solid color-mix(in srgb, var(--color-accent) 55%, transparent);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.14);
  font-size: 0.8125rem;
}

.board-wersja-odloz {
  width: 100%;
  margin-bottom: var(--space-2);
  padding: 6px 10px;
  border: 1px solid color-mix(in srgb, var(--color-text) 16%, transparent);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 0.7812rem;
  cursor: pointer;
}

.board-wersja-odloz:hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
}

/* Zapis samoczynny nie ma nazwy, więc jego wiersz mówi tylko „skąd się wziął" —
   przygaszony, żeby nazwane punkty rzucały się w oczy pierwsze. */
.board-watek-tresc.is-samoczynna {
  color: var(--color-neutral-500);
  font-style: italic;
}

/* --- naklejki ----------------------------------------------------------------
   Znak nie dziedziczy kroju strony: emoji ma własny krój systemowy, a nadanie
   mu Lory kazałoby przeglądarce najpierw szukać go tam, gdzie go nie ma. */
.board-naklejka {
  user-select: none;
  font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif;
}

.board-naklejki-hint {
  margin: 0 0 var(--space-2);
  color: var(--color-neutral-500);
  font-size: 0.75rem;
  line-height: 1.45;
}

/*
 * Osiem w rzędzie, ale tylko dopóki się mieszczą.
 *
 * Sztywne `repeat(8, 1fr)` znaczyło „zawsze osiem" — a przy powiększonym
 * piśmie z ustawień przeglądarki znak rósł razem z resztą i ósma kolumna
 * wychodziła poza panel. `auto-fit` z minimum liczy to samo, gdy jest miejsce,
 * i samo schodzi do siedmiu albo sześciu, gdy go nie ma.
 */
/* Lista wstawiania danych: przyciski jeden pod drugim, bo mają nazwy, a nie
   obrazki — a nazwa jest tu potrzebna, żeby wiedzieć, co się wstawi. */
.board-dane-lista {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.board-dane-lista .button { justify-content: flex-start; }

.board-dane-zmiana {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-divider);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.board-dane-zmiana h3 {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-neutral-500);
}

/* Para przycisków „dodaj / usuń" w jednym rzędzie: to jedna decyzja
   z dwoma kierunkami, a nie dwie osobne. */
.board-dane-para {
  display: flex;
  gap: var(--space-2);
}

.board-dane-para .button { flex: 1; justify-content: center; }

/* Wybór kroju w pasku kontekstowym. Wąski, bo pasek stoi nad zaznaczeniem
   i każdy zbędny piksel odsuwa resztę od miejsca, w którym jest wzrok. */
/* Komunikat tablicy: nad kanwą, pod paskiem narzędzi, wyśrodkowany.
   Nie zabiera miejsca, gdy milczy, i nie łapie kliknięć, gdy mówi — kanwa
   pod nim ma zostać dostępna. */
.board-komunikat {
  position: absolute;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
  max-width: min(32rem, calc(100% - 2 * var(--space-4)));
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: 0 6px 20px color-mix(in srgb, #000 14%, transparent);
  color: var(--color-text);
  font-size: 0.8125rem;
  line-height: 1.45;
  text-align: center;
  pointer-events: none;
}

.board-komunikat.is-blad {
  border-color: color-mix(in srgb, var(--error-ink) 45%, transparent);
  background: color-mix(in srgb, var(--error-ink) 8%, var(--color-bg));
  color: var(--error-ink);
}

.board-kontekst-kroj {
  max-width: 8.5rem;
  min-height: 0;
  margin: 0;
  padding: 2px 4px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 0.75rem;
}

.board-kontekst-kroj:hover {
  background: color-mix(in srgb, currentColor 12%, transparent);
}

/* „A−" i „A+" — para o równej szerokości, żeby nie skakały przy zmianie. */
.board-kontekst-pismo {
  min-width: 2rem;
  font-variant-numeric: tabular-nums;
}

.board-panel-odpowiedz {
  margin: var(--space-2) 0 0;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--error-ink);
}

/* Siatka kształtów. Ta sama zasada, co przy naklejkach: tyle kolumn, ile się
   mieści, żeby powiększone pismo z ustawień przeglądarki nie wypychało
   ostatniej poza panel. */
.board-ksztalty {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(3rem, 1fr));
  gap: 4px;
}

.board-ksztalt-wybor {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  padding: 5px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
}

.board-ksztalt-wybor svg { width: 100%; height: 100%; }

.board-ksztalt-wybor:hover {
  border-color: color-mix(in srgb, var(--color-text) 18%, transparent);
}

.board-ksztalt-wybor[aria-pressed="true"] {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
}

.board-naklejki {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(2rem, 1fr));
  gap: 2px;
}

.board-naklejka-wybor {
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.board-naklejka-wybor:hover {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
}

.board-naklejka-wybor[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
}

/* --- ryciny ------------------------------------------------------------------
   Panel rycin stoi obok naklejek i wygląda jak on, ale różni się jedną rzeczą:
   naklejka to znak, a rycina to RYSUNEK. Kafelek musi więc być na tyle duży,
   żeby dało się rozpoznać, co przedstawia — przy wielkości naklejki serce
   w przekroju jest plamką. Stąd cztery kolumny zamiast kilkunastu. */
.board-ryciny-kategorie {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 8px;
}

.board-ryciny-kat {
  padding: 3px 9px;
  border: 1px solid color-mix(in srgb, var(--color-text) 16%, transparent);
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}

.board-ryciny-kat:hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
}

.board-ryciny-kat[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 28%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 55%, transparent);
}

/* Wiersz stanu. Mówi „wczytuję", „tego jeszcze nie ma" albo „nie udało się" —
   i jest jedynym miejscem, w którym panel tłumaczy, czemu siatka jest pusta.
   Pusta siatka bez wyjaśnienia czyta się jako zepsuty program. */
.board-ryciny-stan {
  margin: 4px 0 8px;
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--color-text) 62%, transparent);
}

.board-ryciny {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr));
  gap: 4px;
}

.board-rycina-wybor {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}

.board-rycina-wybor svg {
  width: 100%;
  height: 100%;
}

.board-rycina-wybor:hover {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
}

.board-rycina-wybor[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 60%, transparent);
}

/* --- pisaki ------------------------------------------------------------------
   Krążek gumki jest jej kursorem: przy tym narzędziu systemowy wskaźnik jest
   wyłączony, bo strzałka celuje rogiem, a gumka środkiem. */
.board-gumka {
  fill: color-mix(in srgb, var(--color-text) 6%, transparent);
  stroke: var(--color-text);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  pointer-events: none;
}

.board-podglad-slad { pointer-events: none; }

.board-grubosci {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding-left: 4px;
}

.board-grubosc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}

.board-grubosc:hover { background: color-mix(in srgb, var(--color-text) 9%, transparent); }

.board-grubosc[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 24%, transparent);
}

.board-grubosc-kropka {
  display: block;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-text) 78%, transparent);
}

.board-obrot-szypulka {
  stroke: var(--color-accent);
  stroke-width: 1.25;
}

/* --- kadrowanie obrazu -------------------------------------------------------
   Widmo pokazuje CAŁY obraz przygaszony, wycinek leży na nim w pełnej sile.
   Przygaszenie robimy kryciem, nie przykryciem białą płachtą: płachta ma jedną
   barwę, a tablica dwa motywy — w ciemnym rozjaśniałaby to, co miała przyćmić. */
.board-kadr-widmo { opacity: 0.28; }
.board-kadr-wycinek { opacity: 1; }

.board-kadr-zrodlo {
  fill: none;
  stroke: color-mix(in srgb, var(--color-accent) 45%, transparent);
  stroke-width: 1;
  stroke-dasharray: 3 4;
}

.board-kadr-okno {
  fill: none;
  stroke: #ffffff;
  stroke-width: 1;
  /* Biała linia na białym zdjęciu znika, więc pod spodem leży cień —
     tańszy niż druga, ciemna linia rysowana obok. */
  filter: drop-shadow(0 0 1.5px rgb(0 0 0 / 0.55));
}

.board-kadr-trzecia {
  stroke: #ffffff;
  stroke-width: 0.75;
  opacity: 0.55;
}

/* Klamry zamiast kwadratów — powód przy `rysujKadr` w edytorze. */
.board-kadr-klamra {
  fill: none;
  stroke: #ffffff;
  stroke-width: 3.5;
  stroke-linecap: butt;
  filter: drop-shadow(0 0 1.5px rgb(0 0 0 / 0.55));
}

/*
 * Prowadnica jest WŁOSOWA i nieprzerwana. Grubsza zaczyna zasłaniać to, co
 * wyrównuje, a przerywana miga przy ruchu — a linia żyje ułamek sekundy
 * i w tym czasie ma powiedzieć jedno: „stoi w linii z tamtym".
 */
.board-prowadnica {
  stroke: var(--board-prowadnica);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

/*
 * Miarka równego odstępu. Ta sama barwa co prowadnica, bo mówi o tym samym —
 * o ustawieniu, nie o treści — ale z zaczepkami na końcach, żeby dało się ją
 * odróżnić od linii wyrównania bez czytania kontekstu.
 */
.board-odstep line {
  stroke: var(--board-prowadnica);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

/*
 * Trafienia wyszukiwania. Wszystkie przygaszone, bieżące pełną mocą — żeby
 * jednym spojrzeniem dało się poznać, czy szukane leży w jednym rogu, czy jest
 * rozsiane po całym diagramie.
 *
 * Barwa ta sama, co prowadnice: to znów informacja o rysunku, a nie jego
 * część. Złoto odpada z tego samego powodu, co tam — obrys kształtu jest
 * złoty, więc złote podświetlenie zlewa się z nim.
 */
.board-trafienie {
  fill: color-mix(in srgb, var(--board-prowadnica) 12%, transparent);
  stroke: var(--board-prowadnica);
  stroke-width: 1.25;
  opacity: 0.45;
}

.board-trafienie-biezace {
  fill: color-mix(in srgb, var(--board-prowadnica) 20%, transparent);
  stroke-width: 2;
  opacity: 1;
}

/* Podświetlenie kształtu, w który celuje łącznik — zanim ręka puści przycisk. */
.board-cel {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2;
  opacity: 0.75;
}

.board-podglad {
  fill: color-mix(in srgb, var(--color-accent) 8%, transparent);
  stroke: var(--color-accent);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

/*
 * Ramka zaznaczania ma WYPEŁNIENIE, w odróżnieniu od podglądu nowego kształtu.
 * Musi być widać, co obejmuje, a sama kreska tego nie pokazuje, kiedy w środku
 * jest kilkanaście kształtów. Kreska ciągła, nie przerywana: ramka wyboru żyje
 * ułamek sekundy i przerywana linia zdąży w tym czasie tylko zamigotać.
 */
.board-ramka-wyboru {
  fill: color-mix(in srgb, var(--color-accent) 10%, transparent);
  stroke: var(--color-accent);
  stroke-width: 1;
}

.board-podglad-linia {
  stroke: var(--color-accent);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  fill: none;
}

/* --- sterowanie widokiem ---------------------------------------------------- */

.board-widok {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  backdrop-filter: blur(6px);
  box-shadow: 0 2px 10px rgb(0 0 0 / 0.08);
}

.board-widok-krok,
.board-widok-miara {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 80%, transparent);
  font: inherit;
  cursor: pointer;
}

.board-widok-krok { width: 26px; }

.board-widok-krok svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
}

/*
 * Miara ma STAŁĄ SZEROKOŚĆ i cyfry o równej szerokości.
 *
 * Bez tego pasek drga przy każdym ruchu kółka: „100%" jest szersze od „75%",
 * więc przyciski obok przesuwają się pod kursorem w trakcie przybliżania —
 * i trafienie w „przybliż" dwa razy z rzędu przestaje być pewne.
 */
.board-widok-miara {
  min-width: 52px;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.board-widok-krok:hover,
.board-widok-miara:hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
  color: var(--color-text);
}

.board-widok-krok:disabled {
  opacity: 0.3;
  cursor: default;
  background: transparent;
}

.board-widok-kreska {
  width: 1px;
  height: 16px;
  margin: 0 2px;
  background: color-mix(in srgb, var(--color-text) 14%, transparent);
}

/* --- pasek kontekstowy ------------------------------------------------------ */

/*
 * Stoi NAD zaznaczeniem, a nie w górnym pasku, i to jest cała jego racja bytu:
 * działania dotyczące zaznaczenia były w pasku narzędzi martwe przez większość
 * czasu, a mimo to zajmowały miejsce — przez nie reszta narzędzi zawijała się
 * do drugiego rzędu na zwykłym laptopie.
 *
 * Położenie ustawia JS, bo bierze się z tego, gdzie akurat leży zaznaczenie.
 * Tutaj zostaje sam wygląd.
 */
.board-kontekst {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 3px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-bg) 95%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: 0 3px 14px rgb(0 0 0 / 0.14);
  white-space: nowrap;
}

.board-kontekst-akcja {
  padding: 4px 9px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
  font: inherit;
  font-size: 0.7812rem;
  cursor: pointer;
}

.board-kontekst-akcja:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  color: var(--color-text);
}

.board-kontekst-akcja[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 22%, transparent);
  color: var(--color-text);
}

.board-kontekst-akcja:disabled { opacity: 0.35; cursor: default; }

/* Jedna akcja w pasku bywa tą, którą się kończy — „Gotowe" przy kadrowaniu.
   Wyróżniona, bo obok stoi cofnięcie kadru i pomyłka między nimi kosztuje
   całą przed chwilą ustawioną ramkę. */
.board-kontekst-akcja.is-glowna {
  background: color-mix(in srgb, var(--color-accent) 26%, transparent);
  color: var(--color-text);
}

.board-kontekst-akcja.is-glowna:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-accent) 38%, transparent);
}

.board-kontekst-wyrownania {
  display: inline-flex;
  align-items: center;
  gap: 1px;
}

.board-kontekst-ikona {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
  cursor: pointer;
}

.board-kontekst-ikona svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.board-kontekst-ikona:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  color: var(--color-text);
}

.board-kontekst-ikona:disabled { opacity: 0.3; cursor: default; }

.board-kontekst-kreska {
  width: 1px;
  height: 15px;
  margin: 0 3px;
  background: color-mix(in srgb, var(--color-text) 14%, transparent);
}

/* --- ramki ------------------------------------------------------------------ */

/*
 * Strona na płaszczyźnie: biały spód i cienki obrys.
 *
 * Biel jest tu po to, żeby kartkę było widać jako kartkę — inaczej zlewa się
 * z płótnem i zostaje z niej sama ramka z drutu. Obrys jest przygaszony
 * z rozmysłu: strona ma być tłem dla treści, a nie kolejnym prostokątem
 * konkurującym z narysowanymi.
 */
.board-ramka-pole {
  fill: #ffffff;
  stroke: color-mix(in srgb, #201f1d 22%, transparent);
  stroke-width: 1;
}

.board-ramka-podpis {
  font-family: var(--font-heading);
  fill: color-mix(in srgb, #201f1d 55%, transparent);
  pointer-events: none;
  user-select: none;
}

/* --- panel stron ------------------------------------------------------------ */

.board-panel {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  bottom: calc(var(--space-3) + 44px);
  display: flex;
  flex-direction: column;
  width: 264px;
  max-width: calc(100% - var(--space-4) * 2);
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-bg) 96%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.board-panel-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
}

.board-panel-head h2 {
  flex: 1 1 auto;
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.125rem;
  font-weight: 700;
}

.board-panel-zamknij {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
  cursor: pointer;
}

.board-panel-zamknij svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
}

.board-panel-zamknij:hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
  color: var(--color-text);
}

.board-pages {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: var(--space-2);
  overflow-y: auto;
  list-style: none;
}

.board-pages-pusto {
  margin: 0;
  padding: var(--space-3);
  color: var(--color-neutral-500);
  font-size: 0.8125rem;
  font-style: italic;
}

.board-strona {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 5px 6px;
  border-radius: var(--radius-md);
  cursor: pointer;
}

.board-strona:hover { background: color-mix(in srgb, var(--color-text) 6%, transparent); }

.board-strona.is-biezaca {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
}

/*
 * Numer w prezentacji, nie numer w liście elementów. Cyfry o równej szerokości,
 * żeby nazwy stron zaczynały się w jednej kolumnie także przy dwucyfrowych.
 */
.board-strona-nr {
  flex: 0 0 auto;
  min-width: 18px;
  color: var(--color-neutral-500);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.board-strona-nazwa {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: 0.8125rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.board-strona-akcje {
  display: flex;
  flex: 0 0 auto;
  gap: 1px;
  opacity: 0;
}

/* Przyciski kolejności odsłaniają się na najechaniu i na ognisku — inaczej
   przy dziesięciu stronach lista jest ścianą ikon. Ognisko musi je pokazywać,
   bo bez tego nie da się ich znaleźć klawiaturą. */
.board-strona:hover .board-strona-akcje,
.board-strona:focus-within .board-strona-akcje { opacity: 1; }

.board-strona-akcja {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.board-strona-akcja:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-text) 10%, transparent);
  color: var(--color-text);
}

.board-strona-akcja:disabled { opacity: 0.25; cursor: default; }

.board-strona-akcja svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- szukanie na tablicy ------------------------------------------------------ */

/*
 * U góry kanwy i na środku, jak pasek szukania w przeglądarce — bo to samo
 * robi i tak samo się go zamyka. W panelu z boku zabierałby miejsce na stałe
 * za czynność, która trwa kilka sekund.
 */
.board-szukanie {
  position: absolute;
  top: var(--space-3);
  left: 50%;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 5px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-bg) 94%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: 0 3px 14px rgb(0 0 0 / 0.12);
  transform: translateX(-50%);
  /*
   * Pasek stoi na środku kanwy i ma stałą zawartość: pole, licznik i trzy
   * przyciski — razem 380 pikseli. Wyśrodkowany w oknie o szerokości
   * trzystu dwudziestu wychodził trzydzieści pikseli ZA LEWĄ KRAWĘDŹ, razem
   * z połową pola do wpisywania. Ta sama ostrożność, co przy pasku
   * kontekstowym: szerokość okna jest granicą, nie sugestią.
   */
  max-width: calc(100vw - var(--space-3) * 2);
}

/*
 * Pole ustępuje jako jedyne — licznik i przyciski nie mają jak. Bez
 * `min-width: 0` element formularza nie kurczy się poniżej swojej naturalnej
 * szerokości, choćby cały pasek już się nie mieścił.
 */
.board-szukanie .board-szukaj-pole {
  flex: 0 1 208px;
  min-width: 0;
  width: 208px;
}

/* Cyfry o równej szerokości: licznik zmienia się przy każdym trafieniu,
   a skacząca szerokość przesuwałaby przyciski pod kursorem. */
.board-szukanie-licznik {
  min-width: 62px;
  padding: 0 4px;
  color: var(--color-neutral-500);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* --- przeglądarka szablonów --------------------------------------------------- */

/* Szersza od pozostałych paneli, bo szablon wybiera się okiem, nie z nazwy. */
.board-panel-szeroki { width: 340px; }

.board-szablony-szukaj {
  padding: var(--space-2) var(--space-3) 0;
}

.board-szukaj-pole {
  width: 100%;
  padding: 5px 8px;
  border: 1px solid color-mix(in srgb, var(--color-text) 18%, transparent);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 0.8125rem;
}

.board-szukaj-pole:focus {
  outline: none;
  border-color: var(--color-accent);
}

.board-kategorie {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  padding: var(--space-2) var(--space-3);
}

.board-kategoria {
  padding: 3px 9px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.board-kategoria:hover { background: color-mix(in srgb, var(--color-text) 8%, transparent); }

.board-kategoria[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 22%, transparent);
  color: var(--color-text);
}

.board-szablony {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 0 var(--space-3) var(--space-3);
  overflow-y: auto;
  list-style: none;
}

.board-szablon { margin-bottom: var(--space-2); }

.board-szablon-przycisk {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}

.board-szablon-przycisk:hover {
  border-color: var(--color-accent);
}

/*
 * Podgląd na białym, bo to podgląd PLIKU, a nie kawałka aplikacji. Stała
 * proporcja, żeby karty stały równo niezależnie od tego, czy szablon jest
 * szeroki, czy wysoki — resztę załatwia `preserveAspectRatio` w samym SVG.
 */
.board-szablon-podglad {
  aspect-ratio: 16 / 9;
  background: #ffffff;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
}

.board-szablon-podglad svg { display: block; width: 100%; height: 100%; }

.board-szablon-nazwa {
  display: block;
  padding: 6px var(--space-2);
  font-size: 0.8125rem;
}

/* --- komentarze --------------------------------------------------------------- */

/*
 * Znacznik wątku. Barwa prowadnicy, bo to znów rzecz O rysunku, a nie jego
 * część — i z tego samego powodu nie złota: złoty krążek na złotym obrysie
 * kształtu zlewa się dokładnie tam, gdzie ma być widoczny.
 */
.board-watek circle {
  fill: var(--board-prowadnica);
  stroke: #ffffff;
  stroke-width: 1.5;
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.2));
}

.board-watek text {
  fill: #ffffff;
  font-family: var(--font-body);
  font-size: 0.6875rem;
  user-select: none;
}

/* Rozwiązany blednie, ale nie znika — po to jest przełącznik na liście. */
.board-watek.is-rozwiazany { opacity: 0.4; }

.board-watek.is-otwarty circle {
  stroke: var(--color-text);
  stroke-width: 2;
}

.board-przelacznik {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  color: var(--color-neutral-500);
  font-size: 0.75rem;
  cursor: pointer;
}

.board-watki {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 0 var(--space-2) var(--space-2);
  overflow-y: auto;
  list-style: none;
}

.board-watek-wpis {
  margin-bottom: var(--space-2);
  padding: var(--space-2);
  border: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.board-watek-wpis:hover {
  border-color: color-mix(in srgb, var(--color-text) 24%, transparent);
}

.board-watek-wpis.is-otwarty { border-color: var(--board-prowadnica); }
.board-watek-wpis.is-rozwiazany .board-watek-tresc { opacity: 0.5; }

.board-watek-glowa { margin-bottom: 2px; }

.board-watek-gdzie {
  color: var(--color-neutral-500);
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
  text-transform: lowercase;
}

.board-watek-tresc {
  margin: 0 0 var(--space-1);
  font-size: 0.8125rem;
  line-height: 1.45;
}

/* Odpowiedź wcięta i z kreską — żeby było widać, że to ciąg dalszy, a nie
   druga uwaga. */
.board-watek-odpowiedz {
  margin: 0 0 var(--space-1);
  padding-left: var(--space-2);
  border-left: 2px solid color-mix(in srgb, var(--color-text) 14%, transparent);
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
  font-size: 0.7812rem;
  line-height: 1.45;
}

/* Wiersz akcji zawija się w całości, a napisy w przyciskach nigdy — inaczej
   „Usuń wątek” łamie się na dwie linijki i przycisk robi się dwa razy wyższy
   od sąsiednich. Lepiej przenieść cały przycisk niżej, niż połamać napis. */
.board-watek-akcje {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-1);
}

/* Kasowanie odsunięte na prawo: dwa pierwsze przyciski prowadzą rozmowę
   dalej, trzeci ją kończy — i lepiej, żeby nie stał tuż obok nich. */
.board-watek-akcje .board-watek-akcja:last-child { margin-left: auto; }

.board-watek-akcja {
  flex: 0 0 auto;
  white-space: nowrap;
  padding: 2px 7px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 68%, transparent);
  font: inherit;
  font-size: 0.75rem;
  cursor: pointer;
}

.board-watek-akcja:hover {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  color: var(--color-text);
}

/* --- panel warstw ------------------------------------------------------------ */

.board-warstwy {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: var(--space-2);
  overflow-y: auto;
  list-style: none;
}

.board-warstwa {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 6px;
  border-radius: var(--radius-md);
  cursor: pointer;
}

.board-warstwa:hover { background: color-mix(in srgb, var(--color-text) 6%, transparent); }

.board-warstwa.is-wybrana {
  background: color-mix(in srgb, var(--color-accent) 20%, transparent);
}

/* Zawartość strony wcięta pod nią — bo tam właśnie leży. */
.board-warstwa.is-dziecko { padding-left: var(--space-4); }

/*
 * Ukryta warstwa przygaszona, ale nie skreślona: ma dalej dać się przeczytać
 * i kliknąć, bo z tej listy się ją odkrywa. Skreślenie sugerowałoby, że jest
 * skasowana — a jest tylko schowana.
 */
.board-warstwa.is-ukryta .board-warstwa-nazwa { opacity: 0.42; }

.board-warstwa-nazwa {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: 0.8125rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.board-warstwa-akcje {
  display: flex;
  flex: 0 0 auto;
  gap: 1px;
  opacity: 0;
}

.board-warstwa:hover .board-warstwa-akcje,
.board-warstwa:focus-within .board-warstwa-akcje { opacity: 1; }

/*
 * Wciśnięty stan — oko przekreślone i zamknięta kłódka — zostaje widoczny
 * zawsze. To nie jest działanie do wykonania, tylko informacja o tym, co już
 * jest, więc chowanie go do najechania ukrywałoby stan dokumentu.
 */
.board-warstwa .board-strona-akcja.is-wlaczona {
  opacity: 1;
  color: var(--color-accent-700);
}

.board-warstwa:not(:hover) .board-warstwa-akcje:has(.is-wlaczona) { opacity: 1; }

.board-warstwa:not(:hover) .board-warstwa-akcje .board-strona-akcja:not(.is-wlaczona) {
  opacity: 0;
}

.board-panel-stopka {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-3);
  border-top: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
}

.board-panel-stopka .button {
  flex: 1 1 0;
  justify-content: center;
  padding-inline: var(--space-2);
  text-align: center;
}

/* --- prezentacja ------------------------------------------------------------ */

/*
 * Pasek prezentacji stoi u dołu na środku i GAŚNIE, dopóki nikt go nie
 * potrzebuje. Slajd ma zajmować ekran, a nie dzielić go ze sterowaniem —
 * ale sterowanie musi być pod ręką w chwili, gdy ręka po nie sięgnie, więc
 * wraca przy najechaniu i przy ognisku klawiatury.
 */
.board-prezenter {
  position: absolute;
  bottom: var(--space-4);
  left: 50%;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: 5px 6px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: 0 3px 14px rgb(0 0 0 / 0.12);
  opacity: 0.25;
  transform: translateX(-50%);
  transition: opacity 160ms ease;
}

.board-prezenter:hover,
.board-prezenter:focus-within { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .board-prezenter { transition: none; }
}

.board-prezenter-krok {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 80%, transparent);
  cursor: pointer;
}

.board-prezenter-krok svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.board-prezenter-krok:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  color: var(--color-text);
}

.board-prezenter-krok:disabled { opacity: 0.3; cursor: default; }

.board-prezenter-licznik {
  min-width: 54px;
  color: var(--color-text);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.board-prezenter-koniec {
  margin-left: 2px;
  padding: 5px 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 80%, transparent);
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}

.board-prezenter-koniec:hover {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  color: var(--color-text);
}

/*
 * W prezentacji znika wszystko poza kanwą i paskiem. Ukrywamy to klasą na
 * widoku, a nie atrybutem na każdym elemencie z osobna: wyjście z prezentacji
 * ma przywrócić dokładnie to, co było, a jedna klasa nie ma jak zapomnieć
 * o którymś przycisku.
 */
.view-board.is-prezentacja .board-head,
.view-board.is-prezentacja .board-tools,
.view-board.is-prezentacja .board-widok,
.view-board.is-prezentacja .board-panel { display: none; }

.view-board.is-prezentacja .board-stage { padding: 0; }

.board-preset {
  max-width: 132px;
  margin-left: 3px;
  padding: 4px 6px;
  border: 1px solid color-mix(in srgb, var(--color-text) 18%, transparent);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 0.75rem;
}

/* --- półka tablic --------------------------------------------------------- */

.shelf-boards { margin-top: var(--space-6, 28px); }

.boards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-4);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.boards-empty {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 0.875rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.board-card {
  display: flex;
  flex-direction: column;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
}

/*
 * Miniatura to ten sam SVG, który idzie do pliku. Wysokość liczona proporcją
 * strony, żeby podgląd nie kłamał o kształcie kartki.
 */
/*
 * Miniatura ma proporcje 4:3, a nie kartki.
 *
 * Dopóki kanwa BYŁA kartką, wysoki kadr pokazywał całą tablicę co do piksela.
 * Teraz kadr pliku bierze się z zawartości, a diagramy wychodzą przeważnie
 * szersze niż wyższe — w kadrze kartki taki rysunek kurczy się do paska
 * pośrodku, z dwoma pustymi polami nad i pod. 4:3 jest na tyle neutralne, że
 * ani szeroki schemat, ani wysoka lista kroków nie zostaje z połową karty
 * pustej.
 *
 * Białe tło musi zostać białe: to spód PLIKU, który wychodzi z eksportu, więc
 * pasy dopełniające kadr mają się z nim zlewać, a nie obrysowywać rysunek
 * prostokątem w innej barwie.
 */
.board-thumb {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #ffffff;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
}

.board-thumb svg { display: block; width: 100%; height: 100%; }

.board-meta { padding: var(--space-2) var(--space-3) var(--space-3); }

.board-meta h3 {
  margin: 0 0 2px;
  font-family: var(--font-heading);
  font-size: 1.0625rem;
  font-weight: 700;
}

.board-sub {
  margin: 0 0 var(--space-2);
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.board-actions { display: flex; gap: 6px; }

/* --- tablica na telefonie i tablecie -----------------------------------------
 *
 * Trzy rzeczy zmieniają się na wąskim ekranie, każda z innego powodu.
 *
 * 1. Przyciski rosną do czterdziestu czterech pikseli. To nie estetyka, tylko
 *    miara palca: poniżej tego rozmiaru trafienie w cel przestaje być pewne
 *    i zaczyna się celowanie, a przy narzędziu rysującym pomyłka kosztuje
 *    kreskę na tablicy.
 *
 * 2. Panel zajmuje CAŁĄ szerokość. Przy dwustu sześćdziesięciu czterech
 *    pikselach na ekranie o trzystu siedemdziesięciu pięciu zostaje pasek
 *    kanwy tak wąski, że nie widać w nim nic — a panel i tak zasłania resztę.
 *    Skoro zasłania, niech zasłania w całości i da się czytać.
 *
 * 3. Pasek może się złamać na dwa rzędy i nie chowamy niczego, żeby tego
 *    uniknąć. Każdy z tych przycisków jest jedyną drogą do tego, co robi —
 *    ta sama zasada, którą kieruje się pasek czytnika.
 */
@media (max-width: 640px) {
  /*
   * Nagłówek łamie się na dwa rzędy: tytuł u góry na całej szerokości,
   * przyciski pod nim.
   *
   * W jednym rzędzie tytuł jest tym, co ustępuje — bo jako jedyny ma
   * `flex: 1 1 auto`. Przy trzystu dwudziestu pikselach zostawało mu
   * dwadzieścia dziewięć: pole, w którym nie widać ani nazwy tablicy, ani
   * tego, że w ogóle da się ją wpisać. Przyciski nie mają jak ustąpić i nie
   * powinny — każdy z nich jest jedyną drogą do tego, co robi.
   */
  .board-head {
    padding: var(--space-2);
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-2);
  }

  .board-head .board-title { flex: 1 1 100%; font-size: 1.1875rem; }
  /*
   * Rząd przycisków też się łamie. Przy powiększonym piśmie z ustawień
   * przeglądarki trzy podpisy w jednym rzędzie mają czterysta pikseli
   * i wychodziły poza okno — a to jedyne miejsce w nagłówku, które ma jeszcze
   * dokąd ustąpić.
   */
  .board-head .topbar-actions {
    flex: 1 1 100%;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  /*
   * Rozmiarów paska tu NIE MA — ustala je poziom zwinięcia (3a i 3b niżej).
   * Stały tutaj wcześniej i wygrywały z poziomami przez samą kolejność
   * w pliku, więc telefon dostawał klawisze czterdziestopikselowe zamiast
   * czterdziestoczteropikselowych z projektu, a paleta nie zwijała się wcale.
   */
  .board-tool { padding: 5px 8px; font-size: 0.75rem; }

  .board-panel {
    left: var(--space-3);
    width: auto;
  }

  /* Pozycja menu też jest celem dla palca — a menu otwiera się na kanwie,
     więc pomyłka w nim otwiera nie ten panel, co trzeba. */
  .board-menu-pozycja { padding: 10px; font-size: 0.875rem; }
  /* Odstęp od krawędzi ten sam, co boczne dopełnienie paska niżej. */
  .board-menu-lista { min-width: 200px; right: var(--space-2); }

  /* Sterowanie widokiem: te same czterdzieści cztery piksele co reszta. */
  .board-widok-krok { width: 38px; height: 36px; }
  .board-widok-miara { height: 36px; }

  /* Pasek kontekstowy stoi nad zaznaczeniem i na telefonie bywa szerszy niż
     ekran — łamiemy go zamiast pozwolić mu wyjechać poza krawędź. */
  .board-kontekst { max-width: calc(100vw - var(--space-4)); flex-wrap: wrap; }
}

/* Znak w przycisku paska czytnika. Ten sam język, co znaki tablicy: sam
   obrys, bez wypełnień, kreska w barwie napisu obok. */
.bar-znak {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- Rysowanie zakotwiczone ---------------------------------------------- */

/* --- Pytania o sens ------------------------------------------------------ */

/*
 * Sekcja modelu odcięta od reszty szuflady linią, bo to jedyne miejsce
 * w całym narzędziu, gdzie coś opuszcza urządzenie i coś kosztuje. Granica
 * ma być widoczna, a nie domyślna.
 */
.quiz-model { margin-top: var(--space-2); }

/* Uprzedzenie o koszcie: zlota wlosowka przy krawedzi, jak wszystko, co
   mowi o pieniadzach albo o wyjsciu danych na zewnatrz. */
.quiz-pierwszy-raz {
  margin: 0 0 var(--space-2);
  padding-left: var(--space-3);
  border-left: 2px solid var(--color-accent);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/* Przycisk sam z siebie, nie rozciagniety: to jedna czynnosc, nie formularz. */
#quiz-generate { align-self: flex-start; }

/*
 * Licznik zlotowek liczbami stalej szerokosci: kwota zmienia sie po kazdym
 * wywolaniu i skakalaby w poziomie przy kazdym odswiezeniu.
 *
 * `min-width: 0` i lamanie: w szufladzie na telefonie „na dzis 1,99 zl
 * z 2,00 zl" nie miescilo sie obok naglowka i wychodzilo poza krawedz ekranu.
 * Teraz spada do wlasnego wiersza, zamiast byc obcinane.
 */
.quiz-budget {
  margin: 0;
  min-width: 0;
  max-width: 100%;
  flex: 0 1 auto;
  font-size: 0.7812rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
  /* Zmierzony kontrast przy 60% to 4,19:1 — poniżej progu. A to akurat
     linijka, która mówi o pieniądzach. */
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

.quiz-budget.is-empty { color: var(--color-accent); }

.quiz-model-why,
.quiz-model-note {
  margin: 0 0 var(--space-2);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 68%, transparent);
}

.quiz-questions { margin-top: var(--space-3); }

.pytanie {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
}

.pytanie:last-of-type { border-bottom: 0; }

.pytanie-krok {
  margin: 0 0 var(--space-1);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.pytanie-tresc {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-size: 1.1875rem;
  line-height: 1.35;
}

.pytanie-warianty {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* Warianty jeden pod drugim i wyrównane do lewej: odpowiedzi bywają zdaniami,
   a wyśrodkowane zdania różnej długości czyta się jak listę haseł. */
.pytanie-warianty button {
  text-align: left;
  width: 100%;
}

.pytanie-warianty button.is-right {
  border-color: var(--color-accent);
  box-shadow: inset 0 0 0 1px var(--color-accent);
}

.pytanie-warianty button.is-wrong {
  border-style: dashed;
  opacity: 0.75;
  text-decoration: line-through;
}

/* Wyłączony przycisk z odpowiedzią to nie przycisk nieczynny, tylko zapis
   tego, co się wybrało — nie może więc zblednąć do nieczytelności. */
.pytanie-warianty button:disabled { opacity: 1; cursor: default; }
.pytanie-warianty button.is-wrong:disabled { opacity: 0.75; }

.pytanie-po { margin-top: var(--space-2); }

.pytanie-ocena {
  margin: 0 0 var(--space-1);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.pytanie-ocena.is-right { color: var(--color-accent); }
.pytanie-ocena.is-wrong {
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.pytanie-wyjasnienie {
  margin: 0 0 var(--space-2);
  font-size: 0.875rem;
  line-height: 1.55;
}

/*
 * Cytat-świadek. To on odróżnia pytanie sprawdzone od zmyślonego, więc dostaje
 * własną formę — wcięcie i złotą linijkę przy krawędzi, tę samą, którą w całym
 * narzędziu ma to, co pochodzi wprost z książki.
 */
.pytanie-swiadek {
  margin: 0 0 var(--space-2);
  padding-left: var(--space-3);
  border-left: 2px solid var(--color-accent);
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.875rem;
  line-height: 1.55;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

/*
 * Podświetlenie świadka po skoku w tekst. Tło, nie obwódka: obwódka wokół
 * zakresu przelewającego się przez kilka wierszy rozpada się na prostokąty,
 * które wyglądają jak błąd składu.
 */
.k-w.is-swiadek {
  background: color-mix(in srgb, var(--color-accent) 22%, transparent);
  border-radius: 2px;
}

/* --- Rytm ---------------------------------------------------------------- */

/*
 * Widoczna jest WYŁĄCZNIE porcja pod oknem.
 *
 * Ukrywamy BARWĄ, nie kryciem pojedynczych słów, i to jest poprawka po
 * prawdziwym błędzie. Warstwa renderująca opakowuje w spany tylko WYRAZY —
 * przecinki, kropki, cudzysłowy, nawiasy i odstępy zostają zwykłymi węzłami
 * tekstu, których żaden selektor nie dosięgnie. Ukrycie samych `.k-w`
 * zostawiało więc na ekranie chmarę znaków przestankowych rozsypanych po całej
 * stronie: zamiast jednego wyrazu w pustce był jeden wyraz w śmietniku,
 * a rozproszenie jest dokładnym przeciwieństwem tego ćwiczenia.
 *
 * `color: transparent` na wszystkim wewnątrz treści obejmuje też węzły tekstu,
 * bo barwa jest dziedziczona — i nie rusza metryk, więc wiersze nie łamią się
 * w trakcie ćwiczenia. Reguła dla porcji ma wyższą szczegółowość, żeby wygrać
 * bez `!important`.
 */
/*
 * Strona zostaje ZŁOŻONA I ZMIERZONA, tylko niewidoczna.
 *
 * `visibility: hidden` nie rusza metryk, więc wiersze zostają dokładnie tam,
 * gdzie były — a to z nich bierze się porcja „jeden wiersz". Znika przy tym
 * WSZYSTKO, także przecinki i nadtytuł rozdziału, które są zwykłymi węzłami
 * tekstu i żadnej regule dla `.k-w` się nie kłaniają.
 */
.pager-content.is-tempo { visibility: hidden; }

/*
 * Scena Rytmu — wyjęta porcja, złożona tym samym krojem co książka.
 *
 * Szerokość jak miara czytelnika, żeby wiersz wyjęty z kolumny złamał się tak
 * samo jak w niej. Przy powiększeniu złamie się inaczej i tak ma być: stopień
 * pisma jest sprawą wygody oka, a porcję odmierza książka.
 */
.tempo-stage {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  pointer-events: none;
  font-family: var(--reader-font);
  font-weight: var(--text-weight);
  /* `--tempo-dopasowanie` ustawia tempo.js, gdy porcja nie mieści się na
     scenie — powód przy funkcji `dopasuj`. */
  font-size: calc(var(--reader-size) * var(--tempo-zoom, 1.6) * var(--tempo-dopasowanie, 1));
  line-height: var(--reader-leading);
  transition: opacity 90ms linear;
}

/*
 * Blok z wyjętą porcją. Szerokość dobrana do treści, ale nie szersza niż miara
 * czytelnika — dzięki temu jeden wyraz tworzy pudełko własnej szerokości
 * i wypada na środku, a kilka wierszy łamie się jak w książce i zostaje
 * wyrównanych do lewej. Prozy wyśrodkowanej nie czyta się dobrze, a to jest
 * ćwiczenie z czytania.
 */
.tempo-tekst {
  width: fit-content;
  /* Ten sam mnożnik dopasowania co w stopniu pisma: wiersze łamią się tak
     samo, tylko są mniejsze. */
  max-width: min(100%, calc(var(--reader-measure) * var(--tempo-zoom, 1.6) * var(--tempo-dopasowanie, 1)));
  text-align: left;
  hyphens: none;
}

.tempo-stage p { margin: 0 0 0.4em; text-indent: 0; }
.tempo-stage p:last-child { margin-bottom: 0; }
.tempo-stage img { display: none; }

@media (prefers-reduced-motion: reduce) {
  .tempo-stage { transition: none; }
}

/*
 * Odczyt Rytmu — co zmieniła strzałka. Pod sceną, cicho i krótko: krojem
 * interfejsu, bo nie jest tekstem książki, i przygaszony, bo nie jest porcją.
 *
 * Tło KRYJĄCE i obwódka. Przy dużej porcji odczyt leży na tekście, a z tłem
 * półprzezroczystym litery spod spodu mieszały się z odczytem w nieczytelną
 * plamę — zobaczone na zrzucie całej strony, nie w pomiarze.
 */
.tempo-odczyt {
  position: absolute;
  left: 50%;
  bottom: var(--space-5);
  z-index: 3;
  max-width: calc(100% - 2 * var(--space-5));
  margin: 0;
  padding: 6px 14px;
  transform: translateX(-50%);
  border-radius: 999px;
  border: 1px solid var(--color-divider);
  background: var(--color-bg);
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  line-height: 1.35;
  text-align: center;
  text-wrap: balance;
  pointer-events: none;
}

/*
 * Klawisze Rytmu w ustawieniach — ściąga, nie ustawienie.
 *
 * Wiersz na klawisz: plakietki po lewej w kolumnie stałej szerokości, czynność
 * po prawej, więc opisy stoją w jednej linii pionowej. `kbd` dostaje krój
 * interfejsu wprost — przeglądarka składa go domyślnie krojem o stałej
 * szerokości, a w interfejsie ma być jeden krój.
 */
.tempo-klawisze { margin: 0 0 var(--space-4); }

.tempo-klawisze-tytul {
  margin: 0 0 var(--space-2);
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.tempo-klawisze-lista {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
}

.tempo-klawisze-lista li { display: flex; align-items: center; gap: 12px; }

.tempo-klawisze .klawisze {
  display: inline-flex;
  flex: none;
  gap: 4px;
  width: 6.5rem;
}

.tempo-klawisze kbd {
  min-width: 1.7em;
  padding: 1px 6px;
  border: 1px solid var(--color-divider);
  border-bottom-width: 2px;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-text) 4%, transparent);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.4;
  text-align: center;
}

/*
 * Krótkie przenikanie zamiast cięcia. Przy dużych porcjach zmienia się naraz
 * spora część ekranu i twarde cięcie kilka razy na sekundę jest męczące dla
 * oka — a dla części osób ryzykowne. Dziewięćdziesiąt milisekund nie rozmywa
 * taktu, bo najkrótszy dopuszczalny odstęp to sto dwadzieścia.
 */
.pager-content.is-tempo .k-w { transition: color 90ms linear; }

@media (prefers-reduced-motion: reduce) {
  .pager-content.is-tempo .k-w { transition: none; }
}

/* Odcisk wgranej powłoki — cichy, ale ma dać się odczytać i przepisać. */
.wersja {
  margin: 0;
  padding: 0 var(--space-6) var(--space-4);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.tempo-rate {
  margin: var(--space-2) 0 0;
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

/* --- Zaznaczanie fragmentu ---------------------------------------------- */

/*
 * Nakładki przewracania stron NIE łapią wskaźnika.
 *
 * Przykrywały cały tekst — nad wyrazem stał `tap-prev`, nie wyraz — przez co
 * w czytniku nie dawało się zaznaczyć ani jednego słowa. Zostają w dokumencie
 * jako cel dla czytników ekranu, które aktywują je po nazwie; kliknięcia
 * myszą i palcem obsługuje scena, licząc, w której jest połowie.
 */
.tap { pointer-events: none; }

.pager-content {
  user-select: text;
  -webkit-user-select: text;
}

.pager-content ::selection { background: color-mix(in srgb, var(--color-accent) 28%, transparent); }

/*
 * Pasek nad zaznaczeniem: zakreślacze, notatka, kotwice.
 *
 * Poziomy i wąski, bo staje nad wierszem tekstu i nie może zasłaniać zdania,
 * do którego się odnosi.
 */
.selection-anchor {
  position: absolute;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  transform: translateX(-50%);
  padding: 6px 12px;
  border: 1px solid var(--color-accent);
  border-radius: 2px;
  background: var(--color-bg);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  white-space: nowrap;
}

.mark-swatches { display: flex; gap: 6px; }

/*
 * Zakreślacz jako próbka barwy, nie jako napis. Barwa niesie tu znaczenie
 * nadane przez ucznia, więc nazwa („różowy") byłaby mniej czytelna niż sam
 * kolor — a przy okazji nie da się jej przetłumaczyć na intencję.
 */
.swatch {
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--color-text) 30%, transparent);
  border-radius: 50%;
  cursor: pointer;
}

.swatch:hover { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.swatch-zolty     { background: var(--mark-zolty); }
.swatch-rozowy    { background: var(--mark-rozowy); }
.swatch-zielony   { background: var(--mark-zielony); }
.swatch-niebieski { background: var(--mark-niebieski); }

/*
 * Zaznaczenie w tekście. Tło, nie barwa liter — litery mają zostać czarne,
 * bo to je się czyta; zakreślacz ma je otaczać, a nie zastępować.
 */
.k-w.is-mark { border-radius: 2px; }
.k-w.is-mark.mark-zolty     { background: var(--mark-zolty); }
.k-w.is-mark.mark-rozowy    { background: var(--mark-rozowy); }
.k-w.is-mark.mark-zielony   { background: var(--mark-zielony); }
.k-w.is-mark.mark-niebieski { background: var(--mark-niebieski); }

/* Notatka dostaje dodatkowo kreskę u dołu — samo tło nie odróżniałoby jej
   od zwykłego zaznaczenia, a to dwie różne rzeczy. */
.k-w.is-note { box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--color-text) 45%, transparent); }

/* --- lista uwag ---------------------------------------------------------- */

/* Przełącznik zakresu listy uwag: dwa stany, nie lista rozwijana — bo stany
   są dwa i oba mieszczą się obok siebie. */
/*
 * ŚLAD TABLICY W TEKŚCIE — trzeci znak, obok podkreślenia i notatki.
 *
 * Kropkowana linia POD słowem, nie tło: tło jest już zajęte przez zaznaczenia
 * w czterech barwach, a fragment bywa i podkreślony, i odłożony na tablicę.
 * Dwa znaki mają się wtedy zsumować, a nie zetrzeć.
 */
.k-w.is-tablica {
  text-decoration: underline;
  text-decoration-style: dotted;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--color-accent) 70%, transparent);
  cursor: pointer;
}

/* Przycisk tablicy w pasku, gdy w tym rozdziale coś jest. Kropka, nie liczba —
   liczba kusi, żeby ją odczytać, a odpowiada tylko na „czy warto zajrzeć". */
.ma-slady { position: relative; }

.ma-slady::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-accent);
}

.notes-zakres {
  display: flex;
  gap: 2px;
  margin-bottom: var(--space-3);
  padding: 2px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}

.notes-zakres-wybor {
  flex: 1;
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}

.notes-zakres-wybor[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
  font-weight: 700;
}

/* Wpis pochodzący z tablicy — ta sama lista, inny znak, żeby było wiadomo,
   dokąd prowadzi kliknięcie. */
.note.z-tablicy .note-jump::before {
  content: "◇ ";
  opacity: 0.7;
}

.notes-count {
  margin: 0;
  padding: 0 var(--space-6) var(--space-3);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.notes { list-style: none; margin: 0; padding: 0 var(--space-4) var(--space-8); overflow-y: auto; }

.notes-chapter {
  padding: var(--space-4) var(--space-2) var(--space-2);
  font-family: var(--font-heading);
  font-size: 0.9375rem;
  font-weight: 700;
  border-bottom: 1px solid var(--color-divider);
}

.note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-divider);
}

/*
 * WPIS, KTÓRY ZGUBIŁ SWOJE MIEJSCE.
 *
 * Wiersz łamie się, żeby wyjaśnienie stanęło POD nazwą, a nie obok niej jako
 * trzecia kolumna: to jest zdanie do przeczytania, nie etykieta do rzucenia
 * okiem. Kreska z boku odróżnia go od sąsiadów, bo inaczej wygląda jak zwykła
 * notatka z długim podpisem.
 */
.note.is-zgubiona {
  flex-wrap: wrap;
  padding-left: var(--space-2);
  border-left: 2px solid var(--color-accent-400);
}

.note-zgubiona {
  /*
   * Na koniec wiersza, choć w kodzie stoi wcześniej. Bez tego łamanie wiersza
   * wypycha nazwę notatki POD wyjaśnienie — a wtedy najpierw czyta się, czego
   * brakuje, a dopiero potem czego to dotyczy.
   */
  order: 1;
  flex-basis: 100%;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--color-neutral-500);
}

/* Zapisany cytat w pasku wskazania — jedyna wskazówka, czego szukać. */
.wskazanie-cytat {
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-style: italic;
  color: var(--color-neutral-500);
}

.note-jump {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  padding: var(--space-2);
  border: 0;
  border-left: 3px solid transparent;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.note-jump:hover { background: color-mix(in srgb, var(--color-text) 5%, transparent); }

/*
 * CZĘŚCI OPISU STOJĄ JEDNA POD DRUGĄ: oznaczenie, cytat, własna uwaga.
 *
 * Kolumna była opisana na samym przycisku, ale jego jedynym dzieckiem jest
 * pudełko z tymi trzema napisami — więc układ zatrzymywał się na pudełku,
 * a napisy w środku sklejały się w jedno zdanie bez odstępu:
 * „…spojrzenie zatrzymujeTa stoi na swoim miejscu.". Wyglądało to jak cytat
 * z doklejonym ogonem, czyli jak zepsuta treść, a nie zepsuty układ.
 */
.note-jump > span {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.note.mark-zolty     .note-jump { border-left-color: var(--mark-zolty); }
.note.mark-rozowy    .note-jump { border-left-color: var(--mark-rozowy); }
.note.mark-zielony   .note-jump { border-left-color: var(--mark-zielony); }
.note.mark-niebieski .note-jump { border-left-color: var(--mark-niebieski); }

.note-quote {
  font-family: var(--reader-font);
  font-size: 0.875rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

.note-text { font-size: 0.8125rem; font-style: italic; }

.note-kind {
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.scope-foot {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: var(--space-2) 0 0;
}

.scope-count {
  font-size: 0.75rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.seg input:disabled + span { opacity: 0.4; }

/* --- Oryginalne strony PDF-a -------------------------------------------- */

/*
 * Przewijanie ciągłe, nie stronami. Na telefonie jest naturalniejsze, a przy
 * dwóch łamach obcięcie strony w połowie boli mniej niż skok o całą stronę.
 */
.pdf-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--space-4) max(var(--space-4), env(safe-area-inset-left))
           var(--space-8) max(var(--space-4), env(safe-area-inset-right));
  scroll-behavior: auto;
  -webkit-overflow-scrolling: touch;
}

/*
 * Kafel strony ma wymiary ZANIM strona się narysuje — stąd aspect-ratio
 * nadawane z kodu. Bez tego pasek przewijania skakałby przy każdej
 * dorysowanej stronie, a zapamiętana pozycja lądowałaby gdzie indziej.
 */
.pdf-page {
  position: relative;
  display: block;
  width: 100%;
  max-width: 62rem;
  margin: 0 auto var(--space-4);
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

.pdf-page canvas { display: block; width: 100%; height: auto; }

/* --- wycinanie fragmentu strony PDF-a ---------------------------------------
   Warstwa nad stronami, obecna tylko przy uzbrojonym wycinaniu. Gdyby leżała
   tam zawsze, przechwytywałaby przewijanie — a przewija się tu znacznie
   częściej, niż wycina. */
/* Pasek trwającego łączenia: nad tekstem, nie nad wszystkim. Ma przypominać,
   co się robi, a nie zasłaniać tego, w czym się wybiera. */
.laczenie-pasek {
  position: absolute;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 8;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: 0 6px 20px color-mix(in srgb, #000 16%, transparent);
  font-size: 0.8125rem;
}

.pdf-wycinek {
  position: absolute;
  inset: 0;
  z-index: 6;
  cursor: crosshair;
  background: color-mix(in srgb, #201f1d 12%, transparent);
}

.pdf-wycinek-ramka {
  position: absolute;
  border: 2px solid var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  pointer-events: none;
}

.pdf-wycinek-akcje {
  position: absolute;
  z-index: 7;
  display: flex;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: 0 6px 20px color-mix(in srgb, #000 22%, transparent);
}

.pdf-wycinek-hint {
  position: absolute;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-text);
  font-size: 0.8125rem;
  pointer-events: none;
}

/*
 * Warstwa tekstu nad obrazem strony — przezroczysta, ale zaznaczalna.
 *
 * Napisy są niewidoczne (`color: transparent`) i leżą dokładnie tam, gdzie
 * na obrazie stoją litery. Dzięki temu przeciągnięcie myszą zaznacza to,
 * co widzi oko, a kopiowanie oddaje prawdziwy tekst, nie obraz.
 *
 * `line-height: 1` nie jest ozdobą: pdf.js ustawia każdemu napisowi własny
 * stopień pisma i liczy położenie od GÓRY pudełka. Odziedziczona
 * interlinia czytnika przesuwałaby każdy wiersz w dół o ułamek wysokości,
 * a zaznaczenie lądowałoby między wierszami.
 */
.pdf-tekst {
  position: absolute;
  inset: 0;
  overflow: hidden;
  line-height: 1;
  text-align: initial;
  text-size-adjust: none;
  forced-color-adjust: none;
  transform-origin: 0 0;
  z-index: 2;
}

.pdf-tekst span,
.pdf-tekst br {
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0% 0%;
  color: transparent;
}

/* Zaznaczenie musi być widoczne, choć litery nie są. */
.pdf-tekst ::selection { background: color-mix(in srgb, var(--color-accent) 42%, transparent); }

/* Uchwyt koncowy pdf.js — zerowej szerokości, do domykania zaznaczenia. */
.pdf-tekst .endOfContent {
  position: absolute;
  inset: 100% 0 0;
  display: block;
  cursor: default;
  user-select: none;
}

.pdf-tekst.selecting .endOfContent { top: 0; }

/*
 * W ciemnym motywie kartka zostaje biała, ale przygaszona. Odwracanie barw
 * zniszczyłoby ryciny i wykresy — a to właśnie dla nich ktoś wybrał oryginał.
 */
:root[data-theme='dark'] .pdf-page { filter: brightness(0.82) contrast(1.02); }

/* Motyw „system" znaczy „idź za ustawieniem systemu" — przygaszamy więc
   tylko wtedy, gdy system NAPRAWDĘ jest ciemny. */
@media (prefers-color-scheme: dark) {
  :root[data-theme='system'] .pdf-page { filter: brightness(0.82) contrast(1.02); }
}

.reader-notice.is-error {
  border-color: color-mix(in srgb, var(--error-ink) 45%, transparent);
  background: color-mix(in srgb, var(--error-ink) 8%, var(--color-bg));
  color: var(--error-ink);
}

/* Komunikat o błędzie zostaje na ekranie — zamyka go kliknięcie. */
.reader-notice.is-dismissable { cursor: pointer; }

/*
 * Pasek postępu w komunikacie — tylko tam, gdzie postęp jest ZNANY.
 *
 * Rysowany jako włosowa kreska u dolnej krawędzi pudełka, szerokością
 * odpowiadająca stosunkowi zrobionego do całości. Bez animacji z własnej
 * woli: kreska ma ruszyć się wtedy, gdy zrobiło się więcej, a nie żeby
 * wyglądało żywo.
 */
.reader-notice.ma-postep { padding-bottom: calc(var(--space-3) + 3px); }

.reader-notice.ma-postep::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: color-mix(in srgb, var(--color-text) 10%, transparent);
}

.reader-notice.ma-postep::before {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 1;
  height: 2px;
  width: calc(var(--postep, 0) * 100%);
  background: var(--color-accent);
}

.reader-notice {
  position: absolute;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%);
  z-index: 3;
  max-width: min(42rem, calc(100% - 2 * var(--space-6)));
  margin: 0;
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--color-divider);
  border-radius: 2px;
  background: var(--color-bg);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
  font-size: 0.8125rem;
  text-align: center;
}

/* --- Czytnik ------------------------------------------------------------ */

.view-reader { display: flex; flex-direction: column; }

.bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 0 0 auto;
  padding: var(--space-2) max(var(--space-6), env(safe-area-inset-left))
           var(--space-2) max(var(--space-6), env(safe-area-inset-right));
  border-bottom: 1px solid var(--color-divider);
}

/*
 * MIKROFON PRZY POLU TEKSTOWYM.
 *
 * Jeden wygląd na siedem pojemników — o rozmieszczenie dba każdy z nich
 * z osobna, niżej. Wspólne zostaje to, co znaczy „dyktuj": kwadrat pod palec,
 * znak z tej samej rodziny co reszta, i wyraźny stan nasłuchu.
 */
.mikrofon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--color-text) 14%, transparent);
  border-radius: var(--radius-md);
  background: none;
  color: inherit;
  cursor: pointer;
}

.mikrofon svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.mikrofon:hover { border-color: color-mix(in srgb, var(--color-text) 30%, transparent); }

/*
 * Nasłuch widać BEZ ANIMACJI: barwa i wypełnienie, nie pulsowanie. Migający
 * punkt na ekranie jest dla części osób męczący, a ta aplikacja ma osobne
 * ustawienia właśnie po to, żeby patrzenie w nią nie bolało.
 */
.mikrofon[aria-pressed='true'] {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
  color: var(--color-accent-700);
}

/* Dopisanie uwagi wprost w szufladzie. Rząd, który na wąskim ekranie łamie
   się na dwa — pole ma wtedy całą szerokość, a przycisk staje pod nim. */
.notes-nowa {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: 0 22px var(--space-3);
}

/*
 * POLE Z MIKROFONEM W ŚRODKU.
 *
 * Owijka przejmuje zachowanie pola w rzędzie — rozciąga się tak samo, więc
 * `flex: 1` na polu dalej działa tak, jak działało. Samo pole dostaje z prawej
 * tyle dopełnienia, żeby tekst nie wchodził pod ikonę.
 */
.pole-mowa {
  position: relative;
  display: block;
  flex: 1 1 auto;
  min-width: 0;
}

.pole-mowa > input,
.pole-mowa > textarea { width: 100%; padding-right: 2.75rem; }

.pole-mowa > .mikrofon {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 2rem;
  height: 2rem;
  border: 0;
  background: none;
}

/* W polu wielowierszowym ikona trzyma się GÓRNEJ krawędzi: przy rosnącym
   tekście środek uciekałby w dół razem z nim. */
.pole-mowa > textarea { padding-right: 2.75rem; }

/*
 * Pytanie o głos stoi NAD innym oknem, więc musi mieć wyższą warstwę.
 *
 * Bez tego oba miały `z-index: 40` z klasy `ask-panel`, a przy równej warstwie
 * wygrywa to, co dalej w dokumencie — czyli okno pytania o tekst. Panel wyboru
 * głosu wystawał wtedy spod niego czterdziestoma pikselami, a jego przyciski
 * były nie do kliknięcia: pod palcem trafiało się w okno leżące na wierzchu.
 */
.mowa-scrim { z-index: 45; }
.mowa-panel { z-index: 50; }

.mowa-panel .mowa-stan { margin: 0; font-style: italic; }
.mowa-akcje { flex-wrap: wrap; }

/*
 * ODCZYT PISMA. Panel szerszy niż pytanie o głos, bo mieści pole z całym
 * odczytem — a odczyt, którego nie widać w całości, sprawdza się gorzej niż
 * ten, który widać, i po to jest to okno.
 */
.odczyt-scrim { z-index: 45; }
.odczyt-panel { z-index: 50; max-width: 34rem; width: min(34rem, calc(100vw - 2rem)); }
.odczyt-panel .mowa-stan { margin: 0; font-style: italic; }
.odczyt-panel .mowa-stan.is-blad { font-style: normal; color: var(--error-ink); }

.odczyt-tekst {
  width: 100%;
  box-sizing: border-box;
  margin: 0.5rem 0 0;
  padding: 0.55rem 0.65rem;
  font: inherit;
  /* Odczyt bywa wierszowany — zawijanie zostawiamy, ale wierszy nie łączymy. */
  white-space: pre-wrap;
  line-height: 1.45;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-neutral-300);
  border-radius: 8px;
  resize: vertical;
}

/* Słowa niepewne — podpowiedź, gdzie patrzeć, a nie ostrzeżenie o awarii. */
.odczyt-watpliwe {
  margin: 0.45rem 0 0;
  font-size: 0.875rem;
  opacity: 0.8;
}

/* Nakładka pisania na kanwie: mikrofon tuż pod polem, żeby nie zasłaniał
   kształtu, na którym się pisze. */
.board-pisanie-mikrofon { position: absolute; z-index: 6; }

/* Znak w pasku czytnika — sam identyfikuje, nie klika. */
/*
 * Sygnet w pasku czytelni. Był 22 px i przygaszony do 0,75 — w efekcie
 * nie dawało się go przeczytać ani zauważyć, a znak, którego nie widać,
 * nie pełni żadnej z obu swoich ról. Teraz ma pełną moc i wysokość rzędu
 * przycisków obok, więc stoi w pasku jako znak, a nie jako plamka.
 */
.bar-mark { flex: none; display: block; }

/*
 * PASEK CZYTNIKA NA TELEFONIE.
 *
 * Zmierzone przed zmianą: przy 320 px pasek z podpisami łamał się na trzy
 * rzędy i brał 136 pikseli — siedemnaście procent ekranu, zanim zaczął się
 * tekst książki.
 *
 * Ustępują trzy rzeczy i wszystkie trzy da się odzyskać: podpis (nazwa
 * zostaje w podpowiedzi i w opisie dla czytnika ekranu), tytuł książki (i tak
 * zostawało mu zero pikseli, a jako element rozciągliwy wypychał przyciski
 * do następnego rzędu) oraz znak firmowy, który niczego nie robi.
 *
 * Czego NIE robimy: nie ściskamy przycisków do jednego rzędu. Dziewięć celów
 * po czterdzieści cztery piksele to trzysta dziewięćdziesiąt sześć — w trzystu
 * dwudziestu nie zmieszczą się nigdy, a wciśnięte siłą dałyby cele
 * dwudziestodziewięciopikselowe, czyli mniejsze niż palec. Zostają dwa rzędy,
 * ale rzędy WYGODNE: cel urósł z trzydziestu jeden pikseli do czterdziestu
 * czterech, a pasek zmalał ze stu trzydziestu sześciu do dziewięćdziesięciu
 * pięciu.
 */
@media (max-width: 640px) {
  .bar {
    gap: 3px;
    padding: var(--space-2) max(var(--space-2), env(safe-area-inset-left))
             var(--space-2) max(var(--space-2), env(safe-area-inset-right));
  }

  .bar .bar-nazwa {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
  }

  .bar .bar-title,
  .bar .bar-mark { display: none; }

  .bar .button {
    width: 44px;
    height: 44px;
    padding: 0;
    justify-content: center;
  }

  .bar .bar-znak { width: 19px; height: 19px; }
}

.bar-title {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.0625rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stage {
  flex: 1 1 auto;
  position: relative;
  display: flex;
  justify-content: center;
  min-height: 0;
  padding: var(--space-8) var(--space-6);
}

/* Faktura papieru. Warstwa bezwzględna, bez wpływu na układ — paginacja jej
   nie odczuwa, bo nie zajmuje miejsca w przepływie. */
.paper {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: var(--paper-tex, none);
  background-size: var(--paper-size, auto);
  mix-blend-mode: var(--paper-blend, multiply);
  opacity: var(--paper-amt, 0);
}

/* Kontener paginacji: stała wysokość i ucięcie tego, co poza kolumną.
   Bez własnych marginesów wewnętrznych — clientWidth musi być dokładnie
   szerokością kolumny, inaczej krok przewracania stron przestaje się zgadzać. */
.pager-viewport {
  width: 100%;
  max-width: var(--reader-measure);
  height: 100%;
  overflow: hidden;
  position: relative;
}

.pager-content {
  column-fill: auto;
  font-family: var(--reader-font);
  font-weight: var(--text-weight);
  font-size: var(--reader-size);
  line-height: var(--reader-leading);
  hyphens: auto;
  /* Do lewej, nie justowanie: szerokość łamu i stopień pisma zmienia tu
     czytelnik, a justowanie przy wąskiej kolumnie robi z odstępów rzeki. */
  text-align: left;
  will-change: transform;
}

/* Strefy dotyku: lewa i prawa połowa ekranu. Przezroczyste — jedyne, co je
   zdradza, to kursor. */
.tap {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  border: 0;
  background: none;
  padding: 0;
  appearance: none;
}

.tap-prev { left: 0; cursor: w-resize; }
.tap-next { right: 0; cursor: e-resize; }

/* Pasek postępu czytania — nad stopką, na całą szerokość. */
.reader-progress { flex: 0 0 auto; height: 2px; background: var(--color-neutral-300); }
.reader-progress > span { display: block; height: 100%; background: var(--color-accent); }

/* Stała wysokość, niezależna od tego, czy etykiety są już wypełnione.
   Bez tego pasek rósł po wpisaniu tekstu, scena się kurczyła i całe łamanie
   stron trzeba było liczyć drugi raz — a zapamiętana pozycja czytania
   przesuwała się o stronę. */
.bar-foot {
  border-bottom: 0;
  justify-content: space-between;
  align-items: center;
  min-height: 40px;
  padding-bottom: max(var(--space-2), env(safe-area-inset-bottom));
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.bar-foot .num { font-variant-numeric: tabular-nums; }

/*
 * Trafienie z wyszukiwania — podświetlenie na trzy sekundy.
 *
 * Barwa złota, ta sama co reszta akcentów, ale bardzo cicho: to jest wskazanie
 * miejsca, a nie zaznaczenie czytelnika. Gdyby wyglądało jak jego zaznaczenie,
 * po chwili nie dałoby się odróżnić, co podkreślił sam, a co znalazła
 * wyszukiwarka.
 *
 * Gaśnie płynnie, żeby zniknięcie nie wyglądało na usterkę odświeżania.
 */
.k-w.is-trafienie {
  background: color-mix(in srgb, var(--color-accent) 26%, transparent);
  border-radius: 2px;
  transition: background 700ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .k-w.is-trafienie { transition: none; }
}

/*
 * Podpisy rozdziałów w stopce chowają się w DWÓCH sytuacjach i z jednego
 * powodu: kolumna jest wąska. Raz dlatego, że wąskie jest okno — to załatwia
 * zapytanie o szerokość niżej. Raz dlatego, że połowę miejsca zabrała tablica,
 * a okno pozostało szerokie; wtedy żadne zapytanie o szerokość okna nie zadziała
 * i stopka łamała się na dwa rzędy. Zmierzone na 1440×900: 51 px zwykle, 81 px
 * w podziale, czyli dziewięć procent wysokości ekranu na cztery przyciski.
 */
.views.podzial .bar-foot .bar-rozdzial .bar-nazwa {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  clip-path: inset(50%);
  overflow: hidden;
}

/* --- Treść -------------------------------------------------------------- */

.pager-content .k-p, .flow .k-p { margin: 0 0 1em; }

/*
 * Nagłówki rozdziałów są częścią KSIĄŻKI, więc idą krojem czytelni, a nie
 * interfejsu. Stał tu krój nagłówków programu i przy szeryfowym interfejsie
 * nie rzucało się to w oczy. Przy bezszeryfowym tytuł rozdziału w innym kroju
 * niż jego tekst wyglądałby jak wklejka z innej książki — i omijałby wybór
 * z listy „Krój pisma".
 */
.pager-content h1, .pager-content h2, .pager-content h3,
.pager-content h4, .pager-content h5, .pager-content h6,
.flow h1, .flow h2, .flow h3, .flow h4, .flow h5, .flow h6 {
  font-family: var(--reader-font);
  font-weight: 400;
  line-height: 1.2;
  margin: 1.5em 0 .75em;
  text-align: left;
  break-after: avoid;
}

.pager-content > :first-child, .flow > :first-child { margin-top: 0; }

.pager-content h1, .flow h1 { font-size: 1.7em; }
.pager-content h2, .flow h2 { font-size: 1.5em; }
.pager-content h3, .flow h3 { font-size: 1.2em; }
.pager-content h4, .flow h4,
.pager-content h5, .flow h5,
.pager-content h6, .flow h6 { font-size: 1em; }

/* Nadkreślenie nad tytułem rozdziału: „Rozdział IV" wersalikami, złote. */
.k-over {
  display: block;
  font-family: var(--reader-font);
  font-size: 0.36em;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin-bottom: 0.9em;
  font-variant-numeric: tabular-nums;
}

/* Ilustracja musi zmieścić się w kolumnie w całości. Wysokość ograniczamy
   względem okna, a nie kolumny: procenty wewnątrz fragmentu wielokolumnowego
   przeglądarki liczą różnie i obrazek potrafiłby wystawać poza stronę. */
.k-img {
  display: block;
  max-width: 100%;
  max-height: 68vh;
  height: auto;
  margin: 1.2em auto;
  break-inside: avoid;
}

/* Kotwica jest klasą na spanie słowa, nie zagnieżdżonym <b>. */
.k-w .k-h { font-weight: inherit; }
.k-w.is-anchor .k-h { font-weight: var(--anchor-weight); }

/* --- Poligon ------------------------------------------------------------ */

.view-playground .wrap { max-width: 820px; }

.pg-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-divider);
}

.pg-head h1 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 2.625rem;
  margin: 0;
}

.pg-head .hint {
  font-style: italic;
  font-size: 0.8125rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

textarea {
  width: 100%;
  min-height: 140px;
  margin-top: var(--space-4);
  padding: var(--space-3);
  resize: vertical;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.875rem;
  line-height: 1.6;
  caret-color: var(--color-accent);
}

textarea:hover { border-color: color-mix(in srgb, var(--color-text) 24%, transparent); }
textarea:focus-visible { border-color: var(--color-accent); outline-offset: 0; }

.pg-stats {
  display: flex;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding: var(--space-3) 0 var(--space-4);
  border-bottom: 1px solid var(--color-divider);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  font-variant-numeric: tabular-nums;
}

.pg-preview { position: relative; padding-top: var(--space-6); }

.flow {
  font-family: var(--reader-font);
  font-weight: var(--text-weight);
  font-size: var(--reader-size);
  line-height: var(--reader-leading);
  max-width: var(--reader-measure);
  hyphens: auto;
  /* Do lewej, nie justowanie: szerokość łamu i stopień pisma zmienia tu
     czytelnik, a justowanie przy wąskiej kolumnie robi z odstępów rzeki. */
  text-align: left;
}

/* --- Szuflady ----------------------------------------------------------- */

.scrim {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: color-mix(in srgb, #201f1d 45%, transparent);
}

.scrim[hidden], .drawer[hidden] { display: none; }

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 11;
  display: flex;
  flex-direction: column;
  width: min(23rem, 100%);
  background: var(--color-bg);
  border-left: 1px solid var(--color-divider);
  box-shadow: var(--shadow-lg);
}

#settings-drawer { width: min(24rem, 100%); }

/*
 * Szuflada szersza od pozostałych — mieści tekst do czytania, a nie listę.
 *
 * MUSI STAĆ PO `.drawer`, i to jest cała historia tej reguły. Długo leżała
 * wyżej w pliku, przy stylach sprawdzianu, gdzie wyglądała logicznie i nie
 * robiła NIC: obie reguły mają tę samą wagę, więc rozstrzyga kolejność,
 * a `.drawer` stało niżej i wygrywało. Szuflada miała 23rem zamiast 38rem
 * i nikt tego nie zauważył, bo wyglądała poprawnie — tylko wężej.
 */
.drawer-wide { width: min(38rem, 100%); }

/*
 * Nagłówek szuflady łamie się, gdy trzeba. Przy podwojonym piśmie z ustawień
 * przeglądarki tytuł i „Zamknij" nie mieszczą się w jednym rzędzie na wąskim
 * ekranie i przycisk wychodził poza okno — czyli akurat ten, którym się z tej
 * szuflady wychodzi.
 */
.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex: 0 0 auto;
  flex-wrap: wrap;
  padding: var(--space-3) 22px;
  border-bottom: 1px solid var(--color-divider);
}

.drawer-head strong {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.375rem;
}

.drawer-close {
  appearance: none;
  border: 0;
  background: none;
  padding: 4px 6px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  /*
   * Siedemdziesiąt procent. Przy sześćdziesięciu ten napis miał w jasnym
   * motywie kontrast 4,19:1 — poniżej progu dla pisma dwunastopunktowego,
   * i to w KAŻDEJ szufladzie aplikacji. Znalazł to nowy zestaw sprawdzający
   * napisy interfejsu, przy pierwszym uruchomieniu; wcześniej mierzony był
   * tylko tekst czytany, a chrom szuflad nie był sprawdzany nigdy.
   */
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

.drawer-close:hover { color: var(--color-accent-700); }

.drawer-body { flex: 1 1 auto; overflow-y: auto; padding: 22px; }

/* --- Spis treści -------------------------------------------------------- */

.toc { list-style: none; margin: 0; padding: var(--space-2) 0; overflow-y: auto; flex: 1 1 auto; }

.toc button {
  appearance: none;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  width: 100%;
  text-align: left;
  border: 0;
  border-left: 2px solid transparent;
  background: none;
  color: inherit;
  font-family: var(--font-body);
  font-size: 0.875rem;
  padding: 11px 22px;
  cursor: pointer;
}

.toc button:hover { background: color-mix(in srgb, var(--color-text) 6%, transparent); }

.toc .n {
  min-width: 22px;
  flex: none;
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--color-neutral-500);
  font-variant-numeric: tabular-nums;
}

.toc .t { flex: 1; }

.toc .pp {
  flex: none;
  font-size: 0.6875rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  font-variant-numeric: tabular-nums;
}

.toc button.is-current { border-left-color: var(--color-accent); color: var(--color-neutral-500); }
.toc li[data-depth='1'] button { padding-left: 40px; }
.toc li[data-depth='2'] button { padding-left: 58px; }

/* --- Ustawienia --------------------------------------------------------- */

.section + .section { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--color-divider); }
.section > .kicker { display: block; letter-spacing: 0.13em; margin-bottom: var(--space-4); }

.control { margin-bottom: var(--space-4); }
.control:last-child { margin-bottom: 0; }

.control > label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
  margin-bottom: var(--space-2);
}

.control > label b {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.875rem;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.control.check label { justify-content: flex-start; align-items: center; cursor: pointer; }
.control .note { font-style: italic; font-size: 0.75rem; color: color-mix(in srgb, var(--color-text) 65%, transparent); }

/* Suwak: tor włosowy, uchwyt jako złote kółko na tle papieru. */
input[type='range'] {
  appearance: none;
  width: 100%;
  background: none;
  height: 13px;
  cursor: pointer;
}

input[type='range']::-webkit-slider-runnable-track { height: 1px; background: var(--color-neutral-400); }
input[type='range']::-moz-range-track { height: 1px; background: var(--color-neutral-400); }

input[type='range']::-webkit-slider-thumb {
  appearance: none;
  width: 13px;
  height: 13px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--color-bg);
  border: 1px solid var(--color-accent);
}

input[type='range']::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--color-bg);
  border: 1px solid var(--color-accent);
}

input[type='range']:hover::-webkit-slider-thumb { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }
input[type='range']:hover::-moz-range-thumb { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }
input[type='range']:disabled { opacity: 0.4; cursor: not-allowed; }

input[type='checkbox'] { accent-color: var(--color-accent); width: 15px; height: 15px; }

select {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.875rem;
}

/* Spód listy rozwijanej rysuje system, nie my — ale barwy opcji podajemy
   wprost, bo bez nich dziedziczą kolor tekstu z motywu i potrafią zniknąć
   na tle, którego nie kontrolujemy. */
option {
  background: var(--color-bg);
  color: var(--color-text);
}

optgroup {
  background: var(--color-bg);
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

select:hover { border-color: color-mix(in srgb, var(--color-text) 24%, transparent); }
select:focus-visible { border-color: var(--color-accent); outline-offset: 0; }

/* Przełącznik segmentowy: jeden obrys, przegrody włosowe, pole aktywne złote. */
.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.seg.wrap2 { grid-auto-flow: row; grid-template-columns: 1fr 1fr; }

.seg label {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 12px;
  cursor: pointer;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 0.8125rem;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

.seg label + label { border-left: 1px solid var(--color-divider); }
.seg.wrap2 label:nth-child(3), .seg.wrap2 label:nth-child(4) { border-top: 1px solid var(--color-divider); }
.seg.wrap2 label:nth-child(3) { border-left: 0; }

.seg input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.seg label:has(input:checked) {
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  color: var(--color-accent-700);
}
.seg label:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg label:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* --- Ochrona wzroku ------------------------------------------------------ */

/* Redukcja niebieskiego. Bursztynowa warstwa mnożona przez całą stronę —
   ilustracje też, bo w nich niebieskiego bywa najwięcej. Nad fakturą papieru.
   Uczciwie: to zmienia tylko to, co wyświetla ta strona. Podświetlenia ekranu
   nie da się z poziomu przeglądarki przyciemnić. */
.night {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  background: rgb(255, 176, 92);
  mix-blend-mode: multiply;
  opacity: var(--night, 0);
}

.night[hidden] { display: none; }

/* --- Węższe ekrany ------------------------------------------------------- */

@media (max-width: 46rem) {
  .wrap { padding: var(--space-6) var(--space-4) 64px; }

  /*
   * Pasek czytnika na telefonie. Przy PDF-ie stoi w nim o jeden przycisk
   * więcej („Oryginał"/„Tekst") i komplet przestaje się mieścić w 390 px —
   * strona zaczyna się wtedy przewijać w bok, co na telefonie jest wadą
   * dotkliwszą niż brak tytułu.
   *
   * Tytuł ustępuje pierwszy, bo jest jedynym elementem paska, który niczego
   * nie robi: czytelnik wie, co czyta. Reszta paska nawiguje.
   */
  .view-reader .bar-title { display: none; }
  .view-reader .bar .button.ghost { padding-inline: 6px; }
  /* Doszedł „Rytm", a przy PDF-ie jeszcze „Oryginał" — komplet nie mieści się
     w 390 px. Pasek się łamie, zamiast chować przyciski: każdy z nich jest
     jedyną drogą do tego, co robi. */
  .view-reader .bar { flex-wrap: wrap; }

  /*
   * Górny pasek biblioteki na telefonie. Znak z podpisem, przełącznik języka,
   * motyw i ustawienia nie mieszczą się w 390 px — strona przewijała się
   * w bok, i to niezależnie od zmian w czytniku.
   *
   * Zwężamy odstępy i pozwalamy paskowi się złamać, zamiast chować którykolwiek
   * z przycisków: w bibliotece nie ma innej drogi do ustawień ani do zmiany
   * języka, więc ukrycie ich zostawiłoby czytelnika bez wyjścia.
   */
  .topbar { flex-wrap: wrap; gap: var(--space-2); padding-inline: var(--space-4); }
  .topbar-actions { gap: 2px; }
  .topbar-actions .button { padding-inline: 8px; }
  .pg-head h1 { font-size: 2rem; }
  .stage { padding: var(--space-4) var(--space-4); }
  .topbar { padding-inline: var(--space-4); }
  /* Na wąskim ekranie podpis odpada, a znak schodzi o stopień. Zmieniamy
     JEDNĄ liczbę — nawiasy idą za nią same, bo mają wysokość w `em`. */
  .brand-strapline { display: none; }
  .brand-mark { width: 30px; height: 30px; }
  .brand-lockup { font-size: 1.375rem; }
}

/* --- Czytnik: dwa rzędy paska ------------------------------------------- */

/*
 * Rząd pierwszy mówi, GDZIE SIĘ JEST, drugi — CO SIĘ ROBI. Rozdzielenie ich
 * kreską byłoby o kreskę za dużo: rzędy różnią się już rolą i wagą pisma,
 * a dwie linie pod sobą zjadałyby scenę i wyglądały jak dwa paski narzędzi
 * z dwóch różnych programów.
 */
.bar-glowny { border-bottom: 0; padding-bottom: 0; }

.bar-narzedzia {
  flex-wrap: wrap;
  padding-top: var(--space-1);
}

/* Motyw i tryb pracy idą na prawy skraj swoich rzędów. */
.bar-motyw { margin-left: auto; color: var(--color-neutral-500); }

/*
 * Przełącznik trybu. Trzy położenia stykają się bokami — to jeden element,
 * nie trzy przyciski obok siebie, i ma tak wyglądać. Obrys wspólny, kreski
 * między położeniami włosowe.
 */
.tryb {
  display: flex;
  margin-left: auto;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.tryb .button {
  border: 0;
  border-radius: 0;
  padding-inline: 12px;
}

.tryb .button + .button { border-left: 1px solid var(--color-divider); }

/*
 * Położenie włączone. Złoto jako wypełnienie o niskim kryciu, nie jako obrys:
 * obrys wewnątrz wspólnej ramki dałby ramkę w ramce, a przy trzech położeniach
 * — trzy różne grubości krawędzi w jednym rzędzie.
 */
.tryb .button[aria-pressed='true'] {
  border-color: var(--color-divider);
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
}

.tryb .button[aria-pressed='true']:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-accent) 24%, transparent);
}

/* Stopka: nawigacja po rozdziałach, miejsce w książce i sprawdzian. */
.bar-foot-srodek {
  display: flex;
  /*
   * `nowrap`, i to jest sedno poprawki.
   *
   * Pole elastyczne z `wrap` NAJPIERW łamie wiersz, a dopiero potem kurczy to,
   * co w nim zostało — więc wielokropek na tytule rozdziału nigdy nie miał
   * szansy powstać: zanim zabrakło miejsca, przyciski stron były już w drugim
   * rzędzie. Z `nowrap` kolejność się odwraca i grupa zostaje w jednym wierszu,
   * a ustępuje ten element, który ma na to pozwolenie — tytuł.
   */
  flex-wrap: nowrap;
  justify-content: center;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  flex: 1;
  min-width: 0;
  text-align: center;
}

/*
 * Nazwa rozdziału USTĘPUJE, zamiast łamać wiersz.
 *
 * Na telefonie środek stopki dostawał 231 px na tytuł rozdziału i przyciski
 * stron; nie mieściły się obok siebie, więc schodziły do drugiego rzędu i cała
 * stopka rosła do 111 px, czyli trzynastu procent ekranu. Skrócenie tytułu
 * wielokropkiem nie odbiera niczego, czego nie widać gdzie indziej — nazwa
 * rozdziału stoi też w spisie treści — a przyciski stron muszą zostać
 * klikalne, bo to jedyny sposób przewracania kartek, odkąd kliknięcie
 * w tekst tego nie robi.
 *
 * `min-width: 0` jest tu obowiązkowe: bez niego pole elastyczne nie kurczy się
 * poniżej swojej treści i wielokropek nigdy nie powstaje.
 */
.bar-foot-srodek #reader-chapter {
  /* `0 1 auto`, nie `1 1 auto`: tytuł ma USTĘPOWAĆ, a nie zabierać wolne
     miejsce. Przy `1` rozpychał się do 173 z 231 px i to on wypychał przyciski
     stron do następnego rzędu. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Przyciski stron i licznik zostają w całości — one nie mają się kurczyć. */
.bar-foot-srodek .bar-strona,
.bar-foot-srodek .num { flex: 0 0 auto; }

.bar-foot .bar-rozdzial {
  flex: none;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.8125rem;
}

.bar-foot .bar-rozdzial:disabled { opacity: 0.35; }

/*
 * „Sprawdź zrozumienie" jest w stopce JEDYNĄ rzeczą, którą się robi, a nie
 * czyta — i ma tak wyglądać.
 *
 * Obrys w barwie akcentu na tle stopki był z daleka nie do odróżnienia od
 * numeru strony i nazwy rozdziału, czyli od napisów, w które się nie klika.
 * Zgłoszone wprost: „to bardzo ważny przycisk, a jest niewidoczny". Pełne
 * tło rozstrzyga to jednym środkiem, tym samym, co przy wejściu do aplikacji.
 */
/*
 * „Sprawdź zrozumienie" jest przyciskiem pełnym i wygląda jak wszystkie inne
 * przyciski pełne: pomarańczowa plama, biała etykieta, pogrubienie. Waga 700
 * nie jest tu ozdobą — biel na tym pomarańczu daje 3,69:1, czyli próg dla
 * pisma pogrubionego od 14 px. Zwykła grubość zabrałaby etykiecie ten próg
 * i to samo zdanie byłoby raz czytelne, a raz nie.
 */
.bar-foot #reader-quiz {
  flex: none;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 700;
  background: var(--klawisz-pelny-tlo);
  border-color: var(--klawisz-pelny-tlo);
  color: var(--klawisz-pelny-tusz);
}

.bar-foot #reader-quiz .bar-nazwa { font-weight: 700; }

.bar-foot #reader-quiz:hover:not(:disabled),
.bar-foot #reader-quiz:active:not(:disabled) {
  background: color-mix(in srgb, var(--klawisz-pelny-tlo) 88%, var(--color-text));
  border-color: color-mix(in srgb, var(--klawisz-pelny-tlo) 88%, var(--color-text));
}

@media (max-width: 900px) {
  /*
   * Podpisy rozdziałów schodzą pierwsze: strzałki mówią to samo, a nazwa
   * zostaje w podpowiedzi i w opisie dla czytnika ekranu.
   *
   * Razem z nimi schodzą podpisy w PASKU NARZĘDZI — i to jest poprawka po
   * pomiarze na tablecie, czyli szerokości, która wypadała między dwoma
   * zapytaniami i przez to nie dostawała żadnego. Podpisy chowały się dopiero
   * poniżej 640 px, a tablet pionowy ma 768–834: siedem przycisków z nazwami
   * nie mieściło się w wierszu i pasek rósł z 48 px do 90, czyli o połowę
   * wysokości drugiego paska. W poziomie ten sam tablet mieścił wszystko
   * w jednym rzędzie — więc usterka pokazywała się dopiero po obróceniu.
   *
   * Nazwa nie ginie: `podpisPaska` wpisuje ją jednocześnie w podpowiedź
   * i w `aria-label`, więc czytnik ekranu i najechanie myszą mówią to samo
   * co przedtem.
   */
  .bar-narzedzia .bar-nazwa,
  .bar-foot .bar-rozdzial .bar-nazwa {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    clip-path: inset(50%);
    overflow: hidden;
  }
}

@media (max-width: 640px) {
  /*
   * DWA RZĘDY SKLEJAJĄ SIĘ W JEDEN CIĄG.
   *
   * Rzędy oddają swoje dzieci pojemnikowi przez `display: contents`, a on
   * układa je zawijanym rzędem — dzięki temu dziesięć celów mieści się
   * w dwóch rzędach po czterdzieści cztery piksele, a nie w trzech.
   *
   * Podział na „gdzie jestem" i „co robię z tekstem" ma sens tam, gdzie jest
   * miejsce na dwa rzędy. Na telefonie liczy się wyłącznie to, ile pikseli
   * zostaje książce: przed sklejeniem pasek brał 161 px z ośmiuset.
   */
  .bar-czytnik {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 3px;
    padding: var(--space-2) max(var(--space-2), env(safe-area-inset-left))
             var(--space-2) max(var(--space-2), env(safe-area-inset-right));
    border-bottom: 1px solid var(--color-divider);
  }

  .bar-czytnik > .bar { display: contents; }

  /* Odepchnięcia na prawy skraj nie mają w jednym ciągu sensu: rzędy zmieniają
     się z każdym przyciskiem, który się chowa. */
  .bar-motyw, .tryb { margin-left: 0; }

  /* Tryb chowa podpisy tak samo jak reszta paska — każde położenie ma własny
     znak, więc po podpisie zostaje coś widocznego, a nie pusty prostokąt.
     Cel pod palec zostaje pełny: 44 px, jak wszędzie indziej w tym pasku. */
  .bar .tryb .button, .tryb .button { width: 44px; }

  .bar-motyw .bar-nazwa {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    clip-path: inset(50%);
    overflow: hidden;
  }
}

/* --- Strona powitalna --------------------------------------------------- */

/*
 * Widok, który tłumaczy produkt. Wszystko poniżej stoi na tokenach z góry
 * pliku, więc motyw ciemny nie wymaga tu ani jednej osobnej barwy — poza
 * jednym wyjątkiem, opisanym przy `.pow-cta`.
 *
 * Miary są tu WIĘKSZE niż w aplikacji i to jest zamierzone. W bibliotece
 * liczy się, ile pozycji mieści się na ekranie; tutaj liczy się, żeby
 * pierwsze zdanie dało się przeczytać z odległości, z jakiej ogląda się
 * stronę, o której jeszcze nic się nie wie.
 */

#view-welcome {
  /* Szerokość treści. Jedna zmienna, bo pasek, sekcja główna, bloki i stopka
     muszą trzymać tę samą oś — inaczej strona „drga" przy przewijaniu. */
  --pow-szer: 1120px;
  --pow-tekst: 34rem;
  background: var(--color-bg);
}

.pow-pasek {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  max-width: var(--pow-szer);
  margin: 0 auto;
  padding: var(--space-4) max(var(--space-6), env(safe-area-inset-left))
           var(--space-4) max(var(--space-6), env(safe-area-inset-right));
  background: var(--color-bg);
}

/*
 * Znak powitania jest TYM SAMYM znakiem, co w pasku aplikacji — te same
 * znaczniki i te same klasy `brand-*`. Zostaje tu wyłącznie odstęp, bo
 * nagłówek powitania ma własny rytm; wszystko, co decyduje o wyglądzie
 * samego znaku, opisuje jedna reguła wyżej, w `.brand-*`.
 */
.pow-znak { display: flex; align-items: center; gap: var(--space-3); }
.pow-znak svg { flex: none; }

.pow-nawigacja {
  display: flex;
  gap: var(--space-5);
  margin-left: auto;
}

.pow-link {
  appearance: none;
  border: 0;
  background: none;
  padding: 6px 2px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.875rem;
  color: var(--color-text);
  border-bottom: 1px solid transparent;
}

.pow-link:hover { border-bottom-color: var(--color-accent); }

.pow-akcje { display: flex; align-items: center; gap: var(--space-2); }
.pow-theme { color: var(--color-neutral-500); }
.pow-otworz { border-color: var(--color-accent); color: var(--color-accent-700); }

/* --- sekcja główna --- */

.pow-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  align-items: center;
  gap: var(--space-8);
  max-width: var(--pow-szer);
  margin: 0 auto;
  padding: clamp(var(--space-5), 4vw, var(--space-8)) var(--space-6);
}

.pow-hero-tekst { max-width: var(--pow-tekst); }

.pow-nadtytul {
  margin: 0 0 var(--space-5);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.pow-tytul {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(2.6rem, 5.4vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

/* Drugie zdanie nagłówka. Akcent jest tu PLAMĄ, nie kreską — strona
   powitalna jest jedynym miejscem, w którym ta reguła ustępuje, i ustępuje
   świadomie: ten ekran ma jedno zadanie i jedno działanie. */
.pow-tytul-akcent { color: var(--color-accent); }

.pow-opis {
  margin: 0 0 var(--space-5);
  font-size: 1.0625rem;
  line-height: 1.62;
  max-width: 26rem;
}

.pow-cta-rzad {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

/*
 * JEDYNE WYPEŁNIENIE ZŁOTEM W CAŁYM PROJEKCIE — i tylko tutaj.
 *
 * Reguła systemu mówi, że akcent jest kreską, nie plamą; wewnątrz aplikacji
 * zostaje tak, jak było. Strona powitalna ma jednak jedno zadanie i jedno
 * działanie, a obrys przegrywa na niej z ilustracją obok. Zaakceptowana
 * makieta pokazuje przycisk wypełniony i to jest tu rozstrzygnięcie.
 *
 * Tusz na złocie zostaje CIEMNY w obu motywach, bo samo złoto w obu motywach
 * jest jasne — jasne pismo dałoby na nim około 2:1.
 */
/* Wejście do aplikacji. Barwę i wypukłość bierze z `.button.primary` —
   tutaj zostaje sam rozmiar, bo to ten sam przycisk, tylko większy. */
.button.pow-cta {
  font-size: 1rem;
  padding: 13px 30px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .5),
    0 10px 18px -10px rgba(168, 76, 0, .75);
}

/* Rozjaśnienie, nie przyciemnienie — i w obu motywach tak samo.
   Token `--color-accent-400` idzie w ciemnym motywie w drugą stronę i tusz
   na nim schodził do 4,49:1, czyli tuż pod próg. */
.button.pow-cta:hover:not(:disabled),
.button.pow-cta:active:not(:disabled) {
  background: color-mix(in srgb, var(--klawisz-pelny-tlo) 88%, var(--color-text));
  border-color: color-mix(in srgb, var(--klawisz-pelny-tlo) 88%, var(--color-text));
  color: #241c0d;
}

.pow-kontynuuj { font-size: 0.9375rem; }

/* Panel wyróżniony: brzoskwinia, obrys w akcencie, tekst ZAWSZE atramentowy.
   Tak każe księga marki i tak jest w zaakceptowanym projekcie. */
.pow-panel {
  margin: 0;
  padding: var(--space-4) var(--space-5);
  border-radius: var(--promien-kafel);
  border: 1px solid color-mix(in srgb, var(--color-accent) 30%, transparent);
  background: var(--papier-pole-tlo);
  color: var(--color-text);
  max-width: 30rem;
}

.pow-darmo {
  margin: 0 0 4px;
  font-weight: 700;
  font-size: 0.9375rem;
}

.pow-nota {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--color-neutral-500);
  max-width: 26rem;
}

/* Wewnątrz panelu nota jest atramentowa — szary tusz na brzoskwini schodzi
   poniżej progu, a barwa panelu ma podnosić, nie przyciemniać. */
.pow-panel .pow-nota { color: var(--color-text); max-width: none; }

.pow-hero-obraz img,
.pow-blok-obraz img,
.pow-krok-obraz img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

.pow-linia {
  max-width: var(--pow-szer);
  margin: var(--space-4) auto 0;
  border: 0;
  border-top: 1px solid var(--color-divider);
}

/* --- trzy obszary --- */

.pow-trzy {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6) var(--space-8);
  max-width: var(--pow-szer);
  margin: 0 auto;
  padding: var(--space-8) var(--space-6);
  list-style: none;
}

.pow-trzy > li { display: flex; flex-direction: column; gap: var(--space-2); }
.pow-trzy .pow-ikona { color: var(--color-accent); margin-bottom: var(--space-1); }

.pow-trzy h2,
.pow-trzy h3 {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.625rem;
  line-height: 1.15;
}

.pow-trzy p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.62;
  color: color-mix(in srgb, var(--color-text) 88%, transparent);
}

.pow-trzy-karty > li {
  border-top: 1px solid var(--color-divider);
  padding-top: var(--space-4);
}

.pow-trzy-karty h3 { font-size: 1.25rem; }

/* --- sekcje --- */

.pow-sekcja {
  max-width: var(--pow-szer);
  margin: 0 auto;
  padding: clamp(var(--space-6), 5vw, 72px) var(--space-6);
}

.pow-naglowek {
  text-align: center;
  max-width: 40rem;
  margin: 0 auto var(--space-8);
}

.pow-naglowek h2 {
  margin: 0 0 var(--space-3);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
  text-wrap: balance;
}

.pow-naglowek p {
  margin: 0;
  font-size: 1.0625rem;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
}

/* --- bloki możliwości --- */

.pow-blok {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-6) 0;
}

.pow-blok.odwrotnie .pow-blok-obraz { order: 2; }

.pow-blok-tekst { max-width: 26rem; }

.pow-numer {
  margin: 0 0 var(--space-2);
  font-size: 0.75rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.pow-blok-tekst h3,
.pow-krok-tekst h3 {
  margin: 0 0 var(--space-3);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  line-height: 1.12;
  text-wrap: balance;
}

.pow-blok-tekst p,
.pow-krok-tekst p {
  margin: 0;
  font-size: 1rem;
  line-height: 1.62;
  color: color-mix(in srgb, var(--color-text) 88%, transparent);
}

/* Próbka kotwic — składana silnikiem czytnika, więc wygląda dokładnie tak,
   jak będzie wyglądał tekst w książce. */
.pow-probka {
  margin-top: var(--space-5);
  border-left: 2px solid var(--color-accent-300);
  padding-left: var(--space-4);
}

.pow-probka-podpis {
  margin: 0 0 4px;
  font-size: 0.6875rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.pow-probka-podpis + .pow-probka-tekst { margin-bottom: var(--space-4); }
.pow-probka-tekst:last-child { margin-bottom: 0; }

.pow-probka-tekst p {
  margin: 0;
  font-family: var(--reader-font);
  font-size: 0.9375rem;
  line-height: 1.6;
  font-weight: var(--text-weight);
}

/* --- kroki --- */

.pow-kroki {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* Nić przewodnia między krokami. Rysowana raz, pod numerami, a nie odcinkami
   przy każdym z nich — odcinki rozjeżdżały się przy krokach różnej wysokości. */
.pow-kroki::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 3rem;
  bottom: 3rem;
  width: 1px;
  background: var(--color-accent-300);
}

.pow-krok {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 4.5rem minmax(0, 1fr);
  align-items: center;
  gap: var(--space-5);
}

.pow-krok-obraz { grid-column: 1; grid-row: 1; }
.pow-krok-nr { grid-column: 2; grid-row: 1; }
.pow-krok-tekst { grid-column: 3; grid-row: 1; max-width: 24rem; }

.pow-krok:nth-child(even) .pow-krok-obraz { grid-column: 3; }
.pow-krok:nth-child(even) .pow-krok-tekst { grid-column: 1; justify-self: end; }

.pow-krok-nr {
  justify-self: center;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--color-accent);
  border-radius: 50%;
  background: var(--color-bg);
  /* Cyfry wersalikowe, nie tekstowe: niska jedynka bez stopki czytała się
     w kółku jak litera „I". Atkinson ma takie cyfry z natury; zapis zostaje,
     żeby zmiana kroju interfejsu nie przywróciła tego kłopotu po cichu. */
  font-family: var(--font-body);
  font-variant-numeric: lining-nums;
  font-size: 1rem;
  color: var(--color-accent-700);
}

.pow-krok-nota {
  margin-top: var(--space-2) !important;
  font-size: 0.875rem !important;
  font-style: italic;
  color: var(--color-neutral-500) !important;
}

/* --- FAQ --- */

.pow-faq-lista {
  max-width: 44rem;
  margin: 0 auto;
  border-top: 1px solid var(--color-divider);
}

/*
 * KRESKI MIĘDZY PYTANIAMI RYSUJE JEDNA REGUŁA — `details + details` w bloku
 * kart niżej. Stała tu jeszcze dolna kreska każdego pytania i obie leżały na
 * sobie: między pytaniami wychodziły 2 px zamiast 1, a pod ostatnim pytaniem
 * kreska dublowała obwódkę karty. Dół listy zamyka sama karta.
 */

/*
 * Wiersz ma wcięcie z obu stron, bo lista jest kartą (blok 7a niżej): bez
 * niego znak stał przyklejony do obwódki. Wartości z projektu — 20 px wcięcia
 * i 14 px między znakiem a pytaniem — w skali odstępów aplikacji.
 */
.pow-faq-lista summary {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.125rem;
}

.pow-faq-lista summary::-webkit-details-marker { display: none; }

/*
 * Znak „+" zamienia się w „−" po rozwinięciu. Rysujemy go sami, bo domyślny
 * trójkąt przeglądarki wygląda w każdej inaczej.
 *
 * ZNAK JEST JEDEN I STOI Z LEWEJ, przed pytaniem — tak rysuje go projekt 7a.
 * Był tu kiedyś drugi, z prawej, dołożony w bloku 7a jako `::after`, i przez
 * pewien czas każde pytanie niosło dwa plusy w dwóch barwach. Kto chce znak
 * przenieść, przenosi TEN, zamiast dopisywać następny.
 */
.pow-faq-lista summary::before {
  content: '+';
  flex: none;
  width: 1rem;
  color: var(--color-accent-700);
  font-size: 1.125rem;
}

.pow-faq-lista details[open] summary::before { content: '\2212'; }

/* Odpowiedź zaczyna się pod pytaniem, nie pod znakiem: wcięcie wiersza,
   szerokość znaku i odstęp za nim. */
.pow-faq-lista p {
  margin: 0 0 var(--space-4);
  padding: 0 var(--space-5) 0 calc(var(--space-5) + 1rem + var(--space-3));
  font-size: 0.9375rem;
  line-height: 1.66;
  color: color-mix(in srgb, var(--color-text) 88%, transparent);
}

/* --- stopka --- */

.pow-stopka {
  max-width: var(--pow-szer);
  margin: 0 auto;
  padding: var(--space-8) var(--space-6) 96px;
  border-top: 1px solid var(--color-divider);
  text-align: center;
}

.pow-stopka .pow-cta-rzad { justify-content: center; }
/* W stopce panel jest już samym pasem — druga brzoskwinia na brzoskwini
   wygląda jak kartka położona na kartce, a nie jak wyróżnienie. */
.pow-stopka .pow-panel {
  margin-inline: auto;
  text-align: center;
  background: none;
  border: 0;
  padding: 0;
  box-shadow: none;
}
.pow-stopka .pow-nota { margin-inline: auto; }

.pow-stopka-tekst {
  margin: 0 0 var(--space-5);
  font-family: var(--font-heading);
  font-size: 1.5rem;
  font-weight: 700;
}

.pow-stopka .byline { margin-top: var(--space-6); }

/* Prywatność i regulamin — najcichszy wiersz na stronie, ale musi dać się
   kliknąć palcem, więc odstęp pionowy jest większy niż sam wygląda: pole
   dotyku kończy się na krawędzi tekstu, nie na krawędzi liter. */
.pow-prawne {
  margin: var(--space-2) 0 0;
  font-size: 0.8125rem;
  color: var(--color-neutral-500);
}

.pow-prawne a {
  color: inherit;
  display: inline-block;
  /* Pionowo drugi stopień skali, nie pierwszy: przy 13 px pisma pierwszy dawał
     pole dotyku wysokie na 29 px, czyli mniej, niż pewnie trafia kciuk. */
  padding: var(--space-2) var(--space-2);
}

.pow-prawne a:hover { color: var(--color-text); }

/* --- wąskie ekrany --- */

@media (max-width: 900px) {
  .pow-hero,
  .pow-blok { grid-template-columns: minmax(0, 1fr); }
  .pow-blok.odwrotnie .pow-blok-obraz { order: 0; }
  /* Po złożeniu w jedną kolumnę ilustracja idzie POD tekst, nie nad niego:
     postawiona na górze zajmowała cały pierwszy ekran, a nagłówek — czyli
     jedyne zdanie, po które ktoś tu przyszedł — spadał poniżej krawędzi. */
  .pow-hero-obraz,
  .pow-blok-obraz { max-width: 30rem; margin-inline: auto; width: 100%; }
  .pow-trzy { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }

  .pow-kroki::before { display: none; }
  .pow-krok,
  .pow-krok:nth-child(even) {
    grid-template-columns: 2.75rem minmax(0, 1fr);
    align-items: start;
    gap: var(--space-3);
  }
  /* Wagę selektorów trzymamy równą tej z układu szerokiego — inaczej reguły
     dla kroków parzystych zostają w mocy i tekst ląduje w kolumnie numeru. */
  .pow-krok:nth-child(n) .pow-krok-nr { grid-column: 1; grid-row: 1; justify-self: start; }
  .pow-krok:nth-child(n) .pow-krok-tekst {
    grid-column: 2;
    grid-row: 1;
    justify-self: start;
    max-width: none;
  }
  .pow-krok:nth-child(n) .pow-krok-obraz { grid-column: 2; grid-row: 2; }
}

@media (max-width: 620px) {
  /* Nawigacja odchodzi pierwsza: na telefonie i tak przewija się kciukiem,
     a „Otwórz Lectano" ma zostać widoczne. */
  .pow-nawigacja { display: none; }
  .pow-akcje .lang-switch { display: none; }
  .pow-theme span { display: none; }
  /* Na telefonie pasek musi zmieścić znak, motyw i wejście do aplikacji
     w 375 px. Nawigacja odeszła wyżej; reszta schodzi o stopień, bo to
     „Otwórz Lectano" ma zostać całe — obcięty przycisk wygląda jak
     zepsuta strona, a nie jak ciasny ekran. */
  .pow-pasek { padding-inline: var(--space-4); gap: var(--space-2); }
  /* Rozmiaru znaku tu NIE ustawiamy. Przy 46rem robi to reguła `brand-mark`
     wspólna dla paska aplikacji i powitania — własne 32 px dawałyby dwa
     nieznacznie różne znaki w tym samym produkcie, czyli dokładnie to, czego
     ujednolicenie miało się pozbyć. */
  .button.pow-otworz { font-size: 0.8125rem; padding: 6px 12px; }
  .pow-hero,
  .pow-sekcja,
  .pow-trzy,
  .pow-stopka { padding-inline: var(--space-4); }
  .pow-cta { width: 100%; }
  .pow-krok-obraz { max-width: 22rem; }
}

/* --- Ustawienia: podstawowe i zaawansowane ------------------------------ */

/*
 * Reszta ustawień chowa się za jednym rozwinięciem. Nie jest to ukrywanie:
 * podpis mówi wprost, co tam jest, a stan rozwinięcia pamięta przeglądarka
 * przez czas życia strony.
 */
.zaawansowane { border-top: 1px solid var(--color-divider); }

.zaawansowane > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

.zaawansowane > summary::-webkit-details-marker { display: none; }

/*
 * Rozwinięcie: strzałka w prawo, obrócona w dół po otwarciu. Obrót zamiast
 * dwóch osobnych znaków, bo to jeden przełącznik w dwóch stanach — a ruch
 * mówi, co się właśnie stało, zamiast podmieniać obrazek bez słowa.
 */
.zaawansowane-strzalka {
  color: var(--color-accent);
  transition: transform 150ms ease;
}

.zaawansowane[open] > summary .zaawansowane-strzalka { transform: rotate(90deg); }

/* Przywrócenie domyślnych stoi na końcu podstawowych, nie na górze:
   to wyjście awaryjne, a nie pierwsza rzecz, po którą się sięga. */
.settings-reset { align-self: flex-start; margin-top: var(--space-2); }

/* --- Menu „Zapisz" w pasku czytnika ------------------------------------- */

/*
 * Wygląd bierze z menu tablicy — to ten sam rodzaj rzeczy i nie ma powodu,
 * żeby dwa rozwijane menu w jednym programie wyglądały inaczej. Stąd wspólne
 * klasy `board-menu-lista` i `board-menu-pozycja`; własne jest tylko
 * zaczepienie, bo tamto wisi pod paskiem tablicy, a to pod przyciskiem.
 */
.menu-zapisu { position: relative; display: inline-flex; }

/*
 * LISTA WYCHODZI POZA KARTĘ CZYTELNI.
 *
 * `.bar-czytnik` jest kartą z zaokrąglonym rogiem i ma `overflow: hidden`,
 * żeby tła pasów nie wychodziły poza ten róg. Lista zapisu wisi wewnątrz tej
 * karty, więc była przycinana do jej krawędzi — zgłoszone jako „po kliknięciu
 * »Zapisz« rozwijane menu jest ucięte". Zmierzone: trzy pozycje na trzy
 * niewidoczne.
 *
 * To ta sama pułapka, co dwa razy na tablicy, i to samo wyjście: `fixed`
 * wyjmuje listę z pudełka przodka, a miejsce liczy skrypt, bo współrzędnych
 * okna nie da się wyprowadzić ze stylu. Ważne, żeby `.menu-zapisu` NIE miało
 * przy tym przekształcenia — przekształcony przodek unieważnia `fixed`.
 */
.menu-zapisu-lista {
  position: fixed;
  right: auto;
  min-width: 232px;
}

.menu-zapisu-lista .board-menu-pozycja:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Nota o pamięci przeglądarki. Nie jest pozycją menu i nie może nią wyglądać:
   bez wskaźnika, bez podświetlenia, mniejszym pismem, za kreską. */
.menu-zapisu-nota {
  margin: 4px 0 0;
  padding: var(--space-2) 10px 4px;
  border-top: 1px solid var(--color-divider);
  font-size: 0.6875rem;
  line-height: 1.5;
  color: var(--color-neutral-500);
}


/* --- Oznaczenia wspierające naukę --------------------------------------- */

/*
 * Nazwy oznaczeń wyglądają jak NAPISY, nie jak przyciski: to zdania ucznia
 * o fragmencie, a rząd pięciu prostokątów nad zaznaczeniem wyglądałby jak
 * drugi pasek narzędzi i zasłaniałby tekst, o który chodzi.
 */
.selection-znaki {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  width: 100%;
  padding-top: 6px;
  margin-top: 2px;
  border-top: 1px solid var(--color-divider);
}

.znak-chip {
  appearance: none;
  border: 1px solid var(--color-divider);
  border-radius: 999px;
  background: transparent;
  padding: 3px 10px;
  font-family: var(--font-body);
  font-size: 0.75rem;
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
}

.znak-chip:hover { background: color-mix(in srgb, var(--color-text) 8%, transparent); }

.znak-chip[aria-pressed='true'] {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  color: var(--color-accent-700);
}

/* Filtr w szufladzie uwag — ten sam znak, inne miejsce. */
.notes-znaki {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 0 var(--space-5) var(--space-3);
}

/*
 * Oznaczenie na liście uwag. Stoi PRZED cytatem, bo odpowiada na pytanie
 * zadawane pierwsze: czym ten wpis jest. Złoty obrys, nie plama — na liście
 * kilkudziesięciu wpisów plamy zlałyby się w tło.
 */
.note-znak {
  display: inline-block;
  margin-right: 6px;
  padding: 1px 7px;
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
  color: var(--color-neutral-500);
  white-space: nowrap;
}


/* Nazwane relacje w pasku kontekstowym tablicy. Chipy, nie przyciski akcji:
   to jest napis do wyboru, a nie polecenie do wykonania. */
.board-kontekst-relacje {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.board-kontekst-relacje .znak-chip {
  font-size: 0.6875rem;
  padding: 2px 8px;
}


/* „Rozwiń" w wierszu listy uwag. Cichy, bo to droga rzadsza niż skok do
   fragmentu — ale stała, więc nie chowa się pod najechaniem. */
.note-rozwin,
.note-wskaz {
  flex: none;
  align-self: center;
  font-size: 0.75rem;
  padding: 4px 10px;
}


/* --- Po sprawdzianie: do czego warto wrócić ----------------------------- */

.quiz-powtorka {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-divider);
}

.quiz-powtorka-tytul {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9375rem;
}

.quiz-powtorka ul { margin: 0; padding: 0; list-style: none; }

.quiz-powtorka li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-divider);
  font-size: 0.875rem;
}

.quiz-powtorka li:last-child { border-bottom: 0; }

/*
 * Stan odpowiedzi. Barwa NIE niesie tu znaczenia sama — niesie je napis,
 * a barwa go tylko wzmacnia. Ktoś, kto nie odróżnia czerwieni od szarości,
 * ma przeczytać „źle" i „bez odpowiedzi" tak samo jak wszyscy.
 */
.quiz-stan {
  flex: none;
  padding: 1px 7px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.6875rem;
  white-space: nowrap;
}

.quiz-stan-blad { color: var(--error-ink); }
.quiz-stan-brak { color: var(--color-neutral-500); }

.quiz-powtorka-tresc { font-weight: 700; }

.quiz-powtorka-czemu,
.quiz-powtorka-cytat {
  flex-basis: 100%;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
}

.quiz-powtorka-cytat {
  font-style: italic;
  padding-left: var(--space-3);
  border-left: 2px solid var(--color-accent-300);
}

.quiz-zglos { flex: none; margin-left: auto; font-size: 0.75rem; }

/*
 * Samoocena i notatka — cichy rząd pod pytaniem.
 *
 * Wyglądają jak „Zgłoś problem", bo należą do tej samej rodziny: to są zdania
 * UCZNIA o odpowiedzi, a nie ocena maszyny. Ocena maszyny stoi wyżej i ma
 * własny, mocniejszy zapis; gdyby te trzy wyglądały tak samo, po tygodniu nie
 * dałoby się poznać, kto co powiedział.
 */
.quiz-samoocena {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  flex: none;
}

.quiz-samoocena-guzik,
.quiz-notatka {
  font-size: 0.75rem;
  color: var(--color-neutral-500);
}

.quiz-samoocena-guzik[aria-pressed='true'] {
  color: var(--color-accent-700);
  font-weight: 700;
}

.quiz-samoocena-guzik:hover,
.quiz-notatka:hover { color: var(--color-text); }


/* „Nie wiem" stoi obok wariantów, ale nie udaje jednego z nich: bez obrysu,
   cichszym pismem. To jest odpowiedź o czymś innym niż one. */
.quiz-nie-wiem {
  color: var(--color-neutral-500);
  font-style: italic;
}


/* Brak odpowiedzi — ani zielono, ani czerwono. Szaro, bo to jest stan
   trzeci, a nie łagodniejsza odmiana błędu. */
.pytanie-warianty .is-brak,
.pytanie-ocena.is-brak {
  border-color: var(--color-neutral-400);
  color: var(--color-neutral-500);
}

/*
 * Blok stoi NA KOŃCU pliku i to jest jego jedyne poprawne miejsce.
 * Reguły poziomów mają tę samą wagę co reguły bazowe paska, więc
 * rozstrzyga kolejność. Postawiony wyżej — a tam wylądował za pierwszym
 * razem — przegrywał z `.board-tool-znak` i telefon dostawał klawisze
 * trzydziestoczteropikselowe zamiast czterdziestoczteropikselowych.
 * Zmierzone, nie przewidziane.
 */
/* ====================================================================
 * ZWIJANIE PASKA — trzy poziomy, jeden komplet przycisków
 *
 * Które narzędzia zostają w pastylce, rozstrzyga JS (`ustawPoziomPaska`):
 * wypadające PRZENOSZĄ SIĘ do panelu „Więcej", a nie chowają się klasą.
 * Tutaj są tylko rozmiary, położenie i to, co da się powiedzieć samym CSS-em.
 *
 * Progi: powyżej 1100 px wariant 2a, 700–1100 wariant 3a, poniżej 700 — 3b.
 * ==================================================================== */

/* --- 3a: tablet ----------------------------------------------------- */
@media (min-width: 700px) and (max-width: 1100px) {
  .board-tools { gap: 3px; }
  .board-tool-znak { width: 38px; height: 38px; }
  .board-tool-znak svg { width: 20px; height: 20px; }

  /*
   * Papier jako ikona. Zostaje listą wyboru — podmiana na własny przycisk
   * zabrałaby obsługę z klawiatury i czytnikami ekranu, którą przeglądarka
   * daje za darmo. Znika sam NAPIS: nazwę niesie ikona i podpowiedź.
   */
  .board-papier {
    min-width: 58px;
    max-width: 58px;
    padding: 0 22px 0 8px;
    /*
     * Napis znika, zostaje ikona. Barwa przezroczysta, a nie `font-size: 0`:
     * rozmiar zerowy potrafi zabrać polu wysokość i zepsuć wyrównanie, a i tak
     * niektóre przeglądarki wyliczają z niego szerokość samoistną.
     * Nazwa nie ginie — niesie ją podpowiedź i opis dla czytników ekranu.
     */
    color: transparent;
    background-image:
      url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgb(92,68,19)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='4' width='17' height='16' rx='2'/%3E%3Cpath d='M7 9h10M7 12.5h10M7 16h6'/%3E%3C/svg%3E"),
      url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb(92,68,19)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E"),
      var(--papier-pole-tlo);
    background-repeat: no-repeat, no-repeat, no-repeat;
    background-position: left 8px center, right 6px center, 0 0;
    background-size: 19px 19px, 11px 11px, auto;
  }
}

/* --- 3b: telefon ---------------------------------------------------- */
@media (max-width: 699px) {
  /*
   * Pastylka schodzi NA DÓŁ ekranu. Kciuk sięga tam bez przekładania telefonu,
   * a na górze zostaje tytuł tablicy, który przy pasku pod nim i tak nie miał
   * gdzie się zmieścić. Odstęp od dołu liczy się z obszarem bezpiecznym —
   * na telefonach z paskiem gestów pasek bez tego leży dokładnie pod nim.
   */
  .board-tools {
    position: fixed;
    z-index: 9;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
    left: 0;
    right: 0;
    margin: 0 auto;
    padding: 5px;
    gap: 2px;
  /*
   * ŚRODEK LICZONY MARGINESEM, NIE `transform`.
   *
   * Przekształcony przodek unieważnia `position: fixed` u wszystkich potomków:
   * przestają liczyć się od okna, a zaczynają od niego. Lista menu „…" wisi
   * WEWNĄTRZ pastylki, więc wyliczone dla niej współrzędne okna lądowały
   * wewnątrz paska — zmierzone: `top: 110px` wychodziło na 899 pikselu przy
   * oknie wysokim na 852, a `top` i `bottom` naraz w pudełku wysokim na 56
   * zgniatały listę do dwudziestu sześciu pikseli. Z zewnątrz wyglądało to
   * dokładnie jak menu, które się nie otwiera — i tak zostało zgłoszone.
   *
   * `left: 0; right: 0` przy `width: max-content` i marginesie `auto` stawia
   * pastylkę w tym samym miejscu, co `translateX(-50%)`, i nie tworzy
   * pudełka odniesienia dla niczego.
   */
  }

  /*
   * STEROWANIE WIDOKIEM USTĘPUJE PASTYLCE.
   *
   * Pastylka jest tu przypięta do dolnej krawędzi OKNA, a sterowanie
   * powiększeniem do dolnej krawędzi TABLICY. Na pełnym ekranie to jedno
   * i to samo miejsce, więc przy podziale — gdzie tablica bywa niska —
   * pastylka wchodziła na „100%" i na przycisk dopasowania. Zgłoszone jako
   * nałożone na siebie narzędzia.
   *
   * Podnosimy sterowanie o wysokość pastylki z odstępem. Ustępuje ono, a nie
   * pastylka, bo pastylka jest tym, po co sięga kciuk najczęściej, i to ona
   * ma zostać w zasięgu bez przekładania telefonu.
   */
  .board-widok {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 8px + 62px);
  }

  /* Czterdzieści cztery piksele to najmniejszy cel, w który palec trafia bez
     celowania. Poniżej zaczyna się chybianie, a chybienie na pasku narzędzi
     znaczy narysowanie czegoś nie tym, czym się chciało. */
  .board-tool-znak { width: 44px; height: 44px; }

  /*
   * Separator schodzi z jedenastu pikseli do pięciu. Rozmiar celów jest
   * nietykalny, więc miejsce trzeba znaleźć tam, gdzie w nic się nie celuje.
   * Zmierzone przy 320 px: z szerokimi separatorami pastylka wychodziła
   * o pięć pikseli poza ekran z każdej strony i przycisk „Więcej" siedział
   * częściowo za krawędzią — czyli był, ale nie dało się go dotknąć.
   */
  .board-sep { width: 5px; min-width: 5px; }
  .board-tool-znak svg { width: 21px; height: 21px; }

  /* Panel „Więcej" wychodzi W GÓRĘ — pod pastylką nie ma już ekranu. */
  .board-menu-lista {
    top: auto;
    right: 0;
    bottom: calc(100% + 8px);
    max-width: calc(100vw - 24px);
    /*
     * Panel przewija się, zamiast rosnąć poza ekran. Mieszkają w nim teraz dwie
     * rzeczy naraz: narzędzia, które wypadły z pastylki, i pozycje otwierające
     * panele boczne. Na telefonie o wysokości 760 px suma tego bywa wyższa niż
     * ekran, a panel, którego górnej części nie da się dosięgnąć, jest gorszy
     * niż panel z paskiem przewijania.
     */
    max-height: calc(100dvh - 140px);
    overflow-y: auto;
    padding: 12px;
    border-color: var(--panel-wiecej-obwodka);
    border-radius: var(--promien-panel);
    background: var(--panel-wiecej-tlo);
    box-shadow: var(--panel-wiecej-cien);
  }
}

/* --- panel „Więcej": narzędzia, które wypadły ------------------------ */
.board-menu-narzedzia {
  display: grid;
  grid-template-columns: repeat(4, 44px);
  gap: 8px;
  padding: 4px;
}

.board-menu-narzedzia .board-tool-znak {
  width: 44px;
  height: 44px;
  border-radius: var(--promien-kafel);
  background: var(--panel-kafel-tlo);
  box-shadow: var(--panel-kafel-cien);
}

.board-menu-narzedzia .board-tool[aria-pressed="true"] {
  background: var(--klawisz-aktywny-tlo);
  box-shadow: var(--klawisz-aktywny-cien);
}

/* Papier w panelu zajmuje cały rząd — jako jedyny niesie napis. */
.board-menu-narzedzia .board-papier {
  grid-column: 1 / -1;
  min-width: 0;
  max-width: none;
  width: 100%;
  height: 40px;
  border-radius: var(--promien-pole);
}

.board-menu-kreska {
  height: 1px;
  margin: 8px 4px;
  background: var(--panel-hairline);
}

/* --- paleta zwinięta do jednej próbki -------------------------------- */
/*
 * Zwinięta paleta pokazuje BARWĘ BIEŻĄCĄ, czyli tę z `aria-pressed`. Widoczność
 * bierze się więc ze stanu, który i tak jest utrzymywany — nie ma osobnego
 * „która próbka jest ta jedna" do rozjechania się z wyborem.
 */
.board-colors.zwinieta .board-color { display: none; }
.board-colors.zwinieta .board-color[aria-pressed="true"] { display: inline-flex; }
.board-colors.zwinieta.rozwinieta .board-color { display: inline-flex; }

.board-colors.zwinieta::after {
  content: "";
  width: 12px;
  height: 12px;
  background:
    url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb(92,74,44)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E")
    center / 12px 12px no-repeat;
}

.board-colors.zwinieta.rozwinieta::after { display: none; }

@media (max-width: 1100px) {
  .board-color { width: 24px; height: 24px; }
}

@media (max-width: 699px) {
  /* Pole ma czterdzieści cztery piksele, kółko w nim dwadzieścia pięć. */
  .board-color { width: 44px; height: 44px; }
  .board-color::before { inset: 9.5px; }
}

/* ====================================================================
 * KARTECZKA NA TABLICY — cień ekranu
 *
 * Cień jest WYŁĄCZNIE na ekranie i nie ma go w zapisanym pliku. To nie
 * przeoczenie: rozmyty cień w SVG wymaga filtra, a filtr rasteryzuje się
 * inaczej na ekranie, w cudzym programie graficznym i na płótnie PDF-a.
 * Plik zostaje płaski i wygląda wszędzie tak samo; podgląd wygląda tak,
 * jak zaprojektowano.
 *
 * `drop-shadow` zamiast `box-shadow`, bo kształt jest ścieżką, nie pudełkiem —
 * `box-shadow` obrysowałby prostokąt otaczający, także wokół ściętego rogu.
 * Cena: `drop-shadow` nie zna rozsunięcia, więc dwuwarstwowość projektu
 * odwzorowujemy dwoma cieniami, a nie jednym z ujemnym rozsunięciem.
 * ==================================================================== */
/*
 * CIEŃ, NIE POŚWIATA — i decyduje o tym jedna zależność między liczbami.
 *
 * `drop-shadow` rozmywa cień o promień `b` we WSZYSTKIE strony od miejsca,
 * w które przesunęło go `o`. Dopóki `b` jest większe od `o`, rozmycie sięga
 * ponad górną krawędź kształtu i dookoła niego — czyli powstaje halo. Tak
 * właśnie było: przesunięcie osiem, rozmycie jedenaście, a do tego barwa
 * rodziny zamiast tuszu. Kształty wyglądały przez to na rozmyte.
 *
 * Trzymamy więc `b <= o`: cień zaczyna się poniżej kształtu i nigdzie nad
 * nim nie wychodzi. Barwa zostaje z rodziny, bo cień na papierze jest ciepły,
 * ale krycie schodzi — nasycona plama pod jasnym kształtem czyta się jak
 * druga figura, nie jak cień.
 */
/*
 * TRZY WARSTWY, KAŻDA O CO INNEGO.
 *
 *   KRAWĘDŹ — `0 0 1px` w barwie tuszu. Rozmycie jednego piksela bez
 *   przesunięcia obrysowuje kształt włosem i to ono daje mu ostrość na jasnym
 *   płótnie. To jedyne miejsce, w którym rozmycie sięga dookoła, i jedyne,
 *   w którym wolno: przy jednym pikselu czyta się jako kreska, nie jako halo.
 *
 *   STYK — `0 1px` tuż pod kształtem. Mówi, że coś na czymś leży.
 *
 *   RZUT — dłuższy, w barwie rodziny, bo cień na papierze jest ciepły.
 *
 * REGUŁA, KTÓREJ PILNUJEMY W DWÓCH OSTATNICH: rozmycie nie może być większe
 * od przesunięcia. `drop-shadow` rozmywa we wszystkie strony od miejsca, do
 * którego przesunął cień; przy większym rozmyciu wychodzi ponad górną krawędź
 * i powstaje poświata. Tak było przy `0 8px 11px` i kształty wyglądały na
 * rozmyte, choć liczby przepisałem wiernie z projektu.
 */
/*
 * JEDEN PRZEBIEG, NIE TRZY — i to jest tu cała decyzja.
 *
 * Były trzy i każdy robił co innego: `0 0 1px` ostrzył krawędź, `0 2px 2px`
 * dawał przyleganie, `0 7px 6px` w barwie rodziny podnosił. Wyglądało to
 * dobrze i kosztowało trzy rozmycia na element, liczone od nowa przy każdym
 * przerysowaniu kanwy. Przy czterystu karteczkach naraz robiło się z tego
 * 243 ms na klatkę — cztery klatki na sekundę, czyli tyle, ile trzeba, żeby
 * przeglądarka wyglądała na zawieszoną.
 *
 * Jeden przebieg musi udźwignąć wszystko naraz, więc jest ciaśniejszy
 * i mocniejszy od tamtego podnoszącego: trzy piksele zamiast siedmiu, 52%
 * zamiast 36. Wybrane okiem z czterech kandydatów na tej samej tablicy —
 * przy `0 4px 4px` i `0 5px 5px` boki karteczek robiły się miękkie i całość
 * siadała w tło, bo zabrakło tamtego włoska po krawędzi.
 *
 * Rozmycie nie przekracza przesunięcia i to zostaje regułą: `drop-shadow`
 * rozmywa we wszystkie strony od przesuniętego położenia, więc przy większym
 * rozmyciu cień wychodzi ponad górną krawędź i zamiast cienia jest poświata.
 */
.board-karteczka {
  filter: drop-shadow(0 3px 3px rgb(var(--cien-rodziny, 146 101 22) / 52%));
}

.board-karteczka.rodzina-zolty { --cien-rodziny: var(--karteczka-zolty-cien); }
.board-karteczka.rodzina-brzoskwiniowy { --cien-rodziny: var(--karteczka-brzoskwiniowy-cien); }
.board-karteczka.rodzina-zielony { --cien-rodziny: var(--karteczka-zielony-cien); }
.board-karteczka.rodzina-rozowy { --cien-rodziny: var(--karteczka-rozowy-cien); }
.board-karteczka.rodzina-niebieski { --cien-rodziny: var(--karteczka-niebieski-cien); }

/* Przy przeciąganiu karteczka się unosi — cień dłuższy, kształt odrobinę
   większy. Sto dwadzieścia milisekund: tyle, żeby oko zauważyło podniesienie,
   za mało, żeby czekać na nie z ręką na myszy. */
.board-ciagniete .board-karteczka {
  filter: drop-shadow(0 11px 11px rgb(var(--cien-rodziny, 146 101 22) / 48%));
}

@media (prefers-reduced-motion: no-preference) {
  .board-karteczka { transition: filter var(--ruch-klawisz); }
}

/*
 * BRYŁY TABLICY — ten sam cień co karteczka, tyle że bez pasma światła.
 *
 * `drop-shadow`, nie `box-shadow`: kształt jest ścieżką, a `box-shadow`
 * obrysowałby prostokąt otaczający — wokół rombu dałoby to prostokątną
 * poświatę zawieszoną w powietrzu. Projekt zaznacza to wprost jako jedną
 * z dwóch rzeczy, bez których bryły cięte wypadają ze stylistyki.
 */
/* Jeden przebieg — powód przy karteczce wyżej. Bryła ma o dwa punkty
   mniej krycia niż karteczka, tak jak miała przy trzech warstwach. */
.board-bryla {
  filter: drop-shadow(0 3px 3px rgb(var(--cien-rodziny, 146 101 22) / 50%));
}

.board-bryla.rodzina-zolty { --cien-rodziny: var(--karteczka-zolty-cien); }
.board-bryla.rodzina-brzoskwiniowy { --cien-rodziny: var(--karteczka-brzoskwiniowy-cien); }
.board-bryla.rodzina-zielony { --cien-rodziny: var(--karteczka-zielony-cien); }
.board-bryla.rodzina-rozowy { --cien-rodziny: var(--karteczka-rozowy-cien); }
.board-bryla.rodzina-niebieski { --cien-rodziny: var(--karteczka-niebieski-cien); }

/* Plakietka pod napisem lacznika — patrz tokeny. */
.board-plakietka {
  fill: var(--plakietka-tlo);
  stroke: var(--plakietka-obwodka);
  stroke-width: 1;
}

/* Pas co drugiego wiersza tabeli — powod przy rysowaniu. */
.board-tabela-pas { fill: var(--tabela-pas); }

/* ====================================================================
 * STRONA POWITALNA — wariant 7a
 *
 * Blok stoi NA KOŃCU pliku, bo nadpisuje reguły o tej samej wadze; wyżej
 * przegrałby kolejnością. Ta sama lekcja co przy poziomach paska.
 *
 * Strona już miała całą strukturę z projektu — nagłówek, hero, trzy filary,
 * sekcje z numerami, pięć kroków, FAQ i stopkę. Tutaj jest wyłącznie ubranie
 * jej w warstwę kart z biblioteki, plus jedna rzecz, której nie było wcale:
 * OŚ KROKÓW.
 * ==================================================================== */

/* --- bloki treści jako karty ----------------------------------------- */

.pow-trzy > li,
.pow-faq-lista,
.pow-stopka {
  border: 1px solid var(--karta-obwodka);
  border-radius: 12px;
  background: var(--karta-tlo);
  box-shadow: var(--karta-cien);
}

.pow-trzy > li { padding: var(--space-5); }

.pow-faq-lista {
  border-top: 1px solid var(--karta-obwodka);
  overflow: hidden;
}

/*
 * Stopka jest kartą CIEPLEJSZĄ od reszty — ostatnia rzecz na stronie i jedyna,
 * która o coś prosi. Odrobina bursztynu odróżnia ją od bloków, które tylko
 * opowiadają.
 */
.pow-stopka {
  margin-top: var(--space-8);
  border-color: var(--stopka-obwodka);
  background: var(--stopka-tlo);
}

/* --- kickery --------------------------------------------------------- */

.pow-numer {
  /* 12,5 px i odstęp 0,16 em z projektu. */
  font-size: 0.78125rem;
  letter-spacing: 0.11em;
  font-variant-numeric: tabular-nums;
}

/* --- oś kroków ------------------------------------------------------- */

/*
 * OŚ RYSUJE `.pow-kroki::before` — JEDNA, na całą listę. Jest tam od dawna,
 * razem z komentarzem tłumaczącym dlaczego: odcinki doklejane do każdego kroku
 * rozjeżdżają się przy krokach różnej wysokości.
 *
 * Dołożyłem tu kiedyś drugą taką linię, na pojedynczych krokach, bo czytając
 * arkusz zatrzymałem się na klamrze reguły `.pow-kroki` i nie zobaczyłem
 * `::before` tuż za nią. Skutek był podwójny: na szerokim ekranie dwie linie
 * leżały na sobie i nie było tego widać, a na telefonie została moja — bo
 * blok mobilny ukrywa tamtą po nazwie i o mojej nie wiedział. Linia biegła
 * wtedy przez środek ilustracji, obok numerów stojących z lewej.
 *
 * Tutaj zostaje więc tylko to, czego naprawdę brakowało: barwa osi z projektu
 * i kółko leżące NA niej, a nie pod nią.
 */
.pow-kroki::before { background: var(--os-kreska); }

/*
 * Kółko z numerem zasłania oś. Bez własnego tła kreska przechodziłaby przez
 * środek cyfry.
 */
.pow-krok-nr {
  position: relative;
  z-index: 1;
  border-color: var(--os-kolko-obwodka);
  background: var(--os-kolko-tlo);
  color: var(--os-kolko-tusz);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4);
}

/* --- FAQ ------------------------------------------------------------- */

.pow-faq-lista details + details {
  border-top: 1px solid var(--faq-kreska);
}

/* Znak „+"/„−" rysuje reguła FAQ wyżej — jedna, z lewej. */

.pow-faq-lista summary:hover { background: var(--faq-hover); }

/* ====================================================================
 * NAGŁÓWEK CZYTELNI — wariant 8a
 *
 * Blok stoi na końcu pliku, bo nadpisuje reguły o tej samej wadze.
 *
 * JEDNA KARTA, NIE DWA PASKI. Do tej pory były to dwa niezależne rzędy,
 * każdy z własną krawędzią u dołu — czytało się to jak dwa paski aplikacji
 * postawione jeden na drugim. Projekt łączy je w jedną kartę z 6a, a pasy
 * rozdziela włoskiem w środku: „gdzie jestem" i „co robię z tekstem" należą
 * do tej samej rzeczy.
 * ==================================================================== */

.bar-czytnik {
  /*
   * NAGŁÓWEK NIE DAJE SIĘ ŚCISNĄĆ, i to nie jest kosmetyka.
   *
   * `.view-reader` jest kolumną flex, a oba pasy miały wcześniej `flex: 0 0
   * auto` z reguły `.bar` — jako bezpośrednie dzieci kolumny. Opakowanie ich
   * w tę kartę wstawiło między nie a kolumnę element bez tej deklaracji,
   * czyli ściśliwy. Przez pierwsze pół sekundy po otwarciu książki tekst
   * dopominał się o miejsce, karta oddawała jedenaście pikseli, a `overflow:
   * hidden` niżej ukrywało, że jej zawartość wystaje.
   *
   * Kosztowało to miejsce w lekturze: tekst składał się na kolumnie wyższej
   * o te jedenaście pikseli, więc strona mieściła więcej, a jej pierwsze
   * słowo było wcześniejsze — i to wcześniejsze zapisywało się jako miejsce
   * czytania. Po każdym odświeżeniu książka cofała się o kawałek strony.
   */
  flex: 0 0 auto;
  margin: var(--space-3) max(var(--space-4), env(safe-area-inset-left))
          var(--space-3) max(var(--space-4), env(safe-area-inset-right));
  border: 1px solid var(--karta-obwodka);
  border-radius: 12px;
  background: var(--czytelnia-tlo);
  box-shadow: var(--czytelnia-cien);
  overflow: hidden;
}

/* Krawędzie znikają z obu pasów; zostaje jeden włos między nimi. */
.bar-czytnik > .bar { border-bottom: 0; }
.bar-czytnik > .bar-glowny { border-bottom: 1px solid var(--czytelnia-wlos); }

/*
 * „Zapisz" jest zwyklym przyciskiem 6a, a nie plaskim jak narzedzia.
 * To jedyna rzecz w gornym pasie, ktora cos ROBI z ksiazka, a nie tylko
 * mowi, gdzie jestesmy — i jako jedyna ma wygladac na przycisk. Motyw
 * zostaje plaski, bo tylko przelacza to, co i tak widac na ekranie.
 */
/*
 * „ZAPISZ" JEST GŁÓWNĄ CZYNNOŚCIĄ TEGO PASKA — i tak wygląda w projekcie:
 * pomarańczowa plama z białą etykietą, jedyna w rzędzie. Do zmiany marki był
 * tu zwykły klawisz w barwie chromu, nieodróżnialny od „Spis treści" obok,
 * choć jako jedyny w pasku wyprowadza pracę z aplikacji na zewnątrz.
 */
.bar-glowny .menu-zapisu > .button {
  height: 34px;
  padding: 0 14px;
  border: var(--klawisz-pelny-obwodka);
  border-radius: 8px;
  font-weight: 700;
  background-color: var(--klawisz-pelny-tlo);
  background-image: var(--klawisz-pelny-grad);
  box-shadow: var(--klawisz-pelny-swiatlo);
  color: var(--klawisz-pelny-tusz);
}

.bar-glowny .menu-zapisu > .button:hover:not(:disabled) {
  background-image: linear-gradient(180deg, #ff9433 0%, #e56800 100%);
}

.bar-glowny .menu-zapisu > .button svg { color: inherit; }

/* --- pas dolny: narzędzia -------------------------------------------- */

/*
 * NARZĘDZIA W PASTYLCE — ta sama obudowa, co przybornik tablicy.
 *
 * Wariant 8a mówił „narzędzia są PŁASKIE, dopóki nie są włączone" i przy
 * czytaniu tekstu było to w porządku: kotwice albo rytm zwykle są włączone,
 * więc widać bursztynowy klawisz i rząd czyta się jak przybornik.
 *
 * Przy ORYGINALE STRONY nie jest włączone nic — nie ma tam ani spisu treści,
 * ani rytmu — i cały rząd wyglądał jak zwykły napis. Zgłoszone jako „nie ma
 * przycisków". Pomiar pokazał, że style obu pasków są co do piksela te same;
 * różnił je wyłącznie brak wciśniętego klawisza. Reguła sama w sobie nie była
 * zła, tylko zakładała, że coś zawsze jest włączone.
 *
 * Pastylka rozstrzyga to inaczej: pojemnik mówi „tu są narzędzia", a klawisze
 * mają widoczny stan spoczynku. To ta sama obudowa, którą ma tablica, więc
 * dwa przyborniki jednego programu przestają wyglądać jak z dwóch programów.
 */
.bar-przybornik {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding: 5px;
  border: 1px solid var(--pasek-obwodka);
  border-radius: var(--promien-pastylka);
  background: var(--pasek-tlo);
  box-shadow: var(--pasek-cien);
}

.bar-narzedzia .bar-przybornik .button.ghost {
  height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--promien-pastylka);
  background: transparent;
  color: var(--klawisz-znak);
  transition: background var(--ruch-klawisz), box-shadow var(--ruch-klawisz);
}

.bar-narzedzia .bar-przybornik .button.ghost:hover:not(:disabled):not([aria-pressed='true']) {
  background: var(--klawisz-hover-tlo);
  box-shadow: var(--klawisz-hover-cien);
}

.bar-narzedzia .bar-przybornik .button.ghost[aria-pressed='true'] {
  background: var(--klawisz-aktywny-tlo);
  color: var(--klawisz-aktywny-znak);
  box-shadow: var(--klawisz-aktywny-cien);
}

.bar-narzedzia .bar-przybornik .button.ghost[aria-pressed='true']:active {
  box-shadow: var(--klawisz-wcisniety-cien);
}

/* Wyblakły znak, nie wyblakły klawisz — powód przy `.board-tool:disabled`. */
.bar-narzedzia .bar-przybornik .button.ghost:disabled {
  opacity: 1;
  color: var(--klawisz-znak-wylaczony);
}

/* --- pas dolny: segment trybu ---------------------------------------- */

/*
 * Segment jest WGŁĘBIONY: pojemnik z cieniem wewnętrznym, a w nim położenia
 * bez własnych krawędzi. Wcześniej były to trzy przyciski w jednej ramce,
 * rozdzielone kreskami — wyglądało to jak trzy osobne przyciski, które
 * przypadkiem stoją obok siebie, a nie jak jeden wybór z trzech.
 */
.tryb {
  flex: 0 0 auto;
  padding: 3px;
  border: 1px solid var(--karta-obwodka);
  border-radius: 10px;
  background: var(--segment-tlo);
  box-shadow: var(--segment-cien);
  overflow: visible;
}

.tryb .button {
  height: 32px;
  border-radius: 7px;
  padding-inline: 12px;
}

/* Kreski między położeniami znikają — od rozdzielania jest odstęp. */
.tryb .button + .button { border-left: 0; }

.tryb .button[aria-pressed='true'] {
  border: 1px solid var(--czytelnia-wlaczony-obwodka);
  background: var(--czytelnia-wlaczony-tlo);
  color: var(--czytelnia-wlaczony-tekst);
  box-shadow: var(--czytelnia-wlaczony-cien);
}

.tryb .button[aria-pressed='true']:hover:not(:disabled) {
  background: var(--czytelnia-wlaczony-tlo);
}

/* --- telefon ---------------------------------------------------------- */

@media (max-width: 640px) {
  /*
   * Na telefonie karta wraca do płaskiego paska i to jest decyzja sprzed
   * tego wariantu, opisana przy regule wyżej: oba pasy zlewają się w jeden
   * rząd, bo liczy się każdy piksel zostawiony książce. Karta z marginesem,
   * zaokrągleniem i cieniem zabrałaby ich kilkanaście.
   */
  .bar-czytnik {
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
  }
  .bar-czytnik > .bar-glowny { border-bottom: 0; }

  /*
   * Cel pod palec ma czterdziesci cztery piksele, nie trzydziesci cztery.
   * Wysokosc z projektu dotyczy myszy; na telefonie obowiazuje miara palca
   * i ona wygrywa — chybienie w pasku czytelni znaczy wyjscie z ksiazki.
   */
  .bar-narzedzia .button.ghost,
  .bar-glowny .menu-zapisu > .button {
    height: 44px;
    min-height: 44px;
  }

  .tryb .button { height: 40px; }
}

/* ====================================================================
 * PANEL USTAWIEŃ — wariant 8b
 *
 * Blok stoi na końcu pliku, bo nadpisuje reguły o tej samej wadze.
 *
 * Wszystko tu jest zawężone do `#settings-drawer`. Szuflad w programie jest
 * kilka — spis treści, notatki, ślady — i one zostają takie, jakie były;
 * projekt dotyczy ustawień. Reguły bez tego zawężenia zmieniłyby cztery
 * miejsca zamiast jednego, a zauważyłoby się to dopiero na zrzutach.
 * ==================================================================== */

/*
 * KARTA, NIE ŚCIANA. Szuflada przyklejona do krawędzi okna wygląda jak część
 * okna przeglądarki; odsunięta o trzy odstępy i zaokrąglona — jak arkusz
 * położony na tekście, czyli tak samo jak nagłówek czytelni z 8a i kafle
 * biblioteki z 6a. Szerokość 344 px pochodzi wprost z projektu.
 */
/*
 * Karta kończy się na treści, a nie na dolnej krawędzi okna. Rozciągnięta na
 * całą wysokość miała pod „Ustawieniami zaawansowanymi" trzysta pikseli
 * pustego papieru — wyglądało to, jakby coś się nie doładowało. `bottom: auto`
 * z górnym ograniczeniem daje jedno i drugie: krótka lista jest krótka, długa
 * przewija się w środku.
 */
#settings-drawer {
  top: var(--space-3);
  right: var(--space-3);
  bottom: auto;
  max-height: calc(100% - 2 * var(--space-3));
  width: min(21.5rem, calc(100% - 2 * var(--space-3)));
  border: 1px solid var(--karta-obwodka);
  border-radius: 12px;
  background: var(--czytelnia-tlo);
  box-shadow: var(--ust-cien);
  overflow: hidden;
}

/*
 * Panel rozwinięty ociepla się cały: obwódka, papier i cień. Rozwinięcie
 * zaawansowanych to jedyny stan „coś tu grzebię", który widać z zewnątrz —
 * „coś zmienione" nie ma w programie własnego znacznika, bo ustawienia
 * zapisują się od razu i nie ma stanu „niezatwierdzone".
 */
#settings-drawer:has(#settings-advanced[open]) {
  border-color: var(--ust-obwodka-zywa);
  background: var(--ust-tlo-zywe);
  box-shadow: var(--ust-cien-zywy);
}

/* --- nagłówek, wersja, jeden włos ------------------------------------- */

/*
 * Kreska idzie POD WERSJĄ, nie pod tytułem. Numer wydania należy do nagłówka
 * — mówi, czego dotyczą ustawienia pod spodem — a rozdzielony od niego kreską
 * wyglądał jak pierwsza pozycja listy.
 */
#settings-drawer .drawer-head {
  padding: 18px 22px 0;
  border-bottom: 0;
}

#settings-drawer .drawer-head strong { font-size: 1.625rem; }

#settings-drawer .wersja {
  margin: 0 22px;
  padding: 4px 0 14px;
  font-size: 0.78125rem;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--color-neutral-500);
  border-bottom: 1px solid var(--color-divider);
}

/*
 * „ZAMKNIJ" — brzoskwiniowe pole z obrysem w akcencie.
 *
 * Tusz jest tu WŁASNY, a nie pożyczony z tokenu aktywnego narzędzia, i to
 * jest poprawka z rebrandingu: dopóki oba były bursztynowe, jeden token
 * obsługiwał oba miejsca. Aktywne narzędzie stało się czarną plamą z białym
 * napisem, więc ten sam token dał tutaj biel na brzoskwini — 1,09:1.
 * Na brzoskwini tekst jest zawsze atramentowy; mówi to wprost księga marki.
 */
#settings-close {
  height: 30px;
  padding: 0 14px;
  border: 1px solid var(--ust-zamknij-obwodka);
  border-radius: 8px;
  background: var(--ust-zamknij-tlo);
  box-shadow: var(--czytelnia-wlaczony-cien);
  color: var(--color-text);
  font-size: 0.71875rem;
  letter-spacing: 0.09em;
}

#settings-close:hover { color: var(--color-accent-700); }
#settings-close:active { box-shadow: var(--klawisz-wcisniety-cien); }

/* --- grupy i pola ------------------------------------------------------- */

#settings-drawer .section > .kicker {
  font-size: 0.71875rem;
  letter-spacing: 0.11em;
  color: var(--color-neutral-500);
}

/*
 * Nazwa pola jest ciemniejsza od wartości, a nie odwrotnie. Wcześniej krzyczała
 * liczba: „19 px" szło pismem nagłówkowym i pełną czernią, a „Rozmiar pisma"
 * szeptało szarością. Czyta się najpierw nazwę — dopiero ona mówi, czego ta
 * liczba dotyczy.
 */
#settings-drawer .control > label {
  font-size: 0.9375rem;
  color: var(--color-text);
  margin-bottom: 10px;
}

#settings-drawer .control > label b {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.875rem;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
}

#settings-drawer .control { margin-bottom: 18px; }

/*
 * Pasek przewijania cichnie. Systemowy jest szeroki na kilkanaście pikseli
 * i szary — na karcie z zaokrąglonym rogiem kładł się w poprzek zaokrąglenia
 * i był najciemniejszą rzeczą w całym panelu.
 */
#settings-body {
  scrollbar-width: thin;
  scrollbar-color: var(--ust-tor) transparent;
}

#settings-body::-webkit-scrollbar { width: 8px; }
#settings-body::-webkit-scrollbar-track { background: none; }

#settings-body::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: 4px;
  background: var(--ust-tor);
  background-clip: content-box;
}

/* --- suwak -------------------------------------------------------------- */

/*
 * Tor pokazuje drogę przebytą. Firefox rysuje ją sam, WebKit nie ma czym —
 * stąd gradient o szerokości `--wypelnienie`, którą ustawia skrypt przy każdym
 * ruchu suwaka. Przy torze grubości włosa to często jedyna rzecz mówiąca,
 * gdzie się jest: sam uchwyt nie odróżnia „blisko początku" od „blisko końca".
 */
#settings-drawer input[type='range'] { height: 16px; }

#settings-drawer input[type='range']::-webkit-slider-runnable-track {
  height: 1px;
  background:
    linear-gradient(var(--ust-tor-przebyty), var(--ust-tor-przebyty))
      left center / var(--wypelnienie, 0%) 1px no-repeat,
    var(--ust-tor);
}

#settings-drawer input[type='range']::-moz-range-track {
  height: 1px;
  background: var(--ust-tor);
}

#settings-drawer input[type='range']::-moz-range-progress {
  height: 1px;
  background: var(--ust-tor-przebyty);
}

#settings-drawer input[type='range']::-webkit-slider-thumb {
  width: 16px;
  height: 16px;
  margin-top: -7.5px;
  border: 1px solid var(--ust-uchwyt-obwodka);
  background: var(--ust-uchwyt-tlo);
  box-shadow: var(--ust-uchwyt-cien);
}

#settings-drawer input[type='range']::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border: 1px solid var(--ust-uchwyt-obwodka);
  background: var(--ust-uchwyt-tlo);
  box-shadow: var(--ust-uchwyt-cien);
}

/* Uchwyt ma już własne tło; podmiana na hover robiła z niego plamę. */
#settings-drawer input[type='range']:hover::-webkit-slider-thumb {
  background: var(--ust-uchwyt-tlo);
}

#settings-drawer input[type='range']:hover::-moz-range-thumb {
  background: var(--ust-uchwyt-tlo);
}

/* --- pole wyboru -------------------------------------------------------- */

/*
 * Osiemnaście pikseli i własny rysunek zamiast `accent-color`. Systemowe pole
 * wyboru jest w każdej przeglądarce inne — inny promień, inna kreska, inny
 * błękit w stanie włączonym — a to jedyny element panelu, którego projekt
 * nie mógłby rozpoznać jako swojego.
 */
#settings-drawer input[type='checkbox'] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border: 1px solid var(--ust-pole-obwodka);
  border-radius: 4px;
  background: var(--ust-pole-tlo);
  box-shadow: var(--ust-pole-cien);
  cursor: pointer;
}

#settings-drawer input[type='checkbox']:checked {
  border-color: transparent;
  background: var(--ust-pole-znak) center / 18px 18px no-repeat,
    var(--ust-pole-wl-tlo);
  box-shadow: none;
}

#settings-drawer input[type='checkbox']:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

#settings-drawer .control.check label { gap: 12px; font-size: 0.9375rem; }

/* --- lista rozwijana ---------------------------------------------------- */

#settings-drawer select {
  height: 42px;
  border-radius: 8px;
  border-color: var(--ust-select-obwodka);
  background: var(--przycisk-zwykly-tlo);
  font-size: 0.9375rem;
}

#settings-drawer select:hover,
#settings-drawer select:focus {
  border-color: var(--ust-select-obwodka-zywa);
}

/* --- wyjście awaryjne --------------------------------------------------- */

/*
 * „Przywróć ustawienia domyślne" przestaje być przyciskiem. Wyglądało to na
 * czynność równie zwyczajną, co przesunięcie suwaka, a jest jedyną w tym
 * panelu, która kasuje CUDZĄ pracę. Zwykły tekst pod kreską nie zaprasza.
 */
#settings-drawer .settings-reset {
  display: block;
  width: 100%;
  height: auto;
  margin: 0;
  padding: 0 0 16px 8px;
  border: 0;
  border-bottom: 1px solid var(--color-divider);
  border-radius: 0;
  background: none;
  text-align: left;
  font-size: 0.90625rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text);
}

#settings-drawer .settings-reset:hover:not(:disabled) {
  background: none;
  color: var(--color-accent-700);
}

/* --- rozwijacz i karta zaawansowanych ----------------------------------- */

#settings-advanced { border-top: 0; }

#settings-advanced > summary {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.78125rem;
  letter-spacing: 0.09em;
  padding: 16px 0;
  color: var(--color-neutral-500);
}

#settings-advanced > summary::before {
  color: var(--color-accent-700);
  font-size: 1rem;
}

/*
 * Wcięta karta. Zaawansowane leżą na innym papierze niż podstawowe, bo są
 * innym rodzajem rzeczy: te ustawia się raz. Bez karty rozwinięcie wyglądało
 * jak nagłe wydłużenie listy, po którym nie było wiadomo, gdzie się skończyło
 * to, po co się tu przyszło.
 */
.ust-karta {
  margin-bottom: 4px;
  padding: 16px;
  border: 1px solid var(--ust-karta-obwodka);
  border-radius: 11px;
  background: var(--ust-karta-tlo);
  box-shadow: var(--ust-karta-cien);
}

/* --- zależność: siła kotwic wisi na kotwicach ---------------------------- */

/*
 * Gaśnie CAŁA grupa, nie sam suwak. Ustawienie, którego etykieta jest żywa,
 * a kontrolka martwa, wygląda na zepsute; wygaszone razem z podpisem wygląda
 * na wyłączone — i to jest prawda.
 */
#settings-drawer .control.zalezne.is-dormant { opacity: 0.55; }
#settings-drawer .control.zalezne.is-dormant input { pointer-events: none; }

/* Krycie nakładało się dwa razy: raz z grupy, raz z reguły dla nieczynnych. */
#settings-drawer .control.zalezne.is-dormant input[type='range']:disabled {
  opacity: 1;
}

/* --- telefon ------------------------------------------------------------ */

@media (max-width: 640px) {
  /*
   * Na telefonie panel wraca na krawędzie. Karta z marginesem zabiera z każdej
   * strony po kilkanaście pikseli, a tu i tak zakrywa cały ekran — więc byłby
   * to margines dookoła niczego.
   */
  #settings-drawer {
    top: 0;
    right: 0;
    bottom: 0;
    max-height: none;
    width: 100%;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /*
   * PASTYLKA NARZĘDZI SCHODZI NA TELEFONIE.
   *
   * Zmierzone przy 320 px: obudowa kosztowała czterdzieści pikseli wysokości
   * paska — sto siedemdziesiąt sześć zamiast stu trzydziestu sześciu — zanim
   * zaczął się tekst książki. To ta sama zasada, dla której wyżej schodzi
   * karta nagłówka: na tym ekranie ustępuje wszystko, co da się odzyskać,
   * a obudowa grupy jest ozdobą wobec czterech znaków w rzędzie.
   *
   * Samo zdjęcie obudowy nie wystarczyło: pojemnik jako osobny element flex
   * pakował narzędzia gorzej niż wtedy, gdy leżały luzem w pasku obok trybu
   * pracy — zostawało dwadzieścia osiem pikseli różnicy na dodatkowym rzędzie.
   * `display: contents` usuwa samo pudełko, a dzieci wracają do rozkładu
   * paska: ten sam układ co przed pastylką, co do piksela.
   */
  .bar-przybornik { display: contents; }

  /*
   * PASTYLKĄ JEST TU CAŁA KARTA NAGŁÓWKA — i to jedyne miejsce, w którym
   * może nią być.
   *
   * Dwie drogi odpadły po pomiarze. Osobny pojemnik na same narzędzia
   * kosztuje na telefonie CAŁY DODATKOWY RZĄD: 117 px bez niego, 174 z nim,
   * tak samo przy 320, 360 i 390 px — poniżej czterystu trzydziestu narzędzia
   * i tryb pracy nie mieszczą się obok siebie w żadnym układzie. Obudowa na
   * samym pasku narzędzi nie rysuje się w ogóle, bo pasek ma tu `display:
   * contents`: jest spłaszczony w rząd karty i nie ma własnego pudełka.
   *
   * Karta nagłówka pudełko ma. Pastylka na niej daje ten sam znak co na
   * tablicy — „tu są przybory" — i kosztuje MINUS DZIESIĘĆ PIKSELI, bo
   * dopełnienie zastępuje odstępy, które pasek i tak miał.
   */
  .bar-czytnik {
    margin: 4px 8px;
    padding: 3px 6px;
    border: 1px solid var(--pasek-obwodka);
    border-radius: var(--promien-pastylka);
    background: var(--pasek-tlo);
    box-shadow: var(--pasek-cien);
  }

  /* Palec potrzebuje czterdziestu czterech pikseli — także tutaj. */
  #settings-close { height: 44px; }
  #settings-drawer .settings-reset { padding-top: 8px; padding-bottom: 20px; }
}

/* ====================================================================
 * CIENIE NA CZAS RUCHU
 *
 * `drop-shadow` rozmywa się osobno dla każdego elementu i liczy od nowa
 * przy każdym przerysowaniu kanwy. Przy czterystu karteczkach w kadrze
 * kosztuje to 65 ms na klatkę zamiast 24 — a przy trzech warstwach cienia,
 * jak było pierwotnie, kosztowało 243, czyli tyle, ile trzeba, żeby
 * przeglądarka wyglądała na zawieszoną. Zejście do jednej warstwy zabrało
 * większość kosztu; te sześćdziesiąt pięć to nadal piętnaście klatek na
 * sekundę, więc tłumienie na czas gestu zostaje.
 *
 * Znacznik zakłada edytor na czas gestu i zdejmuje 160 ms po jego końcu.
 * Nieruchoma tablica ma cienie zawsze; w ruchu nikt ich nie ogląda.
 * ==================================================================== */

.board-swiat[data-ruch='tak'] .board-karteczka,
.board-swiat[data-ruch='tak'] .board-bryla {
  filter: none;
}

/* ====================================================================
 * PRZYBORNIK TABLICY — CZTERY MIEJSCA
 *
 * Domyślnie stoi u góry, w zwykłym przepływie, i tak zostaje: to jest
 * miejsce, w którym był, i zmiana domyślnego położenia bez pytania byłaby
 * przestawieniem komuś warsztatu.
 *
 * Trzy pozostałe wyjmują go z przepływu i kładą NA kanwie. Powód, dla którego
 * w ogóle są: na niskiej tablicy — a taka bywa przy podziale — poziomy pasek
 * zjada pas, którego brakuje rysunkowi, a pionowy przy krawędzi nie zjada nic
 * poza wąskim marginesem.
 * ==================================================================== */

.view-board { position: relative; }

/* Uchwyt różni się od narzędzi: nie robi nic z rysunkiem, więc nie ma stanu
   wciśnięcia i nie bierze udziału w „które narzędzie jest wybrane". */
.board-uchwyt { cursor: grab; color: var(--klawisz-znak-wylaczony); }
.board-uchwyt:hover { color: var(--klawisz-znak); }
.board-uchwyt.jest-ciagniety { cursor: grabbing; }

/*
 * PONIŻEJ TRZYSTU SZEŚĆDZIESIĘCIU PIKSELI UCHWYTU NIE MA.
 *
 * Pastylka zajmuje tam całą szerokość ekranu co do piksela — zmierzone: przy
 * 320 px rozciąga się od zera do trzystu dwudziestu. Uchwyt dokłada trzydzieści
 * cztery piksele i wypycha za krawędź klawisz „…", czyli ten, w którym siedzi
 * cała reszta narzędzi. Przycisk, który jest, ale nie da się go dotknąć, to
 * gorsza strata niż brak możliwości przesunięcia paska.
 *
 * Przy 360 px mieści się dokładnie (359 z 360), więc próg stoi tam.
 */
@media (max-width: 359px) {
  .board-uchwyt { display: none; }
}

/* --- dół ------------------------------------------------------------- */

.view-board[data-przybornik='dol'] .board-tools {
  position: absolute;
  z-index: 6;
  left: 0;
  right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--space-3));
  top: auto;
  /* Środek marginesem, nie `transform` — powód przy pastylce telefonu. */
  margin: 0 auto;
}

/* --- lewo i prawo ---------------------------------------------------- */

/*
 * W pionie pastylka układa narzędzia w kolumnę, a separatory kładą się
 * w poprzek. Bez obrócenia separatora kolumna dostawała jedenaście pikseli
 * pustki zamiast kreski — czyli odstęp bez znaczenia.
 */
.view-board[data-przybornik='lewo'] .board-tools,
.view-board[data-przybornik='prawo'] .board-tools {
  position: absolute;
  z-index: 6;
  /*
   * Pion środkuje się tak samo: `top: 0; bottom: 0` z wysokością `max-content`
   * i marginesem `auto`. Nie ma tu `transform` z tego samego powodu, co niżej
   * przy pastylce telefonu — menu „…" liczy się od okna i musi mieć okno.
   */
  top: 0;
  height: max-content;
  /*
   * ZDEJMUJEMY PRZYPIĘCIE Z TELEFONU, i to jest cała ta poprawka.
   *
   * Na telefonie pastylka jest przypięta do dołu okna: `left: 50%`,
   * `bottom: …`, `transform: translateX(-50%)`. Pionowe zadokowanie dokładało
   * do tego `top: 50%` i `right: …`, nie zdejmując tamtych — a element
   * z ustawionym JEDNOCZEŚNIE `top` i `bottom` nie stoi tam, gdzie mu kazano,
   * tylko ROZCIĄGA SIĘ między jednym a drugim. To samo w poziomie.
   *
   * Zmierzone na ekranie 393 × 852: pastylka 183 × 418 zamiast 54 × 308,
   * czyli od połowy ekranu do prawej krawędzi i od połowy do dołu. Przy
   * promieniu 999 px taki prostokąt maluje się jako owalny bąbel — zgłoszone
   * z telefonu jako „gruba beka zamiast wąskiego paska".
   *
   * Menu „…" przewróciło się przy okazji, choć samo w sobie było zdrowe:
   * lista wisi OBOK pastylki, więc licząc się od jej rozdętej krawędzi
   * lądowała na minus czterdziestu dwóch pikselach, czyli za lewym brzegiem
   * ekranu. Wyglądało to jak menu, które się nie rozwija.
   */
  right: auto;
  bottom: 0;
  left: auto;
  margin: auto 0;
  flex-direction: column;
  width: auto;
  max-height: calc(100% - 2 * var(--space-4));
  /*
   * ŻADNEGO PRZEWIJANIA NA PASTYLCE, i to jest tu ważne.
   *
   * Element przewijany w jednej osi przycina też w drugiej, a lista menu wisi
   * OBOK pastylki, poza jej pudełkiem — więc `overflow-y: auto` obcinał ją do
   * zera i pod spodem widać było kanwę. Dokładnie ta sama pułapka, przez którą
   * menu „…" nie otwierało się w podziale.
   *
   * Przewijanie nie jest tu potrzebne: pionowy przybornik zwija się do
   * najwęższej postaci i mierzy trzysta osiem pikseli, czyli mieści się
   * na każdym ekranie, na którym w ogóle ma sens.
   */
  overflow: visible;
}

.view-board[data-przybornik='lewo'] .board-tools { left: var(--space-3); }
.view-board[data-przybornik='prawo'] .board-tools { right: var(--space-3); }

.view-board[data-przybornik='lewo'] .board-sep,
.view-board[data-przybornik='prawo'] .board-sep {
  width: 22px;
  min-width: 22px;
  height: 11px;
  background:
    linear-gradient(var(--pasek-separator), var(--pasek-separator))
    center / 100% 1px no-repeat;
}

/*
 * Lista „więcej" idzie za przybornikiem.
 *
 * Domyślnie wisi POD paskiem, przy jego prawej krawędzi. Przy przyborniku na
 * dole otwierałaby się poza ekranem, a przy pionowym — obok kanwy zamiast obok
 * klawisza. Każde miejsce dostaje więc własne zaczepienie.
 */
.view-board[data-przybornik='dol'] .board-menu-lista {
  top: auto;
  bottom: calc(100% + 4px);
}

.view-board[data-przybornik='lewo'] .board-menu-lista,
.view-board[data-przybornik='prawo'] .board-menu-lista {
  /*
   * Lista wyśrodkowana na pastylce i ograniczona do wysokości okna.
   *
   * Przy pionowym przyborniku pasek zwija się do najwęższej postaci, więc do
   * menu wędruje większość narzędzi i lista ma pięćset siedemdziesiąt dwa
   * piksele zamiast trzystu. Wyrównana do dołu pastylki wychodziła górą poza
   * ekran — mierzone: górna krawędź na minus siedemnastu.
   */
  top: 50%;
  bottom: auto;
  max-height: calc(100vh - 2 * var(--space-4));
  overflow-y: auto;
  transform: translateY(-50%);
}

.view-board[data-przybornik='lewo'] .board-menu-lista {
  right: auto;
  left: calc(100% + 6px);
}

.view-board[data-przybornik='prawo'] .board-menu-lista {
  right: calc(100% + 6px);
}

/*
 * Przy pionowym przyborniku sterowanie widokiem odsuwa się od tej krawędzi,
 * przy której stoi — inaczej pastylka i „100%" siedzą jedno na drugim
 * dokładnie tak, jak siedziały na telefonie przed poprawką.
 */
.view-board[data-przybornik='prawo'] .board-widok { right: calc(var(--space-3) + 64px); }
.view-board[data-przybornik='dol'] .board-widok {
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--space-3) + 62px);
}

/* --- Znacznik czasu w transkrypcji ---------------------------------------
 *
 * Wygląda jak numer wiersza w wydaniu krytycznym: mniejszy, cichszy i lekko
 * odsunięty od tekstu, który podpisuje. Nie ma być drugim głosem w akapicie —
 * ma być do znalezienia wtedy, gdy się go szuka, i niewidoczny wtedy, gdy się
 * czyta. Stąd kolor `--color-neutral-500`, ten sam, co przy metryczkach kart
 * w bibliotece.
 *
 * `user-select: none` jest tu warunkiem sensu, nie ozdobą: znacznik stoi
 * WEWNĄTRZ akapitu, więc zaznaczenie ciągnięte od jego początku zabierałoby
 * liczbę razem ze zdaniem — do notatki, do wypisu i do sprawdzianu.
 */
.k-czas {
  display: inline-block;
  margin-inline-end: .55em;
  font-family: var(--font-body);
  font-size: .75em;
  font-variant-numeric: tabular-nums;
  font-weight: 400;
  color: var(--color-neutral-500);
  text-decoration: none;
  vertical-align: .12em;
  -webkit-user-select: none;
  user-select: none;
}

a.k-czas:hover, a.k-czas:focus-visible {
  color: var(--color-accent-700);
  text-decoration: underline;
}

/* Kotwice pogrubiają wyrazy wokół; znacznik zostaje cienki niezależnie od
 * ustawienia wagi, bo nie jest wyrazem i nie bierze udziału w rytmie czytania. */
.k-p > .k-czas { font-weight: 400; }

/* --- Sprawdzenie pojęcia -------------------------------------------------
 *
 * Trzy warstwy ułożone w kolejności kosztu: darmowe hasło na wierzchu, płatne
 * i wychodzące na zewnątrz niżej, za przyciskami. Układ jest tu zdaniem
 * o pieniądzach — co dostajesz od razu, a za co trzeba świadomie kliknąć.
 */
.wyjasnij-panel {
  max-width: 34rem;
  gap: var(--space-3);
}

.wyjasnij-warstwa {
  padding: var(--space-3);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-surface) 60%, transparent);
}

.wyjasnij-tresc {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--color-text);
}

/* Skąd to jest — mniejszym pismem, bo pochodzenie czyta się po treści,
   a nie przed nią. Ale czyta się zawsze, więc nie znika i nie szarzeje
   poniżej progu czytelności. */
.wyjasnij-skad {
  margin: var(--space-2) 0 0;
  font-size: 0.75rem;
  color: var(--color-neutral-500);
}

.wyjasnij-skad a {
  color: var(--color-accent-700);
  margin-inline-start: 4px;
}

.wyjasnij-drogi {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.wyjasnij-drogi .button { flex: 1 1 auto; }

/* Zdanie o tym, co wychodzi na zewnątrz, stoi POD przyciskami wysyłki —
   tam się patrzy przed kliknięciem, a nie po nim. */
.wyjasnij-co-jedzie {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.45;
}

@media (max-width: 560px) {
  /* Na telefonie przyciski schodzą pod siebie: dwa obok siebie łamią napisy
     w połowie i żaden z nich nie daje się przeczytać w całości. */
  .wyjasnij-drogi { flex-direction: column; }
}

/* --- Ikony Lucide: jeden zestaw, jedna miara -----------------------------
 *
 * Wspólna klasa zamiast atrybutów powtarzanych przy każdym użyciu. Kreska,
 * zakończenia i kolor stoją na <g> w arkuszu znaków, więc tutaj zostaje wyłącznie
 * rozmiar — trzy stopnie z mapy ikon, nie więcej, bo trzeci rozmiar „na oko"
 * zaczyna się od tego, że komuś coś nie pasuje w jednym panelu.
 *
 *   .ik        16 px — przy etykiecie
 *   .ik-pasek  19 px — w paskach samych ikon
 *   .ik-mala   14 px — w metrykach i stopkach
 */
.ik {
  flex: none;
  width: 16px;
  height: 16px;
  color: inherit;
  vertical-align: -0.2em;
}

.ik-pasek { width: 19px; height: 19px; }
.ik-mala { width: 14px; height: 14px; }

/*
 * Odstęp ikona–etykieta: osiem pikseli, przez `gap` rodzica, nigdy przez
 * margines na samej ikonie. Margines na ikonie zostaje także wtedy, gdy
 * etykieta znika — a w paskach ikonowych etykieta znika z założenia.
 */
.z-ikona {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* --- Pasek obiektu na tablicy: ikony w grupach (11a) ---------------------- */

.board-kontekst-akcja.is-ikona {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
}

/*
 * BURSZTYN TYLKO NA DZIAŁANIACH ODWRACALNYCH.
 *
 * Najechanie na zwykłą akcję podświetla ją ciepło, jak w pasku zaznaczenia —
 * te same trzy tony, żeby oba paski ikon mówiły jednym językiem. Kasowanie
 * niżej dostaje szary stan: bursztyn przy „Skasuj" zapraszałby do kliknięcia
 * w jedyną rzecz, której nie cofa się jednym ruchem.
 */
.board-kontekst-akcja.is-ikona:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border-color: var(--color-accent-300);
  color: var(--color-accent-700);
}

.board-kontekst-akcja.is-ikona.is-kasuj:hover:not(:disabled) {
  background: color-mix(in srgb, var(--color-text) 9%, transparent);
  border-color: transparent;
  color: var(--color-text);
}

.board-kontekst .board-kontekst-kreska {
  height: 22px;
  margin: 0 5px;
}

/*
 * Podpis pod paskiem. Pseudoelement, nie osobny element — pasek odświeża się
 * przez odsłonięcie WSZYSTKICH swoich dzieci i schowanie zbędnych, a osobne
 * dziecko wracałoby przy tym na ekran i wchodziło do każdej listy przycisków.
 */
.board-kontekst::after {
  content: attr(data-podpis);
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 1px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--color-neutral-500);
  white-space: nowrap;
  pointer-events: none;
}

.board-kontekst:not([data-podpis])::after,
.board-kontekst[data-podpis='']::after { content: none; }

.board-kontekst :focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (pointer: coarse) {
  .board-kontekst-akcja.is-ikona { width: 44px; height: 44px; }
}

/* --- Pasek zaznaczenia: jeden rząd ikon (9b) ------------------------------ */

.selection-anchor {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  box-shadow: 0 3px 10px rgb(45 43 43 / 0.16);
}

.selection-rzad {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
}

.selection-kreska {
  width: 1px;
  align-self: stretch;
  margin: 2px 6px;
  background: var(--color-divider);
}

.selection-anchor .swatch {
  width: 22px;
  height: 22px;
  border-color: rgb(32 31 29 / 0.22);
  transition: transform 120ms ease;
}

.selection-anchor .swatch:hover { transform: scale(1.12); }

.sel-ikona,
.selection-znaki .znak-chip.is-ikona {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.sel-ikona[hidden],
.selection-znaki[hidden] { display: none; }

/* Te same trzy tony co w pasku tablicy — oba paski ikon mówią jednym językiem. */
.sel-ikona:hover,
.sel-ikona[aria-expanded='true'],
.selection-znaki .znak-chip.is-ikona:hover,
.selection-znaki .znak-chip.is-ikona[aria-pressed='true'] {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border-color: var(--color-accent-300);
  color: var(--color-accent-700);
}

.selection-znaki {
  flex-wrap: nowrap;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
  width: auto;
  margin: 0;
  padding: 6px 8px 8px;
  border-top: 1px solid var(--color-divider);
}

.selection-znaki .znak-chip.is-ikona {
  width: 32px;
  height: 32px;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}

.selection-znaki-etykieta {
  margin-right: auto;
  padding-left: 4px;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-neutral-500);
}

/* Podpis pod paskiem — ten sam mechanizm co przy pasku tablicy. */
.selection-anchor::after {
  content: attr(data-podpis);
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 1px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--color-neutral-500);
  white-space: nowrap;
  pointer-events: none;
}

.selection-anchor:not([data-podpis])::after,
.selection-anchor[data-podpis='']::after { content: none; }

.selection-anchor :focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (pointer: coarse) {
  .sel-ikona,
  .selection-znaki .znak-chip.is-ikona { width: 44px; height: 44px; }
  .selection-anchor .swatch { width: 28px; height: 28px; }
}

/* --- Panel ustawień z ikonami (9b, 9c) -------------------------------------
 *
 * Ikony wierszy stoją w jednej kolumnie szesnastu pikseli, w szarości, żeby
 * etykiety zostały tym, co się czyta. Bursztyn zostaje na tytule, nagłówkach
 * sekcji i strzałce rozwinięcia — tam, gdzie oznacza strukturę, a nie treść.
 */
.control > label {
  justify-content: flex-start;
  align-items: center;
}

.control > label b { margin-left: auto; }

.control > label > .ik,
.control.check label > .ik {
  color: var(--color-neutral-500);
}

.szuflada-tytul .ik { width: 18px; height: 18px; color: var(--color-accent-700); }

.kicker.z-ikona { gap: 6px; }
.ik-kicker { width: 15px; height: 15px; color: var(--color-accent-700); }

.drawer-close.z-ikona { gap: 6px; }
#scope-clear.z-ikona { gap: 5px; }

@media (pointer: coarse) {
  .drawer-close.z-ikona { min-height: 44px; }
}

/* --- Panele osadzone w stronie: ikona przy etykiecie (10a, 12a–17a) -------- */

.button.z-ikona,
.link.z-ikona { gap: 8px; }

/*
 * KASOWANIE BEZ CZERWIENI I BEZ BURSZTYNU.
 *
 * System nie ma koloru czerwonego i go nie wprowadza. Najechanie na kasowanie
 * jest szare — bursztyn zapraszałby do kliknięcia w jedyną rzecz, której nie
 * cofa się jednym ruchem, a czerwień byłaby drugim akcentem obok bursztynu.
 */
.button.danger:hover:not(:disabled) {
  color: var(--color-text);
  border-color: var(--color-neutral-400);
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
}

.book-actions .button.icon,
.board-actions .button.icon {
  width: 38px;
  height: auto;
  align-self: stretch;
}

.book-format.z-ikona {
  display: flex;
  justify-content: center;
  gap: 6px;
}

.book-format .ik { width: 14px; height: 14px; }

.tag-chip.z-ikona {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.tag-chip .ik { width: 13px; height: 13px; }

/* Ostrzeżenie o pamięci zostaje tekstem bez ramki — kolor ma tylko ikona. */
.kopia-ostrzezenie { align-items: flex-start; }
.kopia-ostrzezenie .ik { margin-top: 0.15em; color: var(--color-accent-700); }

.hint.z-ikona { gap: 8px; }

.board-sub.z-ikona {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 0 0 4px;
}

.board-sub .ik { margin-top: 0.15em; }

.board-thumb.is-pusta {
  display: flex;
  align-items: center;
  justify-content: center;
}

.board-thumb-pusta {
  width: 40px;
  height: 40px;
  color: var(--color-neutral-400);
}

/* Pole kroju na pasku tablicy: zwarte, jak na projekcie — pokazuje wartość. */
.board-kontekst-kroj {
  width: auto;
  min-width: 0;
  max-width: 9rem;
}

@media (pointer: coarse) {
  .book-actions .button.icon,
  .board-actions .button.icon { width: 44px; }
}

/*
 * DWIE STARSZE REGUŁY `display: block` NADPISYWAŁY UKŁAD IKONY Z NAPISEM.
 *
 * `#settings-drawer .settings-reset` i `.section > .kicker` ustawiają blok,
 * a blok nie zna `gap` — więc przy przywróceniu ustawień ikona stała nad
 * napisem, w osobnym wierszu, a w nagłówkach sekcji była przyklejona do
 * pierwszej litery. Poprawka ma wyższą szczegółowość zamiast zmieniać tamte
 * reguły: one dalej obsługują elementy bez ikon.
 */
#settings-drawer .settings-reset.z-ikona {
  display: flex;
  align-items: center;
  gap: 8px;
}

#settings-drawer .section > .kicker.z-ikona {
  display: flex;
  align-items: center;
  gap: 6px;
}

/*
 * Trzy poprawki z przeglądu zrzutów po wdrożeniu ikon.
 *
 * Miniatura pustej tablicy: starsza `.board-thumb svg` rozciąga KAŻDY rysunek
 * w miniaturze na całe pole — słusznie dla podglądu tablicy, źle dla znaku.
 * Przerywany kwadrat wypełniał całą kartę i wyglądał jak element interfejsu
 * do kliknięcia, a nie jak znak „tu jeszcze nic nie ma".
 */
.board-thumb.is-pusta .board-thumb-pusta {
  width: 40px;
  height: 40px;
}

/* Kosz na karcie książki po zawinięciu stoi sam w wierszu, a wtedy
   `align-self: stretch` nie ma do czego się rozciągnąć — spłaszczał się
   do wysokości ikony. Najniższa wysokość równa zwykłemu przyciskowi. */
.book-actions .button.icon,
.board-actions .button.icon { min-height: 34px; }

/* Przywrócenie ustawień stoi przy lewej krawędzi, jak na projekcie —
   `.button` środkuje zawartość, a ten przycisk jest tu wierszem listy. */
#settings-drawer .settings-reset.z-ikona { justify-content: flex-start; }

/* --- Strona powitalna: ruch przy przewijaniu ------------------------------
 *
 * Reguła, od której to się zaczyna, nie dotyczy animacji, tylko UKŁADU:
 * sekcja „Możliwości" była trzy razy tym samym — obraz obok tekstu,
 * naprzemiennie. Trzy bloki zachowujące się identycznie to jeden blok
 * pokazany trzy razy, a przewijanie przestaje być powodem, żeby przewijać.
 *
 * Stąd sześć RÓŻNYCH środków i jedna twarda zasada: żaden dwa razy pod rząd.
 *
 *   hero        plany w różnym tempie (głębia)
 *   trzy karty  wejście z opóźnieniem
 *   blok 1      wycieranie w prawo
 *   blok 2      numer i nagłówek składają się
 *   blok 3      wycieranie z dołu — inny kierunek niż blok 1
 *   pięć kroków numery lądują po kolei
 *   zapis, FAQ  BEZ RUCHU, celowo — spokój też jest środkiem
 *
 * TRZY OGRANICZENIA, KTÓRE RZĄDZĄ KAŻDĄ REGUŁĄ NIŻEJ:
 *
 * 1. Żadnego ruchu w POZIOMIE. Testy mierzą, że przy 375 px nic nie wystaje
 *    w bok i że pięć kółek leży w jednej osi pionowej. Przesunięcie boczne
 *    złamałoby jedno albo drugie, a w zamian nie daje niczego, czego nie da
 *    przesunięcie pionowe.
 * 2. Każda animacja KOŃCZY SIĘ stanem spoczynkowym. Zakresy domykają się,
 *    zanim element dojdzie do środka ekranu, więc pomiar zastaje go już na
 *    swoim miejscu.
 * 3. Bez ruchu strona wygląda dokładnie tak, jak wyglądała. Całość stoi pod
 *    `prefers-reduced-motion: no-preference` ORAZ pod `@supports`, więc kto
 *    prosi o spokój i kto ma starszą przeglądarkę, dostaje tę samą stronę,
 *    co wcześniej. To nie jest zapasowe wyjście — to jest ta sama strona.
 */
:root[data-ruch-powitania="pelny"] {
  @supports (animation-timeline: view()) {

    /* HERO — KSIĄŻKA STOI, RUSZA SIĘ SAMA KARTKA.
       Stała tu paralaksa: obraz, tekst i nadtytuł jechały w różnym tempie,
       żeby zrobić głębię. Miała wadę widoczną dopiero po dołożeniu
       przewracanej kartki — przesuwała CAŁĄ ilustrację, więc książka
       dryfowała razem z kartką i ruch czytał się jak poluzowany rysunek,
       a nie jak przewracanie strony.
       Pierwszy ekran ma jeden środek i jest nim kartka. Reszta hero stoi,
       łącznie z tekstem: tekst sunący przy nieruchomym obrazie wygląda na
       usterkę, nie na głębię.
       Przy okazji odpadło `overflow: hidden`, potrzebne wyłącznie do
       przycinania powiększanego obrazu — a to ono robiło z `.pow-hero-obraz`
       kontener przewijania i zabijało oś kartkowania. */

    /*
     * TRZY KARTY PUCHNĄ W ŚRODKU EKRANU i wracają do swojej wielkości.
     *
     * Stały tu wcześniej BEZ RUCHU i był to wniosek z pomiaru: wejścia
     * z opóźnieniem nie działały, bo karty są widoczne już przy pierwszym
     * wyświetleniu, a `view()` daje fazę wejścia wyłącznie elementowi, który
     * dopiero wjeżdża od dołu — animacja siedziała od razu na swoim końcu.
     *
     * Ta krzywa tamtej przeszkody nie ma, i to jest tu cała sztuczka: nie
     * zależy od WEJŚCIA, tylko od POŁOŻENIA. Zakres `cover` obejmuje cały
     * czas, gdy element jest gdziekolwiek na ekranie, więc karta widoczna od
     * początku po prostu stoi w odpowiednim miejscu krzywej, zamiast być po
     * wszystkim.
     *
     * Szczyt jest w połowie zakresu, czyli gdy karta mija środek ekranu.
     * Powiększenie jest małe z konieczności, nie z ostrożności: karta ma na
     * telefonie pełną szerokość, a wszystko powyżej kilku procent wypycha ją
     * poza ekran i łamie sprawdzenie o braku nadmiaru w bok.
     */
    .pow-trzy > li {
      animation: pow-puchnie linear both;
      animation-timeline: view();
      --pow-puch: 1.11;
    }
    /*
     * TA SAMA KRZYWA NA BLOKACH I KROKACH, ale słabsza. Blok i krok są
     * WYŻSZE od karty i zajmują pół ekranu, więc te same pięć procent czyta
     * się na nich jak skok, a nie jak oddech. Do tego na telefonie mają pełną
     * szerokość — im większy element, tym mniej wolno go powiększyć, zanim
     * wypchnie stronę w bok.
     *
     * Kroków NIE skalujemy przez `.pow-krok`, tylko przez ich zawartość.
     * Powód jest mierzony, nie teoretyczny: oś pięciu kółek i położenie
     * kółka NA osi są sprawdzane liczbowo, a skalowanie całego kroku rusza
     * te punkty. Obraz i tekst nie leżą na osi, więc mogą puchnąć swobodnie.
     */
    .pow-krok-obraz, .pow-krok-tekst {
      animation: pow-puchnie linear both;
      animation-timeline: view();
      --pow-puch: 1.06;
    }

    /*
     * BLOKI MAJĄ INNĄ KRZYWĄ: nie przekraczają swojej wielkości, tylko DO
     * NIEJ DOCHODZĄ. Wjeżdżają wyraźnie mniejsze, na środku ekranu są
     * dokładnie takie, jakie mają być, a wychodząc lekko się kurczą.
     *
     * Różnica wobec kart jest zamierzona i wynika z ROZMIARU, nie z miejsca
     * na stronie. Karta jest niska, więc powiększenie ponad własną miarę
     * czyta się na niej jak podkreślenie — i tak zostaje na WSZYSTKICH
     * kartach, także tych w sekcji o zapisie. Blok zajmuje pół ekranu:
     * powiększony ponad miarę wygląda, jakby się nie mieścił. Dochodzenie do
     * miary daje ten sam skok uwagi bez tego wrażenia, a przy okazji jest
     * bezpieczniejsze — skala poniżej jedności nie ma jak wypchnąć strony
     * w bok.
     */
    .pow-blok {
      animation: pow-dochodzi linear both;
      animation-timeline: view();
    }
    /* BLOK 1 — wycieranie w prawo. Odsłania PRÓBKĘ KOTWIC, czyli jedyne
       miejsce na stronie, gdzie widać sam mechanizm produktu. Ruch jest tu
       po to, żeby oko trafiło na różnicę „bez" kontra „z". */
    .pow-probka {
      animation: pow-wytrzyj-w-prawo linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 35%;
    }
    /* BLOK 2 — numer i nagłówek składają się. Numer idzie pierwszy,
       nagłówek za nim; odwrotna kolejność czytałaby się jak podpis. */
    .pow-blok .pow-numer,
    .pow-blok .pow-blok-tekst h3 {
      animation: pow-sklada linear both;
      animation-timeline: view();
      animation-range: entry 15% cover 28%;
    }
    .pow-blok .pow-blok-tekst h3 { animation-range: entry 8% cover 32%; }
    /* BLOK 3 — też wycieranie, ale Z DOŁU. Inny kierunek niż w bloku 1,
       a między nimi stoi blok 2, więc zasada „nie dwa razy pod rząd”
       trzyma. */
    .pow-blok:last-of-type .pow-blok-obraz {
      animation: pow-wytrzyj-z-dolu linear both;
      animation-timeline: view();
      animation-range: entry 15% cover 30%;
    }
    /* PIĘĆ KROKÓW — numery lądują po kolei, z góry na dół, bo tak samo
       czyta się oś. Rusza się WYŁĄCZNIE kółko: oś i jej pozycja są
       mierzone przez testy i nie mają prawa drgnąć. */
    .pow-krok .pow-krok-nr {
      animation: pow-laduje linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 25%;
    }
  }
}

/* --- Strona powitalna: ruch przy prośbie o spokój -------------------------
 *
 * `prefers-reduced-motion: reduce` znaczy MNIEJ RUCHU, a nie ŻADNEGO — i ta
 * różnica jest tu cała. Kłopotliwe dla błędnika są przesunięcia, powiększenia
 * i paralaksa; samo pojawianie się nie jest. Dlatego przy prośbie o spokój
 * zostaje wyłącznie zmiana krycia: te same trzy elementy odsłaniają się przy
 * przewijaniu, ale NIC SIĘ NIE PRZESUWA, nie skaluje i nie wyciera.
 *
 * Wcześniej stało tu zero i było to za łatwe rozwiązanie. Skutek uboczny
 * wyszedł w praktyce: na maszynie, która prosi o spokój systemowo — a takich
 * jest więcej, niż się wydaje, bo Windows ustawia to razem z efektami okien —
 * strona wyglądała identycznie jak przed całą przebudową i nie było jak
 * odróżnić „uszanowaliśmy preferencję" od „nic nie działa".
 *
 * Hero NIE dostaje tu nic. Paralaksa jest dokładnie tym rodzajem ruchu,
 * o którego brak prosi ta preferencja, a zamiana jej na przygaszanie hero
 * przy przewijaniu utrudniałaby czytanie pierwszego ekranu.
 */
:root[data-ruch-powitania="spokojny"] {
  @supports (animation-timeline: view()) {

    .pow-probka,
    .pow-blok:last-of-type .pow-blok-obraz,
    .pow-krok .pow-krok-nr {
      animation: pow-spokojne-odsloniecie linear both;
      animation-timeline: view();
      /*
       * ZAKRES JEST TU CAŁĄ RZECZĄ, a nie sama wartość krycia. Przy
       * `entry 15% cover 35%` odsłanianie kończyło się, zanim element wszedł
       * na dobre w ekran — więc do chwili, w której ktoś na niego patrzył,
       * było już po wszystkim i strona wyglądała na nieruchomą. Właściciel
       * zgłosił „nic się nie dzieje" i miał rację, choć reguła się wiązała
       * i krycie naprawdę rosło.
       *
       * Teraz zmiana rozkłada się na drogę, którą element pokonuje NA
       * WIDOKU, i schodzi niżej: z 0,06 do pełnego. Sześć setnych zamiast
       * zera, bo przy zerze element, który przy wejściu na stronę jest już
       * widoczny, zostałby niewidzialny na zawsze — ta pułapka zabrała tu
       * już animację trzech kart.
       */
      animation-range: entry 45% cover 75%;
    }
  }
}

/* --- Ilustracje rozłożone na warstwy --------------------------------------
 *
 * Krok pierwszy i czwarty nie są już jednym obrazkiem. Podkład niesie `<img>`
 * — z opisem dla czytnika ekranu, bo opis należy się CAŁEJ ilustracji, nie jej
 * kawałkom — a ruchome elementy leżą na nim jako tło osobnych elementów.
 *
 * Warstwy są widoczne ZAWSZE, w spoczynku dokładnie tam, gdzie były w
 * oryginale. Dopiero ruch jest warunkowy. Gdyby było odwrotnie, przeglądarka
 * bez animacji sterowanych przewijaniem pokazałaby ilustrację bez kart
 * formatów i bez laptopa — czyli zepsutą, a nie spokojną.
 *
 * Pliki wycina `node tools/warstwy.js`; każdy ma pełny kadr oryginału, więc
 * nakładają się bez ustawiania pozycji.
 */
.pow-warstwy { position: relative; }

.pow-warstwy .pow-w {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  pointer-events: none;
}

.pow-w--pdf  { background-image: url('../assets/ilustracje/warstwy/05-otwieranie-materialow.pdf.webp'); }
.pow-w--epub { background-image: url('../assets/ilustracje/warstwy/05-otwieranie-materialow.epub.webp'); }
.pow-w--txt  { background-image: url('../assets/ilustracje/warstwy/05-otwieranie-materialow.txt.webp'); }
.pow-w--ksiazka { background-image: url('../assets/ilustracje/warstwy/07-zapis-urzadzenie-google.ksiazka.webp'); }
/* Te dwie niosą wrysowany podpis, więc adres ustawia im mechanizm językowy
   z `src/ui/app.js`; tutaj tylko wartość na starcie, zanim zdąży zadziałać. */
.pow-w--urzadzenie { background-image: url('../assets/ilustracje/warstwy/07-zapis-urzadzenie-google.urzadzenie.webp'); }
.pow-w--dysk { background-image: url('../assets/ilustracje/warstwy/07-zapis-urzadzenie-google.dysk.webp'); }

:root[data-ruch-powitania="pelny"] {
  @supports (animation-timeline: view()) {

    /*
     * KROK PIERWSZY — trzy formaty zlatują do książki.
     * Każdy w innym tempie i pod innym kątem, bo trzy karty jadące równo to
     * jedna karta pokazana trzy razy. Najdalej idzie środkowa: wchodzi
     * w książkę ostatnia i to ona zamyka ruch.
     */
    .pow-w--pdf, .pow-w--epub, .pow-w--txt {
      animation: pow-format linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 70%;
    }
    .pow-w--pdf  { --pow-dx: 26px; --pow-dy: 40px; --pow-kat: 5deg; }
    .pow-w--epub { --pow-dx: 0px;  --pow-dy: 62px; --pow-kat: -2deg; }
    .pow-w--txt  { --pow-dx: -24px; --pow-dy: 34px; --pow-kat: -6deg; }
    /*
     * KROK CZWARTY — urządzenie i Dysk rozjeżdżają się względem siebie
     * I względem książki. Książka jest kotwicą: rusza się najmniej i w drugą
     * stronę, przez co tamte dwa naprawdę od niej odjeżdżają, zamiast
     * przesuwać się z nią razem.
     */
    .pow-w--ksiazka, .pow-w--urzadzenie, .pow-w--dysk {
      animation: pow-rozjazd linear both;
      animation-timeline: view();
      animation-range: entry 15% cover 75%;
    }
    .pow-w--ksiazka    { --pow-dx: -14px; --pow-dy: 6px;  --pow-skala: 1; }
    .pow-w--urzadzenie { --pow-dx: 30px;  --pow-dy: -26px; --pow-skala: 1.03; }
    .pow-w--dysk       { --pow-dx: 34px;  --pow-dy: 30px; --pow-skala: 1.03; }
  }
}


/* --- Ilustracje rozłożone na warstwy: pozostałe trzy ----------------------- */

.pow-w--03-tabela { background-image: url('../assets/ilustracje/warstwy/03-notatki-tabela-wykres.tabela.webp'); }
.pow-w--03-wykres { background-image: url('../assets/ilustracje/warstwy/03-notatki-tabela-wykres.wykres.webp'); }
.pow-w--03-mapa { background-image: url('../assets/ilustracje/warstwy/03-notatki-tabela-wykres.mapa.webp'); }
.pow-w--03-karteczka { background-image: url('../assets/ilustracje/warstwy/03-notatki-tabela-wykres.karteczka.webp'); }
.pow-w--03-spinacz { background-image: url('../assets/ilustracje/warstwy/03-notatki-tabela-wykres.spinacz.webp'); }
.pow-w--06-mysl { background-image: url('../assets/ilustracje/warstwy/06-czytanie-i-notowanie.mysl.webp'); }
.pow-w--06-mapa { background-image: url('../assets/ilustracje/warstwy/06-czytanie-i-notowanie.mapa.webp'); }
.pow-w--06-olowek { background-image: url('../assets/ilustracje/warstwy/06-czytanie-i-notowanie.olowek.webp'); }
.pow-w--06-strzalki { background-image: url('../assets/ilustracje/warstwy/06-czytanie-i-notowanie.strzalki.webp'); }
.pow-w--08-wyniki { background-image: url('../assets/ilustracje/warstwy/08-pakiet-notebooklm.wyniki.webp'); }
.pow-w--08-notatki { background-image: url('../assets/ilustracje/warstwy/08-pakiet-notebooklm.notatki.webp'); }
.pow-w--08-notebooklm { background-image: url('../assets/ilustracje/warstwy/08-pakiet-notebooklm.notebooklm.webp'); }
.pow-w--08-strzalka { background-image: url('../assets/ilustracje/warstwy/08-pakiet-notebooklm.strzalka.webp'); }

/*
 * KSIĄŻKA W HERO — dwanaście klatek. Pierwsza wpisana na stałe, żeby książka
 * stała na swoim miejscu także tam, gdzie ruch nie działa.
 */
.pow-w--ksiazka-klatki {
  background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-01.webp');
}

:root[data-ruch-powitania="pelny"] {
  @supports (animation-timeline: view()) {

    /*
     * PRZEWRACANA KARTKA. Sąsiednie klatki PRZENIKAJĄ SIĘ — przeglądarka
     * interpoluje `background-image` przez `cross-fade`, zamiast przeskakiwać.
     * Sprawdzone, nie założone: przy przewijaniu widać pary `04+05`, `09+10`.
     * Wychodzi z tego płynniej niż przy twardej podmianie, bo przenikanie
     * działa jak rozmycie ruchu i zakrywa to, że klatek jest tylko dwanaście.
     *
     * Oś to PRZEWIJANIE STRONY, nie wejście elementu w ekran. Książka jest
     * widoczna od pierwszej chwili, więc `view()` nie miałby tu fazy wejścia
     * i kartkowanie byłoby po wszystkim, zanim ktokolwiek zacznie przewijać.
     * Ta sama pułapka zabrała wcześniej animację trzech kart pod hero.
     */
    /*
     * OŚ NAZWANA, NIE „NAJBLIŻSZA". `scroll()` wybiera najbliższy kontener
     * przewijania, a `.pow-hero-obraz` ma `overflow: hidden` — czyli JEST
     * takim kontenerem, tyle że nic się w nim nie przewija. Oś wychodziła
     * wtedy martwa i kartka stała na pierwszej klatce, choć animacja była
     * poprawnie związana. Objaw mylący: `getAnimations()` pokazuje animację,
     * jej klatki są na miejscu, a `currentTime` to `null`.
     *
     * Nazwana oś wskazuje stronę wprost i nie da się jej przypadkiem przykryć
     * czyimś `overflow`.
     */
    #view-welcome { scroll-timeline-name: --pow-strona; }
    .pow-w--ksiazka-klatki {
      animation: pow-kartkowanie linear both;
      animation-timeline: --pow-strona;
      animation-range: 0 90vh;
    }
    /*
     * NOTATKI I TABLICE — kartki rozjeżdżają się lekko, każda w innym tempie.
     * Spinacz zostaje nieruchomy: trzyma tabelę, więc jego ruch bez ruchu
     * tabeli czytałby się jak usterka.
     */
    .pow-w--03-tabela { --pow-dx: 10px; --pow-dy: -12px; }
    .pow-w--03-wykres { --pow-dx: -14px; --pow-dy: 10px; }
    .pow-w--03-mapa { --pow-dx: 16px; --pow-dy: 14px; }
    .pow-w--03-karteczka { --pow-dx: 22px; --pow-dy: 22px; }
    .pow-w--03-tabela, .pow-w--03-wykres,
    .pow-w--03-mapa, .pow-w--03-karteczka {
      animation: pow-dryf linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 75%;
    }
    /*
     * OŁÓWEK SIĘ PRZETACZA. To był pierwszy pomysł właściciela i wtedy nie
     * dało się go zrobić — ołówek był zrośnięty z notesem w jednym obrazku.
     * Teraz leży osobno, więc obraca się naprawdę.
     */
    .pow-w--06-olowek {
      animation: pow-przetacza linear both;
      animation-timeline: view();
      animation-range: entry 15% cover 80%;
    }
    .pow-w--06-mysl { --pow-dx: 14px; --pow-dy: -10px; }
    .pow-w--06-mapa { --pow-dx: 18px; --pow-dy: 12px; }
    .pow-w--06-mysl, .pow-w--06-mapa {
      animation: pow-dryf linear both;
      animation-timeline: view();
      animation-range: entry 25% cover 78%;
    }

    /*
     * KARTA NOTEBOOKLM ODLATUJE — lekko, bo to koniec drogi, a nie wystrzał.
     * Trzy kartki pod nią zostają, żeby było widać, że to ONA się odrywa.
     */
    .pow-w--08-notebooklm {
      animation: pow-odlot linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 80%;
    }
  }
}

/* --- Trzy kartki pakietu przekręcają się względem siebie -------------------
 *
 * ŚRODEK OBROTU JEST TU CAŁĄ RZECZĄ. Każda warstwa niesie pełny kadr 1100x733,
 * więc domyślny środek obrotu leży na środku KADRU, a nie na kartce. Obrót
 * wokół niego przeciąga kartkę po łuku przez pół obrazka — wygląda to na
 * odlatujący papier, nie na przekręcenie. Wartości niżej to zmierzone środki
 * pól nieprzezroczystych każdej warstwy, w procentach kadru.
 *
 * Kąty są małe i RÓŻNE co do znaku: wachlarz ma się rozchylać, a nie obracać
 * w całości. Trzy kartki kręcące się tak samo to jedna kartka pokazana trzy
 * razy — ta sama wada, od której zaczęła się cała ta przebudowa.
 */
.pow-plyta-08 { transform-origin: 56% 37.3%; }
.pow-w--08-wyniki { transform-origin: 36.4% 42.7%; }
.pow-w--08-notatki { transform-origin: 18.8% 54.4%; }
.pow-w--08-notebooklm { transform-origin: 77% 75.9%; }

:root[data-ruch-powitania="pelny"] {
  @supports (animation-timeline: view()) {

    /*
     * KĄTY DOBRANE POMIAREM, NIE NA OKO. Pierwsza wersja miała 1,2 do 3,6
     * stopnia i była niewidoczna: na ilustracji szerokiej na 352 px narożnik
     * kartki przesuwał się wtedy o 2,6 do 7,7 piksela przez CAŁE przewijanie.
     * Właściciel zgłosił, że kartki się nie ruszają, i miał rację — ruch
     * istniał tylko w wyliczonych stylach.
     *
     * Przy tych wartościach narożniki idą o kilkanaście do dwudziestu kilku
     * pikseli, czyli tyle, żeby oko to złapało. Do obrotu dochodzi lekkie
     * ROZSUNIĘCIE, bo sam obrót wokół środków każe kartkom kręcić się
     * w miejscu, a wachlarz ma się otwierać.
     */
    .pow-plyta-08 { --pow-kat: 13deg; --pow-dx: 18px; --pow-dy: -9px; }
    .pow-w--08-wyniki { --pow-kat: -5.5deg; --pow-dx: 0px; --pow-dy: 6px; }
    .pow-w--08-notatki { --pow-kat: -15deg; --pow-dx: -19px; --pow-dy: 11px; }
    .pow-plyta-08, .pow-w--08-wyniki, .pow-w--08-notatki {
      animation: pow-wachlarz linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 80%;
    }
  }
}

/* --- Klatki animacji strony powitalnej ------------------------------------
 *
 * STOJĄ TU, NA POZIOMIE GŁÓWNYM, I NIE WOLNO ICH WSUNĄĆ Z POWROTEM do reguł
 * wyżej. `@keyframes` nie jest regułą warunkową i nie da się go zagnieździć
 * w regule stylu — przeglądarka po prostu go odrzuca. Dopóki opakowaniem było
 * `@media`, wszystko działało; po przejściu na sterowanie atrybutem klatki
 * zniknęły, a animacje zostały przypisane do nazw, których już nie ma.
 * Objaw był mylący: wyliczony `animation-name` pokazywał właściwą nazwę,
 * `getAnimations()` nie zwracał nic, a elementy stały.
 */
@keyframes pow-puchnie {
      0%   { transform: scale(1); }
      50%  { transform: scale(var(--pow-puch, 1.055)); }
      100% { transform: scale(1); }
    }

@keyframes pow-dochodzi {
      0%   { transform: scale(0.80); }
      50%  { transform: scale(1); }
      100% { transform: scale(0.92); }
    }

@keyframes pow-wytrzyj-w-prawo {
      from { clip-path: inset(0 100% 0 0); }
      to   { clip-path: inset(0 0 0 0); }
    }

@keyframes pow-sklada {
      from { opacity: 0; transform: translateY(26px); }
      to   { opacity: 1; transform: translateY(0); }
    }

@keyframes pow-wytrzyj-z-dolu {
      from { clip-path: inset(100% 0 0 0); }
      to   { clip-path: inset(0 0 0 0); }
    }

@keyframes pow-laduje {
      from { opacity: 0; transform: translateY(-20px) scale(0.72); }
      to   { opacity: 1; transform: translateY(0) scale(1); }
    }

@keyframes pow-spokojne-odsloniecie {
      from { opacity: 0.06; }
      to   { opacity: 1; }
    }

@keyframes pow-format {
      from { transform: translate(0, calc(var(--pow-dy) * -1)) rotate(calc(var(--pow-kat) * -1)); }
      to   { transform: translate(var(--pow-dx), 0) rotate(var(--pow-kat)); }
    }

@keyframes pow-rozjazd {
      from { transform: translate(0, 0) scale(1); }
      to   { transform: translate(var(--pow-dx), var(--pow-dy)) scale(var(--pow-skala, 1)); }
    }

@keyframes pow-kartkowanie {
      0.0% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-01.webp'); }
      9.0909% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-02.webp'); }
      18.1818% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-03.webp'); }
      27.2727% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-04.webp'); }
      36.3636% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-05.webp'); }
      45.4545% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-06.webp'); }
      54.5455% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-07.webp'); }
      63.6364% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-08.webp'); }
      72.7273% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-09.webp'); }
      81.8182% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-10.webp'); }
      90.9091% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-11.webp'); }
      100.0% { background-image: url('../assets/ilustracje/warstwy/01-hero-ksiazka-notatki.ksiazka.klatka-12.webp'); }
    }

@keyframes pow-dryf {
      from { transform: translate(0, 0); }
      to   { transform: translate(var(--pow-dx), var(--pow-dy)); }
    }

@keyframes pow-przetacza {
      from { transform: translate(-16px, 10px) rotate(-7deg); }
      to   { transform: translate(18px, -6px) rotate(9deg); }
    }

@keyframes pow-odlot {
      from { transform: translate(0, 0) scale(1) rotate(0deg); }
      to   { transform: translate(34px, -26px) scale(1.06) rotate(3deg); }
    }

@keyframes pow-wachlarz {
      from { transform: translate(0, 0) rotate(0deg); }
      to   { transform: translate(var(--pow-dx), var(--pow-dy))
                        rotate(var(--pow-kat)); }
    }
