/* Styl aplikacji - lekki, bez zaleznosci zewnetrznych. Arkusz jest do pobrania
   bez logowania, wiec ten opis nie mowi, czyj to system (J237).

   Kolory: granat, zloto i grafit znaku. Szarosci sa lekko podbite granatem,
   zeby tlo trzymalo sie z marka, a nie wygladalo na domyslne.

   Granice ekranu (audyt dlugu 22.10.2026, S107): telefon do 640 px (max-width: 640px / min-width: 641px),
   tablet do 1024 px (max-width: 1024px / min-width: 1025px), szeroki ekran od 1440 px. Skrypty biora te same
   liczby z GRANICE w pomocnicy.js. Pozostale progi (480, 520, 760, 900, 1080) dotycza pojedynczych elementow. */
:root {
    --toz-granat: #3a57a2;
    /* Obrys fokusu i ramka pola w fokusie - jedno źródło; tryb ciemny ustawia jasne odpowiedniki (ciemny-arkusz.py),
       więc każda reguła fokusu dostaje kontrast sama, bez ręcznej listy (audyt 08.10.2026, J191). */
    --toz-fokus: var(--toz-granat);
    --toz-fokus-ramka: var(--toz-granat);
    --toz-fokus-poswiata: rgba(58, 87, 162, .28);
    /* Belka menu jest JASNA (właściciel, 20.09.2026: "delikatniejsze, ładniej
       pokolorowane"). Dawna ciemnogranatowa belka ciążyła nad każdą stroną
       i zjadała niebieskie godło, które trzeba było ratować białym krążkiem.
       Teraz kolor marki niesie cienka kreska u góry (granat przechodzący
       w złoto obwódki), złota podkreślka pod otwartą pozycją i granatowe napisy
       na bieli (9:1). Nazwa --toz-belka zostaje - to nadal tło belki. */
    --toz-belka: #ffffff;
    --toz-belka-tekst: #2c4381;
    --toz-belka-linia: #e1e6f0;
    --toz-belka-tlo: #f3f5fa;
    --toz-granat-ciemny: #2c4381;
    --toz-granat-jasny: #eef1f9;
    --toz-zloto: #d7b56d;
    /* Kolory flag przy mailach: to dane wybierane przez człowieka, a nie barwy systemu, więc wyjątek od barw marki na polecenie właściciela (01.11.2026).
       Na bieli co najmniej 3:1 (znak, nie napis), ciemne odpowiedniki w ciemny-arkusz.py. */
    --flaga-czerwony: #d32f2f;
    --flaga-niebieski: #1d4ed8;
    --flaga-zielony: #2e7d32;
    --flaga-szary: #6b7280;
    --flaga-brazowy: #795548;
    --flaga-turkusowy: #00897b;
    --flaga-pomaranczowy: #d9590b;
    --flaga-fioletowy: #7b1fa2;
    --flaga-blekitny: #0277bd;
    --flaga-zolty: #a67c00;

    --toz-bg: #f2f4f8;
    --toz-plyta: #ffffff;
    /* Naglowek tabeli. Bialy jak plyta nie odroznial sie od wierszy -
       przyklejony pod belka menu wygladal jak zwykly wiersz. Odcien jest
       granatem marki rozbielonym o krok mocniej niz --toz-granat-jasny:
       tamten maluje wiersz w stanie "granatowy", wiec naglowek musi byc
       od niego glebszy, a przy tym jasniejszy od --toz-border, zeby kreska
       pod nim nadal byla widoczna. */
    --toz-naglowek-tlo: #e7ecf7;
    --toz-border: #dce0ea;
    /* Ramka pól do wpisywania - ok. 3,3:1 na bieli: puste pole wyróżnia tylko ona (audyt 04.10.2026, F31).
       --toz-border zostaje dla kart, tabel i kresek. */
    --toz-pole-ramka: #858ca1;
    --toz-text: #23262f;
    --toz-muted: #586074;

    --toz-ok: #1f6b45;
    --toz-uwaga: #8a6100;
    --toz-blad: #a52834;
    /* Jasne tła stanów - komunikaty, plakietki, wiersze listy (audyt długu 22.10.2026, S106): jedna zieleń,
       żółć i czerwień zamiast kilku odcieni różnych o 1-3 jednostki. Ciemne odpowiedniki - ciemny-arkusz.py. */
    --toz-tlo-ok: #e3f2ea;
    --toz-tlo-uwaga: #fdf4e0;
    --toz-tlo-blad: #fbe9ea;
    --toz-tlo-blad-kursor: #f7dcde;
    /* Pinezka miejsca niebezpiecznego. Nie czerwien bledu: to nie awaria
       systemu, tylko ostrzezenie dla kogos, kto tam jedzie - i musi odcinac
       sie od granatu pozostalych pinezek na pierwszy rzut oka. */
    --toz-niebezpieczne: #a63a6d;
    /* Pinezka sprawy drugoplanowej - szarosc podbita granatem, zeby nalezala
       do tej samej rodziny co reszta znakow, ale schodzila w tlo. */
    --toz-przygaszone: #949aab;
    /* Plamy mapy "Gdzie najwiecej spraw" (27.10.2026) - ciemny granat marki; skrypt mapy czyta te zmienna,
       wiec tryb ciemny moze ja zmienic jednym wierszem. */
    --mapa-plama: #2c4381;
    /* Podkład kółek legendy plam - szarość kafelka mapy po grayscale(.7), żeby legenda leżała na tym samym tle, co
       plamy na mapie (przegląd 27.10.2026: na płycie karty w trybie ciemnym czytała się odwrotnie niż mapa). */
    --mapa-podklad: #e6e6e6;

    --toz-cien: 0 1px 2px rgba(43, 42, 41, .05), 0 1px 8px rgba(58, 87, 162, .04);
    --toz-promien: 10px;
    --toz-margines: clamp(16px, 2.5vw, 40px);
}

* { box-sizing: border-box; }

/* Strona NIGDY nie przesuwa sie w bok - na telefonie wygladalo to jak zepsuty
   ekran: pusta szara plachta obok kart (wlasciciel: "Czemu mozna uciec poza
   ekran na komorce? Pilnuj tego"). Szerokie rzeczy maja swoj pojemnik
   z przewijaniem (.table-wrap); to jest straznik na wszystko, czego ktos
   kiedys w pojemnik nie wlozy.
   clip, a nie hidden: hidden na body robi z niego pojemnik przewijania i psuje
   przyklejanie (belka menu, naglowek tabeli). Na html hidden jest tylko
   zapasem dla przegladarek bez clip - wartosc z html przechodzi na okno. */
html { overflow-x: hidden; overflow-x: clip; }

/* Miejsce na pasek przewijania stoi zawsze zarezerwowane. Bez tego belka
   z menu byla na krotkich stronach (pisma, teczki, wyroki) szersza o pasek
   niz na dlugich (interwencje) i menu przeskakiwalo przy przejsciu miedzy
   nimi (wlasciciel, 14.09.2026). Przegladarka bez scrollbar-gutter pokazuje
   pasek zawsze - skutek na ekranie jest ten sam. */
html { scrollbar-gutter: stable; }

@supports not (scrollbar-gutter: stable) {
    html { overflow-y: scroll; }
}

body {
    overflow-x: clip;
    margin: 0;
    background: var(--toz-bg);
    /* Jasna poświata u góry strony zamiast płaskiej szarości - głębia bez obrazka.
       Nie "fixed": tło przypięte do okna przerysowuje całą stronę przy przewijaniu. */
    background-image: radial-gradient(1100px 420px at 50% -180px, rgba(58, 87, 162, .10), rgba(58, 87, 162, 0));
    background-repeat: no-repeat;
    color: var(--toz-text);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    -webkit-text-size-adjust: 100%;
}

/* Ewidencja jest szeroka: tabele maja korzystac z calej szerokosci okna,
   a nie miescic sie w kolumnie do czytania. Oddech daje margines boczny. */
.container { width: 100%; max-width: none; margin: 0; padding: 0 var(--toz-margines); }

.topbar {
    background: var(--toz-belka);
    color: var(--toz-belka-tekst);
    border-bottom: 1px solid var(--toz-belka-linia);
    box-shadow: 0 6px 18px rgba(44, 67, 129, .06);
    /* Lista potrafi miec 500 wierszy - menu ma byc pod reka bez wracania
       na gore strony. */
    position: sticky;
    top: 0;
    z-index: 30;
}
/* Kolor marki jako cienka kreska u góry belki: granat tarczy przechodzący
   w złoto obwódki - jedyny mocny akcent, reszta belki jest spokojna. */
.topbar::before { content: ''; display: block; height: 3px; background: linear-gradient(90deg, var(--toz-granat), var(--toz-zloto)); }
/* Przed zalogowaniem belka nie ma nic do pokazania (właściciel, 19.09.2026:
   ekran logowania nie zdradza, czyj to system) - zostaje sama kreska. */
.topbar-pusta .topbar-inner { min-height: 0; }
.topbar :focus-visible { outline-color: var(--toz-fokus); }
.topbar-inner { display: flex; align-items: center; justify-content: space-between; min-height: 60px; gap: 24px; flex-wrap: wrap; }
.brand { display: flex; align-items: center; gap: 10px; color: var(--toz-belka-tekst); font-weight: 700; text-decoration: none; letter-spacing: .01em; }
.brand:hover, .brand:focus-visible { color: var(--toz-granat); text-decoration: none; }
/* Godło na białym tle stoi samo - bez krążka, który ratował je na granacie. */
.brand img { display: block; width: 32px; height: 32px; object-fit: contain; }
/* Pasek nawigacji siega gory i dolu belki, choc same odnosniki zostaja
   wysrodkowane. Chodzi o jedno: rozwijane menu ma sie zaczynac POD BELKA,
   a nie w polowie jej wysokosci - inaczej wchodzi na zlota krawedz i wyglada,
   jakby wypadlo z paska. */
.nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; align-self: stretch; }
.nav a { color: var(--toz-belka-tekst); text-decoration: none; padding: 8px 12px; border-radius: 8px; font-weight: 500; }
.nav a:hover, .nav a:focus { background: var(--toz-belka-tlo); text-decoration: none; }
.nav a.aktywna { background: var(--toz-granat-jasny); box-shadow: inset 0 -2px 0 var(--toz-zloto); font-weight: 600;
    /* Granat z głębią zamiast płaskiej plamy. */
    background-image: linear-gradient(180deg, #f4f6fd, #e2e8f7); }
/* Nazwisko i "Wyloguj" to nie moduły - stoją ciszej, po prawej. */
.nav .nav-konto { color: var(--toz-muted); font-weight: 500; margin-left: 6px; }
.nav .nav-konto:hover, .nav .nav-konto:focus-visible, .nav .nav-konto.aktywna { color: var(--toz-belka-tekst); }

/* --- Menu w grupach --------------------------------------------------------
   Przy osmiu modulach pasek robil sie szerszy niz ekran. Grupa to <details>,
   wiec rozwija sie i zwija bez JavaScriptu, a klawiatura obsluguje ja sama. */
/* Grupa jest wysoka na cala belke, zeby "100%" w polozeniu rozwijanego menu
   znaczylo "dol belki". Sam przycisk zostaje niski i wysrodkowany - stad
   flex w srodku. */
.nav-grupa { position: relative; align-self: stretch; display: flex; align-items: center; }
.nav-grupa > summary {
    list-style: none; cursor: pointer; padding: 8px 12px; border-radius: 8px;
    color: var(--toz-belka-tekst); font-weight: 500; white-space: nowrap; user-select: none;
}
/* Trojkacik rysujemy sami - domyslny znacznik <details> wyglada inaczej
   w kazdej przegladarce i w Safari jest czarny na granatowym tle. */
.nav-grupa > summary::-webkit-details-marker { display: none; }
/* Strzałka jak w polach wyboru: cienki daszek zamiast pełnego trójkąta. */
.nav-grupa > summary::after {
    content: ''; display: inline-block; width: 7px; height: 7px; margin-left: 8px; vertical-align: middle;
    border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); translate: 0 -3px;
    opacity: .7;
}
.nav-grupa > summary:hover, .nav-grupa > summary:focus-visible,
.nav-grupa[open] > summary { background: var(--toz-belka-tlo); }
.nav-grupa.aktywna > summary { background: var(--toz-granat-jasny); font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--toz-zloto); }

.nav-rozwijane {
    /* 100% to dol belki (grupa jest na jej wysokosc), 1px to kreska pod nia,
       ktorej menu nie ma prawa zaslaniac. */
    position: absolute; top: calc(100% + 1px); left: 0; z-index: 40;
    display: flex; flex-direction: column; gap: 2px; min-width: 210px; padding: 6px;
    background: var(--toz-belka); border: 1px solid var(--toz-belka-linia);
    border-radius: 12px; box-shadow: 0 14px 34px rgba(44, 67, 129, .14);
}
.nav-rozwijane a { white-space: nowrap; }
/* W rozwijanej liście otwarta pozycja ma złotą kreskę z lewej, nie od dołu. */
.nav-rozwijane a.aktywna { box-shadow: inset 3px 0 0 var(--toz-zloto); }
/* Maile do przejrzenia przy zakładce Maile i na przycisku „Menu” zwiniętego menu (właściciel, 11.11.2026; App\Poczta\LicznikMenu,
   maile-w-menu.js): złota liczba jak liczba nowych maili przy zakładce listy - granatowa plakietka to „Nowość”. Napis ciemny
   w obu wyglądach, bo tło zostaje złote. Bez ruchu: liczba zmienia się sama co minutę i nie ma ściągać wzroku przy pracy. */
.menu-licznik { display: inline-block; min-width: 1.7em; margin-left: .45em; padding: 0 .5em; border-radius: 999px;
    background: var(--toz-zloto); color: #23262f; font-size: .72rem; font-weight: 700; line-height: 1.6; text-align: center;
    vertical-align: .12em; white-space: nowrap; }
.menu-licznik[hidden] { display: none; }
.menu-licznik-przycisk { margin-left: -2px; }
@media print { .menu-licznik { display: none !important; } }

@media (max-width: 760px) {
    /* Na waskim ekranie belka nie jest przyklejona, wiec rozwiniete menu
       moze po prostu rozepchnac wiersz - nakladka na tak malej szerokosci
       zaslanialaby pol ekranu.
       Grupa wraca wtedy do zwyklego bloku: przy flexie menu wysunelo by sie
       OBOK przycisku, a nie pod nim - nie jest juz wyjete z ukladu. */
    .nav-grupa { display: block; align-self: auto; }
    .nav-rozwijane { position: static; box-shadow: none; margin-top: 4px; }
}
/* --- Menu zwiniete: telefon i waskie okno ---------------------------------
   Wlasciciel: "szczegolnie na komorce wyglada jak chaos. Przy otwieraniu menu
   skacze". Pelne menu administratora potrzebuje ok. 1630 px w jednym wierszu
   (ciasniejsze uklady nizej, przy menu-ciasne).
   Na telefonie lamalo sie na cztery linijki roznej dlugosci (224 px belki),
   a rozwiniecie grupy rozpychalo wiersz: pozostale pozycje przeskakiwaly
   w bok i w dol, a cala strona zjezdzala o 130 px.

   Gdy pasek nie miesci sie w jednym wierszu, na <html> staje klasa
   menu-zwiniete (menu-start.js jeszcze przed narysowaniem strony, potem
   menu.js przy kazdej zmianie szerokosci). W belce zostaje logo i przycisk
   "Menu". Menu otwiera sie jako panel NAD trescia - strona pod spodem nie
   przesuwa sie ani o piksel - a grupy stoja w nim rozwiniete, jedna pod druga,
   bez niczego do rozwijania. Bez JavaScriptu klasy nie ma i menu zostaje
   zwykle: <details> dziala samo. */
.menu-przelacznik { display: none; }

html.menu-zwiniete .topbar-inner { flex-wrap: nowrap; gap: 12px; }
/* Nazwa systemu nie lamie sie na dwie linijki - belka zmienialaby wysokosc,
   a z nia wszystko pod spodem. Na bardzo waskim ekranie skraca sie kropkami. */
html.menu-zwiniete .brand { min-width: 0; }
html.menu-zwiniete .brand span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.menu-zwiniete .menu-przelacznik {
    display: inline-flex; align-items: center; gap: 10px; margin-left: auto;
    min-height: 42px; padding: 0 14px; border-radius: 10px;
    border: 1px solid #c9d2e8; background: var(--toz-belka);
    color: var(--toz-belka-tekst); font: inherit; font-weight: 600; cursor: pointer;
}
html.menu-zwiniete .menu-przelacznik:hover,
html.menu-zwiniete .menu-przelacznik[aria-expanded="true"] { background: var(--toz-granat-jasny); border-color: #b5c2e3; }

/* Trzy kreski rysowane stylem - bez obrazka i bez znaku, ktory kazda
   przegladarka rysuje inaczej. Otwarte menu sklada je w krzyzyk: to samo
   miejsce zamyka. */
.menu-ikona, .menu-ikona::before, .menu-ikona::after {
    display: block; width: 18px; height: 2px; border-radius: 1px; background: currentColor;
}
.menu-ikona { position: relative; }
.menu-ikona::before, .menu-ikona::after { content: ''; position: absolute; left: 0; }
.menu-ikona::before { top: -6px; }
.menu-ikona::after { top: 6px; }
.menu-przelacznik[aria-expanded="true"] .menu-ikona { background: transparent; }
.menu-przelacznik[aria-expanded="true"] .menu-ikona::before { top: 0; transform: rotate(45deg); }
.menu-przelacznik[aria-expanded="true"] .menu-ikona::after { top: 0; transform: rotate(-45deg); }

/* Panel pod zlota krawedzia belki, na cala szerokosc, NAD trescia. Na telefonie
   belka nie jest przyklejona, wiec potrzebuje position, zeby panel mial sie
   do czego odniesc; szerzej jest przyklejona (sticky), a to juz wystarcza. */
@media (max-width: 760px) {
    html.menu-zwiniete .topbar { position: relative; }
}
html.menu-zwiniete .nav {
    display: none;
    position: absolute; left: 0; right: 0; top: calc(100% + 1px); z-index: 40;
    flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 2px;
    padding: 8px var(--toz-margines) 16px;
    /* Dlugie menu przewija sie w panelu, a nie spycha strony. Wysokosc z paskiem adresu (svh): stala, gdy pasek
       sie chowa i wraca (dvh zmienialo sie przy kazdym przewinieciu - wlasciciel, 28.10.2026). */
    max-height: calc(100vh - 66px);
    max-height: calc(100svh - 66px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--toz-belka);
    border-bottom: 1px solid var(--toz-belka-linia);
    box-shadow: 0 18px 36px rgba(44, 67, 129, .16);
}
html.menu-zwiniete.menu-otwarte .nav { display: flex; }

/* Pozycje na cala szerokosc panelu, wysokie na palec (44 px). */
html.menu-zwiniete .nav a,
html.menu-zwiniete .nav .btn-link {
    display: flex; align-items: center; justify-content: flex-start; width: 100%; min-height: 44px;
    padding: 10px 12px; font-size: 1rem; font-weight: 400; text-align: left; white-space: normal;
}
html.menu-zwiniete .nav a.aktywna { box-shadow: inset 3px 0 0 var(--toz-zloto); background: var(--toz-granat-jasny); }

/* Grupa: nazwa to przycisk na cala szerokosc, pozycje rozwija klikniecie
   (wlasciciel, 01.10.2026: rozwiniete na stale dawaly "strasznie dlugie" menu). */
html.menu-zwiniete .nav-grupa { display: block; align-self: auto; }
html.menu-zwiniete .nav-grupa > summary {
    display: flex; align-items: center; justify-content: space-between; min-height: 44px;
    padding: 10px 12px; font-size: 1rem; font-weight: 600; white-space: normal;
}
html.menu-zwiniete .nav-grupa > summary::after { margin-left: 12px; flex: none; }
html.menu-zwiniete .nav-grupa[open] > summary::after { transform: rotate(-135deg); translate: 0 2px; }
html.menu-zwiniete .nav-grupa.aktywna > summary { box-shadow: inset 3px 0 0 var(--toz-zloto); }
html.menu-zwiniete .nav-rozwijane a { padding-left: 28px; }
html.menu-zwiniete .nav-rozwijane {
    position: static; min-width: 0; margin: 0; padding: 0; gap: 2px;
    background: none; border: 0; border-radius: 0; box-shadow: none;
}

/* Konto i wylogowanie na dole, oddzielone od modulow. */
html.menu-zwiniete .nav-konto {
    margin-top: 12px; padding-top: 14px; border-radius: 0; margin-left: 0;
    border-top: 1px solid var(--toz-belka-linia);
}
html.menu-zwiniete .nav .nav-oddzial { border-radius: 10px; margin-top: 6px; }
html.menu-zwiniete .nav-wyloguj { display: block; }

/* Na czas pomiaru w menu.js: rozwiniete grupy nie moga poszerzac paska. */
html.menu-mierzenie .nav-rozwijane { display: none !important; }

/* --- Menu ciasne: laptop -----------------------------------------------------
   Pelne menu administratora potrzebuje ok. 1630 px, wiec na laptopie zawsze
   bylo zwiniete do "Menu" (wlasciciel, 04.10.2026: "zrob wezszy pasek menu").
   Zanim menu sie zwinie, menu.js probuje dwoch ciasniejszych ukladow:
   menu-ciasne - mniejsze odstepy i pismo o pol stopnia mniejsze (ok. 1400 px),
   menu-samo-logo - do tego bez nazwy systemu obok godla (ok. 1210 px).
   Napis "Dzialasz w:" zostaje zawsze - instrukcje kaza go szukac u gory. */
html.menu-ciasne .topbar-inner { gap: 12px; }
html.menu-ciasne .nav { gap: 0; }
html.menu-ciasne .nav > a,
html.menu-ciasne .nav-grupa > summary,
html.menu-ciasne .topbar .btn-link { padding-left: 6px; padding-right: 6px; font-size: .9375rem; }
html.menu-ciasne .nav-grupa > summary::after { margin-left: 6px; }
html.menu-ciasne .nav .nav-oddzial,
html.menu-ciasne .nav .nav-konto { margin-left: 4px; }
/* Bardzo dlugie nazwisko konczy sie kropkami, zamiast zwijac cale menu. */
html.menu-ciasne .nav .nav-konto { max-width: 11em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Nazwa systemu znika tylko z oczu - czytnik ekranu dalej czyta ja w odnosniku. */
html.menu-samo-logo .brand span {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.topbar .btn-link { color: var(--toz-muted); text-decoration: none; padding: 8px 12px; border-radius: 8px; min-height: 0; font-weight: 500; }
.topbar .btn-link:hover, .topbar .btn-link:focus-visible { background: var(--toz-belka-tlo); color: var(--toz-belka-tekst); }

.main { padding: 28px var(--toz-margines) 56px; }
.footer { padding: 0 var(--toz-margines) 24px; color: var(--toz-muted); }
/* Wersja programu pod stopką administratora - własny wiersz (J122/J125/J126). */
.footer .stopka-wersja { display: block; margin-top: 4px; }

.card {
    background: var(--toz-plyta);
    border: 1px solid var(--toz-border);
    border-radius: var(--toz-promien);
    padding: clamp(16px, 2vw, 28px);
    margin-bottom: 24px;
    box-shadow: var(--toz-cien);
}
.card-narrow { max-width: 460px; margin-left: auto; margin-right: auto; }

/* Kafelek, do ktorego wraca sie po dolozeniu albo skasowaniu pliku. Pasek
   gorny jest przyklejony i ma 60 px - bez tego zakotwiczony naglowek ladowal
   dokladnie pod nim i nie bylo widac, gdzie sie wladowalo. */
.card[id] { scroll-margin-top: 76px; }


.h4 { font-size: 1.35rem; margin: 0 0 8px; letter-spacing: -.01em; text-wrap: balance; }
/* Tytul strony ma byc wyrazniejszy niz naglowek sekcji - inaczej wszystkie
   naglowki wygladaja tak samo i nie widac, gdzie sie jest. */
h1.h4 { font-size: 1.7rem; }
h3 { font-size: 1.05rem; margin: 28px 0 4px; letter-spacing: -.005em; }
.h5 { font-size: 1.05rem; margin: 24px 0 4px; letter-spacing: -.005em; }
.card-head + .h5, .card > .h5:first-child { margin-top: 0; }
.muted { color: var(--toz-muted); }
.small { font-size: .875rem; }
.mt { margin-top: 16px; }

.label { display: block; margin: 16px 0 6px; font-weight: 600; font-size: .95rem; }
.form-control {
    /* Wysokosc ustawiamy jawnie i tak samo jak w .btn - przegladarka liczy
       ja inaczej dla input, select i input[type=date], przez co kontrolki
       w jednym rzedzie filtrow stawaly na roznych poziomach. */
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-height: 42px;
    padding: 9px 12px;
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.2;
    border: 1px solid var(--toz-pole-ramka);
    border-radius: 8px;
    background: #fff;
    color: var(--toz-text);
}
/* Pole wielolinijkowe rzadzi sie inaczej niz jednolinijkowe: line-height 1.2
   dobre dla numeru faktury sklejalo wiersze opisu w scianke tekstu.
   Rozciaganie tylko w pionie - poziome rozjezdza siatke formularza,
   a w panelu otwartym nad wierszem tabeli wychodzi poza zasieg wzroku. */
textarea.form-control {
    min-height: 4.5rem;
    line-height: 1.55;
    resize: vertical;
}

/* Kwoty i liczby w formularzach wyrownane do prawej - tak samo jak w tabelach.
   Cyfry porownuje sie miedzy wierszami po koncowce, nie po poczatku: przy
   wyrownaniu do lewej "1 200,00" i "980,00" zaczynaja sie w tym samym miejscu
   i wyzsza kwota wyglada na nizsza.

   Zaczepiamy sie o inputmode="decimal", bo tym oznaczone jest w tym systemie
   kazde pole liczbowe - i nowe pole trafia po wlasciwej stronie samo. */
.form-control[inputmode="decimal"] { text-align: right; }

/* Pole daty na iPhonie: Safari daje mu wlasna, szeroka miare - w szybkiej
   rejestracji faktury wystawalo przez to poza karte - i stawia date na srodku.
   appearance: none zdejmuje wlasny wyglad, min-width: 0 pozwala zejsc do
   szerokosci kolumny. Kalendarz nadal otwiera sie po dotknieciu. */
input.form-control[type="date"],
input.form-control[type="datetime-local"],
input.form-control[type="time"] {
    -webkit-appearance: none;
    appearance: none;
    min-width: 0;
    max-width: 100%;
    text-align: left;
}
input.form-control::-webkit-date-and-time-value { text-align: left; }

/* Potwierdzenie skopiowania daty - stoi chwile obok pola i znika.
   Bez niego skrot dziala po cichu i nie wiadomo, czy cos sie stalo. */
.data-skopiowana {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    background: #eef1f8;
    color: var(--toz-granat);
    font-size: .82rem;
    white-space: nowrap;
}

.form-control:focus, .form-control:focus-visible { outline: 3px solid var(--toz-fokus-poswiata); outline-offset: 0; border-color: var(--toz-fokus-ramka); }
/* Podpowiedź w polu czytelna (4,85:1) - w paskach przypinania to jedyny opis pola (audyt 29.09.2026, C173). */
.form-control::placeholder { color: #6b7185; opacity: 1; }
.form-control[readonly], .form-control:disabled { background: #f4f5f8; color: var(--toz-muted); }
/* Obrys fokusu z klawiatury pełnym granatem - blady (1,74:1) ginął na bieli (audyt 29.09.2026, C171). */
:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; }
.code-input { letter-spacing: .35em; font-size: 1.25rem; text-align: center; }

/* --- Przyciski ---------------------------------------------------------------
   Wszystko o wyglądzie przycisków stoi tutaj (audyt długu 22.10.2026, S98) - także późniejsze
   warstwy (światło, spadki barw, cienie), dawniej dopisywane na końcu arkusza. Kolejność reguł
   jest częścią wyglądu: późniejsza reguła o tej samej wadze wygrywa. Ruch (przejścia, fala)
   zostaje w sekcjach ruchu niżej. */
.btn {
    /* Ta sama regula obsluguje <button> i <a class="btn">. Przegladarka daje
       im rozne domyslne wysokosci i kroj pisma, wiec ustawiamy wszystko
       jawnie - inaczej "Filtruj" obok "Wyczysc" ma inna wielkosc. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    min-height: 42px;
    padding: 0 18px;
    font-family: inherit;
    font-weight: 600;
    font-size: .875rem;
    line-height: 1.2;
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    cursor: pointer;
    text-decoration: none;
    text-align: center;
    white-space: nowrap;
    background: #fff;
    color: var(--toz-text);
    vertical-align: middle;
    -webkit-appearance: none;
    appearance: none;
}
.btn:hover { background: var(--toz-granat-jasny); border-color: #c3cbe2; }
.btn-primary { background: var(--toz-granat); color: #fff; }
.btn-primary:hover, .btn-primary:focus { background: var(--toz-granat-ciemny); }
/* Przycisk wyłączony wygląda na wyłączony (właściciel, 25.09.2026: "jeśli żadna
   zbiórka nie jest zaznaczona to nie uaktywniaj przycisku ... Podobnie w innych
   modułach") - wcześniej "Przypnij do zaznaczonych" czy "Ustaw zaznaczonym" bez
   zaznaczenia był wyłączony, ale wyglądał tak samo jak czynny. Najechanie niczego
   nie podświetla; kolor zostaje, tylko przygaszony. */
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: #fff; border-color: var(--toz-border); }
.btn-primary:disabled:hover, .btn-primary:disabled:focus { background: var(--toz-granat); }
.btn-block { display: flex; width: 100%; margin-top: 20px; }
.btn-link { background: none; border-color: transparent; min-height: 0; padding: 0; color: var(--toz-granat); text-decoration: underline; }
.btn-link:hover { background: none; color: var(--toz-granat-ciemny); }
.btn-maly { min-height: 32px; padding: 0 12px; font-size: .8125rem; }
.btn-danger { background: var(--toz-blad); border-color: var(--toz-blad); color: #fff; }
.btn-danger:hover, .btn-danger:focus { background: #8b202c; border-color: #8b202c; }
.btn-danger:disabled:hover, .btn-danger:disabled:focus { background: var(--toz-blad); border-color: var(--toz-blad); }

/* Przycisk główny odrobinę wyżej od płyty, wciśnięty - o piksel niżej. */
.btn-primary:not(:disabled) { box-shadow: 0 1px 2px rgba(44, 67, 129, .22); }
.btn:not(:disabled):active { transform: translateY(1px); box-shadow: none; }

/* Przycisk główny i przycisk usuwania: pod kursorem cień w kolorze przycisku. */
.btn-primary:not(:disabled):hover { box-shadow: 0 4px 12px rgba(44, 67, 129, .28); }
.btn-danger:not(:disabled):hover { box-shadow: 0 4px 12px rgba(165, 40, 52, .26); }
/* Wciśnięty przycisk jest też pod kursorem - cień ma wtedy zniknąć, nie zostać. */
.btn-primary:not(:disabled):active, .btn-danger:not(:disabled):active { box-shadow: none; }

/* Przycisk główny: granat przechodzący w głębszy granat, światło od góry
   i ukryty po prawej błysk, który pod kursorem przebiega raz przez przycisk.
   Pod kursorem jaśniejszy; wyłączony wygląda jak zwykły i na kursor nie reaguje. */
.btn-primary, .btn-primary:disabled:hover, .btn-primary:disabled:focus {
    border-color: #2f4785;
    background-image:
        linear-gradient(110deg, rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, .38) 50%, rgba(255, 255, 255, 0) 62%),
        linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0) 62%),
        linear-gradient(135deg, #4a68ba 0%, var(--toz-granat) 48%, var(--toz-granat-ciemny) 100%);
}
/* Rozmiar i położenie warstw we wszystkich stanach: dawne reguły pod kursorem ustawiają
   tło skrótem ("background:"), a skrót zeruje rozmiar i położenie - błysk stałby wtedy
   na środku przycisku zamiast czekać poza nim. */
.btn-primary, .btn-primary:hover, .btn-primary:focus, .btn-primary:disabled:hover, .btn-primary:disabled:focus {
    background-size: 250% 100%, 100% 100%, 100% 100%;
    background-repeat: no-repeat;
    background-position: -50% 0, 0 0, 0 0;
}
.btn-primary:not(:disabled):hover, .btn-primary:not(:disabled):focus {
    background-image:
        linear-gradient(110deg, rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, .38) 50%, rgba(255, 255, 255, 0) 62%),
        linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0) 62%),
        linear-gradient(135deg, #4f6ec0 0%, #3f5eae 48%, #31498c 100%);
}

/* Przycisk usuwania: czerwień z głębią, ta sama warstwa światła. */
.btn-danger, .btn-danger:disabled:hover, .btn-danger:disabled:focus {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, .13), rgba(255, 255, 255, 0) 62%),
        linear-gradient(135deg, #c13d4a, var(--toz-blad) 55%, #861d29);
}
.btn-danger:not(:disabled):hover, .btn-danger:not(:disabled):focus {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, .13), rgba(255, 255, 255, 0) 62%),
        linear-gradient(135deg, #c43f4c, #a82a37 55%, #8f2230);
}
/* Kolor fali po kliknięciu (ruch niżej): granatowa, przy usuwaniu czerwona. */
.btn { --fala: rgba(58, 87, 162, .42); }
.btn-danger { --fala: rgba(165, 40, 52, .4); }

/* Zwykły przycisk (nie główny, nie usuwania, nie odnośnik, nie numer otwartej strony): granatowy
   napis na jasnym spadku z granatu - już nie szara plama. Pod kursorem głębszy; wyłączony
   wygląda tak samo z kursorem i bez. */
.btn:not(.btn-primary):not(.btn-danger):not(.btn-link):not(.btn-strona-aktywna) {
    background-image: linear-gradient(180deg, #ffffff, #edf1fb);
    border-color: #cdd6ee;
    color: var(--toz-granat-ciemny);
}
.btn:not(.btn-primary):not(.btn-danger):not(.btn-link):not(.btn-strona-aktywna):not(:disabled):hover {
    background-image: linear-gradient(180deg, #f3f6fd, #dce4f6);
    border-color: #aebce2;
}

/* Zwykły przycisk pod kursorem dostaje granatową poświatę - wiadomo, że jest pod ręką. */
.btn:not(.btn-primary):not(.btn-danger):not(.btn-link):not(:disabled):hover { box-shadow: 0 2px 10px rgba(58, 87, 162, .14); }

/* Przyciski pobierania pism (karta wyroku): dlugi napis na telefonie
   lamie sie w przycisku, zamiast wystawac poza karte. */
.przyciski-pism { display: flex; flex-wrap: wrap; gap: 8px; }
.przyciski-pism .btn { white-space: normal; max-width: 100%; padding-top: 8px; padding-bottom: 8px; }

/* --- Komunikaty -------------------------------------------------------------
   Kreska z lewej w kolorze stanu - komunikat po zapisie widać kątem oka - i znak stanu z lewej
   (obrazek w tle: treść i znaczniki komunikatu zostają takie, jakie były). Tło komunikatu
   ustawia background-color, nie skrót "background:" - skrót zerowałby położenie znaku. */
.alert {
    padding: 12px 16px 12px 46px; border-radius: 8px; margin-bottom: 16px;
    border: 1px solid transparent; border-left-width: 4px;
    background-repeat: no-repeat; background-position: 14px 12px; background-size: 20px 20px;
}
.alert-success { background-color: var(--toz-tlo-ok); border-color: #b6ddc8; border-left-color: var(--toz-ok); color: var(--toz-ok);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='9' fill='%231f6b45'/%3E%3Cpath d='M5.8 10.4l2.8 2.8 5.6-6' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.alert-danger  { background-color: var(--toz-tlo-blad); border-color: #f0bcc1; border-left-color: var(--toz-blad); color: var(--toz-blad);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='9' fill='%23a52834'/%3E%3Cpath d='M10 5.2v5.6' stroke='%23fff' stroke-width='2.2' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='14.2' r='1.3' fill='%23fff'/%3E%3C/svg%3E"); }
.alert-warning { background-color: var(--toz-tlo-uwaga); border-color: var(--toz-zloto); border-left-color: #c9a04a; color: var(--toz-uwaga);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.8l8.6 15.4H1.4z' fill='%23c9a04a' stroke='%23c9a04a' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M10 7.4v4.4' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='14.6' r='1.15' fill='%23fff'/%3E%3C/svg%3E"); }
.alert-info    { background-color: var(--toz-granat-jasny); border-color: #c3cbe2; border-left-color: var(--toz-granat); color: var(--toz-granat-ciemny);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Ccircle cx='10' cy='10' r='9' fill='%233a57a2'/%3E%3Cpath d='M10 9.2v5.4' stroke='%23fff' stroke-width='2.2' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='5.9' r='1.3' fill='%23fff'/%3E%3C/svg%3E"); }

.hint { color: var(--toz-muted); font-size: .875rem; margin: 8px 0 0; }
ul.hint, ol.hint { padding-left: 20px; }
.steps { padding-left: 20px; color: var(--toz-muted); font-size: .95rem; }
.choice { display: flex; gap: 12px; align-items: flex-start; padding: 12px; border: 1px solid var(--toz-border); border-radius: 8px; margin-top: 12px; cursor: pointer; }
.choice input { margin-top: 4px; }

.qr { text-align: center; margin: 20px 0; }
.qr img { max-width: 100%; height: auto; background: #fff; }
.secret { text-align: center; font-size: .95rem; }
.secret code { background: var(--toz-granat-jasny); padding: 4px 8px; border-radius: 6px; letter-spacing: .1em; }

.codes { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 16px 0; }
.codes code { display: block; background: var(--toz-granat-jasny); padding: 10px; border-radius: 6px; text-align: center; letter-spacing: .08em; }
/* "Skopiuj kody" i "Wydrukuj" nad kodami zapasowymi (właściciel, 27.10.2026; kody-zapasowe.js). Na papierze sama
   kartka z kodami: nagłówek, zdanie z datą (.kody-data - tylko na wydruku) i kody w ramkach - tło się nie drukuje.
   Menu, stopka i komunikaty znikają z każdego wydruku (reguły wydruku niżej). */
.kody-przyciski { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }
.kody-przyciski + .codes { margin-top: 10px; }
.kody-data { display: none; }
@media print {
    .kody-zapasowe > :not(h1):not(.kody-data):not(.codes) { display: none !important; }
    .kody-zapasowe .kody-data { display: block; margin: 0 0 12pt; }
    .kody-zapasowe .codes code { background: none; border: 1pt solid #000; font-size: 13pt; }
}

/* "Pokaż" / "Ukryj" w polu hasła (właściciel, 27.10.2026; pokaz-haslo.js owija pole w .pole-hasla). Przycisk stoi
   w prawym rogu, w środku pola, a pole ma z prawej miejsce na niego - tekst nie wchodzi pod napis, a na telefonie
   nic nie zajmuje dodatkowego wiersza. Bez skryptu zwykłe pole. */
.pole-hasla { position: relative; display: block; width: 100%; }
.pole-hasla > .form-control { padding-right: 78px; }
/* Edge ma w polu hasła własne "oko" - obok przycisku "Pokaż" stałyby dwa przełączniki tego samego. */
.pole-hasla > input::-ms-reveal, .pole-hasla > input::-ms-clear { display: none; }
.pokaz-haslo {
    position: absolute; top: 5px; right: 5px; bottom: 5px; min-width: 64px; padding: 0 10px;
    border: 0; border-radius: 6px; background: var(--toz-granat-jasny); color: var(--toz-granat-ciemny);
    font: inherit; font-size: .8125rem; font-weight: 600; cursor: pointer;
}
.pokaz-haslo:hover { background: var(--toz-naglowek-tlo); }
@media print { .pokaz-haslo { display: none; } }

/* Pola wyrownujemy do gory: podpowiedz pod jednym z nich nie moze zsuwac
   sasiadow w dol. Sam przycisk dociagamy do dolu osobno. */
.grid-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; align-items: start; }
.grid-form > div > .label:first-child { margin-top: 0; }
.grid-form-action { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; align-self: end; }
/* Numer konta oddzialu: 32 znaki z odstepami nie mieszcza sie w kolumnie
   po 200 px. Caly wiersz (1 / -1 nie doklada kolumn, wiec strona nie ucieka
   w bok na telefonie), a pole na szerokosc numeru. */
.grid-form > .pole-konto { grid-column: 1 / -1; }
.pole-konto .form-control { max-width: 24rem; }
/* Przelacznik z opisem (np. obsluga AI w karcie oddzialu): opis w kolumnie
   po 200 px zawijal sie co dwa slowa - caly wiersz, jak numer konta. */
.grid-form > .pole-caly-wiersz { grid-column: 1 / -1; }
.pole-caly-wiersz .choice { max-width: 48rem; }
.pole-caly-wiersz > .form-control { max-width: 32rem; }
.pole-caly-wiersz > .stopka-kod { max-width: none; width: 100%; font-family: monospace; font-size: .875rem; }
.inline { display: inline; }
.row-forms { display: flex; gap: 16px; flex-wrap: wrap; }

/* position: relative - bez tego ukryte etykiety dla czytnika ekranu w tabeli
   ("Akcje" w naglowku, "zalaczniki" przy numerze; .sr-only ma position:
   absolute) liczyly polozenie od strony, a nie od pojemnika. Przewijanie
   pojemnika ich nie przycinalo, wiec szeroka tabela rozpychala na telefonie
   cala strone: lista faktur miala 1138 px przy ekranie 375 px i dalo sie
   "uciec" w bok poza wszystkie karty. */
.table-wrap { overflow-x: auto; position: relative;
    /* Pasek przewijania w bok w barwach marki zamiast systemowej szarości; suwak 3:1 do tła karty (J204) -
       jasny #c3cbe2 ginął (1,62:1). */
    scrollbar-color: #858ca1 transparent; }
.table-wrap::-webkit-scrollbar { height: 10px; }
.table-wrap::-webkit-scrollbar-thumb { background: #858ca1; border-radius: 999px; border: 2px solid #fff; }
.table-wrap::-webkit-scrollbar-thumb:hover { background: #5d6a96; }
.table-wrap::-webkit-scrollbar-track { background: transparent; }

/* Lista, ktorej naglowek ma stac na wierzchu.
   Zadnego ograniczenia wysokosci: tabela idzie na cala swoja dlugosc, a strona
   przewija sie normalnie. Okno w oknie - tabela z wlasnym paskiem przewijania
   w srodku przewijanej strony - bylo tu wczesniej i zostalo odrzucone: dwa
   paski przewijania naraz to dwa razy zgadywanie, ktory z nich akurat rusza.
   Pionowego paska wiec nie ma; poziomy zostaje na wypadek tabeli szerszej
   niz okno. To wlasnie ten poziomy pasek robi z pojemnika kontekst
   przewijania - i dlatego naglowek nie przykleja sie w nim, tylko jedzie
   w osobnym pasku nad nim (nizej). */
.table-wrap-ewidencja { overflow: auto; }

/* Nazwy kolumn na wierzchu: pasek z kopia naglowka (assets/js/naglowek-tabeli.js).
   Stoi NAD pojemnikiem, poza przewijaniem w bok, wiec przykleja go do gory
   ekranu sama przegladarka - bez skryptu przy przewijaniu strony. Dawniej
   przesuniecie dopisywal skrypt przy kazdym przewinieciu, a telefon przewija
   strone poza skryptem: poprawka przychodzila klatke po ruchu i naglowek
   skakal (wlasciciel, iPhone).
   --toz-belka-wysokosc: wysokosc przyklejonej belki menu; na telefonie 0,
   bo belka odjezdza razem ze strona.
   W bok pasek jedzie za tabela: animacja sterowana polozeniem tabeli
   (ScrollTimeline; klasa .naglowek-kopia-animowana - wtedy pasek sam sie nie
   przewija), a w starszych przegladarkach skrypt w obie strony. Wlasny pasek
   przewijania w bok jest schowany.
   user-select: none - zaznaczona i skopiowana lista mialaby wiersz nazw kolumn
   dwa razy (kopia i prawdziwy naglowek pod nia). */
.tabela-z-naglowkiem > .naglowek-kopia {
    position: sticky; top: var(--toz-belka-wysokosc, 0px); z-index: 2;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
    -webkit-user-select: none; user-select: none;
}
.tabela-z-naglowkiem > .naglowek-kopia.naglowek-kopia-animowana { overflow: hidden; }
.naglowek-kopia::-webkit-scrollbar { display: none; }
.naglowek-kopia > .table { table-layout: fixed; margin: 0; }
/* Klawiatura chodzi po prawdziwym naglowku, ktory lezy pod paskiem. Jej fokus
   rysujemy na odpowiednim polu kopii (klase dokłada skrypt) - pelny granat jak
   ":focus-visible" w calym systemie od C171 (polprzezroczysta obwodka miala na tle
   naglowka 1,68:1; audyt 04.10.2026, F20). Pasek sie nie chowa: nazwy kolumn
   zostaja takze wtedy, gdy ktos przewija liste z fokusem w naglowku. */
.tabela-z-naglowkiem:has(> .table-wrap-ewidencja thead :focus-visible) > .naglowek-kopia .kopia-fokus {
    outline: 2px solid var(--toz-fokus); outline-offset: -2px;
}

.table { width: 100%; border-collapse: collapse; font-size: .95rem; }
.table th {
    /* Naglowek idzie DOKLADNIE tak, jak tresc kolumny pod nim: tekst do lewej,
       kwoty do prawej, krotkie pola stalej dlugosci na srodek. Srodkowanie
       wszystkiego naraz wygladalo rowno tylko w tabeli z samych liczb -
       w tabeli mieszanej naglowek wisial obok swojej kolumny.
       Wyrownanie dla klas rozstrzyga blok "Wyrownanie w tabelach" nizej. */
    text-align: left; padding: 10px 8px; vertical-align: bottom;
    /* Kreska mocniejsza niz w reszcie tabeli: na kolorowym tle naglowka
       zwykly --toz-border juz sie nie odcina. Ten sam odcien co obwodka
       ".alert-info" i ".btn:hover". */
    border-bottom: 2px solid #c3cbe2;
    font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
    color: #14161c; font-weight: 700;
    /* Naglowek jedzie NAD trescia, wiec rzuca na nia cien: sam kolor mowi
       "to naglowek", cien mowi "stoi wyzej". */
    box-shadow: 0 2px 3px rgba(43, 42, 41, .05);
    /* Tlo pelne, nie przezroczyste: pasek z kopia naglowka (.naglowek-kopia)
       jedzie nad wierszami. Przykleja sie pasek - sam naglowek w tabeli stoi
       w miejscu, bo pojemnik przewijany w bok i tak by go nie puscil. */
    background: var(--toz-naglowek-tlo);
}
/* Kreska pod naglowkiem rysowana W komorce, a nie obramowaniem. Przy
   border-collapse obramowanie nalezy do tabeli i zostaje tam, gdzie naglowek
   stal: przyklejony naglowek jechal bez kreski, a przez odciety pasek jego tla
   przeswitywaly wiersze. Tylko na ekranie - wydruk zdejmuje cienie
   (box-shadow: none), a kreska na papierze ma zostac. */
@media screen {
    .table th {
        border-bottom: 0;
        box-shadow: inset 0 -2px 0 #c3cbe2, 0 2px 3px rgba(43, 42, 41, .05);
    }
}
.table td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--toz-border); vertical-align: top; }

/* Podsumowanie w stopce tabeli jest naglowkiem WIERSZA, nie kolumn - kolor
   robilby z niego drugi naglowek na dole listy. Przyklejanie tez byloby tu
   bledem: gdy ".table th" dawalo position: sticky KAZDEJ komorce naglowkowej,
   "Razem koszty tej sprawy" w teczce scigania potrafilo zaparkowac na gorze
   ekranu razem z nazwami kolumn (dzis przykleja sie tylko pasek z kopia
   naglowka, .naglowek-kopia). Kreska zostaje taka, jaka byla - inaczej dol
   tabeli zrobilby sie ciemniejszy niz przedtem. */
.table tfoot th {
    background: none; position: static; box-shadow: none;
    border-bottom: 2px solid var(--toz-border);
}

/* Przerwa miedzy latami (wlasciciel, 06.11.2026: "dodaj żeby jeśli dane w jakichkolwiek tabelach są poukładane wg dat,
   aby je jakoś widocznie rozdzielić latami i to dotyczy wszystkich tabel") - wiersz z samym rokiem nad wierszami
   kazdego roku, wstawia go assets/js/przerwy-lat.js. Barwy marki: pelny pas granatu z bialym rokiem i zlota kreska
   u dolu - znak, ktorego nie nosi zaden wiersz (przeglad 06.11.2026: jasny granat w tle to barwa stanu "granatowy",
   a zlota kreska z lewej to "tu wrociles" - wiersz-ostatni, tr:target, wpis-swiezy). Bez pasow co drugi wiersz.
   To naglowek grupy wierszy, nie kolumn: bez wielkich liter i cienia naglowka. Rok stoi przy lewym brzegu takze
   w tabeli przewijanej w bok (sticky w pojemniku), a do kopii zaznaczonego tekstu nie idzie. Na wydruku przerw nie
   ma - papier zostaje taki jak dotad.
   Wlasciciel w trakcie budowy: "Tylko ten rok ma być mega widoczny, najlepiej szeroki" - pas na cala szerokosc tabeli,
   wysoki, z duzym, grubym rokiem i grubsza zlota kreska u gory i u dolu (na telefonie troche mniejszy, ale dalej
   wyrazny). */
.table tr.przerwa-lat > th {
    text-align: left; vertical-align: middle; padding: 12px 16px;
    font-size: 1.65rem; line-height: 1.15; font-weight: 800; letter-spacing: .08em; text-transform: none;
    color: #fff; background: var(--toz-granat);
    border-bottom: 0; box-shadow: inset 0 4px 0 var(--toz-zloto), inset 0 -4px 0 var(--toz-zloto);
    -webkit-user-select: none; user-select: none;
}
.przerwa-lat-rok { position: sticky; left: 16px; display: inline-block; }
@media (max-width: 640px) {
    .table tr.przerwa-lat > th { font-size: 1.35rem; padding: 10px 12px; }
    .przerwa-lat-rok { left: 12px; }
}
@media print { .table tr.przerwa-lat { display: none; } }

/* --- Wyrownanie w tabelach: jedna zasada dla calego systemu ----------------
   Kwoty do PRAWEJ - przecinek pod przecinkiem, inaczej dwoch kwot nie da sie
   porownac wzrokiem. Numer porzadkowy, daty i statusy do SRODKA - to sa pola
   o stalej, krotkiej dlugosci i kolumna z nich robi rowna kolumienke.
   Kazdy inny tekst do LEWEJ, bo tekst czyta sie od lewej krawedzi.

   Zasada stoi TUTAJ, a nie przy kazdej tabeli z osobna: nowa tabela ma ja
   dostawac bez pamietania o niej. Uwaga na wagi selektorow - ".table td"
   (0,1,1) bije samo ".liczba" (0,1,0), wiec kazda regula ponizej musi byc
   pisana z "td", inaczej nie zadziala i nikt tego nie zauwazy. */
.table td.liczba,
.table th.liczba { text-align: right; }

.table td.kol-lp-lista,
.table td.kol-data,
.table td.kol-stan,
.table td.kol-zaznacz,
.table td.kol-powiazania,
.table td.kol-zdjecia,
.table th.kol-lp-lista,
.table th.kol-lp,
.table th.kol-data,
.table th.kol-stan,
.table th.kol-zaznacz,
.table th.kol-zdjecia,
.table th.kol-powiazania { text-align: center; }
.table a { color: var(--toz-granat-ciemny); }
/* Liczba-odnośnik w tabeli (zbiórki i posty z Facebooka na listach podopiecznych i celów) - plakietka
   bez podkreślenia (właściciel, 28.09.2026: "w momencie, kiedy są linkami to są bardzo nieczytelne przez
   podkreślenie, które się pojawia pod liczbą"). Tło mówi, że da się kliknąć; cyfry równej szerokości. */
.table a.licznik {
    display: inline-block; min-width: 2em; padding: 1px 8px; border-radius: 999px;
    background: var(--toz-granat-jasny); color: var(--toz-granat-ciemny);
    font-weight: 600; line-height: 1.5; text-align: center; text-decoration: none; font-variant-numeric: tabular-nums;
}
.table a.licznik:hover { background: var(--toz-granat); color: #fff; text-decoration: none;
    /* Granat z głębią, jak przycisk główny. */
    background-image: linear-gradient(135deg, #4a68ba, var(--toz-granat-ciemny)); }
.table a.licznik:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; }
/* Zero w tej samej kapsułce, tylko szarej i bez odnośnika (właściciel, 30.09.2026: "patrz jak to zero
   brzydko wygląda") - goła cyfra stała krzywo obok kapsułek z liczbami. */
.table .licznik-zero {
    display: inline-block; min-width: 2em; padding: 1px 8px; border-radius: 999px;
    background: #f1f3f6; color: var(--toz-muted);
    line-height: 1.5; text-align: center; font-variant-numeric: tabular-nums;
}
/* Zero, które woła o uwagę: otwarta zbiórka bez żadnego posta na Facebooku (właściciel, 30.09.2026). */
.table .licznik-brak { background: var(--toz-tlo-blad); color: var(--toz-blad); font-weight: 600; }
/* Lista podopiecznych, kolumna "Do adopcji": zielone "tak" i obok znaczek Facebooka, gdy jest post do upublicznienia
   (prowadzi do posta). Plakietka i znaczek w jednym wierszu. */
.do-adopcji-tak { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.table a.znak-fb { display: inline-flex; color: #1877f2; text-decoration: none; line-height: 0; }
.table a.znak-fb:hover { color: #0b5fcc; }
.table a.znak-fb:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; border-radius: 50%; }
.znak-fb-ikona { width: 16px; height: 16px; }
/* Porównanie ze stroną TOZ (właściciel, 01.11.2026) - znak w kolumnie obok "Do adopcji". */
.znak-strony { display: inline-flex; line-height: 0; }
.table a.znak-strony { text-decoration: none; }
.table a.znak-strony:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; border-radius: 50%; }
.table .znak-strony-jest, .table a.znak-strony-jest:hover { color: var(--toz-ok); }
.table .znak-strony-brak { color: var(--toz-blad); }
.table .znak-strony-nadmiar, .table a.znak-strony-nadmiar:hover { color: var(--toz-uwaga); }
.znak-strony-ikona { width: 18px; height: 18px; }
/* Ten sam znaczek z napisem "Zobacz na toz.pl" przy nagłówku karty podopiecznego (09.11.2026). Napis może się zawinąć - na telefonie nic nie ucieka w bok. */
.strona-toz-karta { margin: 6px 0 0; }
.strona-toz-karta a.znak-strony { align-items: center; gap: 6px; min-height: 32px; line-height: 1.3; text-decoration: none; font-weight: 600; overflow-wrap: anywhere; }
.strona-toz-karta a.znak-strony-jest { color: var(--toz-ok); }
.strona-toz-karta a.znak-strony-nadmiar { color: var(--toz-uwaga); }
.strona-toz-karta a.znak-strony:hover .strona-toz-napis { text-decoration: underline; }
.strona-toz-karta a.znak-strony:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; border-radius: 4px; }
.strona-toz-karta .znak-strony-ikona { flex: none; }
.strona-toz-podsumowanie { margin-top: 10px; }
.strona-toz-podsumowanie p { margin: 0 0 4px; }
/* Znaczki cech przy imieniu na liście podopiecznych (20.10.2026): kolorowe, proste, z dymkiem od razu (dymek.js). */
.znaki-cech { display: inline-flex; gap: 4px; margin-left: 4px; vertical-align: -2px; }
/* Kolumna znaczków na liście podopiecznych - wąska, za imieniem. */
.table .kol-znaki { width: 1%; white-space: nowrap; padding-left: 4px; padding-right: 4px; }
.kol-znaki .znaki-cech { margin-left: 0; }
.znak-cechy { display: inline-flex; line-height: 0; border-radius: 50%; cursor: help; }
.znak-cechy:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; }
.znak-wirtualna { color: #e03131; }
.znak-wirtualna-w-trakcie { color: #f08c00; }
.znak-dt { color: #1c7ed6; }
.znak-dt-znaleziony { color: #2f9e44; }
.actions { display: flex; flex-direction: column; gap: 4px; }

.badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: .8rem; }
.badge-active { background: var(--toz-tlo-ok); color: var(--toz-ok); }
.badge-invited { background: var(--toz-tlo-uwaga); color: var(--toz-uwaga); }
.badge-disabled { background: var(--toz-tlo-blad); color: var(--toz-blad); }
/* Zakładki nad tabelą (lista "Treści pism" - kategorie pism). Zwykłe odnośniki
   w kształcie kart przyczepionych do górnej krawędzi tabeli; otwarta ma tło
   karty i złotą kreskę jak otwarta pozycja menu. Zawijają się na wąskim ekranie. */
.zakladki { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 -1px; padding: 0 10px; position: relative; z-index: 1; }
.zakladka { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; min-height: 40px;
    border: 1px solid var(--toz-border); border-bottom-color: transparent; border-radius: 10px 10px 0 0;
    background: #f7f8fb; color: var(--toz-belka-tekst); text-decoration: none; font-weight: 500; white-space: nowrap; }
.zakladka:hover, .zakladka:focus-visible { background: var(--toz-granat-jasny); text-decoration: none; }
.zakladka.aktywna { background: var(--toz-plyta); border-bottom-color: var(--toz-plyta); font-weight: 600; position: relative;
    /* Złoto nad granatem, jak kreska nad belką. */
    background-image: linear-gradient(180deg, rgba(215, 181, 109, .16), rgba(255, 255, 255, 0) 70%); }
/* Złota kreska otwartej zakładki - osobny znacznik, żeby przy przejściu do innej zakładki mógł się przesunąć (p. 33). */
.zakladka-znak { position: absolute; left: 6px; right: 6px; top: -1px; height: 2px; border-radius: 2px; background: var(--toz-zloto); pointer-events: none; }
.zakladka-ile { font-size: .78rem; font-weight: 600; padding: 1px 7px; border-radius: 999px;
    background: #e7ecf7; color: var(--toz-granat-ciemny); }
.zakladka.aktywna .zakladka-ile { background: var(--toz-granat); color: #fff; }
/* Nieprzeczytane przy zakładce modułu Maile: druga liczba w złocie, obok liczby wszystkich maili. Napis stały: tło jest złote w obu trybach. */
.zakladka-nowe { margin-left: 4px; font-size: .78rem; font-weight: 700; padding: 1px 7px; border-radius: 999px;
    background: var(--toz-zloto); color: #23262f; }
.karta-pod-zakladkami { border-top-left-radius: 0; }
/* Wiersz nad tabelą: "Twoja zakładka domyślna" albo przycisk, który ją ustawia.
   W karcie, nie w rzędzie zakładek - rząd zawija się, a zakładki mają trzymać się karty. */
.zakladka-start { display: flex; justify-content: flex-end; align-items: center; min-height: 24px;
    margin: -6px 0 8px; font-size: .85rem; }
.zakladka-start .btn-link { font-size: inherit; }
@media (max-width: 640px) {
    .zakladka-start { justify-content: flex-start; margin-top: 0; }
    .zakladki { padding: 0; gap: 4px; margin-bottom: 6px; }
    .zakladka { border-radius: 10px; border-bottom-color: var(--toz-border); padding: 8px 12px; }
    .zakladka.aktywna { border-bottom-color: var(--toz-border); }
    .zakladka-znak { top: auto; bottom: 0; }
    .karta-pod-zakladkami { border-top-left-radius: var(--toz-promien); }
}
@media print { .zakladki, .zakladka-start { display: none; } }
/* Kolumna uwag na liście członków. Ma własną szerokość minimalną: bez niej przeglądarka
   ściskała ją do kilku liter w linii ("Legityma / cja do / wymiany"), bo to jedyna kolumna,
   która umie się zawijać. Kolor i górną granicę bierze z ".table-ewidencja .uwagi". */
.table-ewidencja[data-lista-czlonkow] td.uwagi { min-width: 11rem; max-width: 24rem; }
/* "Nie zaczęty" - spokojna szarość; żółty należy do "brudnopisu". */
.badge-neutral { background: #eef0f4; color: #41465a; }

/* Pole z kursorem nie chowa się pod przyklejoną belką menu ani pod paskiem zapisu przy przechodzeniu Tabem
   (audyt 04.10.2026, F04) - przeglądarka przewija z tym zapasem także przy fokusie, nie tylko przy kotwicach.
   Wysokość belki liczy naglowek-tabeli.js (0, gdy belka nie jest przyklejona). */
html { scroll-padding-top: calc(var(--toz-belka-wysokosc, 0px) + 12px); }
@media (min-width: 481px) {
    html:has(.pasek-zapisu) { scroll-padding-bottom: 96px; }
}

@media (max-width: 760px) {
    /* Na waskim ekranie belka nie jest przyklejona - przyklejona zabieralaby
       miejsce na kazdym ekranie listy. */
    .topbar { position: static; }
    /* Naglowek tabeli trzyma sie gory takze tutaj (wlasciciel: "na komputerze
       zostaje w miejscu, ale na komorce ucieka z ekranu"). Belka odjezdza
       w gore razem ze strona, wiec pasek z kopia naglowka staje przy gornej
       krawedzi ekranu (--toz-belka-wysokosc = 0, patrz .naglowek-kopia). */
    .nav a { padding: 6px 10px; }
}

@media (max-width: 480px) {
    .codes { grid-template-columns: 1fr; }
}

/* --- Panel administratora ------------------------------------------------ */
.card-head { border-bottom: 1px solid var(--toz-border); padding-bottom: 12px; margin-bottom: 16px;
    /* Kreska pod nagłówkiem przechodzi z granatu w złoto i gaśnie w prawo (na wydruku zwykła linia). */
    border-bottom-color: transparent;
    background-image: linear-gradient(90deg, #9fb0dc, #dcc183 45%, rgba(220, 224, 234, 0));
    background-size: 100% 1px; background-repeat: no-repeat; background-position: 0 100%; }
.card-head p { margin: 4px 0 0; }
.card-danger { border-color: #f1aeb5; }
.card-danger .h4 { color: var(--toz-blad); }

.breadcrumb { margin: 0 0 16px; }
/* "← Wróć do listy" jako jasna kapsułka z granatu w złoto - widać ją od razu. */
.breadcrumb a { color: var(--toz-granat); text-decoration: none; font-weight: 600;
    display: inline-flex; align-items: center; gap: 4px; padding: 4px 14px; border-radius: 999px;
    border: 1px solid #d3dbef; background-image: linear-gradient(135deg, #eef2fb, #f8f1df); }
.breadcrumb a:hover { text-decoration: none; border-color: #aebce2; background-image: linear-gradient(135deg, #dfe7f8, #f2e5c4); }
/* Ten sam powrot miedzy kartami w polowie dlugiej strony i na dole strony
   (wlasciciel, 29.09.2026) - zeby nie przewijac na gore. Nigdy w srodku
   formularza. Odstep nad nim daje karta (24 px), pod nim ten sam. */
.breadcrumb-srodek { margin: 0 0 24px; }
.breadcrumb-dol { margin: 20px 0 0; }

.filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; align-items: end; }

/* Kazda komorka filtra to etykieta i kontrolka. Bez tego etykieta lamiaca sie
   na dwie linie ("Stan dla zglaszajacego") zsuwa swoje pole nizej niz sasiednie
   i caly rzad skacze gora-dol. Etykieta rosnie w gore, pola stoja w jednej linii.
   Pasek przyciskow jest wyjatkiem - ma wlasny uklad poziomy i po zlapaniu
   tej reguly ustawial "Filtruj" nad "Wyczysc". */
.filters > div:not(.filters-action) {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-width: 0;
}
.filters > div:not(.filters-action) > .label { margin-top: auto; }
/* Pole wyboru pliku dostaje WLASNY wiersz.
   Przegladarka rysuje w nim swoj przycisk i swoj napis - po polsku
   "Nie wybrano pliku" - i nie skraca go po ludzku, tylko przycina do
   "Ni...ku". W slupku siatki filtrow (minimum 180 px) z komunikatu nie
   zostawalo nic czytelnego, choc to samo pole na innych ekranach, gdzie
   stoi na calej szerokosci formularza, czytalo sie normalnie.
   Szerokosc ograniczamy, zeby pole nie rozciagalo sie przez cala karte. */
.filters > .pole-pliku {
    grid-column: 1 / -1;
    max-width: 460px;
}
/* Przyciski dostaja WLASNY wiersz na calej szerokosci. W komorce siatki obok
   pol byly za ciasno i zawijaly sie jeden pod drugi - a przy szesciu filtrach
   nie ma szerokosci, przy ktorej zmiescilyby sie obok. */
.filters-action {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    margin-top: 4px;
}

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin: 0; }
.facts dt { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--toz-muted); }
.facts dd { margin: 2px 0 0; font-weight: 600; }
/* Długie wartości (adresy e-mail, strony www) łamią się w środku zamiast wychodzić poza kartę; para z klasą
   facts-szeroki zajmuje poza telefonem dwie kolumny (karta urzędu; właściciel, 17.10.2026). Na telefonie siatka
   bywa jednokolumnowa - tam dwie kolumny dołożyłyby kolumnę poza ekranem. */
.facts dd { overflow-wrap: anywhere; }
@media (min-width: 761px) {
    .facts > .facts-szeroki { grid-column: span 2; }
}

/* Kwota, ktorej nie da sie wpisac - system ja liczy. Wyglada jak pole, ale
   nim nie jest: gdyby wygladala jak zwykly tekst, ludzie szukaliby, gdzie ja
   poprawic. */
/* Podsumowanie raportu: tabela jest formularzem, wiec pola kwot siedza
   w komorkach. Waskie, bo kwota ma stala dlugosc, i wyrownane do prawej
   jak reszta liczb w systemie. */
.tabela-podsumowania .kwota-w-tabeli { width: 100%; max-width: 10rem; margin-left: auto;
    text-align: right; font-variant-numeric: tabular-nums; }

/* Naglowek TEJ tabeli stoi nad kwotami, wiec wyrownuje sie tak samo jak one:
   pierwsza kolumna to nazwa wiersza - do lewej, pozostale to kwoty - do prawej.
   Srodkowanie z ".table th" zostawialo "I kwartal" przesuniete wzgledem liczby
   pod spodem, a tu naglowek i tresc czyta sie razem, kolumna po kolumnie.
   Wyjatek jest ZAWEZONY do jednej tabeli: w pozostalych naglowek stoi nad
   kolumnami roznego typu (Lp., daty, tekst, kwoty) i srodek jest tam wlasciwy.
   Selektor z dwiema klasami (0,2,1) bije ".table th" (0,1,1) niezaleznie od
   kolejnosci regul w pliku. */
.table.tabela-podsumowania th { text-align: right; }
.table.tabela-podsumowania th:first-child { text-align: left; }

/* Cztery kwartaly to jedna miarka, wiec maja te sama szerokosc - inaczej
   kolumna wychodzi tym wezsza, im mniej sie w niej wydarzylo. Kwartaly
   pozniejsze niz wybrany stoja PUSTE i to one robily sie chudsze od tych
   z kwotami: tabela wygladala, jakby rok byl krzywy.
   17% na kolumne (4 x 17% + reszta dla nazwy wiersza) trzyma proporcje na
   szerokiej karcie, a min-width nie pozwala zejsc ponizej szerokosci kwoty
   z jej "zl" - przy ciasnym oknie tabela zaczyna sie przewijac w ".table-wrap"
   zamiast sciskac cztery kolumny do roznych szerokosci. */
.table.tabela-podsumowania th:not(:first-child),
.table.tabela-podsumowania td:not(:first-child) { width: 17%; min-width: 9.5rem; }
/* Nazwa wiersza jest naglowkiem (th scope="row"), zeby czytnik ekranu
   powiedzial przy kwocie, CZEGO ona dotyczy. Wyglada jednak jak zwykla
   komorka - inaczej pierwsza kolumna zrobilaby sie wersalikami na szarym
   tle, czyli drugim naglowkiem tabeli. */
.table.tabela-podsumowania th.nazwa-wiersza {
    text-align: left; vertical-align: top; font-size: .95rem; font-weight: 400;
    text-transform: none; letter-spacing: normal; color: inherit;
    border-bottom: 1px solid var(--toz-border); position: static; background: none;
}

/* Kwota tylko do odczytu stoi w TAKIM SAMYM pudelku jak pole do wpisania
   obok: ta sama wysokosc, ten sam odstep od krawedzi, ten sam rozmiar pisma.
   Bez tego liczba w jednej kolumnie stala nizej i mniejsza niz w polu w tej
   samej linijce, a wiersz wygladal na krzywy.

   Ramka jest PRZEZROCZYSTA, a nie zdjeta - inaczej tekst przesuwalby sie
   o piksel wzgledem pola z ramka. */
.tabela-podsumowania .kwota-odczyt {
    display: block;
    box-sizing: border-box;
    width: 100%;
    max-width: 10rem;
    margin-left: auto;
    min-height: 42px;
    padding: 9px 12px;
    font-size: 1rem;
    line-height: 1.2;
    border: 1px solid transparent;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Komorka, ktorej nie da sie wpisac - liczy ja system. */
.tabela-podsumowania td.wyliczona { background: var(--toz-bg); }

/* Pasek pod podkladem: przycisk przepisujacy cele i zdanie o tym, co zrobil. */
.pasek-podkladu { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.pasek-podkladu .hint { margin: 0; }

/* Kwota, ktora sie z czyms nie zgadza: stan otwarcia inny niz zamkniecie
   poprzedniego kwartalu albo przychod wpisany drugi raz w roku. Rozowe tlo,
   nie czerwone - to nie jest blad do poprawienia teraz, tylko roznica, ktora
   ktos ma swiadomie potwierdzic albo naprawic. Powod stoi w tooltipie i pod
   tabela, bo sam kolor nic nie mowi ani przy druku, ani czytnikowi ekranu. */
.pole-niezgodne { background: #fceaf2 !important; border-color: #e79ec0 !important;
    color: #9c2b60; }
.lista-niezgodnosci { margin: 10px 0 0; padding-left: 20px; }
.lista-niezgodnosci li { margin-bottom: 4px; }

.wyliczone { margin: 0; padding: 9px 12px; min-height: 40px;
    background: var(--toz-bg); border: 1px dashed var(--toz-border);
    border-radius: var(--toz-promien); font-weight: 600;
    font-variant-numeric: tabular-nums; }

.action-grid { display: grid; gap: 16px; }
.action-grid form { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.action-grid .muted { flex: 1 1 260px; }


.badge-locked { background: #f6e6d2; color: #7a3e00; }

.nowrap { white-space: nowrap; }

/* --- Dostep konta ----------------------------------------------------------
   Kolumna "Dostep" na liscie kont: nazwy nadanych pakietow. Celowo NIE sa to
   plakietki ".badge" - te oznaczaja stan (aktywne, zablokowane) i mieszanie
   jednego z drugim kazaloby czytac nazwe pakietu jak status konta. */
.dostep-chip {
    display: inline-block;
    margin: 0 4px 4px 0;
    padding: 2px 8px;
    border: 1px solid var(--toz-border);
    border-radius: 6px;
    background: var(--toz-granat-jasny);
    color: var(--toz-granat-ciemny);
    font-size: .8rem;
}
.dostep-chip-pelny { background: var(--toz-tlo-uwaga); border-color: var(--toz-zloto); color: var(--toz-uwaga); }
.dostep-chip-zakaz { background: var(--toz-tlo-blad); border-color: #f0bcc1; color: var(--toz-blad);
    text-decoration: line-through; }
/* Skład pakietu jako podpowiedź (właściciel, 20.09.2026): chip na liście kont
   niesie go w title (i prowadzi do pakietu), listy wyboru pakietów mają pod
   nazwą rozwijane "co zawiera". Wiersze składu łamią się po module. */
.dostep-chip[title] { cursor: help; }
a.dostep-chip { text-decoration: none; }
a.dostep-chip:hover, a.dostep-chip:focus-visible { text-decoration: underline; }
.sklad-pakietu p { white-space: pre-line; margin: 2px 0 0; font-size: .9rem; color: var(--toz-muted); }
.sklad-pakietu summary { cursor: pointer; font-size: .85rem; color: var(--toz-granat); }
.sklad-pakietu { padding: 0 0 6px 30px; }
.pakiety-lista .sklad-pakietu + .uprawnienie { border-top: 1px solid var(--toz-border); }
/* Nadanie pakietów (karta konta, lista kont): kilka naraz, polami wyboru
   (właściciel, 20.09.2026). Ramka jak przy zakładaniu konta. */
.pakiety-do-nadania { border: 0; padding: 0; margin: 0 0 12px; min-width: 0; }
.pakiety-do-nadania > legend { padding: 0; }

/* Co konto naprawdę może - modul po module, na karcie konta. */
.moze-lista { list-style: none; margin: 0 0 8px; padding: 0; }
.moze-lista li { padding: 6px 0; border-bottom: 1px solid var(--toz-border); }
.moze-lista li:last-child { border-bottom: 0; }
/* Lista "czego nie ma" stoi obok listy "co moze" - ma byc czytelna, ale nie
   krzyczec: to nie jest brak do naprawienia, tylko zapas do ewentualnego
   nadania. */
.moze-lista-brak .moze-modul { font-weight: 500; }
/* Bez przygaszania przezroczystością - różnicę daje półgrube pismo nazwy modułu (F32). */
/* Wybor zakresu nad lista "co ta osoba moze": odnosniki jak numery stron,
   bo to wybor widoku, a nie zapis. */
.wybor-zakresu { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 12px; }
.moze-modul { display: inline-block; min-width: 9rem; font-weight: 600; margin-right: 8px; }

/* Wybor "doloz / zablokuj" przy szlifowaniu uprawnien. */
.wybor-efektu { border: 0; padding: 0; margin: 16px 0 0; }
.wybor-efektu > legend { padding: 0; }
/* W polu formularza odstęp daje siatka pól - wybór (np. Pani/Pan na karcie
   członka) zaczyna się na wysokości napisów sąsiednich pól. */
.pole > .wybor-efektu { margin-top: 0; }

/* Rozwiniecie uzyte jako naglowek sekcji: ma wygladac jak naglowek, a nie
   jak odnosnik - inaczej "Ostatnie zdarzenia" czyta sie jak przycisk. */
summary.rozwin { cursor: pointer; margin: 0; }
summary.rozwin::marker { color: var(--toz-granat); }

/* --- Bledy przy polach ---------------------------------------------------- */
.form-control-blad { border-color: var(--toz-blad); background: #fffafa; }
.form-control-blad:focus { outline-color: rgba(165, 40, 52, .3); }

/* Pole z wartoscia, ktora powtarza sie w innej sprawie. Barwa OSTRZEZENIA,
   a nie bledu: powtorka bywa swiadoma (ten sam adres, kolejne zgloszenie),
   wiec nie blokuje zapisu - ma tylko zwrocic uwage. Czerwien znaczy w tym
   systemie "tego nie zapiszesz". */
.form-control-powtorka { border-color: var(--toz-zloto); background: var(--toz-tlo-uwaga); }
.form-control-powtorka:focus { outline-color: rgba(215, 181, 109, .45); }
.pole-blad { margin: 6px 0 0; font-size: .875rem; color: var(--toz-blad); }

/* --- Zapraszanie zbiorcze -------------------------------------------------- */
.zbiorczo { margin-top: 24px; border-top: 1px solid var(--toz-border); padding-top: 16px; }
.zbiorczo summary { cursor: pointer; font-weight: 600; color: var(--toz-granat); }
.zbiorczo textarea { width: 100%; font-family: ui-monospace, Menlo, monospace; font-size: .9rem;
    padding: 10px 12px; border: 1px solid var(--toz-pole-ramka); border-radius: 8px; }
/* Ramka 3:1 jak w .form-control (J204), a pole z błędem dalej czerwone. */
.zbiorczo textarea.form-control-blad { border-color: var(--toz-blad); }

/* --- Pakiety uprawnien ---------------------------------------------------- */
.modul { border: 1px solid var(--toz-border); border-radius: 8px; padding: 12px 16px; margin: 0 0 12px; }
.modul legend { font-weight: 600; padding: 0 6px; font-size: .95rem; }
.uprawnienie { display: flex; gap: 10px; align-items: flex-start; padding: 6px 0; cursor: pointer; }
.uprawnienie input { margin-top: 4px; }
.uprawnienie code { background: none; font-size: .8rem; }

/* --- Faktury -------------------------------------------------------------- */
.liczba { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- Formularz dokumentu --------------------------------------------------
   Faktura ma kilkanascie pol, wiec formularz jest podzielony na sekcje
   odpowiadajace temu, jak czyta sie papierowy dokument: co to za wydatek,
   kiedy, za ile, z czego sie sklada. */
/* Przeglądarka daje fieldsetowi min-inline-size: min-content - fieldset rósł do szerokości tabeli w środku,
   a .table-wrap nie miał czego przewijać i kolumny za prawą krawędzią telefonu znikały (pozycje raportu
   kasowego bez "Kwoty" i "×"; audyt 04.10.2026, F03). Tak samo robi Bootstrap. */
fieldset { min-inline-size: 0; min-width: 0; }
.sekcja { border: 0; padding: 0; margin: 0 0 28px; }
.sekcja + .sekcja { border-top: 1px solid var(--toz-border); padding-top: 24px; }
.sekcja > legend {
    padding: 0;
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--toz-granat);
    /* Tytuł sekcji nie klei się do pierwszej etykiety pod nim. */
    margin-bottom: 10px;
}
.sekcja-opis { margin: 2px 0 16px; color: var(--toz-muted); font-size: .9rem; }

/* Siatka dwunastu kolumn. Wczesniej bylo auto-fill z minmax(250px), przez co
   szerokosc pola wynikala z tego, ile ich sie akurat zmiescilo, a nie z tego,
   co sie w nim pisze - pole na imie i nazwisko dostawalo tyle samo miejsca co
   adres, a czesto caly wiersz. Teraz kazde pole mowi wprost, ile kolumn
   zajmuje: "Kogo dotyczy", "Adres" i "Informacje o adresie" stoja w jednym
   wierszu w proporcjach 4:5:3.

   Dwanascie kolumn, a nie auto-fill, takze dlatego, ze sciezki jawnych torow
   nie ubywa: "span 3" nigdy nie dolozy kolumny niejawnej, a "1 / -1" zawsze
   siega konca wiersza. Przy auto-fill na waskim ekranie zostawala jedna
   kolumna i oba te zapisy zaczynaly znaczyc co innego. */
.pola { display: grid; gap: 16px 20px; grid-template-columns: repeat(12, 1fr); align-items: start; }

/* Szerokosci sa opisane tym, co w polu stoi, a nie liczba kolumn - inaczej
   przy kazdej zmianie siatki trzeba by przechodzic wszystkie szablony.
   Kolejnosc regul ma znaczenie: wszystkie maja te sama specyficznosc, wiec
   wygrywa ostatnia pasujaca. Dlatego od najwezszych do calego wiersza. */
/* Zapis "auto / span N", a nie samo "span N", i to jest tu naprawa, nie ozdoba:
   skrot "grid-column: span 3" ustawia POCZATEK na "span 3", a koniec zostawia
   na auto. Pole z klasa "pole-od-nowa" dostawalo wiec poczatek 1 i koniec auto,
   czyli JEDNA kolumne z dwunastu - "Kogo dotyczy" bylo przez to cztery razy
   wezsze, niz mowily te reguly. */
.pola > .pole { grid-column: auto / span 3; }          /* domyslnie: imie i nazwisko, e-mail, numer */
.pola > .pole-waski { grid-column: auto / span 2; }    /* data, kwota, telefon */
.pola > .pole-duzy { grid-column: auto / span 4; }     /* nazwa sprawy, numer w KSeF */
.pola > .pole-obszerny { grid-column: auto / span 5; } /* nazwa instytucji, czego dotyczy */
.pola > .pole-polowa { grid-column: auto / span 6; }   /* adres, zestaw pol wyboru, wybor plikow */
.pola > .pole-szerokie { grid-column: 1 / -1; }      /* wiersze strukturalne: listy, przelaczniki */

/* Tablet: szesc szerokosci to o cztery za duzo, kiedy w wierszu mieszcza sie
   dwa pola. Wszystko idzie na polowe - rownomiernie, zeby zadne pole nie
   zostalo samo w wierszu obok pustego miejsca. Wyjatkiem sa daty: trzy obok
   siebie nadal sie czytaja, a rozciagniete na pol tabletu wygladaja glupio. */
@media (max-width: 1080px) {
    .pola > .pole,
    .pola > .pole-duzy,
    .pola > .pole-obszerny { grid-column: auto / span 6; }
    .pola > .pole-waski { grid-column: auto / span 4; }
    .pola > .pole-polowa,
    .pola > .pole-szerokie { grid-column: 1 / -1; }
}

/* Telefon: jedno pole w wierszu i koniec dyskusji. */
@media (max-width: 640px) {
    .pola > .pole,
    .pola > .pole-waski { grid-column: 1 / -1; }
}

/* Pole, ktore zawsze zaczyna nowy wiersz - niezaleznie od tego, ile miejsca
   zostalo po poprzednim. Tak "Kogo dotyczy" otwiera wiersz z adresem
   i informacjami o adresie, a nie dokleja sie do oddzialu.
   Stoi PO regulach szerokosci i po obu progach ekranu, bo zmienia tylko
   poczatek. Szerokosc zostaje z tamtych regul - ale tylko dlatego, ze one
   podaja ja jako KONIEC ("auto / span N"). Przy zapisie "span N" ta regula
   zabierala polu cala szerokosc oprocz jednej kolumny. */
.pola > .pole-od-nowa { grid-column-start: 1; }

/* Pole opisowe: cala szerokosc formularza i tyle wysokosci, zeby widziec
   kilkanascie linii naraz. Zgloszenie interwencji bywa dluzsze niz akapit,
   a pisanie go przez okienko na trzy wiersze jest udreka.
   Wysokosc przez min(): na tablecie w poziomie sztywne 14rem zjadaloby
   polowe ekranu razem z drugim takim polem. Powtorka z svh jest dla
   telefonu: wysokosc ekranu z widocznym paskiem adresu, stala w trakcie przewijania. Dawniej dvh - ta rosla
   i malala razem z paskiem, pole zmienialo wysokosc przy kazdym przewinieciu, a strona pod nim skakala
   (wlasciciel, 28.10.2026: "na komorce ekran dziwnie skacze przy przewijaniu"). */
.pola > .pole-opis { grid-column: 1 / -1; }
.pole-opis .form-control { min-height: min(16rem, 38vh); min-height: min(16rem, 38svh); }
.pole-opis-duze .form-control { min-height: min(22rem, 45vh); min-height: min(22rem, 45svh); }

.pole { min-width: 0; }
.pole .label { margin-top: 0; }
.pole .hint { margin-top: 6px; }

/* Liczba z jednostka obok ("Wiek przy przyjeciu": [2] [lata]) - pole liczby
   bierze reszte szerokosci, lista jednostek tyle, ile potrzebuje jej napis. */
.pole-z-jednostka { display: flex; gap: 8px; }
.pole-z-jednostka > .form-control:first-child { flex: 1 1 4rem; min-width: 0; }
.pole-z-jednostka > select.form-control { flex: 0 0 auto; width: auto; }

/* Waluta jest czescia pola, nie podpisem pod nim - dlatego opakowanie
   obejmuje wylacznie input, bez etykiety i podpowiedzi. */
.z-waluta { position: relative; display: block; }
.z-waluta { --toz-waluta: 34px; }
/* Miejsce na "zł" musi przetrwac kazde inne ustawienie odstepow - inaczej
   napis kladzie sie na kwocie. Stad !important zamiast wyscigu specyficznosci.
   Napis w "content" widzi czlowiek przy kazdej kwocie, wiec ma polskie litery
   jak kazdy inny napis na ekranie - plik jest w UTF-8 i niesie je bez klopotu. */
.z-waluta .form-control { padding-right: var(--toz-waluta) !important; text-align: right; font-variant-numeric: tabular-nums; }
.z-waluta::after {
    content: "zł";
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    color: var(--toz-muted); font-size: .85rem; pointer-events: none;
}

.wymagane::after { content: " *"; color: var(--toz-blad); }

/* --- Pozycje faktury ------------------------------------------------------ */
.pozycje { width: 100%; border-collapse: collapse; }
.pozycje th {
    font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
    color: var(--toz-muted); text-align: left; font-weight: 600;
    padding: 0 8px 8px; border-bottom: 1px solid var(--toz-border);
}
.pozycje td { padding: 6px 8px; vertical-align: top; }
.pozycje td:first-child, .pozycje th:first-child { padding-left: 0; }
.pozycje .kol-lp { width: 40px; text-align: center; color: var(--toz-muted); font-variant-numeric: tabular-nums; padding-top: 16px; }
.pozycje .kol-liczba { width: 150px; }
.pozycje .kol-suma { width: 130px; text-align: right; font-variant-numeric: tabular-nums; padding-top: 16px; white-space: nowrap; }
.pozycje .kol-usun { width: 44px; }
.pozycje input { text-align: left; }
.pozycje .kol-liczba input { text-align: right; font-variant-numeric: tabular-nums; }
.pozycje .form-control { min-height: 38px; }

.usun-pozycje {
    width: 34px; height: 40px; line-height: 1;
    border: 1px solid transparent; border-radius: 8px; background: none;
    color: var(--toz-muted); font-size: 1.2rem; cursor: pointer;
}
.usun-pozycje:hover { background: var(--toz-tlo-blad); color: var(--toz-blad); border-color: #f0bcc1; }

.pozycje-stopka { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: 12px; }
.pozycje-suma { font-variant-numeric: tabular-nums; }
.pozycje-suma strong { font-size: 1.05rem; }
.pozycje-roznica { color: var(--toz-uwaga); font-size: .9rem; }
.pozycje-roznica:empty { display: none; }

/* --- Pasek zapisu ---------------------------------------------------------
   Formularz jest dlugi; przycisk zapisu ma byc pod reka niezaleznie od tego,
   gdzie operator akurat jest. */
.pasek-zapisu {
    position: sticky; bottom: 0; z-index: 2;
    display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
    margin: 24px calc(-1 * clamp(16px, 2vw, 28px)) calc(-1 * clamp(16px, 2vw, 28px));
    padding: 14px clamp(16px, 2vw, 28px);
    background: rgba(255, 255, 255, .96);
    border-top: 1px solid var(--toz-border);
    border-radius: 0 0 var(--toz-promien) var(--toz-promien);
    /* Bez rozmycia tła: przy 96% krycia go nie widać, a przeglądarka liczyła je przy każdym przewinięciu
       (audyt 04.10.2026, G15). */
}
.pasek-zapisu .btn-block { display: inline-block; width: auto; margin-top: 0; }
.pasek-zapisu .muted { margin: 0 0 0 auto; font-size: .875rem; }
/* W formularzu-siatce (karta oddzialu) pasek jest jednym z pol siatki. Bez
   calego wiersza stawal w jednej kratce: przyciski jeden pod drugim, trzymane
   u dolu ekranu na polach formularza. Odstep siatki (16 px) plus 8 px daje
   te same 24 px nad paskiem co w zwyklym formularzu. */
.grid-form > .pasek-zapisu { grid-column: 1 / -1; margin-top: 8px; }

/* Na waskim ekranie tabela przestaje byc tabela: kazda pozycja to karta
   z etykietami przy polach, bo poziome przewijanie formularza jest nie do
   uzycia jedna reka. */
@media (max-width: 640px) {
    .pozycje, .pozycje tbody, .pozycje tr, .pozycje td { display: block; width: auto; }
    .pozycje thead { display: none; }
    .pozycje tbody tr {
        border: 1px solid var(--toz-border); border-radius: 8px;
        padding: 34px 10px 10px; margin-bottom: 12px; position: relative;
    }
    .pozycje td { padding: 4px 0; }
    .pozycje td::before { content: attr(data-etykieta); display: block; font-size: .78rem; color: var(--toz-muted); margin-bottom: 2px; }
    .pozycje .kol-lp, .pozycje .kol-usun { position: absolute; top: 6px; padding: 0; }
    .pozycje .kol-lp { left: 10px; font-weight: 600; }
    .pozycje .kol-usun { right: 6px; }
    .pozycje .kol-lp::before, .pozycje .kol-usun::before { content: none; }
    .pozycje .kol-suma { text-align: left; padding-top: 6px; }
    .pozycje .kol-suma:empty { display: none; }
    /* Podpis musi brzmiec slowo w slowo jak naglowek kolumny na szerokim ekranie. */
    .pozycje .kol-suma:not(:empty)::before { content: "Wartość"; display: block; font-size: .78rem; color: var(--toz-muted); }
    .pozycje .kol-liczba { max-width: 200px; }

    .pozycje-stopka { flex-direction: column; align-items: stretch; }

    /* Na telefonie pasek zapisu PRZESTAJE trzymac sie dolu ekranu.
       Przyciski rozciagniete na cala szerokosc lamia sie na trzy, czasem
       cztery rzedy - trzymany pasek zabieral wtedy jedna czwarta ekranu
       przez caly czas pisania. Do tego przy podniesionej klawiaturze
       ladowal dokladnie nad polem, ktore sie akurat wypelnia, a "Anuluj"
       stawal pod kciukiem obok "Zapisz". Na dole formularza jest tam,
       gdzie konczy sie tresc - i nic nie zaslania. */
    .pasek-zapisu {
        position: static;
        backdrop-filter: none;
        background: transparent;
        border-top: 0;
        padding-left: 0;
        padding-right: 0;
        margin-left: 0;
        margin-right: 0;
    }
    .pasek-zapisu .btn { flex: 1 1 auto; text-align: center; }
    .pasek-zapisu .pasek-prawa { margin-left: 0; flex: 1 1 100%; display: flex; }
}

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

/* --- Tabela ewidencji ------------------------------------------------------
   Kolumn jest kilkanascie, wiec tabela ma prawo byc szersza od okna i
   przewijac sie w swoim pojemniku - waznejsze, zeby uklad kolumn zgadzal
   sie z arkuszem, niz zeby wszystko zmiescilo sie bez przewijania. */
.table-ewidencja { font-size: .84rem; }
.table-ewidencja th, .table-ewidencja td { padding: 7px 6px; }
.table-ewidencja td { vertical-align: middle; }
.table-ewidencja .uwagi { max-width: 280px; color: var(--toz-muted); }

/* Bez wlasnego "justify-content": odnosnik jest waski jak jego tresc,
   a o tym, gdzie stanie, rozstrzyga wyrownanie naglowka. Wlasne srodkowanie
   przebijalo je w kolumnach z lamanym tytulem. */
.table th .sort {
    display: inline-flex; align-items: baseline; gap: 4px;
    color: inherit; text-decoration: none;
}
.table th .sort:hover { color: var(--toz-granat); text-decoration: underline; }
.table th .sort-aktywny { color: var(--toz-granat); }
.sort-znak { font-size: .7em; }

.po-terminie { color: var(--toz-blad); font-weight: 600; }
.kol-zostalo { white-space: nowrap; }

.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 16px; }
.pager-kroki { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 auto 0 0; }
.btn-strona-aktywna { cursor: default; }
/* Otwarta strona listy: granat z głębią. Numer otwartej strony nie jaśnieje pod kursorem - biały napis ginął na jasnym tle. */
.btn-strona-aktywna, .btn-strona-aktywna:hover {
    background-color: var(--toz-granat-ciemny);
    background-image: linear-gradient(135deg, #4a68ba, var(--toz-granat-ciemny));
    border-color: var(--toz-granat-ciemny);
    color: #fff;
    box-shadow: 0 3px 10px rgba(44, 67, 129, .25);
}

/* --- Lista faktur: waskie daty, szybkie operacje --------------------------- */
.table-ewidencja th { vertical-align: bottom; line-height: 1.25; }
.table-ewidencja .kol-lp-lista { width: 44px; font-variant-numeric: tabular-nums; }
.table-ewidencja .kol-lp-lista a { display: block; font-weight: 600; text-decoration: none; }
.table-ewidencja .kol-lp-lista a:hover { text-decoration: underline; }
.table-ewidencja .kol-data { width: 92px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.table-ewidencja .kol-akcje { width: 1%; white-space: nowrap; }

.zal-znacznik { margin-left: 6px; font-size: .8rem; color: var(--toz-muted); white-space: nowrap; }

.przelaczniki { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 4px; }
.przelaczniki .label { margin: 0; }
.przelacznik { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
    border: 1px solid var(--toz-border); border-radius: 999px; cursor: pointer; font-size: .9rem; background: #fff; }
.przelacznik:has(input:checked) { border-color: var(--toz-granat); background: var(--toz-granat-jasny); color: var(--toz-granat-ciemny);
    /* Zaznaczony świeci delikatną obwódką w swoim kolorze. */
    background-image: linear-gradient(180deg, #f4f6fd, #e3e9f7);
    box-shadow: 0 0 0 3px rgba(58, 87, 162, .10); }
/* --- Panel szybkiego wpisu (szybka rejestracja nad tabela) ---------------
   Pola lamia sie same, wiec nie ma poziomego przewijania. Poprawka w wierszu
   listy zniknela 13.09.2026 - dwuklik w wiersz otwiera pelny formularz
   (dwuklik-wiersza.js). */
.szybkie > summary { cursor: pointer; font-weight: 600; font-size: .9rem; color: var(--toz-granat); margin-bottom: 12px; }

.panel-pola { display: grid; gap: 12px 16px; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); align-items: end; }
.panel-pole { display: flex; flex-direction: column; gap: 4px; min-width: 0; font-size: .85rem; }
.panel-pole > span:first-child { color: var(--toz-muted); font-weight: 600; }
.panel-pole b { color: var(--toz-blad); font-weight: 600; }
.panel-pole .form-control { font-size: .95rem; min-height: 38px; padding: 6px 10px; }
.panel-szeroko { grid-column: span 2; }
.panel-data { min-width: 150px; }
.panel-kwota { max-width: 220px; }
.panel-flaga { flex-direction: row; align-items: center; gap: 8px; }
.panel-uwagi { grid-column: 1 / -1; }
/* Listy w panelu (daty interwencji, kto sprawdzal - wlasciciel, 24.09.2026):
   wiersze jeden pod drugim, "+ Dodaj kolejna" przy podpisie - pole z jednym
   wierszem ma wtedy prawie te sama wysokosc co sasiednie. */
.panel-lista .powiazania { margin-bottom: 0; }
/* "x" tej samej wysokosci co pole (38 px, nie 40) - inaczej wiersz listy byl
   o 2 px wyzszy od zwyklego pola i rzad panelu rozjezdzal sie o piksel. */
.panel-lista .usun-pozycje { height: 38px; }
.panel-lista .powiazania:has(> .powiazanie) { grid-template-columns: minmax(0, 1fr); }
.panel-lista-glowka { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 8px; }
.panel-lista-glowka > span { color: var(--toz-muted); font-weight: 600; }
/* Przycisk nie wyzszy od podpisu (20 px), zeby podpisy "Daty interwencji" i "Kto
   sprawdzal" staly w jednej linii z podpisami pol obok (wlasciciel, 24.09.2026:
   "pola sa porozstawiane nierowno"). Na ekranie dotykowym przycisk zostaje
   wiekszy - tam wazniejsze jest trafienie palcem (regula nizej, przy 16 px). */
.panel-lista-glowka .btn-maly { min-height: 0; height: 20px; padding: 0 8px; }

/* Pole adresu w panelu interwencji: kontener podpowiedzi pod polem ma zero
   wysokosci (lista unosi sie nad strona), ale jako trzeci element pola dostawal
   odstep i podnosil pole adresu ponad sasiednie (wlasciciel, 24.09.2026: "pola sa
   porozstawiane nierowno"). Odstep pod podpisem zostaje ten sam co w innych polach. */
.panel-pole.panel-adres { gap: 0; }
.panel-pole.panel-adres > span:first-child { margin-bottom: 4px; }

/* Przelaczniki w panelu interwencji (miejsce niebezpieczne, z wieloma zwierzetami)
   - jak na karcie i tej samej wysokosci co pola obok: dol i gora w jednej linii.
   Szerokie tylko na napis, nie na cala komorke. */
.panel-pole.panel-przelacznik { align-items: flex-start; }
.panel-przelacznik .przelacznik { min-height: 38px; box-sizing: border-box; }

/* Opisy takze w panelu maja byc do pisania, a nie do zerkania.
   Selektor jest celowo mocniejszy od '.panel-pole .form-control' powyzej:
   tamten ustawia min-height 38px i wygrywal specyficznoscia, przez co ta
   regula byla martwa. Font 1rem, a nie .95rem: ponizej 16px Safari na
   iPadzie przybliza cala strone przy wejsciu w pole. */
.panel-pole textarea.form-control {
    min-height: min(9rem, 30vh);
    font-size: 1rem;
    line-height: 1.55;
    resize: vertical;
}

/* Panel szybkiej rejestracji interwencji: opis i uwagi na dwie widoczne linie
   (wlasciciel, 24.09.2026: "Zmniejsz te pola textarea do widocznych dwoch linii
   (uzytkownik moze wpisac wiecej)"). Wysokosc bierze sie z rows="2"; dluzszy
   tekst przewija sie w polu, a pole da sie rozciagnac za rog. Selektor mocniejszy
   od '.panel-pole textarea.form-control' wyzej - tamten daje 9 rem. Wczesniej
   byla tu klasa "panel-opis" z 14 rem na opis sprawy. */
.panel-pole.panel-dwie-linie textarea.form-control { min-height: 0; }
.panel-akcje { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 16px; }

/* Wiersz, ktory wlasnie poprawia formularz pod tabela (np. stany interwencji). */
.wiersz-edytowany > td { background: var(--toz-granat-jasny); box-shadow: inset 0 -2px 0 var(--toz-granat); }
.wiersz-edytowany > td:first-child { box-shadow: inset 3px 0 0 var(--toz-granat), inset 0 -2px 0 var(--toz-granat); }

@media (max-width: 640px) {
    .panel-szeroko { grid-column: 1 / -1; }
}

/* --- Ustawienie widoku pod tabela ----------------------------------------- */
.ustawienie-strony { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px;
    padding-top: 12px; border-top: 1px solid var(--toz-border); }
.ustawienie-strony .form-control { width: auto; padding: 6px 10px; font-size: .9rem; }
/* Pole wyboru bierze szerokość najdłuższej opcji ("Odwrotnie: według ... (od ostatniej strony)") i na telefonie
   wychodziło poza ekran (właściciel, 15.10.2026) - nie szersze niż wiersz, napis wybranej opcji się ucina. */
.ustawienie-strony select.form-control { min-width: 0; max-width: 100%; text-overflow: ellipsis; }
/* Ustawienia modułu pod tabelą (właściciel, 19.10.2026: "Stany interwencji przesuń pod tabelę") - ten sam pas co
   kolejność listy; przy niej bez drugiej kreski. */
.ustawienia-listy { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 16px 0 0;
    padding-top: 12px; border-top: 1px solid var(--toz-border); }
.ustawienie-strony + .ustawienia-listy { margin-top: 8px; padding-top: 0; border-top: 0; }

/* --- Pasek zapisu: usuwanie po prawej ------------------------------------- */
.pasek-prawa { margin-left: auto; }

/* --- Zalaczniki ----------------------------------------------------------- */
.zalaczniki { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
.zalaczniki li { display: flex; align-items: center; gap: 12px; padding: 8px;
    border: 1px solid var(--toz-border); border-radius: 8px; }
.zalacznik-podglad { flex: 0 0 auto; width: 64px; height: 64px; border-radius: 6px; overflow: hidden;
    display: flex; align-items: center; justify-content: center; background: var(--toz-granat-jasny);
    color: var(--toz-granat-ciemny); font-weight: 700; text-decoration: none; }
.zalacznik-podglad img { width: 100%; height: 100%; object-fit: cover; }
.zalacznik-opis { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.zalacznik-opis a { word-break: break-word; }

/* Historia dokumentu tuz pod paskiem zapisu - zwinieta, zeby nie przeslaniala
   samej faktury, ale w zasiegu jednego klikniecia. */
.historia { margin-top: calc(20px + clamp(16px, 2vw, 28px)); border-top: 1px solid var(--toz-border); padding-top: 12px; }
.historia > summary { cursor: pointer; font-weight: 600; color: var(--toz-granat); }
.historia .table { margin-top: 12px; }
/* Historia sprawy interwencji stoi na samym dole karty, we własnej ramce
   (właściciel, 24.09.2026: "na dole interwencji ... rozwijane logi") - bez
   kreski i odstępu, które oddzielały ją od paska zapisu. */
.historia.historia-na-dole { margin-top: 0; border-top: 0; padding-top: 0; }
.historia-na-dole .hint { margin: 8px 0 0; }
/* Nagłówek tabeli trzyma górę ekranu (naglowek-tabeli.js), a jego kopia staje
   na początku pojemnika - odstęp nad tabelą musi więc być nad pojemnikiem,
   inaczej spod kopii wystaje pasek prawdziwego nagłówka. */
.historia-na-dole .table-wrap { margin-top: 12px; }
.historia.historia-na-dole .table { margin-top: 0; }
.tabela-historii td { vertical-align: top; }


/* Dodanie faktury: pelny formularz obok zwijanego szybkiego wpisu. */
.dodanie-faktury { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 0 0 16px; }
.table-ewidencja tbody tr { cursor: default; }

/* --- Pulpit: kafelki z liczbami --------------------------------------------
   Kazdy kafelek jest odnosnikiem do listy juz zawezonej do tego, co pokazuje.
   Liczba bez drogi do niej byla by tylko ciekawostka. */
.kafelki { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-bottom: 8px; }
.kafelek {
    display: flex; flex-direction: column; gap: 2px;
    padding: 16px 18px;
    border: 1px solid var(--toz-border);
    border-left: 4px solid var(--toz-granat);
    border-radius: var(--toz-promien);
    background: var(--toz-plyta);
    color: inherit;
    text-decoration: none;
    /* Tło z granatu w złoto. */
    background-image: linear-gradient(135deg, rgba(58, 87, 162, .07), rgba(215, 181, 109, .11));
}
.kafelek:hover, .kafelek:focus-visible { background: var(--toz-granat-jasny); border-color: #c3cbe2; border-left-color: var(--toz-granat); }
.kafelek-liczba { font-size: 1.9rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--toz-granat-ciemny); }
.kafelek-opis { font-size: .9rem; color: var(--toz-text); }
.kafelek-dopisek { font-size: .8rem; color: var(--toz-muted); }
.kafelek-alarm { border-left-color: var(--toz-blad); background-image: linear-gradient(135deg, rgba(165, 40, 52, .07), rgba(215, 181, 109, .06)); }
.kafelek-alarm .kafelek-liczba { color: var(--toz-blad); }

/* Termin rekontroli, ktory juz nadszedl - na liscie ma sie rzucac w oczy. */
.termin-minal { color: var(--toz-uwaga); font-weight: 600; }

/* Mapa do ustawienia punktu przy interwencji. Pin stoi na środku i się nie rusza -
   przesuwa się mapa pod nim, więc nie trzeba celować w kilkupikselowy znacznik. */
.hint-uwaga { color: var(--toz-uwaga); font-weight: 600; }
/* --- Wzory dokumentów pod tabelą modułu ----------------------------------
   Lista ma się dać przebiec wzrokiem: plakietka formatu po lewej niesie
   rozpoznanie od razu, nazwa jest jedyną rzeczą pogrubioną, a zarządzanie
   chowa się za rozwinięciem - przy dwudziestu wzorach pola tekstowe w każdym
   wierszu zamieniają listę w formularz. */
/* Pytanie w oknie aplikacji. Okienko przeglądarki wygląda jak komunikat
   systemu, a nie jak część ewidencji - i właśnie dlatego bywa odklikiwane
   bez czytania.
   Za oknem granatowa matowa szyba zamiast płaskiej szarości, a okno wyraźnie unosi się nad stroną (właściciel,
   27.10.2026, grafika nr 14) - rozmycie i kreska marki u góry okna w sekcji „Grafika przy pracy”. */
.okno-pytania { border: 0; border-radius: var(--toz-promien); padding: 0; max-width: min(420px, calc(100% - 32px));
                box-shadow: 0 24px 64px rgba(20, 29, 61, .34), 0 2px 10px rgba(20, 29, 61, .14); color: var(--toz-text);
                background: var(--toz-plyta); }
.okno-odpowiedzi { border: 0; border-radius: var(--toz-promien); padding: 20px; width: min(640px, calc(100% - 32px)); }
.okno-odpowiedzi::backdrop { background: rgba(26, 38, 82, .42); }
.okno-odpowiedzi textarea { width: 100%; }
/* "Propozycja od AI" nad polem odpowiedzi (06.11.2026): przycisk i stan obok siebie, na telefonie stan pod przyciskiem. Pod polem zdanie, uwagi AI
   i odnośniki do dawnych odpowiedzi - w tle granatu marki ze złotą kreską, jak propozycje przy mailu; długie słowa się łamią. */
.odpowiedz-propozycja { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0 0 8px; min-width: 0; }
.odpowiedz-propozycja[hidden], .propozycja-wynik[hidden] { display: none; }
.odpowiedz-propozycja [data-propozycja-stan] { min-width: 0; overflow-wrap: anywhere; }
.propozycja-wynik { margin: 8px 0 12px; padding: 8px 12px; border-left: 4px solid var(--toz-zloto); border-radius: 6px; background: var(--toz-granat-jasny);
    overflow-wrap: anywhere; }
.propozycja-wynik p, .propozycja-wynik ul { margin: 0; }
.propozycja-wynik ul { padding-left: 1.2rem; }
.propozycja-wynik > * + * { margin-top: 4px; }
/* Okno porównania przy "Propozycji od AI" (08.11.2026; właściciel: "Warto by mi pokazać treść, którą chce zamienić i na jaką. Warto dać mi to do
   edycji"): okno pytania (kreska marki, szyba za oknem, ruch), tylko szersze - "Twój tekst" i propozycja obok siebie, na telefonie jedno pod drugim,
   przyciski wtedy na całą szerokość. Okno przewija się w sobie, gdy nie mieści się na ekranie; strona nie ucieka w bok. */
.okno-pytania.okno-porownania { width: min(960px, calc(100% - 32px)); max-width: min(960px, calc(100% - 32px)); max-height: calc(100% - 32px); overflow: auto; }
.okno-porownania-tytul { margin: 0 0 4px; }
/* Wybór celu dla zbiórki bez celu (09.11.2026) - ramka na karcie zbiórki i nad listą, a na liście w oknie pytania
   (zbiorki-pytanie-o-cel.js). Pola wyboru pod jego nazwą, z wcięciem; na telefonie bez wcięcia. */
.okno-pytania.okno-wyboru-celu { width: min(760px, calc(100% - 32px)); max-width: min(760px, calc(100% - 32px)); max-height: calc(100% - 32px); overflow: hidden auto; overscroll-behavior: contain; }
.wybor-celu.w-oknie { margin: 0; padding: 0; border: 0; box-shadow: none; background: transparent; }
.wybor-celu-pola { margin: 8px 0 4px 36px; }
.wybor-celu .wybor-celu-przyciski { margin-top: 16px; }
@media (max-width: 640px) { .wybor-celu-pola { margin-left: 0; } }
.okno-porownania-pola { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; margin: 12px 0; }
.okno-porownania-pola .pole { min-width: 0; margin: 0; }
.okno-porownania-pola textarea { width: 100%; min-height: 14rem; resize: vertical; }
.okno-porownania .propozycja-wynik { margin: 0 0 16px; }
/* Ostrzeżenie przed odrzuceniem poprawek (przegląd 08.11.2026): stoi pusty od otwarcia, żeby czytnik ekranu ogłosił wpisany tekst. */
.okno-porownania-ostrzezenie { margin: 0 0 12px; font-weight: 600; color: var(--toz-granat-ciemny); }
.okno-porownania-ostrzezenie:empty { margin: 0; }
@media (max-width: 640px) {
    .okno-porownania-pola { grid-template-columns: minmax(0, 1fr); }
    .okno-porownania-pola textarea { min-height: 9rem; }
    .okno-porownania .okno-pytania-przyciski > .btn { flex: 1 1 100%; }
}
/* Zasady odpowiedzi oddziału do czytania (bez prawa zapisu i "Obecne zasady" po cudzym zapisie). */
.tekst-zasad { padding: 10px 14px; border-left: 4px solid var(--toz-granat); border-radius: 6px; background: var(--toz-granat-jasny); overflow-wrap: anywhere; }
/* Pasek karty maila (właściciel, 01.11.2026): odpowiedź i koordynator przed propozycją; czego nie ma, mówi zdanie pod przyciskami. */
.poczekalnia-pasek { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 12px; }
.poczekalnia-pasek > * { min-width: 0; max-width: 100%; }
.poczekalnia-pasek form { margin: 0; }
.poczekalnia-pasek .btn .ikona { margin-right: 6px; }
.poczekalnia-pasek .stan { white-space: normal; }
/* Listwa czynności karty maila (właściciel, 04.11.2026: "posprzątaj, bo teraz mają różny wygląd, są w różnych miejscach"): wszystkie przyciski w jednym miejscu pod metryczką,
   w rzędach według rodzaju - odpowiedź, decyzja (pod propozycją), porządek, adres nadawcy - jednej wielkości. Porządek i adres oddziela cienka kreska. Na telefonie przyciski
   się zawijają, a długi napis łamie się w przycisku, zamiast przesuwać stronę w bok. */
.mail-listwa { display: grid; gap: 12px; margin: 0 0 12px; min-width: 0; }
.mail-listwa > * { margin: 0; min-width: 0; max-width: 100%; }
.mail-listwa > .poczekalnia-pasek { gap: 8px; }
.mail-listwa > .poczekalnia-czynnosci, .mail-wiecej-tresc > .mail-porzadek, .mail-wiecej-tresc > .mail-adres { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mail-wiecej-tresc > .mail-porzadek, .mail-wiecej-tresc > .mail-adres { padding-top: 12px; border-top: 1px solid var(--toz-border); }
.mail-listwa > :first-child, .mail-listwa > .mail-wiecej:first-child .mail-wiecej-tresc > :first-child { border-top: 0; padding-top: 0; }
/* Rząd porządku i adresu nadawcy pod "Więcej czynności" (10.11.2026): na komputerze i tablecie zawsze rozwinięte, bez napisu - jak dotąd. Na telefonie
   napis jest przyciskiem, a na-telefonie.js zamyka blok na start (data-zwin-na-telefonie). */
.mail-wiecej-tresc { display: grid; gap: 12px; min-width: 0; }
.mail-wiecej > summary { display: none; }
@media (max-width: 640px) {
    .mail-wiecej { padding-top: 12px; border-top: 1px solid var(--toz-border); }
    .mail-listwa > .mail-wiecej:first-child { padding-top: 0; border-top: 0; }
    .mail-wiecej > summary { display: inline-flex; align-items: center; gap: 6px; list-style: none; cursor: pointer; }
    .mail-wiecej > summary::-webkit-details-marker { display: none; }
    .mail-wiecej > summary::after { content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg) translateY(-2px); }
    .mail-wiecej[open] > summary::after { transform: rotate(-135deg) translateY(-1px); }
    .mail-wiecej[open] > summary { margin-bottom: 12px; }
    .mail-wiecej-tresc > :first-child { padding-top: 0; border-top: 0; }
}
.mail-listwa form { margin: 0; }
.mail-listwa .btn { white-space: normal; max-width: 100%; padding-top: 6px; padding-bottom: 6px; }
.mail-listwa .btn .ikona { margin-right: 6px; }
.mail-listwa .flagi-wybor .btn { padding-top: 0; padding-bottom: 0; }
.mail-listwa .flagi-wybor .btn .ikona { margin-right: 0; }
.mail-listwa .poczekalnia-pomin { display: contents; }
.mail-listwa .poczekalnia-dolacz { flex: 1 1 100%; padding: 0; border: 0; align-items: flex-end; }
.mail-listwa .poczekalnia-dolacz .pole { max-width: 40rem; }
.mail-listwa .poczekalnia-propozycja, .mail-wyjasnienie { margin: 0; }
.mail-wyjasnienie p, .mail-wyjasnienie ul { margin: 0; }
.mail-wyjasnienie p + p, .mail-wyjasnienie p + ul { margin-top: 4px; }
.mail-adres > form { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.mail-przenies { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.mail-przenies .form-control { width: auto; min-width: 10rem; max-width: 100%; }
.mail-przenies .hint { flex-basis: 100%; margin: 0; }
.mail-uwaga { flex-basis: 100%; margin: 0; }
/* Zaufane e-maile na karcie maila (05.11.2026): przycisk rozwija w miejscu małe pole na całą szerokość rzędu, pola obok siebie, na telefonie jedno pod drugim. */
.mail-zaufany { min-width: 0; max-width: 100%; }
.mail-zaufany[open] { flex-basis: 100%; }
.mail-zaufany > summary { list-style: none; }
.mail-zaufany > summary::-webkit-details-marker { display: none; }
.mail-zaufany-pola { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; margin-top: 8px; padding: 12px; border: 1px solid var(--toz-border); border-radius: var(--toz-promien); max-width: 48rem; }
.mail-zaufany-pola .pole { flex: 1 1 12rem; min-width: 0; margin: 0; }
.mail-zaufany-adres, .mail-zaufany-sprzeciw { flex-basis: 100%; margin: 0; overflow-wrap: anywhere; }
.mail-zaufany-sprzeciw .hint { margin: 0 0 4px; }
/* Mail usunięty ze skrzynki albo leżący w jej koszu (0263): skreślony, ale w kolorze tekstu, więc w trybie ciemnym czyta się tak samo. */
.mail-skreslony { text-decoration: line-through; text-decoration-thickness: 1px; }
.poczekalnia-powod { flex-basis: 100%; margin: 0; }
.poczekalnia-odpowiedz { margin: 0 0 12px; }
/* Adres odbiorcy nie urywa się na telefonie: strona ma overflow-x: clip, więc końca, czyli domeny, nie dałoby się przewinąć. */
.poczekalnia-odpowiedz p, .okno-odpowiedzi p { overflow-wrap: anywhere; }
/* Tak samo adres w masce przy napisie „nie doszło” (napis_niedoreczenia, 0261): domena bez łącznika nie miałaby gdzie się złamać. */
.adres-w-masce { overflow-wrap: anywhere; }
/* Adres z listy Zaufane e-maile w zakładce Zaufane: długi adres łamie się w komórce, strona nie ucieka w bok. */
.mail-adres-wysylek { overflow-wrap: anywhere; min-width: 9rem; }
.poczekalnia-szablon { display: grid; gap: 12px; max-width: 48rem; justify-items: start; }
.poczekalnia-szablon .pole { width: 100%; }
.poczekalnia-odpowiedz > summary { cursor: pointer; font-weight: 600; }
.poczekalnia-odpowiedz textarea { width: 100%; max-width: 48rem; }
.maile-kopie { margin: 0 0 12px; }
.maile-kopie > summary { cursor: pointer; }
.maile-kopie input { width: 100%; max-width: 48rem; }
/* Podpowiedzi adresów (właściciel, 02.11.2026): ta sama lista co przy adresie sprawy, nad formularzem, nie szersza od pola; długi adres zawija się w niej zamiast przesuwać okienko w bok. */
.adresaci-podpowiedzi { max-width: 48rem; overflow-wrap: anywhere; }
.maile-pliki-przekazu { border: 0; margin: 12px 0; padding: 0; min-width: 0; }
.maile-pliki-przekazu label { display: block; overflow-wrap: anywhere; }
/* "Dodaj podpis" (właściciel, 01.11.2026): pozycje rozwijają się pod przyciskiem, w miejscu, także w okienkach, które przycinają to, co wystaje. */
.maile-podpis { margin: 8px 0 0; }
.maile-podpis > summary { list-style: none; }
.maile-podpis > summary::-webkit-details-marker { display: none; }
.maile-podpis-pozycje { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
/* Mail nad polem odpowiedzi i przełącznik cytatu (właściciel, 02.11.2026): blok zwinięty, bez własnego paska przewijania. */
.maile-nad-polem { margin: 0 0 12px; }
.maile-nad-polem > summary { cursor: pointer; }
.maile-nad-polem p { margin: 8px 0 0; }
.maile-nad-polem p:empty { display: none; }
.maile-nad-polem .tresc-maila { margin: 8px 0 0; max-width: 48rem; }
.maile-cytat { margin: 8px 0 0; }
.maile-pliki { margin: 12px 0; }
.maile-pliki .form-control { width: 100%; }
.maile-pliki .hint { margin: 6px 0 0; }
/* Okno "Dodaj organizację z mapy" (właściciel, 01.11.2026): przewija się całe, jednym palcem; mapa, wyniki i lista wybranych nie mają
   własnych pasków, a przyciski zostają w zasięgu nad dolną krawędzią. Na wąskim ekranie lista wybranych schodzi pod mapę. */
/* Obok "Dodaj organizację z mapy" stoi "Dodaj urząd z mapy" (06.11.2026) - przyciski w jednym rzędzie, na wąskim ekranie łamią się
   do następnego, okno urzędów ma ten sam układ i te same klasy. */
.odpowiedz-organizacje { display: inline-block; margin: 8px 8px 0 0; }
.okno-organizacji { border: 0; border-radius: var(--toz-promien); padding: 16px; width: min(960px, calc(100% - 32px)); max-width: none;
                    max-height: calc(100vh - 32px); max-height: calc(100svh - 32px); overflow: hidden auto; overscroll-behavior: contain;
                    box-shadow: 0 24px 64px rgba(20, 29, 61, .34), 0 2px 10px rgba(20, 29, 61, .14); color: var(--toz-text);
                    background: var(--toz-plyta); scrollbar-gutter: stable; }
.okno-organizacji::backdrop { background: rgba(26, 38, 82, .42); }
.okno-organizacji > h2:focus { outline: none; }
.okno-organizacji [data-organizacje-info]:empty, .okno-organizacji [data-urzedy-info]:empty { display: none; }
.okno-organizacji-wyniki { margin: 0 0 12px; padding: 0; list-style: none; border: 1px solid var(--toz-border); border-radius: 6px;
                           overflow-wrap: anywhere; }
.okno-organizacji-grupa { padding: 7px 10px 2px; font-size: .8rem; font-weight: 600; color: var(--toz-muted); }
.okno-organizacji .mapa-wynik[aria-pressed="true"] { background: var(--toz-granat-jasny); font-weight: 600; }
.okno-organizacji-uklad { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 16px; align-items: start; }
.okno-organizacji .mapa-zgloszen .mapa-plotno { height: min(52vh, 460px); }
/* Zaznaczona chorągiewka stoi nad innymi, ale tylko w obrębie płótna: nad przyciskami + i − przechwytywałaby ich kliknięcia. */
.okno-organizacji .mapa-plotno { isolation: isolate; }
.okno-organizacji-wybor { min-width: 0; }
.okno-organizacji-wybor .hint { margin-top: 0; }
.okno-organizacji-wybrane { margin: 0; padding: 0; list-style: none; }
.okno-organizacji-wybrane li { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 6px 0;
                               border-top: 1px solid var(--toz-border); overflow-wrap: anywhere; }
.okno-organizacji-wybrane li > span { min-width: 0; }
.okno-organizacji-przyciski { position: sticky; bottom: -16px; margin: 12px -16px -16px; padding: 12px 16px; border-top: 1px solid var(--toz-border);
                              background: var(--toz-plyta); z-index: 5; }
@media (max-width: 760px) {
    .okno-organizacji-uklad { grid-template-columns: minmax(0, 1fr); }
    .okno-organizacji .mapa-zgloszen .mapa-plotno { height: 280px; }
}
.okno-pytania::backdrop { background: rgba(26, 38, 82, .42); }
.okno-pytania-tresc { padding: 20px; }
.okno-pytania-tekst { margin: 0 0 16px; font-size: 1rem; line-height: 1.5; }
.okno-pytania-przyciski { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
/* Przyciski wysyłki w okienku odpowiedzi trzymają się razem po prawej: brak miejsca przenosi do następnego rzędu oba naraz. Na telefonie każdy stoi w swoim rzędzie.
   Bez marginesu z lewej: zabrałby wolne miejsce w rzędzie i odsunął Anuluj z wersją roboczą do lewej krawędzi, gdy „Wyślij i zakończ” nie ma (przegląd 03.11.2026). */
.okno-wysylka { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; max-width: 100%; }

/* Ekran pytania przed usunięciem - wspólny dla modułów. */
.ekran-pytania { max-width: 640px; }
.pytanie-co { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: 4px 14px;
              margin: 12px 0; padding: 12px; background: var(--toz-bg); border-radius: 8px; }
.pytanie-co dt { font-size: .82rem; color: var(--toz-muted); }
.pytanie-co dd { margin: 0; font-weight: 600; word-break: break-word; }
.pytanie-skutki { margin: 12px 0; padding-left: 20px; }
.pytanie-skutki li { margin-bottom: 4px; }
/* Pytanie z wyborem (gdzie usunąć post) - zgoda "Tak, usuń" stoi niżej,
   żeby nie czytała się jak kolejna odpowiedź. */
.ekran-pytania .wybor-efektu { margin-bottom: 14px; }

.oddzial-akcje { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
/* Papier firmowy oddzialu - karta pod ustawieniami oddzialu. */
.papier-opis { max-width: 72ch; margin: 0 0 14px; }
.papier-stan { margin: 0; overflow-wrap: anywhere; }
/* Włączenie dokumentu i listy, pod którymi stoi (Wzory umów, 15.10.2026). */
.dokument-dostepnosc { margin-bottom: 12px; }
.dokument-dostepnosc .badge { margin-right: 6px; }
.dokument-dostepnosc .zbiorczo { margin-top: 12px; padding-top: 10px; }
/* Wzory pod listami na ekranie Wzorów umów (14.10.2026): każdy wzór osobno, listy do zaznaczenia w kolumnach. */
.wzor-pod-listami { border-top: 1px solid var(--toz-border); padding: 14px 0; display: grid; gap: 8px; }
.wzor-pod-listami .papier-stan .badge { margin-left: 6px; }
.wzor-listy { border: 0; margin: 8px 0; padding: 0; display: grid; gap: 2px 16px;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); }
.wzor-listy legend { padding: 0; margin-bottom: 4px; }
.papier-akcje { margin-top: 12px; }
.papier-wgraj { display: grid; gap: 12px; margin-top: 20px; max-width: 620px; }
.papier-wgraj .strefa-zrzutu { margin-bottom: 0; }
.papier-wgraj .form-control { width: 100%; }
.papier-wgraj .hint { margin: 4px 0 0; }
/* Kilka przycisków w jednej komórce tabeli - np. przywrócenie obok wyrzucenia. */
.akcje-wiersza { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.lista-osob { margin: 6px 0 8px; padding-left: 20px; }

.wzory-karta .card-head { margin-bottom: 4px; }
.wzory-pusto { color: var(--toz-muted); padding: 14px 0; margin: 0; }

.wzory { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 6px; }
.wzor { display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px;
        border: 1px solid var(--toz-border); border-radius: 10px;
        background: var(--toz-plyta); transition: border-color .12s, box-shadow .12s; }
.wzor:hover { border-color: var(--toz-granat-jasny); box-shadow: var(--toz-cien); }
@media (prefers-reduced-motion: reduce) { .wzor { transition: none; } }

/* Plakietka formatu. Barwy stonowane - mają odróżniać, nie krzyczeć. */
.wzor-typ { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
            min-width: 46px; height: 34px; padding: 0 6px; border-radius: 7px;
            font-size: .68rem; font-weight: 700; letter-spacing: .04em;
            background: #eceef4; color: #4a5470; }
.wzor-typ[data-typ="pdf"]  { background: #fbeaea; color: #8f2f2f; }
.wzor-typ[data-typ="doc"],
.wzor-typ[data-typ="docx"],
.wzor-typ[data-typ="odt"]  { background: #e8eefb; color: #2f4d8f; }
.wzor-typ[data-typ="xls"],
.wzor-typ[data-typ="xlsx"],
.wzor-typ[data-typ="ods"]  { background: #e6f2ea; color: #216340; }

.wzor-tresc { flex: 1 1 auto; min-width: 0; }
.wzor-nazwa { font-weight: 600; word-break: break-word; text-decoration: none; }
.wzor-nazwa:hover, .wzor-nazwa:focus-visible { text-decoration: underline; }
.wzor-do-czego { margin: 2px 0 0; font-size: .9rem; color: var(--toz-text); }
.wzor-meta { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 0; }
.wzor-chip { display: inline-block; padding: 1px 8px; border-radius: 999px;
             font-size: .74rem; background: var(--toz-bg); color: var(--toz-muted);
             border: 1px solid var(--toz-border); }
/* Oddział wyróżniony: to jedyna rzecz, której przeoczenie kosztuje wysłanie
   do własnej gminy pisma napisanego dla cudzej. */
.wzor-chip-oddzial { background: var(--toz-tlo-uwaga); border-color: #e8d3a4; color: var(--toz-uwaga); font-weight: 600; }
/* Zamknięty oddział: dokument zostaje, ale nie udaje bieżącego. */
.wzor-chip-zamkniety { background: var(--toz-bg); border-style: dashed; color: var(--toz-muted); font-weight: 600; }

.wzor-akcje { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
/* Strzałki kolejności. Puste miejsce na skraju listy zostaje, żeby przyciski
   obok nie skakały przy każdym przesunięciu. */
.wzor-kolejnosc { display: inline-flex; flex-direction: column; gap: 1px; }
.wzor-strzalka { display: block; width: 24px; height: 17px; padding: 0; line-height: 15px;
                 border: 1px solid var(--toz-border); border-radius: 5px; background: var(--toz-plyta);
                 color: var(--toz-granat); font-size: .72rem; cursor: pointer; }
.wzor-strzalka:hover { background: var(--toz-granat-jasny); }
.wzor-strzalka-pusta { border-color: transparent; background: none; color: transparent; cursor: default; }
.wzor-zarzadzanie > summary { cursor: pointer; font-size: .82rem; color: var(--toz-granat);
                              padding: 6px 8px; border-radius: 8px; list-style: none; }
.wzor-zarzadzanie > summary::-webkit-details-marker { display: none; }
.wzor-zarzadzanie > summary:hover { background: var(--toz-granat-jasny); }
.wzor-zarzadzanie[open] { position: relative; }
.wzor-zarzadzanie-tresc { position: absolute; right: 0; top: 100%; z-index: 5; width: min(340px, 78vw);
                          margin-top: 6px; padding: 12px; background: var(--toz-plyta);
                          border: 1px solid var(--toz-border); border-radius: 10px;
                          box-shadow: 0 8px 24px rgba(0, 0, 0, .14); }
.wzor-edycja-wiersz { display: flex; gap: 6px; }
.wzor-edycja-wiersz .input { flex: 1 1 auto; min-width: 0; }
.wzor-usuwanie { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--toz-border); }
/* "Zdejmij z listy" z lewej, "Anuluj" z prawej - wyjście z rozwinięcia bez żadnej zmiany
   (właściciel, 02.10.2026). Kreskę i odstęp niesie wiersz, nie sam formularz. */
.wzor-zarzadzanie-stopka { display: flex; align-items: center; justify-content: space-between; gap: 8px;
                           margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--toz-border); }
.wzor-zarzadzanie-stopka .wzor-usuwanie { margin: 0; padding: 0; border: 0; }
.wzor-dodaj-akcje { display: flex; flex-wrap: wrap; gap: 8px; }
.label-maly { font-size: .78rem; }

.wzor-dodaj { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--toz-border); }
.wzor-dodaj > summary { cursor: pointer; font-weight: 600; color: var(--toz-granat); }
.wzor-dodaj-form { display: grid; gap: 12px; margin-top: 12px; max-width: 620px; }
.wzor-dodaj-form .pole { margin: 0; }
.wzor-dodaj-form .input, .wzor-dodaj-form .form-control { width: 100%; }
.wzor-dodaj-form .hint { margin: 4px 0 0; }

@media (max-width: 640px) {
    .wzor { flex-wrap: wrap; }
    .wzor-akcje { width: 100%; justify-content: flex-end; }
    .wzor-zarzadzanie-tresc { position: static; width: auto; box-shadow: none; }
}

/* --- Zbiorcza mapa interwencji ----------------------------------------------
   Pinezka niesie DWIE informacje naraz: kształt mówi o dokładności trafienia,
   barwa o tym, czy miejsce oznaczono jako niebezpieczne. Dokładność musi dać
   się odczytać bez rozróżniania barw, bo to od niej zależy, czy ktoś dojedzie
   pod właściwą bramę.

   Barwy są dwie i tyle. Wcześniej pinezka brała kolor stanu sprawy - mapa
   wychodziła z tego witrażem, a legenda i tak pokazywała co innego, bo
   żadnego stanu nie znała. Stan sprawy jest w dymku, słowami. */
.mapa-stany { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }

.mapa-legenda { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0 0 10px;
                font-size: .82rem; color: var(--toz-muted); }
.legenda-pozycja { display: inline-flex; align-items: center; gap: 7px; }
/* Ujemne marginesy w .pin służą wyłącznie temu, żeby pinezka siedziała środkiem
   na swoich współrzędnych. W legendzie kropka jest zwykłym elementem wiersza -
   te marginesy ściągały ją spod podpisu, i to inaczej dla każdego rozmiaru. */
.legenda-pozycja { align-items: center; }
/* W legendzie znak nie stoi na współrzędnych, tylko w linijce tekstu - dostaje
   więc własne pudełko, a nóżkę rysuje ::after (na mapie służy ono za pole
   kliknięcia, tutaj nie ma czego klikać). */
.legenda-pozycja .pin { position: relative; width: 14px; height: 24px; margin: 0;
                        flex: 0 0 auto; background: none; }
.legenda-pozycja .pin::before { left: 0; top: 0; }
.legenda-pozycja .pin::after { left: 6px; top: 12px; width: 2px; height: 12px;
                               background: var(--pin-barwa); }

.mapa-zgloszen { position: relative; border: 1px solid var(--toz-border);
                 border-radius: 8px; overflow: hidden; }
.mapa-zgloszen .mapa-plotno { height: min(70vh, 620px); }

/* Pinezka mapy zbiorczej to DOKŁADNIE ten sam znak, co na karcie interwencji -
   ta sama nóżka i ta sama główka, w jednej definicji niżej (.mapa-pin, .pin).
   Osobne wymiary "na oko" dawały grubą główkę na krótkim ogonku i znak
   wyglądał jak co innego niż ten, który ludzie znają z karty.

   Znaki różnią się WYŁĄCZNIE barwą, i to jedną zmienną - główka i nóżka biorą
   ją z tego samego miejsca, więc nie mogą się rozjechać:
     * granatowa - sprawa w toku,
     * szara     - stan oznaczony w panelu jako drugoplanowy (u nas rekontrola),
     * różowa    - miejsce niebezpieczne; ta barwa wygrywa z pozostałymi.

   Dokładność adresu ("pod numerem" / "gdzieś przy tej ulicy" / "gdzieś w tej
   miejscowości") mówi podpowiedź przy najechaniu i dymek po kliknięciu. */
.pin { padding: 0; border: 0; cursor: pointer; --pin-barwa: var(--toz-granat); }

/* Nóżka ma dwa piksele szerokości, więc sama w sobie jest nie do trafienia
   palcem. Pole kliknięcia dokładamy przezroczystym prostokątem wokół główki. */
.pin::after { content: ''; position: absolute; left: -13px; top: -18px;
              width: 28px; height: 40px; }

/* Sprawa drugoplanowa schodzi w tło: mapa pełna rekontroli przykrywała
   świeże interwencje. */
.pin-przygaszony { --pin-barwa: var(--toz-przygaszone); }

/* Ostrzeżenie wygrywa: stoi PO przygaszeniu, więc sprawa drugoplanowa pod
   niebezpiecznym adresem dalej rzuca się w oczy. */
.pin-niebezpieczne { --pin-barwa: var(--toz-niebezpieczne); }

/* Kilka spraw pod tymi samymi współrzędnymi to jedna pinezka z liczbą w rogu (właściciel, 27.10.2026) - wcześniej
   leżały pinezka na pinezce i wyglądały jak jedna. Złoto marki z białą obwódką, jak główka pinezki. */
.pin-liczba { position: absolute; left: 4px; top: -22px; z-index: 1; min-width: 16px; height: 16px; padding: 0 4px;
    box-sizing: border-box; border: 1px solid #fff; border-radius: 8px; background: var(--toz-zloto);
    color: var(--toz-granat-ciemny); font-size: 10px; font-weight: 700; line-height: 14px; text-align: center; }
.legenda-pozycja .pin-liczba { left: 8px; top: -7px; }

/* Dymek pinezki z kilkoma sprawami: adres raz (gdy wspólny), pod nim sprawy po kolei, każda z własnym "Otwórz
   interwencję". Dymek nie wychodzi nad górny brzeg mapy, a długa lista przewija się SAMA - nagłówek z adresem i "×"
   zostają na miejscu (przegląd 27.10.2026: przy przewijaniu całego dymka "×" odjeżdżał w górę). Szerokość zostawia
   z prawej miejsce na dwie kolumny przycisków sterowania (ok. 80 px, do tego brzegi i odstęp) - na telefonie dymek
   przykrywał "+", "↑" i "←". */
.mapa-zgloszen .mapa-dymek { display: flex; flex-direction: column; width: min(320px, calc(100% - 108px));
    max-height: calc(100% - 54px); overflow-y: auto; }
.mapa-zgloszen .mapa-dymek > * { flex-shrink: 0; }
.mapa-zgloszen .mapa-dymek > .dymek-sprawy { flex-shrink: 1; min-height: 72px; overflow-y: auto; }
/* Wąski ekran: obok przycisków zostawał pasek na kilka słów w wierszu - dymek idzie na całą szerokość mapy, ale
   zaczyna się pod przyciskami (trzy rzędy po 32 px z odstępami kończą się ok. 115 px od góry mapy). */
@media (max-width: 480px) {
    .mapa-zgloszen .mapa-dymek { right: 12px; width: auto; max-height: calc(100% - 42px - 124px); }
}
.dymek-sprawy { list-style: none; margin: 0 0 8px; padding: 0; }
.dymek-sprawa { padding: 6px 0; border-top: 1px solid var(--toz-border); }
.dymek-sprawa .dymek-opis { margin-bottom: 4px; }
.dymek-sprawa-stan { margin: 0 0 2px; font-size: .9rem; font-weight: 600; }

/* --- Mapa "Gdzie najwięcej spraw" (właściciel, 27.10.2026) ------------------
   Przełącznik "Pinezki / Gdzie najwięcej spraw" ma własny wiersz nad filtrami. Plamy rysuje skrypt na warstwie
   nad kafelkami - pod przyciskami sterowania i pod dymkiem; kliknięcia przechodzą przez nią do mapy. Kafelki
   schodzą do szarości, żeby plamy w barwie marki odcinały się od kolorowego podkładu. */
.filters > .mapa-tryb { grid-column: 1 / -1; }
.mapa-tryb .przelaczniki { margin: 0; }
.mapa-warstwa { position: absolute; left: 0; top: 0; pointer-events: none; }
.mapa-zageszczenie .mapa-plotno img { filter: grayscale(.7); }
.mapa-uwaga { margin: 10px 0 0; font-size: .85rem; font-weight: 600; color: var(--toz-uwaga); }
.mapa-legenda-plam { margin: 10px 0 4px; }
/* Legenda to te same plamy co na mapie: płaski środek do 35% promienia, potem do zera (SRODEK_PLAMY
   w mapa-zgloszen.js), a gęstość = 1 - (1 - porcja)^spraw - jasna: jedna sprawa z adresem (porcja .16),
   ciemna: piętnaście w jednym miejscu (.93), rozlana: trzy bez dokładnego adresu (porcja .07, razem .2).
   Kółko (::before) leży na kwadraciku w barwie kafelka (--mapa-podklad), jak plama na mapie - półprzezroczysta
   plama na płycie karty wyglądała inaczej niż na mapie, a w trybie ciemnym "jasna" znikała, a "ciemna" świeciła. */
.legenda-plama { position: relative; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 4px;
    background: var(--mapa-podklad); }
.legenda-plama::before { content: ''; position: absolute; inset: 3px; border-radius: 50%;
    background: radial-gradient(closest-side, var(--mapa-plama) 35%, transparent 100%); }
.legenda-plama-jasna::before { opacity: .16; }
.legenda-plama-ciemna::before { opacity: .93; }
.legenda-plama-rozlana { width: 40px; height: 40px; }
.legenda-plama-rozlana::before { opacity: .2; }
.mapa-legenda-opis { margin: 0; font-size: .82rem; color: var(--toz-muted); }

/* Część sprawy uchwały, która dotyczy jednego powodu: widać ją dopiero po wybraniu tego powodu
   (obowiązki z § 15 przy wykluczeniu z pkt 3, zaległości przy skreśleniu z pkt 4). Tylko tam,
   gdzie przeglądarka zna :has - w starszej część zostaje widoczna, a serwer i tak bierze ją
   pod uwagę wyłącznie przy swoim powodzie. */
@supports selector(:has(*)) {
    .przy-powodzie { display: none; }
    .sprawa-pola:has(input[name="powod"][value="3"]:checked) .przy-powodzie-3,
    .sprawa-pola:has(input[name="powod"][value="4"]:checked) .przy-powodzie-4 { display: block; }
}

/* Chorągiewka - znak innej organizacji (0169; właściciel, 01.10.2026: "flagami czy czymś
   podobnym, byle odróżniało się od pinów"). Pinezka to sprawa, chorągiewka to organizacja:
   różnią się kształtem, nie tylko barwą. Zielona - działa interwencyjnie, szara - nie;
   pozycja orientacyjna ma przerywany maszt i wyblakły proporzec. */
.flaga { position: absolute; width: 2px; height: 26px; margin: -26px 0 0 -1px; padding: 0; border: 0;
         background: var(--flaga-barwa); cursor: pointer; --flaga-barwa: #5f6673; }
.flaga::before { content: ''; position: absolute; left: 2px; top: 0; width: 17px; height: 13px;
                 background: var(--flaga-barwa); clip-path: polygon(0 0, 100% 50%, 0 100%); }
/* Maszt ma dwa piksele - pole kliknięcia dokładamy przezroczystym prostokątem. */
.flaga::after { content: ''; position: absolute; left: -9px; top: -5px; width: 34px; height: 36px; }
.flaga:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 6px; }
.flaga-interwencyjna { --flaga-barwa: #1c7a45; }
.flaga-orientacyjna { background: repeating-linear-gradient(var(--flaga-barwa) 0 4px, transparent 4px 7px); }
.flaga-orientacyjna::before { opacity: .5; }
/* Zaznaczona w oknie "Dodaj organizację z mapy": sama barwa marki, kształt zostaje. */
.flaga-wybrana { --flaga-barwa: var(--toz-granat); z-index: 1; }
.legenda-pozycja .flaga { position: relative; display: inline-block; margin: 0 16px 0 0; height: 22px; cursor: default; }
.legenda-pozycja .flaga::after { content: none; }

/* Znak urzędu (06.11.2026; właściciel: "może dodaj też urzędy na mapach , też się to przyda, tak jak z organizacjami"):
   domek z daszkiem - granat ze złotym dachem, w barwach marki. Pinezka to sprawa, chorągiewka organizacja, domek urząd:
   różnią się kształtem. Punkt przybliżony (środek ulicy albo miejscowości) jest wyblakły; zaznaczony w oknie przy mailu -
   złoty. Podstawa domku stoi na punkcie. */
.znak-urzedu { position: absolute; width: 16px; height: 12px; margin: -12px 0 0 -8px; padding: 0; border: 0; border-radius: 0 0 2px 2px;
               background: var(--znak-urzedu-barwa); box-shadow: 0 0 0 1.5px #fff, 0 1px 4px rgba(20, 29, 61, .45); cursor: pointer;
               --znak-urzedu-barwa: var(--toz-granat-ciemny); --znak-urzedu-dach: var(--toz-zloto); }
.znak-urzedu::before { content: ''; position: absolute; left: -3px; top: -9px; width: 22px; height: 9px; background: var(--znak-urzedu-dach);
                       clip-path: polygon(50% 0, 100% 100%, 0 100%); }
/* Pole kliknięcia większe niż sam domek - przezroczysty prostokąt, jak przy chorągiewce. */
.znak-urzedu::after { content: ''; position: absolute; left: -9px; top: -14px; width: 34px; height: 32px; }
.znak-urzedu:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 5px; }
.znak-urzedu-przyblizony { opacity: .55; }
.znak-urzedu-wybrany { --znak-urzedu-barwa: var(--toz-zloto); --znak-urzedu-dach: var(--toz-granat-ciemny); opacity: 1; z-index: 1; }
.legenda-pozycja .znak-urzedu { position: relative; display: inline-block; margin: 9px 10px 0 3px; vertical-align: -1px; cursor: default; }
.legenda-pozycja .znak-urzedu::after { content: none; }
.urzad-mapa { margin: 12px 0; }
.urzad-mapa .mapa-plotno { height: 240px; cursor: default; }
/* Punkt przybliżony na karcie urzędu (środek ulicy albo miejscowości) - wyblakła pinezka, jak wyblakły znak pod listą (06.11.2026). */
.urzad-mapa .mapa-pin-przyblizony { opacity: .55; }

/* Dymek organizacji: każda dana w swoim wierszu, pod nimi jeden przycisk "Kopiuj dane". */
.dymek-dana { margin: 0 0 4px; font-size: .9rem; overflow-wrap: anywhere; }
.dymek-dana-nazwa { padding-right: 22px; font-weight: 600; }
/* Na małej mapie w karcie interwencji (240 px na telefonie) dymek nie wychodzi nad górny brzeg - "×" i nazwa zawsze
   widać, a reszta przewija się w dymku (audyt 04.10.2026, F09). */
.mapa-scena .mapa-dymek { bottom: 12px; max-height: calc(100% - 24px); overflow-y: auto; }

/* Przełącznik "pokaż inne organizacje" nad mapą w edycji interwencji. */
.przelacznik-mapy { display: inline-flex; margin: 0 0 0 12px; }

/* Ikonka Facebooka na liście organizacji - sama ikonka, gdy organizacja ma stronę. */
.ikona-fb { display: inline-flex; align-items: center; justify-content: center; color: #1877f2; }
.ikona-fb:hover { color: var(--toz-granat-ciemny); }

.mapa-dymek { position: absolute; left: 12px; bottom: 42px; z-index: 4; width: min(320px, 78%);
              padding: 12px 38px 12px 12px; background: var(--toz-plyta);
              border: 1px solid var(--toz-border); border-radius: 10px;
              box-shadow: 0 8px 24px rgba(0, 0, 0, .18); }
.dymek-stan { margin: 0 0 2px; font-weight: 600; }
/* Adres jest tym, po co ktoś ten dymek otwiera - stoi wyżej niż stan sprawy
   i jest największym tekstem w środku. */
.dymek-adres { margin: 0 0 4px; font-weight: 600; color: var(--toz-text); }
.dymek-opis { margin: 0 0 8px; font-size: .85rem; color: var(--toz-muted); }
.dymek-akcje { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 6px; }
.dymek-drobne { margin: 0; font-size: .78rem; color: var(--toz-muted); }
.dymek-uwaga { margin: 0 0 8px; font-size: .85rem; color: var(--toz-uwaga); font-weight: 600; }
.dymek-zamknij { position: absolute; right: 2px; top: 2px; border: 0; background: none;
                 font-size: 1.2rem; line-height: 1; color: var(--toz-muted); cursor: pointer;
                 /* Cel do trafienia palcem i myszą, nie sam znak "×" (audyt 29.09.2026, C177). */
                 min-width: 32px; min-height: 32px; padding: 4px; }

/* Lista adresów z rejestru pod polem adresu. Unosi się nad formularzem,
   żeby nie przesuwała pól przy każdym wpisanym znaku - tak samo jak lista
   wyszukiwarki nad mapą, i wygląda tak samo, bo robi to samo. */
.adres-podpowiedzi { position: relative; }
.adres-wyniki { left: 0; right: 0; top: 100%; z-index: 5; }

/* Wyszukiwarka miejsc nad mapą. Lista wyników unosi się nad płótnem, żeby
   nie przesuwała mapy w dół przy każdym wpisanym znaku. */
.mapa-szukaj { position: relative; z-index: 2; display: flex; gap: 6px; padding: 8px;
               background: var(--toz-plyta); border-bottom: 1px solid var(--toz-border); }
.mapa-szukaj .input { flex: 1 1 auto; min-width: 0; }
.mapa-szukaj .btn { flex: 0 0 auto; }
/* Na telefonie przycisk obok zostawiał polu 155 px i podpowiedź się ucinała - pole bierze cały wiersz. */
@media (max-width: 520px) {
    .mapa-szukaj { flex-wrap: wrap; }
    .mapa-szukaj .input { flex-basis: 100%; }
}
.mapa-wyniki { position: absolute; left: 8px; right: 8px; top: 100%; margin: 2px 0 0; padding: 0;
               list-style: none; background: var(--toz-plyta); border: 1px solid var(--toz-border);
               border-radius: 6px; box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
               max-height: 260px; overflow-y: auto; }
.mapa-wynik { display: block; width: 100%; padding: 7px 10px; border: 0; background: none;
              text-align: left; font: inherit; color: var(--toz-text); cursor: pointer; }
.mapa-wynik:hover, .mapa-wynik.wybrany, .mapa-wynik:focus-visible { background: var(--toz-granat-jasny); }
.mapa-wynik-opis { display: block; font-size: .8rem; color: var(--toz-muted); }
.mapa-wynik-brak { padding: 7px 10px; font-size: .875rem; color: var(--toz-muted); }
/* Adres wpisany dokladnie tak, jak stoi w rejestrze. To POTWIERDZENIE, nie brak -
   cisza w tym miejscu znaczylaby dokladnie odwrotna wiadomosc. */
.adres-potwierdzony { padding: 7px 10px; font-size: .875rem; color: var(--toz-ok); }
/* Propozycje pod adresem od AI z maila (05.11.2026) - stoją w treści karty, nie unoszą się nad nią: nikt w tym polu
   nie pisze, a lista ma być widać od razu. Wygląd jak pozycje podpowiedzi, bo kliknięcie robi to samo. */
.adres-propozycje { list-style: none; margin: 4px 0 0; padding: 0; border: 1px solid var(--toz-border); border-radius: 6px;
                    background: var(--toz-plyta); overflow-wrap: anywhere; }
.adres-sprawdz p { margin: 0; }
/* Wspolrzedne na miare liczb ("50.667985, 17.927076"): pole na cala szerokosc
   karty rozciagalo dwadziescia znakow na metr ekranu.
   Trzy klasy w selektorze, bo ogolne .form-control ustawia szerokosc calej
   kolumny - wygrywamy waga, a nie kolejnoscia w pliku. */
.gps-wiersz { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; }
.gps-wiersz .form-control.pole-gps { flex: 0 0 auto; width: 24ch; max-width: 100%; font-variant-numeric: tabular-nums; }

/* Gdzie to jest - linijka pod polem "Adres": gmina, wojewodztwo, odleglosc od
   siedziby oddzialu. Przy wspolrzednych wygladala na opis liczb; pod adresem
   opisuje miejsce, czyli to, o co czlowiek pyta, planujac wyjazd. Osobny wiersz
   pod polem, wiec zawijanie na telefonie robi sie samo. */
.adres-polozenie { display: flex; flex-wrap: wrap; gap: 2px 14px; margin: 4px 0 0; font-size: .875rem;
                   color: var(--toz-muted); font-variant-numeric: tabular-nums; }
.mapa-scena { position: relative; }
.mapa-punktu { position: relative; margin-top: 8px; border: 1px solid var(--toz-border); border-radius: 8px; overflow: hidden; }
.mapa-plotno { position: relative; height: 320px; background: #e8eef3; cursor: grab;
               touch-action: pan-y; overflow: hidden; }
/* Podpowiedź pokazywana, gdy ktoś próbuje przesunąć mapę jednym palcem. */
.mapa-dotyk { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
              background: rgba(35, 38, 47, .65); color: #fff; font-size: .95rem; text-align: center;
              padding: 16px; pointer-events: none; opacity: 0; transition: opacity .15s; }
.mapa-dotyk.widoczna { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .mapa-dotyk { transition: none; } }
.mapa-plotno.ciagniemy { cursor: grabbing; }
.mapa-plotno img { position: absolute; width: 256px; height: 256px; user-select: none; pointer-events: none; }
/* Pin: kropka z nóżką. Ten sam znak stoi na mapie zbiorczej (.pin) - jedna
   definicja, żeby nie rozjechały się przy najbliższej poprawce. Nóżka kończy
   się dokładnie na współrzędnych, główka siedzi nad nią.
   Barwę niesie zmienna, więc każdy z nich ustawia swoją jednym wierszem. */
.mapa-pin, .pin { position: absolute; width: 2px; height: 22px; margin: -22px 0 0 -1px;
    background: var(--pin-barwa); }
.mapa-pin::before, .pin::before { content: ''; position: absolute; left: -6px; top: -12px;
    width: 14px; height: 14px; border-radius: 50%; background: var(--pin-barwa);
    border: 2px solid #fff; box-sizing: border-box; }

/* Na karcie interwencji pinezka stoi zawsze na środku płótna i jest ozdobą -
   klika się mapę pod nią. */
.mapa-pin { left: 50%; top: 50%; --pin-barwa: var(--toz-blad); pointer-events: none; }
.mapa-sterowanie { position: absolute; right: 8px; top: 8px; display: flex; flex-direction: column; gap: 4px; }
.mapa-sterowanie .btn { background: #fff; min-width: 32px; }
/* Mapa interwencji i organizacji: obok + i − cztery strzałki przesuwania, w dwóch kolumnach - jednym dotknięciem,
   bez przeciągania (audyt 23.10.2026, T18). */
.mapa-sterowanie-pelne { display: grid; grid-template-columns: repeat(2, auto); }
.mapa-stopka { display: flex; justify-content: space-between; gap: 12px; margin: 0;
    padding: 4px 8px; font-size: .78rem; background: var(--toz-bg); border-top: 1px solid var(--toz-border);
    font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .mapa-plotno { height: 240px; } }



/* --- Wydruk ---------------------------------------------------------------
   Ewidencja bywa drukowana do segregatora albo dla ksiegowej. Na papierze
   nie ma sensu nawigacja, filtry ani przyciski - liczy sie sama tabela
   i to, czego dotyczy. */
@media print {
    /* Mapa na papierze to prostokąt kafelków i dwa przyciski, których nie da
       się nacisnąć. Współrzędne drukują się osobno, w polu wyżej. */
    .topbar, .footer, .filters, .filters-action, .przelaczniki, .szybkie,
    .dodanie-faktury, .pager, .ustawienie-strony, .ustawienia-listy, .kol-akcje, .pasek-zapisu,
    .alert, .mapa-punktu, .breadcrumb-srodek, .breadcrumb-dol { display: none !important; }

    body { background: #fff; font-size: 11pt; }
    .container, .main { padding: 0; max-width: none; }
    .card { border: 0; box-shadow: none; padding: 0; margin: 0 0 12pt; }
    .table-wrap { overflow: visible; }
    .table-ewidencja { font-size: 8.5pt; }
    .table-ewidencja th { position: static; border-bottom: 1pt solid #000; color: #000; }
    /* Na papierze naglowek i tak jest czarna kreska, a kolorowe tlo zjada tusz.
       Osobna regula, NIE doklejona do ".table th, .table td" nizej: tlo na
       komorce zamalowaloby barwy stanow wierszy. */
    .table th { background: #fff; box-shadow: none; }
    /* Pasek z kopia naglowka jest dla ekranu. Na papierze drukuje sie prawdziwy
       naglowek, a tabela wraca na swoje miejsce - bez podjazdu pod pasek
       (margin-top wpisany przez naglowek-tabeli.js). */
    .naglowek-kopia { display: none !important; }
    .tabela-z-naglowkiem > .table-wrap-ewidencja { margin-top: 0 !important; }
    .table th, .table td { padding: 3pt 4pt; }
    .table tbody tr { page-break-inside: avoid; }

    /* Na papierze nie da sie przewinac pola - opis obciety na dziewiatej
       linii wyglada jak komplet i nikt nie zauwaza, ze czegos brakuje. */
    textarea.form-control, .pole-opis .form-control, .pole-opis-duze .form-control {
        min-height: 0;
        height: auto;
        overflow: visible;
        border: 1px solid #999;
        white-space: pre-wrap;
        page-break-inside: auto;
    }
    thead { display: table-header-group; }   /* naglowek powtarza sie na kazdej stronie */
    a { color: #000; text-decoration: none; }
    .kafelek { break-inside: avoid; }
}

.dodaj-zalacznik { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 16px; }

/* --- Przeciaganie plikow --------------------------------------------------
   Strefa jest widoczna od razu (przerywana ramka), a nie dopiero w trakcie
   przeciagania: inaczej nikt sie nie domysli, ze da sie tu cokolwiek upuscic. */
.strefa-zrzutu {
    position: relative;
    border: 2px dashed var(--toz-border);
    border-radius: var(--toz-promien);
    padding: 12px;
    margin-bottom: 16px;
}
/* Przejście tylko dla tych, którzy ruchu nie wyłączyli (audyt 04.10.2026, F50). */
@media (prefers-reduced-motion: no-preference) {
    .strefa-zrzutu { transition: border-color .12s, background-color .12s; }
}
.strefa-zrzutu .dodaj-zalacznik { margin-bottom: 0; }
.strefa-zrzutu-aktywna { border-color: var(--toz-granat); background: var(--toz-granat-jasny); }
/* Dziecko strefy nie moze przechwycic zrzutu - inaczej upuszczenie prosto
   na przycisk "Dolacz" trafia w niego, a nie w strefe. */
.strefa-zrzutu-aktywna * { pointer-events: none; }
.zrzut-meldunek { margin: 8px 0 0; color: var(--toz-granat-ciemny); font-weight: 600; }

/* --- Paczka do przekazania ------------------------------------------------ */
.paczka-pasek { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 8px 0 0; }
.paczka-pasek .muted { max-width: 46ch; }

/* Suma kontrolna w calosci, nie w skrocie.
   Skrot z dymkiem wygladal schludniej, ale sluzy do przepisania na papier
   albo do porownania z tym, co przysle druga strona - a wtedy potrzeba
   wszystkich 64 znakow, nie pierwszych szesnastu.

   user-select: all - jedno klikniecie zaznacza cala sume, bez celowania
   w jej poczatek i koniec. Lamanie w dowolnym miejscu, bo to jeden dlugi
   ciag bez spacji i inaczej rozpycha kafelek. */
.suma-kontrolna {
    display: block;
    margin-top: 4px;
    font-size: .7rem;
    line-height: 1.35;
    color: var(--toz-muted);
}
/* PDF z aktywna trescia na karcie (audyt 01.11.2026, Q53) - plik zostaje, zdanie mowi, zeby otwierac go ostroznie. */
.uwaga-pliku { display: block; margin-top: 4px; font-size: .8125rem; line-height: 1.35; color: var(--toz-uwaga); }
/* Sprawdzenie zdjecia interwencji (wlasciciel, 29.10.2026: "ten komunikat jest za dlugi (...) Daj to moze do tooltip
   i cos pokombinuj z tymi przyciskami"): w kafelku sama plakietka (pelny opis w dymku) albo przycisk "Sprawdz zdjecie",
   szczegoly i przyciski w okienku (atrybut popover - bez skryptu; display tylko przy otwartym, inaczej regula
   wygladu przykrylaby schowanie z przegladarki i okienko stalo na stronie). */
.sprawdzenie-zdjecia { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 4px; }
.sprawdzenie-szczegoly { min-height: 0; padding: 2px 4px; font-size: .8125rem; }
/* Suma kontrolna w okienku zdjecia (wlasciciel, 29.10.2026) - cala, jednym kliknieciem zaznaczona, jak w kafelku. */
.suma-kontrolna-kod { display: block; font-size: .75rem; overflow-wrap: anywhere; word-break: break-all; user-select: all; }
.sprawdzenie-plakietka { border: 0; font: inherit; font-size: .75rem; font-weight: 600; cursor: pointer; line-height: 1.5; }
.sprawdzenie-plakietka:hover { text-decoration: underline; }
.okno-sprawdzenia {
    border: 0; border-radius: var(--toz-promien); padding: 20px;
    width: min(460px, calc(100% - 32px)); max-height: calc(100vh - 32px); max-height: calc(100svh - 32px); overflow: auto;
    background: var(--toz-plyta); color: var(--toz-text);
    box-shadow: 0 12px 40px rgba(35, 38, 47, .28);
}
.okno-sprawdzenia::backdrop { background: rgba(26, 38, 82, .42); }
.okno-sprawdzenia-tytul { margin: 0 0 12px; font-size: 1rem; font-weight: 600; overflow-wrap: anywhere; }
.okno-sprawdzenia-tytul .muted { display: block; font-weight: 400; font-size: .8125rem; }
.okno-sprawdzenia-fakty { margin: 0 0 12px; display: grid; gap: 8px; }
.okno-sprawdzenia-fakty dt { font-size: .75rem; font-weight: 600; color: var(--toz-muted); text-transform: uppercase; letter-spacing: .04em; }
.okno-sprawdzenia-fakty dd { margin: 2px 0 0; line-height: 1.45; }
.okno-sprawdzenia .hint { margin: 0 0 16px; }
.okno-sprawdzenia-przyciski { display: flex; flex-wrap: wrap; gap: 8px; }
.okno-sprawdzenia-przyciski form { margin: 0; }
.okno-sprawdzenia-przyciski > .btn:last-child { margin-left: auto; }
/* Poczekalnia - poczta oddzialu (wlasciciel, 30.10.2026): stan skrzynki z "Sprawdz teraz", propozycja nad przyciskami,
   tresc maila jako zwykly tekst z zachowanymi liniami (zawija sie, zeby strona nie uciekala w bok na telefonie). */
.poczekalnia-stan { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.poczekalnia-stan ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.poczekalnia-pominiete { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin: 12px 0 0; }
.poczekalnia-pominiete > span { flex: 1 1 20em; min-width: 0; }
.poczekalnia-propozycja { margin: 0 0 12px; padding: 10px 14px; border-left: 4px solid var(--toz-granat); border-radius: 6px;
    background: var(--toz-granat-jasny); }
/* Powód przy raporcie o niedoręczeniu niesie adres w masce (0261), a domena bez łącznika nie miałaby gdzie się złamać: bez zawijania tekst wychodził poza kartę. */
.poczekalnia-propozycja p { margin: 0; overflow-wrap: anywhere; }
.poczekalnia-propozycja .hint { margin-top: 4px; }
.poczekalnia-czynnosci { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 16px; }
.poczekalnia-czynnosci form { margin: 0; }
.poczekalnia-dolacz, .poczekalnia-pomin { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
    padding: 10px 12px; border: 1px solid var(--toz-border); border-radius: 6px; }
.poczekalnia-dolacz .label { margin: 0; }
.poczekalnia-dolacz { flex: 1 1 100%; min-width: 0; }
.poczekalnia-dolacz .pole { flex: 1 1 100%; min-width: 0; }
.poczekalnia-dolacz .form-control { width: 100%; max-width: 100%; }
.poczekalnia-tryb, .poczekalnia-adres { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; margin: 12px 0 0; }
.poczekalnia-tryb > div, .poczekalnia-adres > div { min-width: 0; max-width: 100%; }
.poczekalnia-tryb .hint { flex-basis: 100%; margin: 0; }
/* "Ustawienia poczty" na dole listy maili (12.11.2026): jedna zwijana część, stan w nagłówku zwykłym pismem, przy kilku oddziałach grupy
   pod nazwą oddziału. Po zapisie lista wraca tu kotwicą (część otwiera zwin.js), więc komunikat z góry strony idzie za ekranem. */
.ustawienia-poczty-stan { margin-left: 6px; font-weight: 400; }
.ustawienia-poczty > .hint { margin: 8px 0 0; }
.ustawienia-poczty-oddzial > .h5 { margin: 16px 0 0; }
.ustawienia-poczty-oddzial + .ustawienia-poczty-oddzial { margin-top: 16px; border-top: 1px dashed var(--toz-border); }
.main:has(#ustawienia-poczty:target) > .alert { position: sticky; top: calc(var(--toz-belka-wysokosc, 0px) + 8px); z-index: 5; }
@media (max-width: 640px) {
    /* Telefon: pola na całą szerokość, długie opcje trybu AI ucinają się w polu zamiast wypychać stronę w bok. */
    .ustawienia-poczty .poczekalnia-tryb > div { flex: 1 1 100%; }
    .ustawienia-poczty select.form-control { min-width: 0; max-width: 100%; text-overflow: ellipsis; }
}
.poczekalnia-dolacz .hint, .poczekalnia-pliki { flex-basis: 100%; margin: 0; }
.poczekalnia-pliki { border: 0; padding: 0; display: grid; gap: 4px; }
.poczekalnia-naglowki { margin: 0 0 12px; display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; }
.poczekalnia-naglowki > div { display: contents; }
.poczekalnia-naglowki dt { font-weight: 600; color: var(--toz-muted); }
.poczekalnia-naglowki dd { margin: 0; overflow-wrap: anywhere; }
.tresc-maila { margin: 0 0 12px; padding: 12px 14px; max-width: 100%; white-space: pre-wrap; overflow-wrap: anywhere;
    font: inherit; line-height: 1.5; background: var(--toz-bg); border: 1px solid var(--toz-border); border-radius: 6px; }
.poczekalnia-zalaczniki { margin: 0; padding-left: 20px; display: grid; gap: 4px; overflow-wrap: anywhere; }
.poczekalnia-do-sprawy p { margin: 0 0 8px; }
.poczekalnia-do-sprawy .poczekalnia-pliki, .poczekalnia-do-sprawy > .przelacznik { margin: 0 0 8px; }
.poczekalnia-ai { margin: 0 0 10px; padding: 8px 12px; border-radius: 6px; background: var(--toz-plyta); border: 1px solid var(--toz-border); }
.poczekalnia-ai p { margin: 0 0 6px; }
.poczekalnia-ai-lista { margin: 0 0 6px; padding-left: 20px; display: grid; gap: 4px; overflow-wrap: anywhere; }
.poczekalnia-tresc summary { cursor: pointer; font-weight: 600; margin: 4px 0 8px; }
.poczekalnia-tresc .tresc-maila { background: var(--toz-plyta); }
/* Maile sprawy jeden pod drugim (wlasciciel, 01.11.2026): tekst zawija sie bez wlasnego paska przewijania, mail od nas wyroznia
   tylko barwa marki, a blok bez wlasnego tekstu jest nizszy. Ostrzezenie zostaje na ekranie po powrocie na mail w polowie strony. */
.rozmowa-mail { padding-top: 14px; padding-bottom: 14px; margin-bottom: 14px; overflow-wrap: anywhere; }
.rozmowa-mail-od-nas { border-left: 4px solid var(--toz-granat); }
.rozmowa-mail-od-nas .rozmowa-kierunek { color: var(--toz-granat); font-weight: 600; }
.rozmowa-mail-krotki { padding-top: 8px; padding-bottom: 8px; }
.rozmowa-mail p { margin: 0 0 6px; }
.rozmowa-naglowek { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-bottom: 6px; }
.rozmowa-kierunek { color: var(--toz-muted); }
.rozmowa-metryczka { display: flex; flex-wrap: wrap; gap: 0 16px; color: var(--toz-muted); }
.rozmowa-temat { color: var(--toz-muted); }
.rozmowa-tekst { margin: 8px 0; white-space: pre-wrap; line-height: 1.5; }
.rozmowa-mail .poczekalnia-czynnosci { gap: 8px 12px; margin-top: 8px; }
/* Cytat maila spoza systemu (07.11.2026, właściciel: "Wygląda na to że urzytkownik sam sobie odpisał, ale u nas tego nie widać") i cytaty w pełnym tekście karty: kreska z lewej
   w przygaszonym granacie i przygaszony nagłówek. Złota kreska z lewej to znak "tu wróciłeś", a granatowa 4px - mail od nas, więc tu cieńsza i jaśniejsza. Kreska ok. 3:1
   do tła, a treść cytatu zwykłą barwą (przegląd 07.11.2026: pod samym podpisem cały cytat to sprawa - nie może wyglądać na drugorzędny). */
.cytat-maila { margin: 8px 0; padding: 2px 0 2px 12px; border-left: 3px solid #7a8ab5; overflow-wrap: anywhere; }
.cytat-maila-uwaga.cytat-maila-nad { margin: 8px 0 0; }
.cytat-maila-nad + .cytat-maila { margin-top: 4px; }
.cytat-maila > summary { cursor: pointer; color: var(--toz-granat); font-weight: 600; }
.cytat-maila-zwiniety[open] > summary { margin-bottom: 6px; }
.cytat-maila-naglowek { margin: 0 0 4px; color: var(--toz-muted); font-size: .875rem; }
.cytat-maila-uwaga { display: block; margin: 0 0 6px; color: var(--toz-granat-ciemny); font-weight: 600; }
.cytat-maila .rozmowa-tekst { margin: 0; }
.tresc-maila-tekst { display: block; }
.cytat-maila-blok { display: block; margin: 6px 0; padding-left: 10px; border-left: 3px solid #7a8ab5; }
/* Rozmowa z tą osobą pod kartą maila (właściciel, 02.11.2026): zwinięta to zwykła karta z napisem, a maile po rozwinięciu stoją jak w mailach sprawy. */
.rozmowa-osoby > summary { padding-top: 14px; padding-bottom: 14px; margin-bottom: 14px; cursor: pointer; }
.rozmowa-osoby > summary h2 { display: inline; margin: 0; }
.rozmowa-osoby > p { margin: 0 0 14px; overflow-wrap: anywhere; }
/* Karta maila otwarta z interwencji (wlasciciel, 02.11.2026): sprawa nad odpowiedzia, a w mailach sprawy pod karta obwodka przy otwartym mailu. */
.rozmowa-mail-ten { outline: 2px solid var(--toz-granat); outline-offset: -2px; }
/* Nowy mail w rozmowie z tą osobą (właściciel, 06.11.2026: "tylko nieprzeczytane maile można jakoś specjalnie podświetlić, aby pokazać, że są nowe"): barwy marki -
   złota obwódka dookoła i jasne złoto w tle, plakietka "nowy" w granacie (.stan-nowy niżej, za .stan). Bez złotej kreski z lewej, bo to znak "tu wróciłeś", a mail od nas ma już kreskę
   granatu z lewej. Kolor bloku mówi tylko o jego stanie. To samo złoto w zdaniu u góry karty, które mówi, ile takich maili stoi niżej. */
.rozmowa-mail-nowy { background-color: #fbf5e7; border-color: var(--toz-zloto); box-shadow: 0 0 0 1px var(--toz-zloto); }
.mail-nowe-w-rozmowie { margin: 0 0 12px; padding: 8px 12px; border: 1px solid var(--toz-zloto); border-radius: 6px; background: #fbf5e7;
    color: var(--toz-granat-ciemny); font-weight: 600; overflow-wrap: anywhere; }
.mail-nowe-w-rozmowie a { color: inherit; }
.sprawa-maila { margin: 0 0 12px; padding: 10px 14px; border-left: 4px solid var(--toz-granat); border-radius: 6px; background: var(--toz-granat-jasny);
    overflow-wrap: anywhere; scroll-margin-top: calc(var(--toz-belka-wysokosc, 0px) + 8px); }
.sprawa-maila h2 { margin: 0 0 6px; }
.sprawa-maila-pole { margin: 10px 0 2px; font-size: .875rem; font-weight: 600; }
.sprawa-maila .rozmowa-tekst { margin: 0; }
.sprawa-maila .hint { margin: 0; }
.main:has(.rozmowa-mail) > .alert-warning, .main:has(.rozmowa-mail) > .alert-danger, .main:has(.rozmowa-mail) > .alert-success { position: sticky; top: calc(var(--toz-belka-wysokosc, 0px) + 8px); z-index: 5; }
/* Lista maili po flagowaniu z menu w wierszu wraca do tego wiersza, więc komunikat stojący u góry zostałby poza ekranem. Sukcesu nie trzeba, bo kolor widać w wierszu, a ostrzeżenie i "czeka na skrzynkę" idą za ekranem. */
.main:has(#maile-flaga-wiersza) > .alert-warning, .main:has(#maile-flaga-wiersza) > .alert-danger, .main:has(#maile-flaga-wiersza) > .alert-info { position: sticky; top: calc(var(--toz-belka-wysokosc, 0px) + 8px); z-index: 5; }
/* Czynność z listy maili (12.11.2026: usunięcie, przeniesienie, zaznaczone hurtem): strona wraca tam, gdzie była (ulatwienia.js, cz. 4b - listy
   z data-na-miejscu), więc komunikat o wyniku - każdy, także błąd - stoi pod belką menu, a na telefonie przy górze ekranu. Znak na treści stawia skrypt
   tylko po takim powrocie; on też układa kilka komunikatów jeden pod drugim i stawia pasek z nazwami kolumn tabeli pod nimi. Bez skryptu jak dotąd. */
.main[data-komunikat-przyklejony] > .alert[role="alert"] { position: sticky; top: calc(var(--toz-belka-wysokosc, 0px) + 8px); z-index: 5; }
.main[data-komunikat-przyklejony] .tabela-z-naglowkiem > .naglowek-kopia { top: calc(var(--toz-belka-wysokosc, 0px) + var(--toz-komunikaty-wysokosc, 0px)); }
/* Krzyżyk zamyka komunikat po działaniu (właściciel 12.11.2026; ulatwienia.js, cz. 4c): ten sam przycisk co w dymkach i w pasku o wylogowaniu.
   Klasę komunikatowi i przycisk dokłada skrypt, znak rysuje arkusz - treść komunikatu zostaje, jaka była. Niska waga reguły: komunikat przyklejony
   pod belką (reguły wyżej) zostaje przyklejony. Na wydruku krzyżyka nie ma. */
.alert-zamykany { position: relative; padding-right: 52px; }
.alert-zamknij { top: 5px; right: 6px; color: inherit; opacity: .75; }
.alert-zamknij::before { content: "\00d7"; }
.alert-zamknij:hover, .alert-zamknij:focus-visible { opacity: 1; }
@media print { .alert-zamknij { display: none; } }
.suma-etykieta {
    display: inline-block;
    margin-right: 4px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    font-size: .62rem;
}
.suma-kontrolna code {
    user-select: all;
    overflow-wrap: anywhere;
    letter-spacing: .01em;
    background: #f4f5f8;
    border: 1px solid var(--toz-border);
    border-radius: 5px;
    padding: 0 4px;
}
.strefa-zrzutu-podpis { margin: 0 0 8px; color: var(--toz-muted); font-size: .8125rem; }

/* --- Podglad zalacznika ---------------------------------------------------
   Element <dialog> daje uwiezienie ogniska, Escape i tlo za darmo - recznie
   pisany "modal" musialby to wszystko odtwarzac i zwykle odtwarza zle. */
.podglad {
    width: min(1100px, 94vw);
    max-width: none;
    height: min(88vh, 900px);
    padding: 0;
    border: 1px solid var(--toz-border);
    border-radius: var(--toz-promien);
    background: var(--toz-plyta);
    color: var(--toz-text);
    box-shadow: 0 12px 40px rgba(35, 38, 47, .28);
    overflow: hidden;
}
/* Wąski pas strony za oknem podglądu - ta sama granatowa szyba co za oknem pytania (27.10.2026, grafika nr 14). */
.podglad::backdrop { background: rgba(18, 27, 58, .62); }
.podglad-pasek {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--toz-border);
    background: var(--toz-plyta);
}
.podglad-nazwa { font-weight: 600; margin-right: auto; overflow-wrap: anywhere; }
/* Przeskakiwanie miedzy plikami: "1 z 12" miedzy przyciskami, liczby rownej
   szerokosci, zeby przyciski nie skakaly przy przejsciu z 9 na 10. */
.podglad-licznik { font-variant-numeric: tabular-nums; min-width: 5ch; text-align: center; font-size: .875rem; }
/* Okno to kolumna: pasek ma tyle wysokości, ile potrzebuje (na telefonie dwa rzędy), scena bierze resztę -
   dawniej sztywne "100% - 57px" spychało zdjęcie poza okno, gdy pasek urósł (audyt 04.10.2026, F02). */
.podglad[open] { display: flex; flex-direction: column; }
/* Zdjęcie leży na głębokim granacie z miękkim spadkiem (jaśniej za środkiem zdjęcia, ciemniej przy brzegach), a nie
   na prawie czarnym - zwierzak ładniej się na nim odcina (właściciel, 27.10.2026, grafika nr 14). */
.podglad-scena {
    display: flex; align-items: center; justify-content: center;
    flex: 1 1 auto; min-height: 0;
    background: radial-gradient(120% 95% at 50% 38%, #26355f 0%, #18213f 58%, #0f152c 100%);
}
/* Zdjecie ma sie zmiescic w calosci, a nie byc przycietym kadrem - podglad
   sluzy do obejrzenia, nie do ozdoby. */
.podglad-scena img, .podglad-scena video { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Zdjęcie przesuwa się palcem w bok (p. 40, podglad-plikow.js); pionowe przewijanie i powiększanie dwoma palcami zostają. */
.podglad-scena img { touch-action: pan-y pinch-zoom; }
.podglad-scena iframe { width: 100%; height: 100%; border: 0; background: #fff; }
.podglad-brak { color: #e7e9f0; padding: 24px; text-align: center; }

@media (max-width: 640px) {
    .podglad { width: 100vw; height: 100vh; border-radius: 0; border: 0; }
    /* Nazwa pliku w osobnym rzędzie, przyciski pod nią - "Zamknij" zawsze na ekranie, przy prawej krawędzi. */
    .podglad-pasek { flex-wrap: wrap; gap: 8px; padding: 8px 12px; }
    .podglad-nazwa { flex-basis: 100%; margin-right: 0; }
    .podglad-dopisek { display: none; }
    .podglad-zamknij { margin-left: auto; }
}
/* min-width: 0 - pole pliku ma wlasna, szeroka miare ("Wybierz pliki Nie
   wybrano pliku"), a element flex nie schodzi ponizej niej sam z siebie. Na
   telefonie pole wystawalo przez to poza ramke strefy zrzutu. */
.dodaj-zalacznik .form-control { flex: 1 1 260px; width: auto; min-width: 0; max-width: 100%; }
/* Opis pod polem nie moze kleic sie do ramki pustego stanu pod nim. */
.hint + .pusto { margin-top: 16px; }

/* Puste stany: widoczne, ze to stan, a nie brakujaca tresc. */
.pusto {
    margin: 0;
    padding: 28px 16px;
    text-align: center;
    color: var(--toz-muted);
    border: 1px dashed var(--toz-border);
    border-radius: var(--toz-promien);
    background: #fafbfd;
}
.pusto .btn { margin-top: 12px; }

/* Termin po czasie: kolor plus slowo - na wydruku i dla czytnika ekranu
   sam kolor nie niesie zadnej informacji. */
.znacznik-terminu {
    display: block;
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--toz-blad);
}
.przelaczniki { border: 0; padding: 0; margin: 4px 0 0; }
.przelaczniki > legend { padding: 0; }

/* Odnosnik pomijajacy nawigacje - widoczny dopiero, gdy ktos na niego trafi
   klawiszem Tab. Dla osoby uzywajacej klawiatury to roznica miedzy jednym
   a kilkunastoma nacisnieciami przy kazdym przejsciu miedzy stronami. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 8px;
    z-index: 100;
    padding: 10px 16px;
    background: var(--toz-plyta);
    color: var(--toz-granat-ciemny);
    border: 2px solid var(--toz-granat);
    border-radius: 8px;
    font-weight: 600;
}
.skip-link:focus { left: 8px; }
#tresc:focus { outline: none; }

/* --- Wybor oddzialow -------------------------------------------------------
   Oddzialow jest ponad piecdziesiat, wiec lista musi sie miescic w ekranie
   i dac przeszukac. */
.wybor-oddzialow { border: 0; padding: 0; margin: 16px 0 0; }
.wybor-oddzialow > legend { padding: 0; }
.oddzial-wszystkie { padding: 8px 10px; border: 1px solid var(--toz-border); border-radius: 8px; background: #fff; }
.oddzialy-narzedzia { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 10px 0 8px; }
.oddzialy-narzedzia .form-control { flex: 1 1 220px; width: auto; max-width: 320px; }
.oddzialy {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 2px 12px;
    max-height: 260px;
    overflow-y: auto;
    padding: 8px;
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    background: #fff;
}
.oddzialy-wygaszone { opacity: .45; pointer-events: none; }

/* --- Wybor uprawnien (helpers.php: wybor_uprawnien) ---------------------------
   Wlasciciel (16.09.2026): pojedyncze uprawnienia zaznacza sie po kilka naraz.
   Kilkadziesiat pozycji w kilkunastu modulach - ramka z wyszukiwaniem, jak przy
   oddzialach, zeby formularz nie rozciagal sie na kilka ekranow. */
.wybor-uprawnien { border: 0; padding: 0; margin: 16px 0 0; min-width: 0; }
.wybor-uprawnien > legend { padding: 0; }
.uprawnienia-lista {
    max-height: 320px;
    overflow-y: auto;
    padding: 4px 12px 8px;
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    background: #fff;
}
.uprawnienia-modul + .uprawnienia-modul { margin-top: 6px; border-top: 1px solid var(--toz-border); }
.uprawnienia-modul-nazwa { margin: 8px 0 0; font-weight: 600; font-size: .9rem; color: var(--toz-granat-ciemny); }
/* Dwie grupy w jednej ramce - "do dołożenia" i "do zabrania" (właściciel,
   19.09.2026). Skrypt pokazuje jedną naraz; bez skryptu obie, z podpisami. */
.uprawnienia-grupa { margin: 10px 0 2px; font-weight: 700; font-size: .85rem; text-transform: uppercase; letter-spacing: .02em; color: var(--toz-szary-tekst, #555); }
[data-grupa] + [data-grupa] { margin-top: 10px; padding-top: 8px; border-top: 2px solid var(--toz-border); }

/* --- Nowe konto, krok 2 (admin/nowe-konto.php) -----------------------------
   Wlasciciel (17.09.2026): zaproszenie wychodzi dopiero po wybraniu pakietow.
   Pakietow jest kilkanascie, wiec lista bez wlasnego paska przewijania. */
.pakiety-lista {
    display: grid;
    gap: 2px;
    padding: 4px 12px;
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    background: #fff;
}
.pakiety-lista .uprawnienie + .uprawnienie { border-top: 1px solid var(--toz-border); }
.lista-nowych-kont { margin: 8px 0 0; padding-left: 20px; }
.lista-nowych-kont li { padding: 2px 0; }

/* --- Filtry ewidencji: zwarcie ---------------------------------------------
   Glowna trescia strony jest tabela, wiec formularz filtrow ma zajmowac
   tyle miejsca, ile naprawde potrzebuje - nie wiecej. */
.karta-filtrow { padding: 14px clamp(14px, 1.6vw, 20px); }
.karta-filtrow .card-head { padding-bottom: 8px; margin-bottom: 12px; }
.karta-filtrow h1.h4 { font-size: 1.35rem; margin-bottom: 2px; }

.filters-zwarte { grid-template-columns: repeat(auto-fit, minmax(136px, 1fr)); gap: 8px 10px; }
.filters-zwarte .label {
    margin: 0 0 2px;
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--toz-muted);
}
.filters-zwarte .form-control { min-height: 34px; padding: 5px 8px; font-size: .9rem; }
.filters-zwarte .filters-action { margin-top: 6px; gap: 8px 16px; }
.filters-zwarte .przelaczniki { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.filters-zwarte .przelacznik { padding: 3px 9px; font-size: .82rem; }

/* Kolumny, ktore rozpychala nie tresc, tylko dlugi naglowek albo jeden
   nietypowy wpis. Tabela ma sie miescic w typowym oknie bez przewijania. */
.table-ewidencja th.liczba, .table-ewidencja td.liczba { max-width: 96px; }
/* Kwoty nie moga sie lamac, ale ich naglowki juz tak - inaczej "Kwota z 1,5%"
   rozpycha kolumne szeroka na dwie liczby. */
.table-ewidencja th.liczba { white-space: normal; }
/* Klasy kolumn, a nie atrybuty data-pole: te nosila dawna poprawka w wierszu
   i zniknely razem z nia (13.09.2026). */
.table-ewidencja td.kol-numer { max-width: 140px; overflow-wrap: anywhere; }
.table-ewidencja td.kol-sprawa,
.table-ewidencja td.kol-od-kogo,
.table-ewidencja td.kol-zwrot { max-width: 170px; }
/* Wybor daty jest krotki - nie potrzebuje takiej samej kolumny jak pola tekstowe. */
.filters-zwarte .filtr-daty { min-width: 130px; }

/* ---------------------------------------------------------------------------
   Interwencje
   --------------------------------------------------------------------------- */

/* Plakietka stanu. Kolor tylko wzmacnia nazwe - nigdy jej nie zastepuje,
   bo przy wydruku i dla osoby nierozrozniajacej barw zostaje sam tekst. */
.stan {
    display: inline-block;
    padding: 1px 8px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: .82rem;
    line-height: 1.5;
    white-space: nowrap;
}

/* Plakietka, ktora ma krzyczec: pelna czerwien, bialy pogrubiony napis
   wielkimi literami. Brak dokumentow przy sprawie (wlasciciel, 24.09.2026:
   "bardziej podkresl brak dokumentow") - blada czerwona plakietka ginela na
   wierszu pokolorowanym na czerwono stanem u nas ("Nowe"). */
.stan-alarm {
    background: var(--toz-blad);
    border-color: var(--toz-blad);
    color: #fff;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}
/* "Brak" dokumentow na liscie interwencji mowi po najechaniu, kto
   interweniowal i kiedy (wlasciciel, 24.09.2026) - interwencje-kto-i-kiedy.js.
   Dymek stoi w miejscu ekranu: nad belka z menu (30), pod rozwijanymi
   menu (40). Kursor ze znakiem zapytania zdradza, ze jest co przeczytac. */
[data-kto-i-kiedy] { cursor: help; }
.dymek-kto-kiedy {
    position: fixed;
    z-index: 35;
    max-width: min(320px, calc(100vw - 16px));
    padding: 8px 10px;
    background: var(--toz-plyta);
    color: var(--toz-text);
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
    font-size: .85rem;
    line-height: 1.45;
}
.dymek-kto-kiedy p { margin: 0; }
.dymek-kto-kiedy .dymek-kto-kiedy-tytul { margin-bottom: 4px; font-weight: 600; }
.dymek-kto-kiedy-podpis, .dymek-kto-kiedy-drobne { color: var(--toz-muted); }
/* Dymek pokazywany od razu (dymek.js, atrybut data-dymek) - dzis nad znaczkiem
   Facebooka na liscie podopiecznych: kiedy opublikowano post (wlasciciel,
   28.09.2026: "ten dymek musi sie pojawiac natychmiast"). Bez przejsc i bez
   opoznienia; myszka przechodzi przez niego, wiec nie zaslania klikniecia. */
.dymek-od-razu {
    position: fixed;
    z-index: 35;
    max-width: min(300px, calc(100vw - 16px));
    padding: 6px 10px;
    background: var(--toz-plyta);
    color: var(--toz-text);
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
    font-size: .85rem;
    line-height: 1.45;
    text-align: center;
    pointer-events: none;
}
.dymek-od-razu p { margin: 0; }
.dymek-od-razu .dymek-od-razu-tytul { font-weight: 600; }
.dymek-od-razu .dymek-od-razu-drobne { color: var(--toz-muted); font-size: .78rem; }
.stan-szary     { background: #eef0f4; border-color: #d8dce4; color: #41465a; }
.stan-zielony   { background: var(--toz-tlo-ok); border-color: #bcdcc9; color: var(--toz-ok); }
.stan-zolty     { background: var(--toz-tlo-uwaga); border-color: #e8d3a4; color: var(--toz-uwaga); }
.stan-czerwony  { background: var(--toz-tlo-blad); border-color: #eec3c8; color: var(--toz-blad); }
.stan-granatowy { background: var(--toz-granat-jasny); border-color: #c5cfe8; color: var(--toz-granat-ciemny); }
/* Nowy mail w rozmowie z tą osobą (06.11.2026): granat ze złotą obwódką - za .stan, której przezroczysta obwódka inaczej by wygrała. */
.stan-nowy      { background: var(--toz-granat); border-color: var(--toz-zloto); color: #fff; font-weight: 700; }
/* Kazda z tych par przechodzi prog AA (kontrast tekstu do tla powyzej 4.5:1) -
   plakietka ma byc czytelna takze wtedy, gdy kolor nic komus nie mowi. */
.stan-pomaranczowy { background: #fdeee0; border-color: #f0cba6; color: #8a4b00; }
.stan-rozowy       { background: #fceaf2; border-color: #eec3d7; color: #9c2b60; }
.stan-fioletowy    { background: #f2ecfa; border-color: #d5c6ec; color: #5a3b8f; }
.stan-turkusowy    { background: #e2f4f4; border-color: #b3dedd; color: #0f5f60; }
.stan-brazowy      { background: #f2ece5; border-color: #d9c8b4; color: #6b4a2a; }
/* Druga dziesiatka barw (migracja 0084). Kolor maluje teraz caly wiersz listy
   interwencji, wiec barw musi byc WIECEJ niz stanow - kazdy stan ma swoja. */
.stan-morski       { background: #e3eff7; border-color: #b9d3e6; color: #10496e; }
.stan-oliwkowy     { background: #eef1de; border-color: #ccd6a5; color: #4f5a12; }
.stan-sliwkowy     { background: #f1e8f0; border-color: #d5bcd2; color: #6d2a63; }
.stan-piaskowy     { background: #f7f0e2; border-color: #e3d3b0; color: #6f5518; }
.stan-wrzosowy     { background: #ecebf6; border-color: #c8c6e4; color: #45418a; }
.stan-miedziany    { background: #f9ebe3; border-color: #e7c5b0; color: #8a4326; }
.stan-lazurowy     { background: #e3f1fb; border-color: #b6d8f0; color: #0d5480; }
.stan-limonkowy    { background: #ecf5df; border-color: #c9e0a9; color: #3f6413; }
.stan-koralowy     { background: #fdece8; border-color: #f2c4b8; color: #97341f; }
.stan-stalowy      { background: #e9edf1; border-color: #c4ccd6; color: #3b4855; }
/* Dwie barwy flag maili, których nie ma wśród stanów (10.11.2026): kolor flagi w wierszu listy maili wybiera się z listy plakietek
   (w-wierszu.js), każdą w barwie swojej flagi. Próg AA jak wyżej. */
.stan-niebieski    { background: #e6ecfb; border-color: #bccbf0; color: #1e3a8a; }
.stan-blekitny     { background: #e1f1fa; border-color: #afd6ec; color: #075985; }
/* Bialy to nie barwa, tylko jej brak: plakietka zostaje sama obwodka, zeby
   nadal bylo widac, ze to plakietka, a nie luzny napis. */
.stan-bialy        { background: #fff; border-color: var(--toz-border); color: #41465a; }

/* --- Wiersz listy w kolorze NASZEGO stanu --------------------------------
   Po kolorze rozpoznaje sie sprawe rzutem oka na cala liste, bez czytania
   kolumny stanu. Odcien jest znacznie jasniejszy od plakietki: tam kolor
   niesie jedno slowo, tutaj cala linijke tekstu i musi zostac czytelna.

   Plakietka zostaje na swoim miejscu. Kolor wzmacnia nazwe, nigdy jej nie
   zastepuje - na wydruku (tla znikaja) i dla osoby nierozrozniajacej barw
   informacja ma byc w slowie. */
.table tbody tr.wiersz-stan-szary { background: #eef0f4; }
.table tbody tr.wiersz-stan-szary:hover { background: #e5e8ef; }
.table tbody tr.wiersz-stan-zielony { background: var(--toz-tlo-ok); }
.table tbody tr.wiersz-stan-zielony:hover { background: #d9ece2; }
.table tbody tr.wiersz-stan-zolty { background: var(--toz-tlo-uwaga); }
.table tbody tr.wiersz-stan-zolty:hover { background: #f6e9cb; }
.table tbody tr.wiersz-stan-czerwony { background: var(--toz-tlo-blad); }
.table tbody tr.wiersz-stan-czerwony:hover { background: var(--toz-tlo-blad-kursor); }
/* "Alarm" na wierszu to ta sama jasna czerwien co "czerwony" - pelna
   czerwien zostaje przy plakietce, cala linijka w niej bylaby nieczytelna. */
.table tbody tr.wiersz-stan-alarm { background: var(--toz-tlo-blad); }
.table tbody tr.wiersz-stan-alarm:hover { background: var(--toz-tlo-blad-kursor); }
.table tbody tr.wiersz-stan-granatowy { background: var(--toz-granat-jasny); }
.table tbody tr.wiersz-stan-granatowy:hover { background: #dfe5f3; }
.table tbody tr.wiersz-stan-pomaranczowy { background: #fdeee0; }
.table tbody tr.wiersz-stan-pomaranczowy:hover { background: #f9e2ce; }
.table tbody tr.wiersz-stan-rozowy { background: #fceaf2; }
.table tbody tr.wiersz-stan-rozowy:hover { background: #f7dbe8; }
.table tbody tr.wiersz-stan-fioletowy { background: #f2ecfa; }
.table tbody tr.wiersz-stan-fioletowy:hover { background: #e9dff5; }
.table tbody tr.wiersz-stan-turkusowy { background: #e2f4f4; }
.table tbody tr.wiersz-stan-turkusowy:hover { background: #d3ecec; }
.table tbody tr.wiersz-stan-brazowy { background: #f2ece5; }
.table tbody tr.wiersz-stan-brazowy:hover { background: #e9ded1; }
.table tbody tr.wiersz-stan-morski { background: #e3eff7; }
.table tbody tr.wiersz-stan-morski:hover { background: #d4e5f1; }
.table tbody tr.wiersz-stan-oliwkowy { background: #eef1de; }
.table tbody tr.wiersz-stan-oliwkowy:hover { background: #e4e9ca; }
.table tbody tr.wiersz-stan-sliwkowy { background: #f1e8f0; }
.table tbody tr.wiersz-stan-sliwkowy:hover { background: #e7dae6; }
.table tbody tr.wiersz-stan-piaskowy { background: #f7f0e2; }
.table tbody tr.wiersz-stan-piaskowy:hover { background: #efe4cd; }
.table tbody tr.wiersz-stan-wrzosowy { background: #ecebf6; }
.table tbody tr.wiersz-stan-wrzosowy:hover { background: #e0deef; }
.table tbody tr.wiersz-stan-miedziany { background: #f9ebe3; }
.table tbody tr.wiersz-stan-miedziany:hover { background: #f2ddd1; }
.table tbody tr.wiersz-stan-lazurowy { background: #e3f1fb; }
.table tbody tr.wiersz-stan-lazurowy:hover { background: #d3e8f7; }
.table tbody tr.wiersz-stan-limonkowy { background: #ecf5df; }
.table tbody tr.wiersz-stan-limonkowy:hover { background: #dfeecb; }
.table tbody tr.wiersz-stan-koralowy { background: #fdece8; }
.table tbody tr.wiersz-stan-koralowy:hover { background: #f8dbd4; }
.table tbody tr.wiersz-stan-stalowy { background: #e9edf1; }
.table tbody tr.wiersz-stan-stalowy:hover { background: #dde3ea; }
/* Biel: wiersz wyglada tak, jak wygladal, zanim kolory weszly na liste -
   razem z tym samym odcieniem pod kursorem, co kazdy inny wiersz tabeli. */
.table tbody tr.wiersz-stan-bialy { background: transparent; }
.table tbody tr.wiersz-stan-bialy:hover { background: #f6f8fc; }

/* Sciganie: osoba i adres w jednej kolumnie. Interwencje: sam adres -
   ta sama szerokosc, bo adres zajmuje mniej wiecej tyle samo miejsca. */
.kol-dotyczy { min-width: 15rem; }

.pod-spodem {
    display: block;
    color: var(--toz-muted);
    font-size: .85rem;
    line-height: 1.35;
}

/* Ostrzezenie o powtorce. Ma byc widoczne, ale nie ma blokowac pracy -
   to podpowiedz, a nie blad, wiec zolto, nie czerwono. */
.powtorka {
    margin: 0 0 14px;
    padding: 10px 14px;
    background: var(--toz-tlo-uwaga);
    border: 1px solid #e8d3a4;
    border-left: 4px solid var(--toz-uwaga);
    border-radius: var(--toz-promien);
    color: #4a3a10;
    font-size: .9rem;
}

.powtorka ul {
    margin: 6px 0 0;
    padding-left: 18px;
}

.powtorka li { margin-bottom: 2px; }
.powtorka li span { color: var(--toz-muted); }
/* Uwagi o osobie zgłaszającej z wcześniejszych interwencji - na górze ramki
   powtórek i wyraźniej niż trafienia: numer sprawy znajdzie się na liście,
   a "zgłasza przez adwokata" stoi tylko tutaj. */
.powtorka-osoba { margin: 0 0 8px; padding: 6px 10px; background: #fff; border: 1px solid #e0b252;
                  border-radius: var(--toz-promien); color: #3d2e05; font-size: .95rem; }
.powtorka-osoba:last-child { margin-bottom: 0; }
.powtorka-osoba strong { color: #7a4d00; }
/* Zdanie pod listą kart w ramce "ta osoba ma już kartę" (Zarząd, 27.10.2026) - bez zwykłego odstępu akapitu. */
.powtorka-dopisek { margin: 8px 0 0; }

/* Stan wycofany zostaje na liscie - stare zgloszenia dalej go maja. */
/* Przygaszony kolorem tekstu, nie przezroczystością - przyciski i plakietki zostają czytelne (audyt 29.09.2026, C181). */
.wiersz-wycofany td { color: var(--toz-muted); }

/* Składki miesiąc po miesiącu na karcie: rocznik to <details> z podsumowaniem
   w jednej linii, miesiące listą jedno pod drugim (właściciel, 19.09.2026). */
.rok-skladek { border-top: 1px solid var(--toz-border); }
.rok-skladek:first-of-type { border-top: 0; }
.rok-skladek > summary { cursor: pointer; padding: 10px 0; }
.rok-skladek > summary .muted { margin-left: 8px; }
.lista-miesiecy { list-style: none; margin: 0 0 10px; padding: 0; max-width: 460px; }
.lista-miesiecy li { display: flex; justify-content: space-between; align-items: center; gap: 12px;
    padding: 5px 0 5px 18px; border-top: 1px dashed var(--toz-border); }
/* Lata opłacone w całości stoją jedną linią (właściciel, 22.09.2026) - napis
   "opłacone w całości" obok lat, liczba miesięcy dalej, jak w zwykłym roczniku. */
.rok-skladek > summary strong + span:not(.muted) { margin-left: 8px; }

/* Poprawka miesięcy zapisanych bez wpłaty - zwinięta pod formularzem wpłaty,
   żeby nie myliła się z nim; rozwija się tym samym gestem co panele list. */
.zdejmij-skladki { margin-top: 20px; }
.zdejmij-skladki > summary { cursor: pointer; font-weight: 600; font-size: .9rem; color: var(--toz-granat); margin-bottom: 12px; }

/* Stawki opłat pod listą członków (właściciel, 23.09.2026): wąska tabela, żeby
   kwoty stały blisko nazw, i zasada z uchwały pod nią. Dla kogo jest stawka
   ulgowa - osobną linią pod wierszem opłaty, drobnym pismem, pod kwotami; wiersz
   opłaty i ta linia to jedna pozycja, więc kreska stoi dopiero pod linią. */
.tabela-oplat { max-width: 760px; }
.tabela-oplat tr.z-ulga > td { border-bottom: 0; padding-bottom: 2px; }
.tabela-oplat tr.ulga-dla-wiersz > td { padding-top: 0; text-align: right; }
.tabela-oplat .ulga-dla { display: inline-block; max-width: 30rem; font-size: .8rem; color: var(--toz-muted); }
/* Na telefonie trzy kolumny mieszczą się co do kilku pikseli - węższe odstępy
   w komórkach, żeby tabela nie przewijała się w bok o te piksele. */
@media (max-width: 480px) {
    .tabela-oplat th, .tabela-oplat td { padding-left: 5px; padding-right: 5px; }
}
.zasady-oplat { margin: 12px 0 0; }
/* Stawka składki nad formularzem wpłaty; kwoty za wybrany okres to przyciski,
   które wpisują się w pole "Kwota". */
.stawka-skladki { margin: 0 0 12px; }
.stawka-skladki [data-za-okres] { display: block; margin-top: 4px; }
.stawka-skladki [data-za-okres][hidden] { display: none; }
.stawka-skladki .btn { margin: 2px 0; }

/* Podglad barw pod lista wybieralna: sama nazwa "turkusowy" nie mowi nic
   o tym, jak plakietka wyglada obok pozostalych. */
.podglad-kolorow { display: flex; flex-wrap: wrap; gap: 4px 6px; margin-top: 8px; }

/* Kolumna akcji w zwyklej tabeli (nie tylko w ewidencji): przyciski stoja
   w rzedzie i nie lamia sie w polowie napisu. */
.table .kol-akcje { width: 1%; white-space: nowrap; }
.table .kol-akcje > * { vertical-align: middle; }
.table .kol-akcje .btn + .inline, .table .kol-akcje .inline + .inline { margin-left: 6px; }

/* Ostrzezenie o miejscu niebezpiecznym. Ma sie rzucac w oczy na liscie -
   ktos to czyta przed wyjazdem w teren, a nie po powrocie. */
.znacznik-niebezpieczny {
    display: inline-block;
    margin-top: 3px;
    padding: 1px 8px;
    background: var(--toz-tlo-blad);
    border: 1px solid var(--toz-blad);
    border-radius: 999px;
    color: var(--toz-blad);
    font-size: .76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    /* Na waskim ekranie napis lamie sie na dwie linijki ("WIELE / ZWIERZAT") i plakietka bierze cala szerokosc
       komorki - linijki na srodek, nie przy lewej krawedzi (wlasciciel, 29.10.2026, zrzut z telefonu). */
    text-align: center;
}

/* "Wiele zwierzat" stoi obok "Miejsca niebezpiecznego" i wyglada jak ono, ale
   w zlocie, a nie w czerwieni: to przygotowanie do wyjazdu (transport, druga
   osoba), a nie zagrozenie. */
.znacznik-zwierzeta { background: var(--toz-tlo-uwaga); border-color: var(--toz-zloto); color: var(--toz-uwaga); }

/* "Potrzeba pomocy" i "Miejmy na oku" - ten sam ksztalt co ostrzezenia obok,
   ale w granacie marki: to przypomnienie, nie zagrozenie. */
.znacznik-miejsca {
    display: inline-block; margin-top: 3px; padding: 1px 8px; border-radius: 999px;
    border: 1px solid #c3cbe2; background: var(--toz-granat-jasny); color: var(--toz-granat);
    font-size: .76rem; font-weight: 600; white-space: nowrap; text-align: center;
}

/* Liczba spraw pod tym samym adresem, w nawiasie za adresem. Cicha - to
   dopowiedzenie, nie druga tresc komorki. */
.adres-licznik { color: var(--toz-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.naglowek-dopisek { font-weight: 400; font-size: .75rem; color: var(--toz-muted); text-transform: none; letter-spacing: 0; }

/* Ostrzezenie zapala sie DOPIERO po zaznaczeniu. Czerwony napis przy pustym
   polu wyboru mowi "uwaga, niebezpiecznie" o kazdym adresie po kolei, wiec
   po tygodniu nie znaczy juz nic. */
.przelacznik-ostrzegawczy:has(input:checked) {
    color: var(--toz-blad);
    font-weight: 700;
    border-color: var(--toz-blad);
    background: var(--toz-tlo-blad);
    box-shadow: 0 0 0 3px rgba(165, 40, 52, .10);
}

/* Sprawa jest opisem - w kolumnie miesci sie jej poczatek, calosc w dymku. */
.kol-sprawa { max-width: 22rem; }
/* Lista wyrokow: opis sprawy stoi po prawej (wlasciciel, 17.09.2026), a ostatnia
   kolumna dostaje tyle miejsca, ile zostanie - bez tego "Znecanie sie nad psem"
   lamalo sie po jednym slowie i wiersz rosl na pol ekranu. */
.table[data-lista-wyrokow] .kol-sprawa { min-width: 18rem; }
.table[data-lista-wyrokow] .kol-dotyczy { min-width: 12rem; }
.kol-teczka { max-width: 14rem; }

/* Wykaz wplat przy wyroku: data i kwota zajmuja tyle, ile naprawde potrzebuja,
   a cala reszta szerokosci idzie na uwage - wlasciciel prosil o szerokie pole
   (18.09.2026). Bez tego kwota brala trzecia czesc tabeli na kilka cyfr.
   min-width pilnuje drugiej strony: na telefonie tabela przewija sie w swojej
   obudowie, ale zadna rubryka nie moze zostac scisnieta do samego "zl". */
.table[data-powtarzalne="wplata"] td.kol-data,
.table[data-powtarzalne="wplata"] th.kol-data { width: 11rem; min-width: 10rem; }
.table[data-powtarzalne="wplata"] td.liczba,
.table[data-powtarzalne="wplata"] th.liczba { width: 10rem; min-width: 8rem; }
.table[data-powtarzalne="wplata"] td.kol-usun,
.table[data-powtarzalne="wplata"] th.kol-usun { width: 3rem; }
.table[data-powtarzalne="wplata"] .kol-uwaga { min-width: 16rem; }

/* Pasek sprawy nad kartą pisma: gdzie to pismo leży i co się w sprawie stało. */
.pasek-sprawy {
    margin: 0 0 1rem;
    padding: .5rem .75rem;
    border-left: 3px solid var(--toz-border);
    background: var(--toz-granat-jasny);
    border-radius: 0 var(--toz-promien) var(--toz-promien) 0;
}

.pasek-sprawy-zalega { border-left-color: var(--toz-blad); }

/* Pasek zatwierdzenia raportu. Ton spokojny, nie alarmowy: to jest stan
   dokumentu, a nie awaria - ale ma być widoczny od razu po wejściu. */
.pasek-zatwierdzenia {
    margin: 0 0 1rem;
    padding: .6rem .75rem;
    border-left: 3px solid var(--toz-ok);
    background: var(--toz-granat-jasny);
    border-radius: 0 var(--toz-promien) var(--toz-promien) 0;
}

.zatwierdzenie-stan { margin: 0; display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.pasek-zatwierdzenia .hint { margin: .25rem 0 .5rem; }

/* Import: jedna sekcja na rodzaj danych. Rodzajów będzie tyle, ile ewidencji,
   więc muszą się od siebie odróżniać na jednym ekranie. */
.sekcja-importu { padding-top: 16px; border-top: 1px solid var(--toz-border); margin-top: 16px; }
.sekcja-importu:first-of-type { padding-top: 0; border-top: 0; margin-top: 0; }

/* Podglad importu rozbity na grupy. Wiersze z bledem ida pierwsze i w calosci -
   przy kilku tysiacach faktur kilkanascie zlych wierszy nie ma prawa sie schowac
   ani w kolejnosci z pliku, ani pod ucieciem listy. */
.grupa-importu { margin: 20px 0 4px; display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap; }
.grupa-importu:first-of-type { margin-top: 12px; }
.grupa-blad { color: var(--toz-blad); }
.grupa-blad::before { content: ""; width: .55rem; height: .55rem; border-radius: 50%; background: var(--toz-blad); flex: none; }
.grupa-uwaga { color: var(--toz-uwaga); }
.grupa-uwaga::before { content: ""; width: .55rem; height: .55rem; border-radius: 50%; background: var(--toz-zloto); flex: none; }
.grupa-importu-zwijana { margin-top: 20px; }
.grupa-importu-zwijana > summary { cursor: pointer; font-weight: 600; color: var(--toz-granat); }
.grupa-importu-zwijana > summary:hover { color: var(--toz-granat-ciemny); }
.grupa-importu-zwijana .table-wrap { margin-top: 12px; }
.powody-importu { margin: 0 0 12px; padding-left: 1.2rem; color: var(--toz-text); }
.powody-importu li { margin: .15rem 0; }
.powody-importu strong { font-variant-numeric: tabular-nums; }

/* Terminy zlozenia raportu 1,5% - stoja nad lista, bo to jedyne pytanie,
   z ktorym sie na nia wchodzi. */
.terminy-raportow { margin: 0; padding-left: 1.2rem; }
.terminy-raportow li { margin: .25rem 0; line-height: 1.7; }
.terminy-raportow .badge { margin-left: .35rem; letter-spacing: .02em; }

/* Faktura niefiskalna: kwota jest widoczna, ale do sum wchodzi zerem.
   Przekreslenie mowi to bez czytania - inaczej suma pod lista wyglada zle. */
.kwota-niefiskalna { color: var(--toz-muted); text-decoration: line-through; }
.kwota-niefiskalna .badge { text-decoration: none; }

/* Lista raportow 1,5%: caly wiersz mowi, jak jest z terminem.
   Kolor tla, a nie samej komorki - w tabeli na jedenascie kolumn pojedyncza
   komorka gubi sie, a pytanie brzmi "co z tym kwartalem", nie "co z ta data".
   Znacznik slowny stoi obok w komorce terminu, bo przy druku kolor znika. */
.table tbody tr.wiersz-spozniony { background: var(--toz-tlo-blad); }
.table tbody tr.wiersz-spozniony:hover { background: var(--toz-tlo-blad-kursor); }
.table tbody tr.wiersz-blisko-terminu { background: var(--toz-tlo-uwaga); }
.table tbody tr.wiersz-blisko-terminu:hover { background: #faecce; }

/* Karta wyroku: uwagi do całego wyroku stoją pod wykazem wpłat i jego
   przyciskiem "+ Dodaj wpłatę" (właściciel, 23.09.2026) - kreska i odstęp
   oddzielają je od wpłat, żeby nie czytały się jak uwaga do ostatniej z nich. */
.uwagi-wyroku { margin-top: 1rem; padding-top: .25rem; border-top: 1px solid var(--toz-border); }

/* Raport inspektorski: wiersz "opis - pole - wartość poprzednia".

   Formularz przychodzi z zarządu głównego i jest listą kilkudziesięciu
   krótkich pytań z jedną liczbą przy każdym. Siatka .pola stawiałaby cztery
   takie pola w rzędzie i trzeba by szukać, które opis należy do którego
   okienka; tu każdy wiersz to jedno pytanie, jak na papierze. */
.wiersze-raportu-lista { display: flex; flex-direction: column; }

.wiersz-raportu {
    display: grid;
    /* Środkowa kolumna mieści i pole liczbowe, i przełącznik tak/nie -
       oba rodzaje wierszy stoją w tej samej siatce, więc muszą się w niej
       zmieścić bez ściskania. */
    grid-template-columns: 1fr 8.5rem 9rem 9rem;
    align-items: center;
    gap: .5rem 1rem;
    /* Odsunięcie w bok: tło podświetlenia wychodzi odrobinę poza tekst,
       a sam tekst zostaje w linii z resztą formularza. */
    margin: 0 -.5rem;
    padding: .3rem .5rem;
    border-bottom: 1px solid var(--toz-border);
}

.wiersz-raportu .label { margin: 0; font-weight: 400; }
.wiersz-raportu .pole-blad { grid-column: 1 / -1; margin: 0; }

/* Który opis jest od którego pola (właściciel, 23.09.2026: "przy jeżdżeniu
   pomiędzy linijkami nie dzieje mi się z tymi liniami tak, abym faktycznie
   widział który opis jest od której linii"). Podświetla się CAŁY wiersz -
   opis, pole i wartość poprzednia: pod myszą lekko, jak wiersz tabeli,
   a z kursorem w polu (kliknięcie, Tab) mocniej, z kreską z lewej - jak
   wiersz w edycji na listach. */
/* Pod myszą o odcień mocniej niż wiersz tabeli (#f6f8fc) - tam wiersz trzyma
   się kolumn, tu opis stoi daleko od pola i tło musi je spiąć wyraźnie. */
.wiersz-raportu:hover { background: #f0f3fa; }
.wiersz-raportu:focus-within {
    background: var(--toz-granat-jasny);
    box-shadow: inset 3px 0 0 var(--toz-granat);
}
/* Sam kolor, bez pogrubienia - grubszy opis łamałby się inaczej i wiersz
   skakałby przy przechodzeniu Tabem. */
.wiersz-raportu:focus-within .label { color: var(--toz-granat-ciemny); }

/* Przełącznik tak/nie w raporcie inspektorskim.

   Pod spodem stoją dwa zwykłe pola wyboru (radio) - dzięki temu przełącznik
   działa bez JavaScriptu, obsługuje strzałki i Tab, a czytnik ekranu czyta go
   jak grupę dwóch opcji. Widać z niego wyłącznie etykiety, ostylowane
   na przyciski; stan bierze się z :checked, a nie ze skryptu. */
.przelacznik-tak-nie {
    display: inline-flex;
    /* Ukryte pole wyboru siedzi w środku przełącznika, a nie gdzieś na stronie -
       dzięki temu przewinięcie do fokusu ląduje na przycisku. */
    position: relative;
    border: 1px solid var(--toz-border);
    border-radius: var(--toz-promien);
    overflow: hidden;
    background: var(--toz-plyta);
}

/* Pole zostaje na miejscu (fokus musi mieć gdzie stanąć), ale go nie widać. */
.przelacznik-tak-nie input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip-path: inset(50%);
    overflow: hidden;
}

.przelacznik-tak-nie label {
    padding: .3rem .9rem;
    font-size: .9375rem;
    line-height: 1.4;
    color: var(--toz-muted);
    cursor: pointer;
    user-select: none;
}

.przelacznik-tak-nie label + input + label { border-left: 1px solid var(--toz-border); }

.przelacznik-tak-nie input:checked + label {
    background: var(--toz-granat);
    color: #fff;
    font-weight: 600;
}

/* Fokus z klawiatury musi być widoczny na SAMYM przycisku, nie na ukrytym polu. */
.przelacznik-tak-nie input:focus-visible + label {
    outline: 2px solid var(--toz-fokus);
    outline-offset: -2px;
}

/* Złoto tylko na zaznaczonej, granatowej połowie - na białej było prawie niewidoczne (C171). */
.przelacznik-tak-nie input:checked:focus-visible + label {
    outline-color: var(--toz-zloto);
}

.przelacznik-tak-nie input:disabled + label { cursor: default; opacity: .6; }
/* Wybór, którego w tej chwili nie ma (np. lista nowoprzyjętych, gdy wśród
   zaznaczonych jest ktoś przyjęty dawno) - przygaszony cały, nie tylko kółko. */
.uprawnienie:has(input:disabled) { cursor: default; opacity: .6; }

/* Wartość z poprzedniego kwartału - obok pola, przygaszona: to jest tło
   dla decyzji, a nie druga liczba do wpisania. */
.poprzednio { font-size: .875rem; color: var(--toz-muted); }
.poprzednio strong { color: var(--toz-text); font-variant-numeric: tabular-nums; }

/* Kolumna „Szacowane” (13.10.2026) - to, co system policzył sam; obok „poprzednio”, w kolorze akcentu,
   żeby nie mylić podpowiedzi z wartością z poprzedniego raportu. */
.szacowane { font-size: .875rem; color: var(--toz-muted); }
.szacowane strong { color: var(--toz-granat); font-variant-numeric: tabular-nums; }
.szacowane-opis { margin-top: .5rem; font-size: .875rem; }
.szacowane-opis ul { margin: .5rem 0 0; padding-left: 1.25rem; }
.szacowane-wpisz { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 .75rem; }

@media (max-width: 640px) {
    .wiersz-raportu { grid-template-columns: 1fr 8.5rem; }
    .poprzednio, .szacowane { grid-column: 1 / -1; }
    .szacowane:empty { display: none; }
}

/* Podpowiedź sprawy po zewnętrznym znaku pisma.

   Dwa miejsca, jeden wygląd: pasek nad formularzem (rysuje serwer przy piśmie
   bez sprawy) i linijka pod samym polem znaku (dokłada skrypt w trakcie
   pisania). Nie alarm - to podpowiedź, więc ton jest spokojny, a nie czerwony. */
.pasek-podpowiedzi {
    margin: 0 0 1rem;
    padding: .5rem .75rem;
    border-left: 3px solid var(--toz-granat);
    background: var(--toz-granat-jasny);
    border-radius: 0 var(--toz-promien) var(--toz-promien) 0;
}

.podpowiedz-wstep { margin: 0 0 .35rem; }

.podpowiedz-sprawa {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .5rem;
    margin-top: .35rem;
}

.podpowiedz-znaku {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    margin: .5rem 0 0;
    padding: .5rem .6rem;
    border-left: 3px solid var(--toz-granat);
    background: var(--toz-granat-jasny);
    border-radius: 0 var(--toz-promien) var(--toz-promien) 0;
    font-size: .875rem;
}

.podpowiedz-znaku-sprawa {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .4rem;
}

/* Podkład pod polem opisu: treść do przepisania, nie do zapisania.
   Przygaszony, żeby na pierwszy rzut oka było widać, że to nie jest raport. */
.pole-podklad {
    background: var(--toz-granat-jasny);
    color: var(--toz-muted);
}

/* Pole szukania dokładane nad listą wyboru rekordu.
   flex-basis, bo pojemnik powtarzalnych wierszy jest siatką - bez tego pole
   stawało obok pierwszej listy zamiast nad wszystkimi. */
.szukajka { margin-bottom: .5rem; flex-basis: 100%; width: 100%; }
.szukajka .hint { margin-top: .25rem; }

/* Powiazania faktury: zwierzak, kilku zwierzakow albo inna sprawa. */
/* Wpisow bywa kilka, ale kazdy to imie i nazwisko albo nazwa sprawy - jakies
   dwadziescia kilka znakow. Ustawione jeden pod drugim marnowaly caly wiersz
   na pole i pustke obok niego, wiec ida obok siebie i lamia sie do nowej
   linii dopiero wtedy, gdy zabraknie miejsca.

   Siatka o rownych kolumnach, a nie flex z max-width. Przy flexie wpisy
   w niepelnej ostatniej linii rosly az do max-width, a w pelnej byly
   wezsze - druga linia dat albo osob nie trzymala sie kolumn pierwszej,
   dopoki ktos jej nie dopelnil. auto-fill zostawia puste kolumny, wiec
   pojedynczy wpis dalej nie rozciaga sie na caly formularz, a od tego
   zaczela sie ta poprawka. min(17rem, 100%): na waskim telefonie jedna
   kolumna na cala szerokosc, bez wystawania za ramke.

   :has(> .powiazanie), bo ta sama klasa pojemnika stoi przy interwencjach
   pisma w sciganiu - tam wiersz ma szerokosc najdluzszej opcji listy
   i siatka obcielaby opisy interwencji. */
/* --- Terminy interwencji (właściciel, 25.09.2026) -------------------------
   Termin to data i osoby, które przy nim były (interwencje/_terminy.php):
   data stałej szerokości, obok osoby, które się zawijają, na końcu "Usuń
   termin". Podpisy kolumn stoją raz, nad listą - każde pole ma i tak własny
   opis dla czytnika ekranu. Na telefonie wszystko jedno pod drugim. */
.terminy { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.terminy-glowka { display: grid; grid-template-columns: 11rem 11rem minmax(0, 1fr); gap: 10px; padding: 0 9px;
                  margin: 2px 0 4px; font-size: .78rem; font-weight: 600; color: var(--toz-muted); }
/* Stan dokumentów przy każdym terminie (właściciel, 25.09.2026) - kolumna
   między datą a osobami. Organizacja bez czynnych stanów dokumentów pola nie
   ma, więc i kolumny. */
.termin { display: grid; grid-template-columns: 11rem 11rem minmax(0, 1fr) auto; gap: 8px 10px; align-items: start;
          padding: 8px; border: 1px solid var(--toz-border); border-radius: 8px; background: var(--toz-plyta); }
.terminy-glowka-bez-dokumentow { grid-template-columns: 11rem minmax(0, 1fr); }
.terminy-bez-dokumentow .termin { grid-template-columns: 11rem minmax(0, 1fr) auto; }
/* Osoby w siatce równych kolumn, a nie w zawijanym rzędzie: w rzędzie każde
   pole dzieliło szerokość z sąsiadami i z "+ Osoba", więc przy trzeciej
   i czwartej osobie wszystkie się zwężały, a piąta w nowym rzędzie znów była
   szeroka (właściciel, 25.09.2026: "pola osób dodawanych do terminu interwencji
   zmniejszają się powyżej 4 w linii"). Kolumny mają tę samą szerokość w każdym
   rzędzie; na wąskim ekranie jedna kolumna na całą szerokość. */
.termin-osoby { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
                align-items: center; gap: 6px 10px; min-width: 0; }
.termin-osoba { display: flex; align-items: center; gap: 4px; min-width: 0; }
.termin-osoba .form-control { flex: 1 1 auto; min-width: 0; }
.termin-dodaj-osobe { justify-self: start; }
.termin-usun { align-self: center; white-space: nowrap; }
/* Pod listą "+ Dodaj kolejny termin" i "Dziś, ze mną" (właściciel, 27.10.2026) - w jednym rzędzie, a gdy miejsca
   brak, jeden pod drugim, bez wychodzenia w bok. Te same małe przyciski pod "Rekontrola najwcześniej": "za tydzień",
   "za 2 tygodnie", "za miesiąc" - w wąskim polu daty łamią się w kolejne rzędy. */
.terminy-przyciski,
.szybkie-daty { display: flex; flex-wrap: wrap; gap: 6px 8px; }
.szybkie-daty { margin-top: 6px; }
/* W panelu nad listą terminy biorą cały rząd - wiersz terminu jest szerszy
   niż dwie kolumny panelu. */
.panel-terminy { grid-column: 1 / -1; }
.panel-terminy .terminy { margin-bottom: 0; }
/* Podpis pola dokumentów w samym terminie - tylko na telefonie, gdzie nie ma
   podpisów kolumn. Data i osoby mówią same za siebie (kalendarz, "imię
   i nazwisko"), a samo "Zbędne" czy "Brak" - nie. */
.termin-podpis { display: none; }
@media (max-width: 640px) {
    .terminy-glowka { display: none; }
    .termin, .terminy-bez-dokumentow .termin { grid-template-columns: minmax(0, 1fr); }
    .termin-podpis { display: block; margin-bottom: 2px; font-size: .78rem; font-weight: 600; color: var(--toz-muted); }
}

.powiazania { display: flex; flex-wrap: wrap; gap: 8px 10px; margin-bottom: 8px; }
.powiazania:has(> .powiazanie) { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr)); }
.powiazanie { display: flex; align-items: center; gap: 6px; min-width: 0; }
.powiazanie .form-control { flex: 1 1 auto; min-width: 0; }

/* --- Zabrane zwierzaki ----------------------------------------------------
   Wiersz niesie trzy pola (imie, rodzaj, data), a nie jedno - wiec zajmuje
   caly wiersz i dzieli sie na kolumny wewnatrz. Bez tego siatka z regul
   powyzej wcisnelaby wszystkie trzy w szerokosc jednej kolumny. */
.powiazania.powiazania-zwierzaki { grid-template-columns: minmax(0, 1fr); flex-direction: column; }
.powiazanie-zwierzak { width: 100%; gap: 8px; }
/* Imie po nazwie pola, nie ":first-child" - pierwsze w wierszu stoi ukryte
   pole klucza, wiec tamta regula nigdy nie trafiala, imie bralo szerokosc
   calego wiersza i sciskalo reszte: z daty zostawalo "dd/mm/". Imie, gatunek
   i data nie rosna, zeby w kazdym wierszu staly jedno pod drugim. */
.powiazanie-zwierzak input[name="zwierzak_imie[]"] { flex: 0 1 18rem; }
/* Ile kart w TOZ ma imie z wiersza - pole tylko do czytania zaraz za imieniem,
   z tlem pola zablokowanego, zeby nikt nie probowal w nim pisac. */
.powiazanie-zwierzak .zwierzak-ile {
    flex: 0 0 3rem;
    box-sizing: border-box;
    display: flex; align-items: center; justify-content: center;
    min-height: 42px;
    border: 1px solid var(--toz-border);
    border-radius: 8px;
    background: #f4f5f8;
    color: var(--toz-muted);
    font-variant-numeric: tabular-nums;
}
/* Kolumna gatunku: "gatunek *" musi sie zmiescic w podpowiedzi, inaczej
   widac "gatune" i nie wiadomo, czego pole dotyczy. Tez po nazwie pola - miedzy
   imieniem a gatunkiem stoi liczba kart, wiec "pole tekstowe zaraz za polem
   tekstowym" juz go nie znajduje. */
.powiazanie-zwierzak input[name="zwierzak_gatunek[]"] { flex: 0 1 10rem; }
.powiazanie-zwierzak input[type="date"] { flex: 0 1 11rem; min-width: 9rem; }
/* "Karta w TOZ" (bez karty / zaloz nowa / karta, ktora zwierzak juz ma)
   bierze reszte wiersza; dlugie opisy kart tna sie w polu. */
.powiazanie-zwierzak .zwierzak-karta { flex: 1 1 14rem; }
/* Sposob odebrania (13.10.2026) - stala szerokosc, zeby "interwencyjnie po zgodzie gminy" sie miescilo. */
.powiazanie-zwierzak .zwierzak-odebranie { flex: 0 1 15rem; }

.dodaj-wiersze { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.dodaj-wiersze .dodaj-ile { width: 4.5rem; }
.dodaj-wiersze .dodaj-gatunek { width: 9rem; }
.zwierzak-znacznik { white-space: nowrap; }

/* Skad podopieczny sie wzial - pasek na karcie, z odnosnikiem do zgloszenia. */
.zrodlo-podopiecznego { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.zrodlo-podopiecznego > span:first-child { margin-right: auto; }

@media (max-width: 640px) {
    .powiazanie-zwierzak { flex-wrap: wrap; }
    .powiazanie-zwierzak input,
    .powiazanie-zwierzak select { flex: 1 1 100% !important; }
    /* Liczba kart zostaje w jednej linii z imieniem, ktorego dotyczy. */
    .powiazanie-zwierzak input[name="zwierzak_imie[]"] { flex: 1 1 0 !important; min-width: 0; }
    /* Pola wiersza stoja tu jedno pod drugim - kreska mowi, gdzie konczy sie
       jeden zwierzak, a zaczyna nastepny. "~", nie "+": wiersz dodany
       przyciskiem staje za wzorem wiersza (template), nie za poprzednim. */
    .powiazanie-zwierzak ~ .powiazanie-zwierzak { border-top: 1px solid var(--toz-border); padding-top: 10px; }
}

/* Dolna granica jest tu wazniejsza niz gorna. Bez niej uklad tabeli sciskal
   kolumne tak, ze dwuwyrazowa nazwa lamala sie w srodku kafelka - "Biuro"
   nad "rachunkowe" - a to wyglada na usterke, nie na decyzje. */
.kol-powiazania { min-width: 9rem; max-width: 16rem; }

.powiazanie-znacznik {
    display: inline-block;
    /* Kafelek nigdy szerszy niz kolumna: inaczej dluga nazwa wystaje poza
       obramowanie zamiast sie zlamac. */
    max-width: 100%;
    margin: 1px 4px 1px 0;
    padding: 2px 8px;
    background: var(--toz-granat-jasny);
    border: 1px solid #c5cfe8;
    border-radius: 999px;
    font-size: .82rem;
    /* Nazwa, ktora sie nie miesci, lamie sie na srodku, a nie do lewej -
       druga linijka dosunieta do krawedzi wyglada jak zle sklejony kafelek.
       Wlasny odstep miedzy liniami, bo przy domyslnym dwie linijki w tak
       niskim kafelku sklejaja sie ze soba. */
    text-align: center;
    line-height: 1.35;
    color: var(--toz-granat-ciemny);
}

/* Materialy przy interwencji: zdjecia i filmy w dwoch osobnych galeriach. */
.materialy { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
.materialy li { display: flex; align-items: flex-start; gap: 10px; padding: 10px;
    border: 1px solid var(--toz-border); border-radius: var(--toz-promien); background: var(--toz-plyta); }

.material-podglad { flex: 0 0 auto; display: block; width: 96px; }
.material-podglad img { width: 96px; height: 96px; object-fit: cover; border-radius: 6px; display: block; }

/* Film dostaje wiecej miejsca niz miniatura zdjecia - inaczej nie da sie
   trafic w przyciski odtwarzacza, zwlaszcza palcem na telefonie. */
video.material-podglad { width: 100%; max-width: 320px; height: auto; border-radius: 6px; background: #000; }
.materialy li:has(video) { flex-direction: column; }

/* Kolejność zdjęć i plików przeciąganiem myszą (właściciel, 14.10.2026; przestaw-pliki.js). Uchwyt to droga
   z klawiatury (strzałki); myszą chwyta się cały kafelek. */
.przestaw-kafelek { cursor: grab; }
.przestaw-niesiony { opacity: .45; }
.przestaw-zapis .przestaw-kafelek { cursor: progress; }
.przestaw-uchwyt { flex: 0 0 auto; align-self: center; width: 14px; height: 26px; padding: 0; border: 0;
    border-radius: 4px; cursor: grab; opacity: .6;
    background: radial-gradient(circle, var(--toz-muted) 1.5px, transparent 1.7px) 0 1px / 7px 6px; }
.przestaw-uchwyt:hover, .przestaw-uchwyt:focus-visible { opacity: 1; }
.przestaw-podpowiedz { margin: 0 0 8px; }
.przestaw-meldunek { margin: 8px 0 0; }

.material-pdf, .material-znak { display: flex; align-items: center; justify-content: center;
    width: 96px; height: 96px; border: 1px solid var(--toz-border); border-radius: 6px;
    background: #f6f7fa; color: var(--toz-muted); font-weight: 700; font-size: .8rem; text-decoration: none; }
/* Film i zdjęcie bez małej kopii (HEIC) na kafelku karty - sam znak rodzaju, plik ładuje się dopiero w podglądzie
   (04.10.2026: "Pełne zdjęcie powinno się ładować jak użytkownik będzie chciał je zobaczyć"). */
.material-znak { flex-direction: column; gap: 6px; color: var(--toz-granat-ciemny); background: var(--toz-granat-jasny); }
.material-znak:hover { text-decoration: none; border-color: var(--toz-granat); }
.material-film::before {
    content: ''; width: 34px; height: 34px; border-radius: 999px;
    background: var(--toz-granat) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 6.5v11l9-5.5z' fill='%23fff'/%3E%3C/svg%3E") center / 22px no-repeat;
}
.material-zdjecie::before {
    content: ''; width: 34px; height: 28px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 20'%3E%3Crect x='1' y='1' width='22' height='18' rx='3' fill='none' stroke='%233a57a2' stroke-width='1.8'/%3E%3Ccircle cx='8' cy='7' r='2' fill='%23d7b56d'/%3E%3Cpath d='M3 17l6-6 4 4 3-3 5 5z' fill='%233a57a2'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Zaznaczanie wielu faktur i wspolne "czego dotyczy". */
.kol-zaznacz { width: 2.2rem; text-align: center; }
.kol-zaznacz input { margin: 0; }

.zbiorcze {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
    margin-top: 14px; padding: 12px 14px;
    background: var(--toz-granat-jasny);
    border: 1px solid #c5cfe8; border-radius: var(--toz-promien);
}
/* Stan w kolorze "alarm" (na start "Brak" dokumentow) na czerwono takze
   w polu wyboru na karcie i w szybkiej rejestracji (wlasciciel, 24.09.2026:
   "jesli dokumenty sa potrzebne to napis ma byc na czerwono"). Pozycje
   rozwinietej listy zostaja zwykle. */
select:has(option[data-kolor="alarm"]:checked) { color: var(--toz-blad); font-weight: 600; }
select:has(option[data-kolor="alarm"]) option { color: var(--toz-text); font-weight: 400; }
/* min-width 0 i max-width: lista wyboru bierze szerokosc z najdluzszej pozycji
   ("Stan dla zglaszajacego: bez zmiany") i na telefonie wystawala z paska. */
.zbiorcze .form-control { flex: 1 1 260px; width: auto; min-width: 0; max-width: 100%; min-height: 36px; }
.zbiorcze-licznik { font-size: .88rem; color: var(--toz-muted); font-variant-numeric: tabular-nums; }
.zbiorcze-licznik-aktywny { color: var(--toz-granat-ciemny); font-weight: 700; }
/* "Zapłacono dnia" pod listą faktur (właściciel, 27.10.2026): drugi wiersz paska zbiorczego - własny rząd,
   pole daty na swoją szerokość (nie 260 px jak pole tekstowe), błąd pod spodem. */
.zbiorcze-wiersz { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-width: 0; }
.zbiorcze .zbiorcze-data { flex: 0 1 11rem; }
/* Pasek zaznaczeń maili (07.11.2026, maile/_akcje-zaznaczonych.php): wybór folderu z przyciskiem "Przenieś" trzyma się razem, a na telefonie
   zajmuje cały rząd zamiast wystawać w bok. */
.maile-przenies { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; max-width: 100%; }
.zbiorcze .maile-przenies .form-control { flex: 0 1 16rem; }

/* Włącznik przypomnień o składkach nad listą członków: wiersz na oddział -
   nazwa, stan, przycisk (tylko dla uprawnionych). */
.przypomnienia-oddzialow { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.przypomnienia-oddzialow li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 6px 0; border-top: 1px solid var(--toz-border); }
.przypomnienia-oddzialow li:first-child { border-top: 0; padding-top: 0; }

/* Pasek u góry: gdzie ta osoba teraz pracuje (oddział roboczy) - pastylka
   w odcieniu złota obwódki, żeby odróżniała się od pozycji menu. */
.nav .nav-oddzial { background: #fbf6e8; border: 1px solid #eadfbf; border-radius: 999px; padding: 6px 12px; font-weight: 400; margin-left: 6px; }
.nav .nav-oddzial:hover, .nav .nav-oddzial:focus-visible { background: #f6edd3; }
.nav .nav-oddzial strong { font-weight: 700; }

/* Wybór oddziału roboczego: lista przełączników w kolumnie. */
.przelaczniki-lista { flex-direction: column; align-items: flex-start; }

/* Strona konta: przełącznik w jednym wierszu ze stanem i przyciskiem. */
.przelacznik-w-wierszu { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 6px 0; border-top: 1px solid var(--toz-border); }
.przelacznik-w-wierszu:first-of-type { border-top: 0; }

@media print { .zbiorcze, .kol-zaznacz { display: none !important; } }
/* Na wydruku bez podświetlenia wiersza raportu inspektorskiego. */
@media print {
    .wiersz-raportu:hover, .wiersz-raportu:focus-within { background: none; box-shadow: none; }
    .wiersz-raportu:focus-within .label { color: inherit; }
}

/* --- Rejestr scigania: szerokosci kolumn -----------------------------------
   Ograniczenia z listy faktur trafiaja tu przez te same klasy kolumn, a tam
   "Sprawa" to jedno-dwa slowa z listy wybieralnej. Tutaj to glowna kolumna
   tabeli - zdanie, po ktorym sprawe sie rozpoznaje - wiec 170 px lamalo ja
   na cztery linijki, podczas gdy obok zostawalo puste miejsce.

   Selektor jest zawezony klasa tabeli, wiec wygrywa waga (0,3,1), a nie
   kolejnoscia w pliku - inaczej rozstrzygalby o tym przypadek. */
.table-ewidencja[data-lista-sciganie] td.kol-sprawa { max-width: 24rem; }
.table-ewidencja[data-lista-sciganie] td.kol-od-kogo { max-width: 12rem; }
.table-ewidencja[data-lista-sciganie] td.uwagi { max-width: 20rem; }

/* Ustawienia systemu: przelacznik z opisem pod spodem i drobne dopiski
   pod polami. Bez tego opis siadal w jednej linii z etykieta i para
   "co to robi" / "jak sie nazywa" przestawala byc czytelna. */
.choice .hint { display: block; margin-top: 2px; }
.table td .hint { display: block; margin-top: 2px; }
.row-forms .btn { align-self: center; }

/* Odczyt faktury z pliku: dokument z lewej, formularz z prawej.
   Podglad musi zostac na ekranie przy przewijaniu dlugiego formularza -
   inaczej "sprawdz, czy sie zgadza" znaczy przewijanie w gore i w dol
   przy kazdym polu. Na waskim ekranie panele staja jeden pod drugim. */
.odczyt-uklad { display: grid; grid-template-columns: minmax(320px, 40%) 1fr; gap: 20px; align-items: start; }
/* Kilka plikow jednej faktury (zdjecie kazdej strony) stoi jedno pod drugim.
   Panel przewija sie wtedy sam, w granicach ekranu - przyklejony panel
   wyzszy niz ekran chowalby dolne strony tam, dokad nie da sie przewinac. */
.odczyt-podglad { position: sticky; top: 16px; background: #fff; border: 1px solid var(--toz-border);
                  border-radius: 12px; padding: 12px; max-height: calc(100vh - 32px); overflow-y: auto; }
.odczyt-plik + .odczyt-plik { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--toz-border); }
.odczyt-naglowek { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.odczyt-naglowek strong { flex: 1 1 auto; word-break: break-word; }
.odczyt-ramka { width: 100%; height: min(76vh, 900px); border: 1px solid var(--toz-border); border-radius: 8px; background: #fff; }
.odczyt-obraz { display: block; width: 100%; height: auto; max-height: min(76vh, 900px);
                object-fit: contain; border: 1px solid var(--toz-border); border-radius: 8px; background: #fff; }
/* Ekran odczytu: wybrane pliki (strony jednej faktury) z "Usun" przy kazdym
   i "Dodaj kolejna strone" pod lista (odczyt-pliki.js). Dluga nazwa zdjecia
   z telefonu lamie sie, zamiast wypychac strone w bok. */
.pliki-odczytu { margin: 10px 0 0; padding-left: 1.6em; }
.pliki-odczytu li { padding: 3px 0; }
.pliki-odczytu li > span { overflow-wrap: anywhere; margin-right: 8px; }
.dodaj-strone { margin-top: 8px; }
/* Napis zamiast ramki, gdy przegladarka PDF-ow na stronie nie pokazuje
   (pdf-na-stronie.js). */
.odczyt-bez-pdf { margin-bottom: 0; }
.odczyt-bez-pdf p { margin: 0; }
.odczyt-bez-pdf p + p { margin-top: 8px; }
.odczyt-tresc { min-width: 0; }
.odczyt-tresc .card { margin-top: 0; }

/* Telefon i tablet: bez podgladu dokumentu - "to za male ekrany, aby to
   obslugiwac" (wlasciciel, 24.09.2026). Zostaja nazwy plikow z "Otworz
   osobno", formularz na cala szerokosc. Tablet poznajemy po dotyku jako
   glownym sposobie wskazywania, a nie po szerokosci: tablet trzymany
   poziomo jest szerszy niz niejeden laptop. Waskie okno komputera -
   po szerokosci, jak dotad. */
@media (max-width: 900px), (hover: none) and (pointer: coarse) {
    .odczyt-uklad { grid-template-columns: 1fr; }
    .odczyt-podglad { position: static; max-height: none; overflow: visible; }
    .odczyt-widok { display: none; }
    .odczyt-naglowek { margin-bottom: 0; }
}

/* Element schowany ma zostac schowany takze wtedy, gdy jego wlasna klasa
   ustawi kiedys "display". Lista niezgodnosci w raporcie 1,5% chowa sie
   i pokazuje w trakcie pisania - reguly przegladarki nie moga tu przegrac
   przez dopisana pol roku pozniej regulke ukladu. */
[hidden] { display: none !important; }

/* Wyrok prawomocny z niezaplacona nawiazka: sa pieniadze do odzyskania
   i biegnie termin. Sam kolor nic nie mowi przy druku ani czytnikowi ekranu,
   wiec obok kwoty stoi jeszcze slowo "zalega" - to jest ta informacja,
   a kolor tylko prowadzi do niej wzrok. */
.table tbody tr.wiersz-zalega { background: var(--toz-tlo-blad); }
.table tbody tr.wiersz-zalega:hover { background: var(--toz-tlo-blad-kursor); }
.table tbody tr.wiersz-zalega td { border-bottom-color: #f0bcc1; }

/* Pismo "do realizacji" (wlasciciel, 17.09.2026) - ta sama czerwien co przy
   zalegajacym wyroku: w obu przypadkach to jest wiersz, przy ktorym cos trzeba
   zrobic. Kolumny "Status" na liscie nie ma - slowo stoi tylko dla czytnika ekranu,
   a w trybie wysokiego kontrastu znak daje osobna regula (forced-colors, J205). */
.table tbody tr.wiersz-do-realizacji { background: var(--toz-tlo-blad); }
.table tbody tr.wiersz-do-realizacji:hover { background: var(--toz-tlo-blad-kursor); }
.table tbody tr.wiersz-do-realizacji td { border-bottom-color: #f0bcc1; }

/* Wyrok: dziesiec rubryk, ktorych przy zwyklym pismie nikt nie wypelni.
   Pokazuja sie dopiero po zaznaczeniu przelacznika - chowa je sam CSS,
   wiec dziala to bez JavaScriptu. Przegladarka, ktora nie zna :has,
   pokaze wszystko: gorzej, ale nic sie nie psuje. */
.sekcja-wyrok:has(#czy_wyrok:not(:checked)) .pola-wyroku { display: none; }

/* Walne (wlasciciel, 21.09.2026: "robmy to jednolicie") - tak samo jak wyrok:
   pola rozwija dopiero przelacznik "Przygotuj dokumenty". Cel tylko przy
   nadzwyczajnym, pola drugiego terminu dopiero po zaznaczeniu zgody na inny
   termin - a do tego czasu podpowiedz mowi, jaki drugi termin wyjdzie
   z wytycznych. Sam CSS, bez JavaScriptu. */
.sekcja-walne:has(#przygotuj_dokumenty:not(:checked)) .pola-walnego { display: none; }
.sekcja-walne:has(input[name="walne_rodzaj"][value="zwyczajne"]:checked) .pole-cel-walnego { display: none; }
.sekcja-walne:has(#walne_termin2_inny:not(:checked)) .pole-drugiego-terminu { display: none; }
.sekcja-walne:has(#walne_termin2_inny:checked) .drugi-termin-domyslny { display: none; }

/* Karta przypomnienia: widać tylko pola zaznaczonego sposobu wysyłki
   (właściciel, 22.09.2026 - doszły "jednorazowo" i "w wybranych datach",
   pięć zestawów pól naraz byłoby nieczytelne). Bez :has widać wszystkie,
   jak dotąd, a serwer bierze te, które pasują. */
.sekcja-harmonogramu:has(input[name="powtarzanie"][value="jednorazowo"]:checked) .pole-harmonogramu:not(.dla-jednorazowo),
.sekcja-harmonogramu:has(input[name="powtarzanie"][value="w_datach"]:checked) .pole-harmonogramu:not(.dla-w_datach),
.sekcja-harmonogramu:has(input[name="powtarzanie"][value="rocznie"]:checked) .pole-harmonogramu:not(.dla-rocznie),
.sekcja-harmonogramu:has(input[name="powtarzanie"][value="kwartalnie"]:checked) .pole-harmonogramu:not(.dla-kwartalnie),
.sekcja-harmonogramu:has(input[name="powtarzanie"][value="miesiecznie"]:checked) .pole-harmonogramu:not(.dla-miesiecznie) { display: none; }

/* Zestawienie z wykresami nad Uchwałami (właściciel, 28.10.2026: „przy przełączaniu rok po roku na od dnia do dnia
   pokazuj lub chowaj odpowiednie pozycje z datami”): widać pola lat albo pola dni - tego okresu, który jest zaznaczony.
   Bez :has widać wszystkie, a serwer i tak bierze te, które pasują do okresu. */
.zestawienie-okres:has(input[name="tryb"][value="lata"]:checked) .pole-dni,
.zestawienie-okres:has(input[name="tryb"][value="dni"]:checked) .pole-lat { display: none; }

/* Wiersz ze zgloszeniem przy pismie - uklad jak przy powiazaniach faktury:
   lista wyboru i "x" obok siebie, a nie jeden pod drugim. Bez tej reguly
   .form-control (display:block, width:100%) spychal przycisk pod pole. */
.interwencja { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.interwencja .form-control { flex: 1 1 auto; min-width: 0; }

/* --- Pola formularzy: jedna wysokosc takze na telefonie ---------------------
   Wlasciciel (zrzut filtrow faktur z iPhone'a): "Na komorce kazde ma inna
   wielkosc". Safari na iPhonie rysuje liste wyboru po swojemu i nie slucha
   min-height ani padding - wychodzila nizsza od pola tekstowego, a etykiety
   w jednym wierszu filtrow rozjezdzaly sie w pionie ("Data" nizej niz "Od
   dnia"). Pole wyszukiwania dostawalo tam z kolei wlasny, zaokraglony wyglad.
   appearance: none oddaje wyglad arkuszowi, a strzalke listy rysujemy sami.
   Pola dat maja to samo wyzej, przy .form-control.

   Stoi na koncu pliku z rozmyslem: reguly zwartych filtrow i paneli (padding,
   tlo pola z bledem) sa wczesniej, a te maja wygrac takze kolejnoscia. */
input.form-control[type="search"] { -webkit-appearance: none; appearance: none; }
input.form-control[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }

/* :not([multiple]):not([size]) - lista wielokrotnego wyboru nie ma strzalki.
   Przy okazji waga (0,3,1) bije ".form-control:disabled" i "-blad", ktore
   ustawiaja skrotem "background" - bez tego strzalka znikalaby z pola
   zablokowanego albo oznaczonego bledem. */
select.form-control:not([multiple]):not([size]) {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 34px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%235f6478' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px 8px;
}

/* Ponizej 16 px Safari na telefonie przybliza cala strone przy wejsciu w pole:
   ekran skacze, a pola znowu zmieniaja wielkosc. Na ekranach dotykowych pismo
   w polach ma wiec zawsze 16 px - takze w zwartych filtrach i panelach, ktore
   na myszce zostaja drobniejsze. */
@media (pointer: coarse) {
    .form-control,
    .filters-zwarte .form-control,
    .panel-pole .form-control,
    .ustawienie-strony .form-control { font-size: 16px; }

    /* "+ Dodaj kolejna..." w panelu interwencji - pod palec, nie pod podpis. */
    .panel-lista-glowka .btn-maly { height: auto; min-height: 32px; }
}

/* --- Pole wielokrotnego wyboru w filtrach (helpers.php: wybor_wielu) --------
   Wlasciciel: w filtrach zamiast list wyboru pola, w ktorych da sie wybrac
   kilka opcji. Zamkniete wyglada jak lista wyboru - ta sama wysokosc i ta sama
   strzalka, wiec rzad filtrow sie nie rozjezdza. Otwarte pokazuje pola do
   zaznaczania NAD trescia, a strona pod spodem sie nie przesuwa.
   Wagi: "summary.form-control" pod ".wybor-wielu >" (0,2,1) bije
   ".filters-zwarte .form-control" (0,2,0) - inaczej zwarty filtr zabieral
   miejsce na strzalke i napis na nia wchodzil. */
.wybor-wielu { position: relative; min-width: 0; }
.wybor-wielu > summary.form-control {
    display: flex; align-items: center;
    list-style: none; cursor: pointer; user-select: none;
    padding-right: 34px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%235f6478' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px 8px;
}
/* Trojkacik <details> kazda przegladarka rysuje po swojemu - strzalke daje tlo. */
.wybor-wielu > summary::-webkit-details-marker { display: none; }
.wybor-wielu-stan { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.wybor-wielu[open] > summary.form-control { border-color: var(--toz-fokus-ramka); }
/* Zawezony filtr widac bez otwierania - tak samo jak zaznaczony przelacznik. */
.wybor-wielu-aktywny > summary.form-control {
    /* Ramka ze zmiennej fokusu - w trybie ciemnym jasna (granat miał tam 2,43:1; J203). */
    border-color: var(--toz-fokus-ramka);
    background-color: var(--toz-granat-jasny);
    color: var(--toz-granat-ciemny);
}

.wybor-wielu-lista {
    position: absolute; top: calc(100% + 4px); left: 0; z-index: 25;
    min-width: 100%; width: max-content; max-width: calc(100vw - 16px);
    max-height: 18rem; overflow-y: auto;
    margin: 0; padding: 6px;
    display: flex; flex-direction: column; gap: 2px;
    background: #fff; border: 1px solid var(--toz-border); border-radius: 10px;
    box-shadow: 0 12px 28px rgba(16, 20, 33, .18);
}
/* Pole przy prawym brzegu ekranu: lista otwiera sie w lewo, zamiast wystawac
   za ekran (a tam przycina ja straznik overflow-x: clip). Klase dokłada skrypt. */
.wybor-wielu-do-prawej .wybor-wielu-lista { left: auto; right: 0; }
.wybor-wielu-opcja {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px; border-radius: 6px;
    cursor: pointer; font-weight: 400; font-size: .92rem; line-height: 1.3;
    text-transform: none; letter-spacing: normal; color: inherit;
}
.wybor-wielu-opcja:hover { background: var(--toz-granat-jasny); }
.wybor-wielu-opcja input { flex: none; width: 16px; height: 16px; margin: 0; accent-color: var(--toz-granat); }
.wybor-wielu-opcja:has(input:checked) { color: var(--toz-granat-ciemny); font-weight: 600; }
.wybor-wielu-wyczysc {
    align-self: flex-start; margin: 4px 0 0; padding: 4px 8px;
    border: 0; background: none; color: var(--toz-granat); font: inherit; font-size: .85rem;
    text-decoration: underline; cursor: pointer;
}
@media (pointer: coarse) {
    /* Palec, nie kursor: kazda opcja wysoka na 44 px, pole do zaznaczania wieksze. */
    .wybor-wielu-opcja { min-height: 44px; font-size: 16px; }
    .wybor-wielu-opcja input { width: 20px; height: 20px; }
    .wybor-wielu-wyczysc { min-height: 44px; font-size: 16px; }
}
@media print {
    .wybor-wielu-lista { display: none; }
}

/* --- Zarząd: adresy do skopiowania (zarzad/skopiowane.php) ----------------
   Pole jest tylko do odczytu, ale ma wyglądać na pole do zaznaczenia -
   człowiek kopiuje z niego ręcznie, gdy schowek nie jest dostępny. */
.kopiuj-adresy textarea { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9rem; }
/* Kilka adresów e-mail urzędu - każdy w swojej linii, pole tak wysokie jak lista (rows z szablonu), bez zapasu
   na opis (właściciel, 17.10.2026). */
textarea.form-control.pole-adresow { min-height: 0; }

/* --- Zbiórki i pieniądze przy podopiecznych (właściciel, 25.09.2026) -------
   Udział w zbiórce to pole z procentem, tak jak kwota jest polem z "zł";
   nowy podopieczny to imię i pod nim lista kart o tym imieniu. */
.z-procentem { position: relative; display: block; }
.z-procentem .form-control { padding-right: 28px !important; text-align: right; font-variant-numeric: tabular-nums; }
.z-procentem::after {
    content: "%";
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    color: var(--toz-muted); font-size: .85rem; pointer-events: none;
}
.tabela-przypietych td.kol-udzial,
.tabela-przypietych th.kol-udzial { width: 8rem; min-width: 7rem; }
.tabela-przypietych td.liczba,
.tabela-przypietych th.liczba { width: 11rem; min-width: 9rem; }
.tabela-przypietych td.kol-usun,
.tabela-przypietych th.kol-usun { width: 3rem; }
.tabela-przypietych td:first-child { min-width: 16rem; }
.przypiety-nowy { display: grid; gap: 6px; }
/* Suma pieniędzy karty - pierwsza rzecz, której się tu szuka. */
.pieniadze-suma { margin: 0 0 16px; font-size: 1.05rem; }
.pieniadze-suma strong { font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.kwota-ujemna { color: var(--toz-blad); }
.stan-pobierania { margin: 0 0 12px; padding-left: 1.2rem; }
.stan-pobierania li { margin: 4px 0; }
.stan-pobierania .hint-uwaga { display: block; }
/* Na telefonie wiersz podopiecznego zbiórki w dwóch rzędach: u góry kto,
   pod spodem udział, kwota i "×" - w jednym rzędzie pole udziału chowało
   się za prawą krawędzią, a strona i tak nie może uciekać w bok. */
@media (max-width: 640px) {
    .tabela-przypietych thead { display: none; }
    .tabela-przypietych, .tabela-przypietych tbody { display: block; width: 100%; }
    .tabela-przypietych tr {
        display: grid; grid-template-columns: 7.5rem minmax(0, 1fr) auto; align-items: center;
        gap: 6px 10px; padding: 10px 0; border-bottom: 1px solid var(--toz-border);
    }
    .tabela-przypietych td { display: block; padding: 0; border: 0; }
    .tabela-przypietych td:first-child { grid-column: 1 / -1; min-width: 0; }
    .tabela-przypietych td.kol-udzial,
    .tabela-przypietych td.liczba,
    .tabela-przypietych td.kol-usun { width: auto; min-width: 0; }
}
/* Kafelek "Pieniądze" na karcie podopiecznego: nazwa zbiórki i opis wpisu
   nie łamią się po jednym słowie - na telefonie tabela przewija się w ramce. */
#pieniadze .kol-zbiorka { min-width: 12rem; }
#pieniadze .kol-opis { min-width: 12rem; }
/* Zbiórka ponad cel albo z osiągniętym celem - zielono, jak dobra wiadomość. */
.ponad-cel { color: var(--toz-ok); font-weight: 600; }
/* Podopieczni zbiórki na liście zbiórek - imiona z udziałem, zawijane. */
.table td.kol-podopieczni { min-width: 10rem; max-width: 18rem; }
/* Lista celów (0146): strzałki kolejności obok siebie, zamknięte pozycje przygaszone,
   pod kartą pozycji przyciski zamknięcia i usunięcia w jednym rzędzie. */
.kol-przesun { width: 1%; white-space: nowrap; }
.kol-przesun form + form { margin-left: 4px; }
.btn.przesun { min-width: 2.2rem; padding-left: 6px; padding-right: 6px; }
.tabela-celow tr.wiersz-przygaszony td { color: var(--toz-muted); }
.akcje-pozycji { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 16px; }
/* Zdjęcia zbiórek (kopie z zrzutka.pl): na liście miniatura przed nazwą - stały
   prostokąt, także pusty przy zbiórce bez zdjęcia, żeby nazwy stały równo;
   na karcie zdjęcie najwyżej 480 px szerokości i 320 px wysokości (okładka
   zrzutka.pl to 480 x 252, zdjęcie kwadratowe nie spycha kwot w dół). */
.zbiorka-z-miniatura { display: flex; align-items: center; gap: 10px; min-width: 12rem; }
.miniatura-zbiorki {
    flex: 0 0 64px; width: 64px; height: 34px; object-fit: cover;
    border-radius: 4px; border: 1px solid var(--toz-border); background: var(--toz-bg);
}
/* Karta posta: propozycja przypięcia podopiecznych i celów zbiórki z linku na zrzutka.pl (0159).
   Wiersze jeden pod drugim, przycisk przy nazwie; na telefonie zawijają się jak tekst. */
.propozycje-zrzutki {
    margin: 12px 0; padding: 10px 12px;
    border: 1px solid var(--toz-border); border-radius: 6px; background: var(--toz-bg);
}
.propozycje-zrzutki p { margin: 0 0 8px; }
.lista-propozycji { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.lista-propozycji form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Lista podopiecznych: wybrane zdjęcie przy imieniu - z posta z Facebooka (0157),
   ze zbiórki albo z plików karty (0160). Na karcie: zdanie, co stoi przy imieniu,
   i przycisk przy zdjęciu, zbiórce i poście - miniatura, plakietka i przycisk w jednym rzędzie. */
.podopieczny-z-miniatura { display: flex; align-items: center; gap: 10px; }
.zdjecie-na-liscie { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 8px 0 0; }
.wybor-na-liste { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 4px; }
.miniatura-podopiecznego {
    flex: 0 0 40px; width: 40px; height: 40px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--toz-border); background: var(--toz-bg);
}
.zdjecie-zbiorki {
    display: block; width: auto; height: auto; max-width: min(100%, 480px); max-height: 320px; margin: 0 0 16px;
    border-radius: 8px; border: 1px solid var(--toz-border); background: var(--toz-bg);
}
/* Pasek "Przypnij do zaznaczonych" pod listą zbiórek: wąski udział z podpisem,
   a błędy i wskazówka - każde w swoim wierszu paska. */
.zbiorcze .z-procentem { flex: 0 0 6.5rem; }
.zbiorcze .z-procentem .form-control { width: 100%; }
.zbiorcze-etykieta { font-size: .88rem; color: var(--toz-muted); }
.zbiorcze .pole-blad,
.zbiorcze .zbiorcze-wskazowka { flex-basis: 100%; margin: 0; }
/* "Ile zebrano" pod listą zbiórek: "Razem" pogrubione i oddzielone od wierszy
   oddziałów; niepełna suma - gwiazdka z wyjaśnieniem pod tabelą. */
.tabela-zebrano tfoot td { font-weight: 700; }
.tabela-zebrano tfoot td .muted { font-weight: 400; }
.tabela-zebrano tbody + tfoot tr:first-child td { border-top: 2px solid var(--toz-border); }
/* Na telefonie tabela przewija się w bok, a nazwa oddziału nie łamie się na trzy wiersze. */
.tabela-zebrano td:first-child { min-width: 8.5rem; }
.niepelne { color: var(--toz-uwaga); font-weight: 700; margin-left: 2px; }

/* --- Uchwały: treść uchwały (0147) ------------------------------------------
   Powód sprawy i obowiązki z § 15 - jedna opcja w wierszu, długi tekst przepisu
   łamie się pod kółkiem, a nie pod nim. */
.wybor-powodu { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 8px; cursor: pointer; line-height: 1.4; }
.wybor-powodu input { margin-top: 3px; flex: none; }

/* --- Zbiórki: pasek "Przypnij do zaznaczonych" z przełącznikiem podopieczny/cel ---
   Grupa pól nie tworzy własnego pudełka - pola zostają w rzędzie paska (flex),
   a ukryta przełącznikiem grupa znika w całości. */
.zbiorcze-grupa { display: contents; }
.zbiorcze-grupa[hidden] { display: none; }

/* Posty z Facebooka (moduł Media, 27.09.2026: "jedno zdjęcie oraz fragment
   tekstu, po wejściu do środka cały tekst"). Na liście kwadratowa miniatura
   przycięta do środka (zdjęcia z Facebooka bywają poziome, kwadratowe i
   pionowe) i początek treści obok; na karcie zdjęcie w całości i cały tekst
   z nowymi liniami tak, jak na Facebooku. */
.post-z-miniatura { display: flex; align-items: flex-start; gap: 12px; min-width: 16rem; }
.miniatura-posta {
    flex: 0 0 72px; width: 72px; height: 72px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--toz-border); background: var(--toz-bg);
}
.fragment-posta { max-width: 70ch; overflow-wrap: anywhere; }
/* Wiersz, do którego lista wraca po "Odepnij" (#post-...) - nad nim zapas na przyklejony nagłówek tabeli. */
.tabela-postow tbody tr[id] { scroll-margin-top: 3.5rem; }
.zdjecie-posta {
    display: block; width: auto; height: auto; max-width: min(100%, 560px); max-height: 560px; margin: 0 0 16px;
    border-radius: 8px; border: 1px solid var(--toz-border); background: var(--toz-bg);
}
.tresc-posta { white-space: pre-line; overflow-wrap: anywhere; max-width: 70ch; margin: 0 0 20px; line-height: 1.55; }
/* Podpowiedź do rodzaju sprawy: pod listą "Nowa sprawa" na karcie uchwały
   i w nagłówku strony sprawy - tabelka faktów mniejszym pismem. */
.podpowiedz-sprawy { font-size: .9rem; }
/* Osoby spoza listy członków w sprawie przyjęcia (0153). */
.sprawa-wpisane-tytul { margin: 18px 0 4px; }
.sprawa-wpisane td { vertical-align: top; }
.sprawa-wpisane .form-control { min-width: 9em; }
.podpowiedz-sprawy .facts { margin: 8px 0 0; }
.podpowiedz-sprawy.facts { margin: 0 0 24px; }
.podpowiedz-sprawy dt { color: var(--toz-muted); }
/* Sprawa uchwały na karcie uchwały (27.09.2026) - pod paskiem wyboru rodzaju,
   oddzielona kreską od listy spraw i od zebrania niżej. */
.sprawa-na-karcie { margin: 18px 0 28px; padding: 16px 0 4px; border-top: 1px solid var(--toz-border);
    /* Kotwica #sprawa-formularz - nagłówek nie ląduje pod przyklejoną belką (jak .card[id]),
       a ujemny margines paska zapisu nie zjada odstępu przed "Zebraniem". */
    scroll-margin-top: 76px; display: flow-root; }

/* Cele dotykowe na telefonie (audyt 29.09.2026, C180): pola wyboru w tabelach, strzałki kolejności
   wzorów, znaczek Facebooka przy imieniu i kółko-odnośnik z inicjałami w dzienniku zdarzeń (13.11.2026) - bez zmiany
   wyglądu na komputerze. Kółko-odnośnik: obrys przy fokusie na brzegu powiększonego pola (6 px od kółka), dalej poza
   złotym pierścieniem własnego kółka (3,5 px) i w odstępie komórki. */
@media (pointer: coarse) {
    .kol-zaznacz input { width: 22px; height: 22px; }
    .wzor-kolejnosc { gap: 4px; }
    .wzor-strzalka { width: 32px; height: 28px; line-height: 26px; }
    .table a.znak-fb, .table a.znak-strony, .table a.kolko-z-podpisem { padding: 6px; margin: -6px; }
    .table a.kolko-z-podpisem:focus-visible { outline-offset: 0px; }
    .dymek-zamknij { min-width: 44px; min-height: 44px; }
}

/* --- Wygładzenie wyglądu (właściciel, 02.10.2026: "weź trochę grafikę popraw
   użytkownikom, żeby im się łatwiej i przyjemniej pracowało") ----------------
   Same drobiazgi, bez zmiany układu: kolory i odstępy, które dotąd brały się
   z ustawień przeglądarki, i łagodne przejścia tam, gdzie coś reaguje na mysz.
   Reguły stoją na końcu i mają niską wagę - nie przebijają niczego, co ekran
   ustawia sam. */

/* Odnośnik bez własnej klasy miał domyślny niebieski przeglądarki ("Nie pamiętam
   hasła", "Kto ma dane uprawnienie?", nazwy wzorów) - obcy przy granacie marki. */
a { color: var(--toz-granat-ciemny); text-underline-offset: 2px; }
a:not([class]):hover { color: var(--toz-granat); }

/* Pola wyboru i przełączniki w kolorze marki zamiast systemowego. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--toz-granat); }
input[type="checkbox"], input[type="radio"], label.przelacznik, label.uprawnienie { cursor: pointer; }
input[type="checkbox"]:disabled, input[type="radio"]:disabled { cursor: not-allowed; }

/* Zaznaczony tekst - jasny granat zamiast systemowego błękitu. */
::selection { background: #cfd9f2; color: var(--toz-text); }

/* Karta z samym przyciskiem "Dodaj ..." nie ma pustego pasa pod spodem. */
.card > .dodanie-faktury:last-child { margin-bottom: 0; }

/* Tabela pod paskiem filtrów w tej samej karcie (terminarz) dostaje oddech. */
.filters + .table-wrap, .filters + .tabela-z-naglowkiem, .filters + .pusto,
.filters + .przelacznik-kolumn + .table-wrap, .filters + .przelacznik-kolumn + .tabela-z-naglowkiem { margin-top: 16px; }


/* Przełącznik pod kursorem pokazuje, że da się go kliknąć. */
/* Tylko niezaznaczony: zaznaczony ma własne barwy (także czerwone przy przełączniku
   ostrzegawczym) i pod kursorem ich nie zmienia. */
.przelacznik:not(:has(input:checked)):hover { border-color: #c3cbe2; background: var(--toz-belka-tlo); }

/* Wiersz pod kursorem wyraźniej - w tabeli na kilkanaście kolumn oko trzyma się linii. */
.table tbody tr:hover { background: #f1f4fb; }

/* Pole pod kursorem zapowiada, że da się w nie pisać. */
/* :where() trzyma wagę zwykłej klasy - pole z błędem, powtórką i pole w trakcie pisania
   zachowują własną ramkę. */
.form-control:where(:not([readonly]):not(:disabled):not(:focus):not(.form-control-blad):not(.form-control-powtorka)):hover { border-color: #5d6a96; }

/* Łagodne przejścia kolorów; kto wyłączył animacje w systemie, nie dostaje żadnej. */
@media (prefers-reduced-motion: no-preference) {
    .btn, .form-control, .przelacznik, .nav a, .nav-grupa > summary, .zakladka, .kafelek {
        transition: background-color .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease;
    }
    .btn { transition-property: background-color, border-color, color, box-shadow, transform; }
}

/* Na telefonie główne pole "Szukaj" zajmuje cały wiersz paska filtrów - w połowie
   szerokości podpowiedź ("nazwisko, e-mail, telefon...") była ucięta po dwóch słowach. */
@media (max-width: 520px) {
    .filters > div:has(> #q, > #f-q) { grid-column: 1 / -1; }
}
/* Na szerszym ekranie to samo pole bierze dwie kolumny paska - obok i tak zostaje puste
   miejsce, a w jednej kolumnie (136 px) podpowiedź nie mieściła się także na komputerze.
   #f-q to to samo pole na liście postów i celów zbiórek. */
@media (min-width: 521px) {
    .filters-zwarte > div:has(> #q, > #f-q) { grid-column: span 2; }
}

/* ===========================================================================
   Efekty wizualne (właściciel, 02.10.2026: "powprowadzaj jakieś extra efekty
   graficzne, wizualne, animacyjne itd. Daję Ci wolną rękę").

   Zasady tej sekcji - każda z nich pilnuje czegoś, co już raz się zepsuło
   albo zepsułoby po cichu (pilnuje ich tests/unit-efekty.php):
   - ruch mówi "kliknięcie doszło" albo "to się właśnie pojawiło"; nic nie rusza
     się bez powodu, nic nie znika samo i nic nie zmienia rozmiaru;
   - wszystko, co się rusza, stoi w @media (prefers-reduced-motion: no-preference) -
     kto wyłączył animacje w systemie, dostaje ekran nieruchomy;
   - karta (.card) i treść strony nie dostają animacji, która na nich zostaje
     (forwards / both), ani przesunięcia: taki element jest osobną warstwą,
     a lista filtra wystająca z karty chowałaby się pod następną kartą. Animuje
     się sam element, który się pojawia (lista, okno, komunikat);
   - nic pod kursorem nie ucieka (hover + przesunięcie migocze na krawędzi);
   - ekran logowania dostaje te same efekty, ale żadnego znaku rozpoznawczego;
   - dymek z podpowiedzią (.dymek-od-razu) i mapy zostają bez ruchu.
   =========================================================================== */

/* --- Tło i znaki marki ------------------------------------------------------ */

/* Tytuł strony ma znak z lewej: pionową kreskę z granatu w złoto - te same barwy
   co kreska nad belką menu. Nie zabiera wysokości i nie jest częścią tekstu. */
h1.h4::before {
    content: ''; display: inline-block; width: 4px; height: .82em; margin-right: 10px;
    border-radius: 2px; vertical-align: -.06em;
    background: linear-gradient(180deg, var(--toz-granat), var(--toz-zloto));
}


/* Pole z klasą "input" (opis wzoru, szukanie na mapie) wyglądało jak surowe pole
   przeglądarki z czarną ramką - dostaje ramkę i obwódkę jak reszta pól. */
.input {
    min-height: 34px; padding: 5px 9px; font: inherit; font-size: .9rem; color: var(--toz-text);
    /* Ramka jak w .form-control (3:1 wobec tła) - jasna linia znikała na białym pasku, np. szukanie nad mapą (J204). */
    background: #fff; border: 1px solid var(--toz-pole-ramka); border-radius: 8px;
}
.input:focus, .input:focus-visible { outline: 3px solid var(--toz-fokus-poswiata); outline-offset: 0; border-color: var(--toz-fokus-ramka); }
@media (pointer: coarse) {
    .input { font-size: 16px; }
}
/* Safari rysuje pole szukania po swojemu (zaokrąglone, z lupką) i nie słucha ramki. */
input.input[type="search"] { -webkit-appearance: none; appearance: none; }
input.input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
/* Puste pole szukania: Chrome trzyma miejsce na niewidoczny krzyżyk „wyczyść”, więc podpowiedź w wąskim
   polu filtra traciła ostatnie litery („nazwisko, e-mai”). Krzyżyk wraca, gdy w polu coś jest. */
input[type="search"]:placeholder-shown::-webkit-search-cancel-button { display: none; }

/* Wiersz pod kursorem dostaje granatową kreskę z lewej - w szerokiej tabeli widać,
   który to wiersz, także gdy ma własny kolor stanu. Rysuje się tylko pod kursorem.
   Wiersz w trakcie poprawki ma własne kreski, a nagłówek wiersza (th) własną linię - zostają.
   Tylko tam, gdzie jest kursor: na telefonie "hover" zostaje po dotknięciu, a kreska
   wchodziłaby pod tekst w tabelach ułożonych w karty. */
@media (hover: hover) { .table tbody tr:not(.wiersz-edytowany):hover > td:first-child { box-shadow: inset 3px 0 0 var(--toz-granat); } }

/* Pusta lista: odcisk łapy nad napisem - po zalogowaniu wiadomo, czyj to system,
   a puste miejsce przestaje wyglądać jak błąd. Na ekranach przed logowaniem pustych
   list nie ma. Rysunek stoi w arkuszu, nie w treści strony. */
p.pusto::before {
    content: ''; display: block; width: 34px; height: 34px; margin: 0 auto 10px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23b9c3de'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Pasek "strona się wczytuje" u samej góry okna - zakłada go efekty.js po kliknięciu
   w odnośnik albo wysłaniu formularza, gdy odpowiedź nie przychodzi od razu. */
.postep-strony {
    position: fixed; left: 0; right: 0; top: 0; z-index: 90; height: 3px; pointer-events: none; opacity: 0;
    background-color: var(--toz-zloto);
    background-image: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .9) 50%, rgba(255, 255, 255, 0));
    background-repeat: no-repeat; background-size: 30% 100%; background-position: -45% 0;
}
html.w-drodze .postep-strony { opacity: 1; }

/* Wylogowanie zauważone przez skrypt w tle (wylogowanie-w-tle.js; audyt 08.10.2026, J42) - pasek u góry okna,
   widoczny także przy formularzu przewiniętym daleko w dół: nad belką menu i rozwijanymi listami, pod paskiem
   wczytywania. Barwy komunikatu ostrzeżenia, "×" jak w dymkach. */
.wylogowano-w-tle {
    position: fixed; left: 0; right: 0; top: 0; z-index: 45; margin: 0; border-radius: 0; padding-right: 56px;
    box-shadow: 0 6px 18px rgba(44, 67, 129, .14);
}
.wylogowano-w-tle .dymek-zamknij { top: 50%; right: 6px; transform: translateY(-50%); }
@media print { .wylogowano-w-tle { display: none; } }

@media print {
    h1.h4::before, p.pusto::before, .postep-strony { display: none; }
    /* Poświata tła i granat odnośników są dla ekranu - na papierze biel i czerń jak dotąd. */
    body { background-image: none; }
    a { color: #000; }
}

/* --- Ruch --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
    /* Przejście między stronami: stara treść gaśnie, nowa wchodzi od dołu o kilka
       punktów. Belka menu stoi w miejscu. Robi to przeglądarka (Chrome, Safari);
       starsza po prostu pokazuje stronę jak dotąd. Przesuwa się obraz strony,
       nie jej elementy - skrypty mierzące tabelę i menu widzą je na swoim miejscu. */
    @view-transition { navigation: auto; }
    .topbar { view-transition-name: belka; }
    ::view-transition-old(root) { animation: toz-strona-zgas .12s ease-out both; }
    ::view-transition-new(root) { animation: toz-strona-wejdz .22s ease-out both; }
    ::view-transition-old(belka) { display: none; }
    ::view-transition-new(belka), ::view-transition-group(belka) { animation: none; }

    /* Przeglądarka bez przejść między stronami: sama treść wchodzi z przezroczystości.
       Bez przesunięcia (nagłówek tabeli mierzy swoje położenie przy wczytaniu)
       i bez "forwards" - po 0,18 s po animacji nie zostaje nic. */
    @supports not (view-transition-name: none) {
        .main { animation: toz-zjaw .18s ease-out backwards; }
    }

    /* Kreska nad belką rysuje się od lewej po wczytaniu strony - odpowiedź na pasek
       wczytywania sprzed chwili (sam ruch kreski stoi niżej, razem z przebiegającym światłem).
       Belka pod przewiniętą stroną ma mocniejszy cień. */
    .topbar::before { transform-origin: 0 50%; }
    @supports (animation-timeline: scroll()) {
        .topbar { animation: toz-belka-cien linear both; animation-timeline: scroll(root block); animation-range: 0 140px; }
    }

    /* Godło w belce odchyla się pod kursorem - sam obrazek, nie odnośnik. */
    .brand img { transition: transform .22s cubic-bezier(.2, .8, .2, 1); }
    .brand:hover img, .brand:focus-visible img { transform: rotate(-8deg) scale(1.07); }

    /* Komunikat po zapisie wjeżdża z góry - widać, że pojawił się teraz. Nie znika sam.
       Tylko komunikat strony (nad treścią); uwagi stojące na stałe w kartach się nie ruszają. */
    .main > .alert { animation: toz-komunikat .34s cubic-bezier(.2, .8, .2, 1) backwards; }

    /* Rozwijane listy (filtr, "Zmień" przy wzorze) i panel menu na telefonie otwierają
       się płynnie. Panel menu rozpoznajemy po przycisku, nie po klasach strony: menu.js
       zdejmuje je przy każdym pomiarze paska, a telefon mierzy przy przewijaniu - animacja
       po klasach odtwarzałaby się w kółko. Z tego samego powodu lista grupy w pasku menu
       zostaje bez ruchu: pomiar chowa ją na chwilę i otwarta lista mrugałaby przy każdej
       zmianie rozmiaru okna. */
    .wybor-wielu[open] > .wybor-wielu-lista,
    .wzor-zarzadzanie[open] > .wzor-zarzadzanie-tresc { animation: toz-rozwin .15s ease-out; }
    .menu-przelacznik[aria-expanded="true"] + .nav { animation: toz-rozwin .2s ease-out; }

    /* Okno pytania i podgląd pliku: tło ciemnieje, okno podnosi się na miejsce. */
    .okno-pytania[open] { animation: toz-okno .2s cubic-bezier(.2, .8, .2, 1); }
    .podglad[open] { animation: toz-zjaw .18s ease-out; }
    .okno-pytania[open]::backdrop, .podglad[open]::backdrop { animation: toz-zjaw .2s ease-out; }

    /* Pole z błędem po odrzuconym zapisie drga raz - oko trafia od razu tam, gdzie trzeba poprawić. */
    .form-control-blad { animation: toz-drgnienie .36s ease-in-out .12s 1; }
    /* Raport kasowy sprawdza pola w trakcie pisania - tam pole drgałoby pod kursorem
       przy każdym przecinku w kwocie. */
    [data-pozycje-kasy] .form-control-blad { animation: none; }

    /* Zaznaczone pole wyboru "wskakuje" - potwierdzenie kliknięcia. Klasę dokłada efekty.js
       po kliknięciu; pole zaznaczone przy wczytaniu strony stoi nieruchomo. */
    .przelacznik input.klikniete:checked { animation: toz-wskok .22s ease-out; }

    /* Łapa w pustej liście stawia się jak pieczątka. */
    p.pusto::before { animation: toz-lapa .5s cubic-bezier(.2, .8, .2, 1) .08s backwards; }

    /* Pasek wczytywania: światło przebiega po złotej kresce, dopóki strona nie odpowie. */
    .postep-strony { transition: opacity .18s ease-out; }
    html.w-drodze .postep-strony { animation: toz-postep 1.05s linear infinite; }

    @keyframes toz-strona-zgas { to { opacity: 0; } }
    @keyframes toz-strona-wejdz { from { opacity: 0; transform: translateY(8px); } }
    @keyframes toz-zjaw { from { opacity: 0; } }
    @keyframes toz-kreska { from { transform: scaleX(0); } }
    @keyframes toz-belka-cien { to { box-shadow: 0 8px 22px rgba(44, 67, 129, .16); } }
    @keyframes toz-komunikat { from { opacity: 0; transform: translateY(-10px); } }
    @keyframes toz-rozwin { from { opacity: 0; transform: translateY(-6px); } }
    @keyframes toz-okno { from { opacity: 0; transform: translateY(12px) scale(.97); } }
    @keyframes toz-drgnienie { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }
    @keyframes toz-wskok { from { transform: scale(.55); } 60% { transform: scale(1.18); } }
    @keyframes toz-lapa { from { opacity: 0; transform: scale(.55) rotate(-18deg); } }
    @keyframes toz-postep { from { background-position: -45% 0; } to { background-position: 145% 0; } }
}

/* ===========================================================================
   Grafika, ciąg dalszy (właściciel, 03.10.2026: "weź się pobaw tą stroną
   graficznie"). Te same zasady co w "Efektach wizualnych" wyżej: nic się tu
   nie rusza, nic nie zmienia układu ani rozmiaru - same barwy, kreski i cyfry.
   =========================================================================== */

/* Terminarz, kolumna "Zostało": plakietka w barwie pilności - po terminie czerwona,
   dziś i jutro bursztynowa, w tym tygodniu granatowa, dalej sam szary napis. */
.zostalo {
    display: inline-block; padding: 1px 9px; border-radius: 999px; white-space: nowrap;
    font-size: .82rem; font-weight: 600; line-height: 1.55; font-variant-numeric: tabular-nums;
}
.zostalo-po      { background: var(--toz-tlo-blad); color: var(--toz-blad); box-shadow: inset 0 0 0 1px #f1c9ce; }
.zostalo-blisko  { background: var(--toz-tlo-uwaga); color: var(--toz-uwaga); box-shadow: inset 0 0 0 1px #efdcae; }
.zostalo-tydzien { background: var(--toz-granat-jasny); color: var(--toz-granat-ciemny); }
.zostalo-dalej   { color: var(--toz-muted); font-weight: 500; }

/* Plakietka w wąskiej kolumnie stanu nie łamie się na dwa wiersze
   ("raport / inspektorski") - wiersz tabeli zostaje jednej wysokości. */
.table td.kol-stan .badge { white-space: nowrap; }
/* Pole "Stan" w wierszu listy celów (właściciel, 09.11.2026: "a nie lepiej to zmieniać polem "stan" i pozwalać nim
   przełączać ?") - wąskie, w barwie plakietki stanu (zielone otwarte, szare zamknięte); "Zmień" tylko bez skryptu. */
.wybor-stanu-formularz { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin: 0; }
select.form-control.wybor-stanu:not([multiple]):not([size]) {
    display: inline-block;
    width: auto;
    max-width: 100%;
    min-height: 32px;
    padding: 4px 30px 4px 10px;
    font-size: .875rem;
    background-position: right 10px center;
}
.wybor-stanu-otwarty { border-color: #bcdcc9; color: var(--toz-ok); font-weight: 600; }
.wybor-stanu-zamkniety { color: #41465a; }
/* Na dotyku jak każde pole (przegląd 09.11.2026): 16 px pisma, bo mniejsze Safari przybliża przy wejściu w pole, i 44 px pod palec. */
@media (pointer: coarse) {
    select.form-control.wybor-stanu:not([multiple]):not([size]) { font-size: 16px; min-height: 44px; }
}

/* Cyfry tej samej szerokości w datach i numerach porządkowych - kolumna dat
   stoi równo jak w kalendarzu, a nie "pływa" przy jedynkach. */
.kol-data, .kol-lp-lista, .kol-lp { font-variant-numeric: tabular-nums; }

/* Bez pasów co drugi wiersz (właściciel, 03.10.2026: "nie maluj co drugiej linii w tabelkach, bo to myli,
   szczególnie jak wykorzystujemy kolory do oznaczania czegoś") - kolor wiersza mówi tylko o jego stanie. */

/* Tytuł sekcji formularza dostaje tę samą kreskę co tytuł strony, tylko mniejszą -
   widać, że "Adres", "Dane osoby", "Kwoty" to kolejne części jednej karty. */
.sekcja > legend::before {
    content: ''; display: inline-block; width: 3px; height: .95em; margin-right: 7px;
    border-radius: 2px; vertical-align: -.12em;
    background: linear-gradient(180deg, var(--toz-granat), var(--toz-zloto));
}

@media print {
    .sekcja > legend::before { display: none; }
    .zostalo { padding: 0; background: none; box-shadow: none; color: #000; }
}

/* ===========================================================================
   Kolor i ruch (właściciel, 03.10.2026: "Pobaw się trochę kolorystyką
   i animacjami, tak, aby strona była bardziej dynamiczna i przyciągała wzrok").
   Zasady "Efektów wizualnych" obowiązują dalej (pilnuje ich unit-efekty):
   cały ruch tylko w bloku prefers-reduced-motion; karta, treść strony i wiersz
   tabeli wchodzą samą przezroczystością, bez przesunięcia i bez "zostaje";
   nic pod kursorem nie ucieka; wydruk zostaje bez ozdób.
   =========================================================================== */

/* --- Barwy ------------------------------------------------------------------ */

/* Barwna poświata za treścią (element w layout.php): granat z lewej, złoto z prawej,
   chłodny błękit u dołu. Widać ją w odstępach między kartami - karty i belka zostają białe.
   Warstwy przypięte do ekranu mają wysokość dużego ekranu (lvh), a nie dolną krawędź okna: na telefonie pasek adresu
   chowa się i wraca przy przewijaniu, a warstwa do dolnej krawędzi rozciągała się wtedy razem z nim i tło skakało
   (właściciel, 28.10.2026). Tak samo .tlo-swiatlo, .okazja-tlo, .swieto i .logowanie-tropy - pilnuje unit-telefon. */
.tlo-zorza {
    position: fixed; inset: 0 0 auto; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none;
    background:
        radial-gradient(42% 38% at 8% 6%, rgba(58, 87, 162, .28), rgba(58, 87, 162, 0) 70%),
        radial-gradient(36% 34% at 94% 2%, rgba(215, 181, 109, .38), rgba(215, 181, 109, 0) 70%),
        radial-gradient(48% 42% at 78% 100%, rgba(96, 134, 214, .21), rgba(96, 134, 214, 0) 70%),
        radial-gradient(34% 30% at 2% 92%, rgba(215, 181, 109, .19), rgba(215, 181, 109, 0) 70%);
}

/* Lekki wzór w tle (właściciel, 16.10.2026: "troszkę delikatnych kolorów i jakiś lekkich grafik w tle systemu, tak,
   aby go nie zwalniać"): łapki, serduszko i listek - maska jednego kafelka SVG w treści arkusza (bez pobierania),
   w granacie marki, prawie przezroczyste. Leży w nieruchomej warstwie zorzy ZA treścią - widać go tylko w odstępach
   między kartami; bez ruchu, więc nie kosztuje nic przy przewijaniu. */
.tlo-zorza::after {
    content: ''; position: absolute; inset: 0;
    background: var(--toz-granat); opacity: .055;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(18 22) rotate(-18 12 12) scale(.5)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(122 34) scale(.62)'%3E%3Cpath d='M12 21s-7.5-4.6-10-9.2C.3 8.6 2.1 4.5 6 4.5c2.3 0 3.8 1.3 6 3.6 2.2-2.3 3.7-3.6 6-3.6 3.9 0 5.7 4.1 4 7.3C19.5 16.4 12 21 12 21z'/%3E%3C/g%3E%3Cg transform='translate(70 118) rotate(10 12 12) scale(.66)'%3E%3Cpath d='M2 22C2 10 10 2 22 2c0 12-8 20-20 20zm2-2c4-6 9-11 15-15-6 4-11 9-15 15z' fill-rule='evenodd'/%3E%3C/g%3E%3Cg transform='translate(146 132) rotate(24 12 12) scale(.42)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Ccircle cx='92' cy='60' r='2'/%3E%3Ccircle cx='30' cy='160' r='2.4'/%3E%3Ccircle cx='180' cy='92' r='1.8'/%3E%3C/svg%3E") 0 0 / 200px 200px repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(18 22) rotate(-18 12 12) scale(.5)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(122 34) scale(.62)'%3E%3Cpath d='M12 21s-7.5-4.6-10-9.2C.3 8.6 2.1 4.5 6 4.5c2.3 0 3.8 1.3 6 3.6 2.2-2.3 3.7-3.6 6-3.6 3.9 0 5.7 4.1 4 7.3C19.5 16.4 12 21 12 21z'/%3E%3C/g%3E%3Cg transform='translate(70 118) rotate(10 12 12) scale(.66)'%3E%3Cpath d='M2 22C2 10 10 2 22 2c0 12-8 20-20 20zm2-2c4-6 9-11 15-15-6 4-11 9-15 15z' fill-rule='evenodd'/%3E%3C/g%3E%3Cg transform='translate(146 132) rotate(24 12 12) scale(.42)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Ccircle cx='92' cy='60' r='2'/%3E%3Ccircle cx='30' cy='160' r='2.4'/%3E%3Ccircle cx='180' cy='92' r='1.8'/%3E%3C/svg%3E") 0 0 / 200px 200px repeat;
}

/* Karta z tytułem strony ma u góry kreskę w barwach marki - granat w złoto, jak kreska
   nad belką. To tylko warstwa obrazka: kolor tła karty zostaje taki, jaki był. */
.card:has(> .card-head > h1) {
    background-image: linear-gradient(90deg, var(--toz-granat), #6f86c9 45%, var(--toz-zloto)),
        linear-gradient(155deg, rgba(58, 87, 162, .09) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 70%, rgba(215, 181, 109, .13) 100%);
    background-size: 100% 4px, 100% 100%; background-repeat: no-repeat; background-position: 0 0, 0 0;
}

/* Każda inna karta ma u góry tę samą kreskę marki, tylko cieńszą i łagodniejszą - strona
   wygląda jak jedna całość w granacie i złocie. Jak wyżej: sama warstwa obrazka. */
.card:not(:has(> .card-head > h1)) {
    background-image: linear-gradient(90deg, rgba(58, 87, 162, .6), rgba(111, 134, 201, .55) 45%, rgba(215, 181, 109, .75));
    background-size: 100% 3px; background-repeat: no-repeat; background-position: 0 0;
}



/* Tytuł strony w spadku barwy: od głębokiego granatu do granatu marki. Tylko na ekranie
   i tylko tam, gdzie przeglądarka umie wypełnić napis obrazkiem - inaczej zwykły kolor. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    @media screen {
        h1.h4 {
            background-image: linear-gradient(90deg, #1d2748, var(--toz-granat) 70%, #5470bd);
            -webkit-background-clip: text; background-clip: text; color: transparent;
        }
    }
}

/* Karta pytania przed usunięciem: kreska czerwona, nie granatowa - to nie zwykły ekran. */
.card.card-danger:has(> .card-head > h1), .card.card-danger:not(:has(> .card-head > h1)) {
    background-image: linear-gradient(90deg, var(--toz-blad), #d4707b 55%, rgba(212, 112, 123, .4));
    background-size: 100% 4px; background-repeat: no-repeat; background-position: 0 0;
}

/* Karta z samym przyciskiem "Dodaj ..." pod filtrami: jasna smuga z granatu w złoto -
   najważniejsze działanie na stronie widać od razu. */
.card:has(> .dodanie-faktury:only-child) {
    background-image: linear-gradient(90deg, rgba(58, 87, 162, .6), rgba(111, 134, 201, .55) 45%, rgba(215, 181, 109, .75)),
        linear-gradient(100deg, rgba(58, 87, 162, .10), rgba(255, 255, 255, 0) 45%, rgba(215, 181, 109, .16));
    background-size: 100% 3px, 100% 100%; background-repeat: no-repeat; background-position: 0 0, 0 0;
}


/* Tytuły części kart (h2) w granacie marki. */
.card .h5 { color: var(--toz-granat-ciemny); }

/* Łapa w pustej liście w spadku z granatu w złoto (ten sam kształt, wycięty maską). */
@supports ((-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E")) or (mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E"))) {
    p.pusto::before {
        background: linear-gradient(135deg, var(--toz-granat), #7d8fd0 50%, var(--toz-zloto));
        -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
        opacity: .5;
    }
}

/* Tytuł części karty (h2) ma z lewej mały znak w barwach marki - jak kreska przy tytule strony, tylko lżejszy. */
.card-head > h2::before, .koszty-ai-naglowek h2::before {
    content: ''; display: inline-block; width: 8px; height: 8px; margin-right: 9px; border-radius: 3px;
    vertical-align: .12em; background: linear-gradient(135deg, var(--toz-granat), var(--toz-zloto));
}

/* Zaznaczony wiersz listy (pole z lewej) ma lekki granatowy odcień - widać od razu, co pójdzie do paska działań.
   Warstwa obrazka, więc kolor stanu wiersza (np. po terminie) zostaje pod spodem. */
.table tbody tr:has(> td.kol-zaznacz input:checked) > td { background-image: linear-gradient(rgba(58, 87, 162, .09), rgba(58, 87, 162, .09)); }
.table tbody tr:has(> td.kol-zaznacz input:checked) > td.kol-zaznacz { box-shadow: inset 3px 0 0 var(--toz-granat); }

/* Stopka: ślad łapek idący przez stronę, tuż nad napisem - lekka grafika na pożegnanie strony. */
.footer::after {
    content: ''; display: block; width: 240px; height: 40px; margin: 10px 0 0 auto; opacity: .3;
    background: linear-gradient(90deg, var(--toz-granat), var(--toz-zloto));
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 40'%3E%3Cg transform='translate(0 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(40 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(82 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(124 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(166 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(208 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 40'%3E%3Cg transform='translate(0 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(40 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(82 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(124 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(166 18) rotate(80 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3Cg transform='translate(208 4) rotate(95 24 24) scale(.36)'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
}

/* Stopka oddzielona kreską marki, gasnącą w prawo. */
.footer::before {
    content: ''; display: block; height: 1px; margin-bottom: 14px;
    background: linear-gradient(90deg, rgba(58, 87, 162, .45), rgba(215, 181, 109, .6) 35%, rgba(215, 181, 109, 0));
}


/* Nagłówek tabeli: lekki spadek barwy z góry w dół zamiast płaskiej plamy. */
@media screen {
    .table thead th {
        background-image: linear-gradient(180deg, #eef2fb, #d8e0f5);
        box-shadow: inset 0 -2px 0 var(--toz-zloto), 0 2px 3px rgba(43, 42, 41, .05);
    }
}

/* Plakietka stanu ma z przodu kropkę w swoim kolorze - kolor widać od razu,
   także przy krótkim napisie. */
.stan::before {
    content: ''; display: inline-block; width: .5em; height: .5em; margin-right: .38em;
    border-radius: 50%; background: currentColor; vertical-align: .08em; opacity: .8;
}
.stan-alarm::before { opacity: 1; }

/* Kafelki z liczbami: liczba w kolorowym spadku (tło kafelka - w jego sekcji wyżej). */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    @media screen {
        .kafelek-liczba {
            background-image: linear-gradient(90deg, var(--toz-granat-ciemny), #5a76c6);
            -webkit-background-clip: text; background-clip: text; color: transparent;
        }
        .kafelek-alarm .kafelek-liczba { background-image: linear-gradient(90deg, #8f1f2b, #cf4a58); }
    }
}

@media print {
    .tlo-zorza, .stan::before, .footer::before, .footer::after { display: none; }
    .card, .card:has(> .card-head > h1), .card:not(:has(> .card-head > h1)), .card:has(> .dodanie-faktury:only-child),
    .card.card-danger:has(> .card-head > h1), .card.card-danger:not(:has(> .card-head > h1)), .card-head { background-image: none; }
    .card-head { border-bottom-color: var(--toz-border); }
    .btn:not(.btn-primary):not(.btn-danger):not(.btn-link):not(.btn-strona-aktywna), .breadcrumb a { background-image: none; }
}

/* --- Ruch --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
    /* Poświata dryfuje bardzo powoli - strona "oddycha", nic nie skacze. Warstwa
       przesuwa się w całości (bez przerysowania), więc nie obciąża przewijania. */
    .tlo-zorza { will-change: transform; animation: toz-zorza 38s ease-in-out infinite alternate; }

    /* Karty strony pojawiają się po kolei - sama przezroczystość i "backwards": po animacji na karcie
       nie zostaje nic (zasada "Efektów"). Szybko (04.10.2026, przegląd przejść): cała strona stoi
       po ćwierć sekundy, bo między listą a kartą przechodzi się kilkadziesiąt razy dziennie. */
    .main > .card:nth-child(1) { animation: toz-zjaw .24s ease-out backwards; }
    .main > .card:nth-child(2) { animation: toz-zjaw .24s ease-out .04s backwards; }
    .main > .card:nth-child(3) { animation: toz-zjaw .24s ease-out .08s backwards; }
    .main > .card:nth-child(n+4) { animation: toz-zjaw .24s ease-out .12s backwards; }

    /* Wiersze listy wchodzą krótką falą od góry - pierwsze piętnaście po kolei, następne do czterdziestego
       (tyle mieści najwyższy ekran) razem z ostatnim z fali; dalsze stoją od razu. Wszystko widać po 0,4 s.
       Też sama przezroczystość. */
    .table-wrap-ewidencja .table tbody tr:nth-child(1) { animation: toz-zjaw .2s ease-out 0.03s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(2) { animation: toz-zjaw .2s ease-out 0.04s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(3) { animation: toz-zjaw .2s ease-out 0.05s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(4) { animation: toz-zjaw .2s ease-out 0.06s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(5) { animation: toz-zjaw .2s ease-out 0.07s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(6) { animation: toz-zjaw .2s ease-out 0.08s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(7) { animation: toz-zjaw .2s ease-out 0.09s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(8) { animation: toz-zjaw .2s ease-out 0.10s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(9) { animation: toz-zjaw .2s ease-out 0.11s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(10) { animation: toz-zjaw .2s ease-out 0.12s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(11) { animation: toz-zjaw .2s ease-out 0.13s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(12) { animation: toz-zjaw .2s ease-out 0.14s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(13) { animation: toz-zjaw .2s ease-out 0.15s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(14) { animation: toz-zjaw .2s ease-out 0.16s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(15) { animation: toz-zjaw .2s ease-out 0.17s backwards; }
    .table-wrap-ewidencja .table tbody tr:nth-child(n+16):nth-child(-n+40) { animation: toz-zjaw .2s ease-out .18s backwards; }

    /* Kreska tytułu strony i tytułów sekcji rośnie od dołu, kreska pod nagłówkiem karty
       rysuje się od lewej - strona "składa się" na oczach, w pół sekundy. */
    h1.h4::before { transform-origin: 50% 100%; animation: toz-rosnij .4s cubic-bezier(.2, .8, .2, 1) .08s backwards; }
    .sekcja > legend::before { transform-origin: 50% 100%; animation: toz-rosnij .35s cubic-bezier(.2, .8, .2, 1) .15s backwards; }
    .card-head { animation: toz-linia .5s cubic-bezier(.2, .8, .2, 1) .1s backwards; }

    /* Przycisk główny pod kursorem: światło przebiega raz przez przycisk. Kliknięty
       przycisk wypuszcza falę - "kliknięcie doszło" (klasę dokłada efekty.js po wciśnięciu). */
    .btn-primary:not(:disabled):hover { animation: toz-blysk .8s ease-out; }
    .btn.klik-fala { animation: toz-fala .5s ease-out; }
    .btn-primary:not(:disabled):hover.klik-fala { animation: toz-blysk .8s ease-out, toz-fala .5s ease-out; }

    /* Po kresce marki nad belką co kilka sekund przebiega światło - system "żyje", a nic się
       nie przesuwa. Rysunek kreski jak wyżej (granat w złoto), światło to druga warstwa. */
    .topbar::before {
        background-image: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .95), rgba(255, 255, 255, 0)),
            linear-gradient(90deg, var(--toz-granat), var(--toz-zloto));
        background-size: 22% 100%, 100% 100%; background-repeat: no-repeat; background-position: -40% 0, 0 0;
        animation: toz-kreska .55s cubic-bezier(.2, .8, .2, 1) backwards, toz-polysk 9s ease-in-out 1.6s infinite;
    }
    /* Kreska rysuje się od nowa tylko na pierwszej stronie wizyty (menu-start.js zapamiętuje to na czas
       otwartej karty przeglądarki) - przy każdym kliknięciu migała nad całą stroną. Światło zostaje. */
    html.kreska-byla .topbar::before { animation: toz-polysk 9s ease-in-out 1.6s infinite; }

    /* Termin po czasie i brak dokumentów pulsują trzy razy po wczytaniu - oko trafia
       tam od razu. Potem stoją spokojnie. */
    .zostalo-po { animation: toz-puls-terminu 1.5s ease-out .5s 3; }
    .stan-alarm { animation: toz-puls-alarmu 1.5s ease-out .5s 3; }

    @keyframes toz-zorza {
        from { transform: translate3d(0, 0, 0) scale(1.08); }
        50%  { transform: translate3d(-2.5%, 1.5%, 0) scale(1.14) rotate(.6deg); }
        to   { transform: translate3d(2%, -1%, 0) scale(1.1) rotate(-.4deg); }
    }
    @keyframes toz-rosnij { from { transform: scaleY(0); } }
    @keyframes toz-polysk { 0% { background-position: -40% 0, 0 0; } 16%, 100% { background-position: 140% 0, 0 0; } }
    @keyframes toz-linia { from { background-size: 0% 1px; } }
    @keyframes toz-blysk { from { background-position: 150% 0, 0 0, 0 0; } to { background-position: -50% 0, 0 0, 0 0; } }
    @keyframes toz-fala { from { box-shadow: 0 0 0 0 var(--fala); } to { box-shadow: 0 0 0 10px transparent; } }
    @keyframes toz-puls-terminu {
        0%        { box-shadow: inset 0 0 0 1px #f1c9ce, 0 0 0 0 rgba(165, 40, 52, .45); }
        70%, 100% { box-shadow: inset 0 0 0 1px #f1c9ce, 0 0 0 7px rgba(165, 40, 52, 0); }
    }
    @keyframes toz-puls-alarmu {
        0%        { box-shadow: 0 0 0 0 rgba(165, 40, 52, .5); }
        70%, 100% { box-shadow: 0 0 0 7px rgba(165, 40, 52, 0); }
    }
}

/* --- Święto po dobrym zapisie (App\Swieto, swieto.js; właściciel, 03.10.2026) ---------------
   Zwierzak dostał dom, sprawa z terminarza załatwiona, raport zatwierdzony: z dołu ekranu
   wyfruwają łapki, serduszka i iskry w barwach marki, na środku na chwilę staje napis.
   Scena nie łapie kliknięć, stoi pod paskiem wczytywania i znika sama (skrypt ją usuwa). */
.swieto { position: fixed; inset: 0 0 auto; height: 100vh; height: 100lvh; z-index: 80; pointer-events: none; overflow: hidden; }
.swieto-drobina {
    position: absolute; left: var(--x); bottom: -48px; width: var(--rozmiar); height: var(--rozmiar);
    background-position: center; background-size: contain; background-repeat: no-repeat; opacity: 0;
}
.swieto-lapa       { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%233a57a2'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E"); }
.swieto-lapa-jasna { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%237d8fd0'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E"); }
.swieto-lapa-zloto { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23d7b56d'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E"); }
.swieto-serce      { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23d7b56d'%3E%3Cpath d='M12 21s-7.5-4.6-9.6-9.2C.9 8.4 3 4.5 6.8 4.5c2.1 0 3.6 1.1 5.2 3 1.6-1.9 3.1-3 5.2-3 3.8 0 5.9 3.9 4.4 7.3C19.5 16.4 12 21 12 21z'/%3E%3C/svg%3E"); }
.swieto-iskra      { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23e3c47e'%3E%3Cpath d='M12 1.5l2.4 7.1 7.1 2.4-7.1 2.4L12 20.5l-2.4-7.1-7.1-2.4 7.1-2.4z'/%3E%3C/svg%3E"); }
.swieto-napis {
    position: absolute; left: 50%; top: 38%; transform: translate(-50%, -50%);
    padding: 14px 30px; border-radius: 999px; white-space: normal; width: max-content; max-width: calc(100vw - 32px);
    box-sizing: border-box; text-align: center;
    font-size: clamp(1.4rem, 4vw, 2.2rem); font-weight: 800; letter-spacing: .01em;
    color: var(--toz-granat-ciemny); background: #fff; border: 2px solid var(--toz-zloto);
    box-shadow: 0 18px 50px rgba(44, 67, 129, .25), 0 0 0 6px rgba(215, 181, 109, .18);
    opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
    .swieto-drobina { animation: toz-swieto-lot var(--czas) cubic-bezier(.2, .7, .3, 1) var(--opoznienie) forwards; }
    /* Połysk po napisie (grafika nr 23, 27.10.2026): raz, jasne złote pasmo w tle samej pigułki, od lewej do prawej -
       jak błysk na medalu; czeka poza pigułką, przebiega, gdy napis już stoi. */
    .swieto-napis { animation: toz-swieto-napis 2.6s cubic-bezier(.2, .8, .2, 1) .15s forwards, toz-swieto-polysk .8s ease-in-out .85s;
        background-image: linear-gradient(105deg, rgba(215, 181, 109, 0) 40%, rgba(215, 181, 109, .38) 50%, rgba(215, 181, 109, 0) 60%);
        background-repeat: no-repeat; background-size: 250% 100%; background-position: 100% 0;
    }
    @keyframes toz-swieto-polysk { from { background-position: 100% 0; } to { background-position: 0 0; } }
    @keyframes toz-swieto-lot {
        0%   { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg) scale(.6); }
        12%  { opacity: 1; }
        75%  { opacity: 1; }
        100% { opacity: 0; transform: translate3d(var(--dryf), -110vh, 0) rotate(var(--obrot)) scale(1.05); }
    }
    @keyframes toz-swieto-napis {
        0%   { opacity: 0; transform: translate(-50%, -50%) scale(.6); }
        14%  { opacity: 1; transform: translate(-50%, -50%) scale(1.06); }
        22%  { transform: translate(-50%, -50%) scale(1); }
        78%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
        100% { opacity: 0; transform: translate(-50%, -60%) scale(.96); }
    }
}
@media print { .swieto { display: none; } }

/* --- Kalendarz w Terminarzu (właściciel, 04.10.2026) --------------------------------------------
   Miesiąc od poniedziałku: sprawy z Terminarza, zaplanowane przypomnienia i święta zwierzęce.
   Siedem równych kolumn, które się nie rozpychają (minmax(0, 1fr)) - długa nazwa kończy się
   wielokropkiem, a cała stoi w dymku. Na telefonie zostaje lista samych dni, w których coś jest. */
.kalendarz-nawigacja { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px; }
.kalendarz-miesiac { min-width: 12ch; text-align: center; font-size: 1.15rem; color: var(--toz-granat-ciemny); }
.kalendarz-miesiac::first-letter { text-transform: uppercase; }
.kalendarz-swieta { margin-left: auto; font-size: .9rem; font-weight: 600; }
.kalendarz-dzis-wiersz { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.kalendarz-dzis-wiersz p { margin: 0; }
.kalendarz-dzis-panstwowe {
    display: inline-block; padding: 6px 14px 6px 36px; border-radius: 999px;
    border: 1px solid #d3d9ea; color: var(--toz-granat-ciemny);
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 16'%3E%3Crect x='.5' y='.5' width='23' height='15' rx='2' fill='%23fff' stroke='%23b9c2d9'/%3E%3Cpath d='M.5 8h23v5.5a2 2 0 0 1-2 2h-19a2 2 0 0 1-2-2z' fill='%23d4213d'/%3E%3C/svg%3E") 12px 50% / 18px 12px no-repeat, #f6f7fb;
}
.kalendarz-dzis-urodziny {
    display: inline-block; padding: 6px 14px 6px 34px; border-radius: 999px;
    border: 1px solid #c9d3ee; color: var(--toz-granat-ciemny);
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .5c1.7 1.8 2.1 3.1 1.3 4-.7.8-1.9.8-2.6 0-.8-.9-.4-2.2 1.3-4z' fill='%23ff8f00'/%3E%3Cpath d='M12 2.4c.7.8.9 1.4.5 1.8-.3.3-.7.3-1 0-.4-.4-.2-1 .5-1.8z' fill='%23ffe082'/%3E%3Crect x='11.1' y='5' width='1.8' height='3.6' rx='.5' fill='%2342a5f5'/%3E%3Cpath d='M11.1 6.2l1.8-.9M11.1 7.8l1.8-.9' stroke='%23fff' stroke-width='.6'/%3E%3Crect x='5.5' y='8.4' width='13' height='5.2' rx='1.6' fill='%23f8bbd0'/%3E%3Cpath d='M5.5 10.3c1.1 1 2.1 1 3.2 0s2.1-1 3.3 0 2.1 1 3.3 0 2.1-1 3.2 0' fill='none' stroke='%23fff' stroke-width='1.4' stroke-linecap='round'/%3E%3Crect x='3' y='13.3' width='18' height='7' rx='2' fill='%23ec407a'/%3E%3Cpath d='M3 15.5c1.5 1.3 3 1.3 4.5 0s3-1.3 4.5 0 3 1.3 4.5 0 3-1.3 4.5 0' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round'/%3E%3Ccircle cx='7' cy='18.4' r='.9' fill='%23ffeb3b'/%3E%3Ccircle cx='12' cy='18.6' r='.9' fill='%2381d4fa'/%3E%3Ccircle cx='17' cy='18.4' r='.9' fill='%23aed581'/%3E%3Cellipse cx='12' cy='21.4' rx='10.5' ry='1.4' fill='%23cfd8dc'/%3E%3C/svg%3E") 12px 50% / 16px 16px no-repeat, linear-gradient(90deg, #f1f4fc, #fffaf0);
}
.kalendarz-dzis-swieto {
    display: inline-block; margin: 0 0 12px; padding: 6px 14px 6px 34px; border-radius: 999px;
    border: 1px solid #e8d7ae; color: #6f5518;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23c9a04a'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") 12px 50% / 16px 16px no-repeat, linear-gradient(90deg, #fbf3df, #fffaf0);
}
.kalendarz-tydzien, .kalendarz-dni { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.kalendarz-tydzien span {
    padding: 4px 0; text-align: center; font-size: .72rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--toz-muted);
}
.kalendarz-dni { margin: 0; padding: 0; list-style: none; }
.kalendarz-dzien {
    display: flex; flex-direction: column; gap: 3px; min-width: 0; min-height: 96px; padding: 6px;
    border: 1px solid var(--toz-border); border-radius: 8px; background: #fff;
}
.kalendarz-weekend { background: #f8f9fc; }
.kalendarz-poza { background: #f8f9fc; }
/* Przygaszony kolorem, nie przezroczystością - zdarzenia zostają w pełnej barwie (audyt 04.10.2026, F32). */
.kalendarz-poza .kalendarz-numer { color: var(--toz-muted); }
.kalendarz-dzis { border-color: var(--toz-zloto); box-shadow: inset 0 0 0 1px var(--toz-zloto), 0 0 0 3px rgba(215, 181, 109, .2); }
.kalendarz-numer { font-size: .85rem; font-weight: 700; color: var(--toz-granat-ciemny); font-variant-numeric: tabular-nums; }
.kalendarz-dzis .kalendarz-numer {
    display: inline-flex; align-items: center; justify-content: center; width: 1.9em; height: 1.9em;
    border-radius: 999px; background: linear-gradient(135deg, #4a68ba, var(--toz-granat-ciemny)); color: #fff;
}
/* Pełna data dla czytnika ekranu (na telefonie widać ją zamiast numeru). */
.kalendarz-opis { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.zdarzenie {
    display: block; min-width: 0; padding: 2px 6px; border-radius: 6px; border-left: 3px solid transparent;
    font-size: .74rem; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none;
}
a.zdarzenie:hover { text-decoration: underline; }
.zdarzenie-swieto { background: linear-gradient(90deg, #fbf3df, #fffaf0); border-left-color: var(--toz-zloto); color: #6f5518; }
.zdarzenie-swieto::before {
    content: ''; display: inline-block; width: .95em; height: .95em; margin-right: 4px; vertical-align: -.12em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23c9a04a'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Święto państwowe (właściciel, 04.10.2026: "I dodaj do kalendarza święta państwowe") - dzień ustawowo wolny:
   plakietka z flagą, a sam dzień wolny jak niedziela, z numerem podkreślonym złotem. */
.zdarzenie-panstwowe { background: #f6f7fb; border-left-color: var(--toz-granat-ciemny); color: var(--toz-granat-ciemny); font-weight: 600; }
.zdarzenie-panstwowe::before {
    content: ''; display: inline-block; width: 1.1em; height: .75em; margin-right: 4px; vertical-align: -.02em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 16'%3E%3Crect x='.5' y='.5' width='23' height='15' rx='2' fill='%23fff' stroke='%23b9c2d9'/%3E%3Cpath d='M.5 8h23v5.5a2 2 0 0 1-2 2h-19a2 2 0 0 1-2-2z' fill='%23d4213d'/%3E%3C/svg%3E") center / contain no-repeat;
}
.kalendarz-wolne { background: #f6f7fb; }
.kalendarz-wolne .kalendarz-numer { color: var(--toz-granat); text-decoration: underline 2px var(--toz-zloto); text-underline-offset: 3px; }
/* Dziś w dzień wolny: numer zostaje biały na granatowym kółku "dziś". */
.kalendarz-dzis.kalendarz-wolne .kalendarz-numer { color: #fff; text-decoration: none; }
/* Urodziny członka (właściciel, 04.10.2026: "ma sie pojawić ładny tort czy coś aby było porządnie widać że to urodziny";
   "nie musi być w barwach systemu, poza tym jeden starczy koło imienia") - jeden kolorowy tort przy podpisie;
   bez przejścia do karty członka. */
.zdarzenie-urodziny {
    background: linear-gradient(90deg, #fff4dc, #f1f4fc); border-left-color: var(--toz-zloto);
    color: var(--toz-granat-ciemny); font-weight: 600;
    /* Podpis odróżnia osoby końcówką ("Pieczk." / "Piecza.") - zawija się, zamiast urywać wielokropkiem. */
    white-space: normal; overflow-wrap: anywhere;
}
.zdarzenie-urodziny::before {
    content: ''; display: inline-block; width: 1.25em; height: 1.25em; margin: -.15em 4px 0 0; vertical-align: -.3em;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .5c1.7 1.8 2.1 3.1 1.3 4-.7.8-1.9.8-2.6 0-.8-.9-.4-2.2 1.3-4z' fill='%23ff8f00'/%3E%3Cpath d='M12 2.4c.7.8.9 1.4.5 1.8-.3.3-.7.3-1 0-.4-.4-.2-1 .5-1.8z' fill='%23ffe082'/%3E%3Crect x='11.1' y='5' width='1.8' height='3.6' rx='.5' fill='%2342a5f5'/%3E%3Cpath d='M11.1 6.2l1.8-.9M11.1 7.8l1.8-.9' stroke='%23fff' stroke-width='.6'/%3E%3Crect x='5.5' y='8.4' width='13' height='5.2' rx='1.6' fill='%23f8bbd0'/%3E%3Cpath d='M5.5 10.3c1.1 1 2.1 1 3.2 0s2.1-1 3.3 0 2.1 1 3.3 0 2.1-1 3.2 0' fill='none' stroke='%23fff' stroke-width='1.4' stroke-linecap='round'/%3E%3Crect x='3' y='13.3' width='18' height='7' rx='2' fill='%23ec407a'/%3E%3Cpath d='M3 15.5c1.5 1.3 3 1.3 4.5 0s3-1.3 4.5 0 3 1.3 4.5 0 3-1.3 4.5 0' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round'/%3E%3Ccircle cx='7' cy='18.4' r='.9' fill='%23ffeb3b'/%3E%3Ccircle cx='12' cy='18.6' r='.9' fill='%2381d4fa'/%3E%3Ccircle cx='17' cy='18.4' r='.9' fill='%23aed581'/%3E%3Cellipse cx='12' cy='21.4' rx='10.5' ry='1.4' fill='%23cfd8dc'/%3E%3C/svg%3E") center / contain no-repeat;
}
.zdarzenie-raport { background: var(--toz-granat-jasny); border-left-color: var(--toz-granat); color: var(--toz-granat-ciemny); }
.zdarzenie-umowa  { background: #fff; border-left-color: var(--toz-zloto); color: var(--toz-granat-ciemny); }
.zdarzenie-wpis   { background: #eef0f4; border-left-color: #9aa3b8; color: #2d3140; }
.zdarzenie-stale  { background: #fff; border: 1px dashed #b3c0e3; border-left: 3px solid #b3c0e3; color: var(--toz-granat-ciemny); }
.zdarzenie-po     { background: var(--toz-tlo-blad); border-left-color: var(--toz-blad); color: var(--toz-blad); font-weight: 600; }
.kalendarz-legenda { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: 14px 0 0; }
.kalendarz-legenda .zdarzenie { display: inline-block; }
.kalendarz-nic { margin: 10px 0 0; }

@media (max-width: 640px) {
    .kalendarz-tydzien { display: none; }
    .kalendarz-dni { grid-template-columns: minmax(0, 1fr); gap: 6px; }
    .kalendarz-pusty, .kalendarz-poza { display: none; }
    .kalendarz-dzien { min-height: 0; }
    .kalendarz-dzien .kalendarz-numer { display: none; }
    .kalendarz-opis { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal;
        font-size: .85rem; font-weight: 700; color: var(--toz-granat-ciemny); }
    .zdarzenie { white-space: normal; padding: 6px 8px; font-size: .85rem; }
    /* Rodzaj zdarzenia słowem przed nazwą - na telefonie nie ma dymka (F38). */
    .zdarzenie .zdarzenie-rodzaj { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto;
        clip-path: none; white-space: normal; font-weight: 600; }
    .kalendarz-dzien { gap: 6px; }
    .kalendarz-swieta { margin-left: 0; }
}
@media print {
    .kalendarz-nawigacja .btn { display: none; }
}

/* --- Chwile radości (właściciel, 27.10.2026: „działaj” - grafika nr 20, 23 i 27) -----------------------------------
   Pieczęć przy zamknięciu sprawy interwencji (layout.php, App\Pieczec), promienie za napisem sceny święta (swieto.js)
   i śpiący piesek w pustym Terminarzu (zarzad/terminarz.php). Za treścią albo w wolnym polu, bez klikania, raz; ruch
   tylko w bloku ruchu - bez ruchu w systemie pieczęci nie ma, a piesek śpi nieruchomo. Barwy: granat i złoto marki. */

/* nr 23 - promienie: miękkie złote koło światła i wieniec 12 cienkich, bladych promieni (na zmianę złoto i jasny
   granat, ok. 30% krycia) za pigułką napisu. Sięgają --zasieg poza pigułkę (jej wielkość daje swieto.js) i gasną ku
   brzegom (maska), więc nie kładą pasków na tabeli; gdy napis stoi, obracają się o 36 stopni - kąt to zarejestrowana
   zmienna, przeglądarka bez @property pokaże promienie bez obrotu. Gasną razem z napisem; scena ucina je do ekranu. */
@property --swieto-kat { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.swieto-promienie {
    --zasieg: 56px;
    position: absolute; left: 50%; top: 38%; opacity: 0; pointer-events: none; border-radius: 50%;
    width: calc(var(--szer, 320px) + 2 * var(--zasieg)); height: calc(var(--wys, 64px) + 2 * var(--zasieg));
    transform: translate(-50%, -50%);
    background:
        radial-gradient(closest-side, rgba(215, 181, 109, .45), rgba(215, 181, 109, .16) 62%, rgba(215, 181, 109, 0)),
        repeating-conic-gradient(from var(--swieto-kat), rgba(215, 181, 109, .32) 0deg 2.5deg, rgba(215, 181, 109, 0) 2.5deg 30deg,
            rgba(125, 143, 208, .3) 30deg 32.5deg, rgba(125, 143, 208, 0) 32.5deg 60deg);
    -webkit-mask: radial-gradient(closest-side, #000 50%, rgba(0, 0, 0, 0));
    mask: radial-gradient(closest-side, #000 50%, rgba(0, 0, 0, 0));
}
@media (max-width: 640px) { .swieto-promienie { --zasieg: 28px; } }

/* nr 20 - pieczęć przy zamknięciu sprawy: w wolnym polu pod belką z prawej (miejsce powitania dnia), nie większa od
   pigułki powitania. Koło na płycie karty ze złotym pierścieniem, łapka i nazwa stanu w granacie (SVG w layout.php -
   barwy tutaj, więc ciemny wygląd przelicza je jak resztę arkusza), obok numer sprawy albo liczba spraw. Zapala ją
   tylko ruch: wchodzi większa i obrócona, „stuka” z drgnięciem, raz rozchodzi się złoty pył (kropkowany pierścień),
   po ok. 3 s gaśnie. Pył mieści się w odstępie od brzegu ekranu - strona nie ucieka w bok. */
.pieczec {
    position: fixed; top: 62px; right: 16px; z-index: 15; pointer-events: none; opacity: 0;
    display: flex; align-items: center; gap: 8px;
}
.pieczec-podpis {
    padding: 4px 12px; border-radius: 999px; background: #fff; color: var(--toz-granat-ciemny);
    font-size: .92rem; font-weight: 700; white-space: nowrap; box-shadow: 0 6px 18px rgba(44, 67, 129, .14);
}
.pieczec-znak { position: relative; display: block; width: 60px; height: 60px; border-radius: 50%; box-shadow: 0 6px 18px rgba(44, 67, 129, .18); }
.pieczec-krazek { display: block; width: 100%; height: 100%; overflow: visible; transform: rotate(-6deg); }
.pieczec-pierscien { fill: var(--toz-plyta); stroke: var(--toz-zloto); stroke-width: 2.6; }
.pieczec-pierscien-wewn { fill: none; stroke: var(--toz-zloto); stroke-width: 1.2; }
.pieczec-kropka { fill: var(--toz-zloto); }
.pieczec-lapka { fill: var(--toz-granat); }
.pieczec-napis { fill: var(--toz-granat-ciemny); font-size: 7.4px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; }
/* Dłuższa własna nazwa stanu (szablon liczy znaki: ponad 20 i ponad 28) - mniejsze litery, żeby zmieściła się na jednym
   okrążeniu z przerwą u dołu (przegląd 27.10.2026; textLength przy napisie po łuku Safari pomija i ucina końce). */
.pieczec-napis-dlugi { font-size: 5.6px; letter-spacing: .2px; }
.pieczec-napis-najdluzszy { font-size: 4.4px; letter-spacing: 0; }
@media (max-width: 760px) {
    .pieczec { top: 58px; right: 12px; }
    .pieczec-znak { width: 50px; height: 50px; }
    .pieczec-podpis { padding: 3px 10px; font-size: .85rem; }
}
@media print { .pieczec { display: none; } }

/* nr 27 - śpiący piesek w pustym Terminarzu: gdy nic nie czeka (szablon daje p.pusto-spi tylko tej gałęzi - puste
   „pokaż zrobione” i same przypomnienia zostają przy łapie), zamiast łapy zwinięty w kłębek piesek w tym samym spadku
   granat-złoto, nos pod ogonem. Przy wejściu bok dwa razy unosi się w oddechu, a znad głowy po kolei wypływają trzy
   złote „z” i gasną (ok. 2,5 s, raz). Pod sceną „Zrobione!” ruch czeka, aż scena zejdzie ze strony (swieto.js zdejmuje
   ją po 4,5 s) - bez własnego skryptu. Bez ruchu w systemie piesek śpi nieruchomo; na telefonie rysunki pustych list
   są schowane, „z” razem z nimi. */
p.pusto-spi { position: relative; }
p.pusto-spi::before {
    width: 58px; height: 35px; transform-origin: 50% 100%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 66 40'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='66' height='40' fill='%23fff'/%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23000' stroke-width='6' stroke-linecap='round'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M9.8 24q2.2 1.8 4.4 0' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/%3E%3C/mask%3E%3C/defs%3E%3Cg mask='url(%23m)' fill='%23b9c3de'%3E%3Cpath d='M20 37c-5 0-6.5-6.5-3.5-13C21 15 30 12 40 12c12 0 20 6 20 14 0 6.5-5 11-13 11z'/%3E%3Ccircle cx='16.5' cy='25' r='8.5'/%3E%3Cellipse cx='8.5' cy='29' rx='7' ry='4.4' transform='rotate(-6 8.5 29)'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z'/%3E%3C/g%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23b9c3de' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E");
}
@supports ((-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E")) or (mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E"))) {
    p.pusto-spi::before {
        background-image: linear-gradient(135deg, var(--toz-granat), #7d8fd0 50%, var(--toz-zloto));
        -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 66 40'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='66' height='40' fill='%23fff'/%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23000' stroke-width='6' stroke-linecap='round'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M9.8 24q2.2 1.8 4.4 0' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/%3E%3C/mask%3E%3C/defs%3E%3Cg mask='url(%23m)'%3E%3Cpath d='M20 37c-5 0-6.5-6.5-3.5-13C21 15 30 12 40 12c12 0 20 6 20 14 0 6.5-5 11-13 11z'/%3E%3Ccircle cx='16.5' cy='25' r='8.5'/%3E%3Cellipse cx='8.5' cy='29' rx='7' ry='4.4' transform='rotate(-6 8.5 29)'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z'/%3E%3C/g%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E");
        mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 66 40'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='66' height='40' fill='%23fff'/%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23000' stroke-width='6' stroke-linecap='round'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M9.8 24q2.2 1.8 4.4 0' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/%3E%3C/mask%3E%3C/defs%3E%3Cg mask='url(%23m)'%3E%3Cpath d='M20 37c-5 0-6.5-6.5-3.5-13C21 15 30 12 40 12c12 0 20 6 20 14 0 6.5-5 11-13 11z'/%3E%3Ccircle cx='16.5' cy='25' r='8.5'/%3E%3Cellipse cx='8.5' cy='29' rx='7' ry='4.4' transform='rotate(-6 8.5 29)'/%3E%3Cpath d='M15.5 17.5c4.5-1.6 9.6.4 10 5.4.3 3.6-1.4 7.4-4 8.1-2.4-3.2-4.4-7.4-6-13.5z'/%3E%3C/g%3E%3Cpath d='M59.5 24.5c3.5 8-1.5 12.2-11 12.2H17c-7.5 0-12.5-2-13.4-5.6-.6-2.6.8-4.9 3.6-5.6' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E");
    }
}
@media (max-width: 640px) { p.pusto-spi::after { display: none; } }
@media print { p.pusto-spi::after { display: none; } }

@media (prefers-reduced-motion: no-preference) {
    .swieto-promienie {
        animation: toz-swieto-promienie 2.6s cubic-bezier(.2, .8, .2, 1) .15s forwards, toz-swieto-obrot 2.6s linear .15s forwards;
    }
    @keyframes toz-swieto-promienie {
        0%   { opacity: 0; transform: translate(-50%, -50%) scale(.5); }
        16%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
        78%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
        100% { opacity: 0; transform: translate(-50%, -50%) scale(1.03); }
    }
    @keyframes toz-swieto-obrot { to { --swieto-kat: 36deg; } }

    .pieczec { animation: toz-pieczec 3.4s ease-in-out .25s forwards; }
    .pieczec-krazek { animation: toz-pieczec-stuk .55s cubic-bezier(.3, .7, .4, 1) .25s backwards; }
    .pieczec-znak::after {
        content: ''; position: absolute; inset: 0; border: 3px dotted var(--toz-zloto); border-radius: 50%; opacity: 0;
        animation: toz-pieczec-pyl .75s ease-out .55s;
    }
    @keyframes toz-pieczec {
        0%   { opacity: 0; }
        4%   { opacity: 1; }
        84%  { opacity: 1; }
        100% { opacity: 0; }
    }
    @keyframes toz-pieczec-stuk {
        0%   { transform: translateY(-14px) scale(1.7) rotate(-26deg); }
        58%  { transform: scale(.92) rotate(-4deg); }
        76%  { transform: scale(1.05) rotate(-7deg); }
        100% { transform: rotate(-6deg); }
    }
    @keyframes toz-pieczec-pyl {
        0%   { opacity: .95; transform: scale(.92); }
        100% { opacity: 0; transform: scale(1.45); }
    }

    p.pusto-spi::before { animation: toz-lapa .5s cubic-bezier(.2, .8, .2, 1) .08s backwards, toz-spi-oddech 1.1s ease-in-out .7s 2; }
    p.pusto-spi::after {
        content: ''; position: absolute; left: calc(50% - 13px); top: 16px; width: 24px; height: 24px; opacity: 0;
        background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30' fill='none' stroke='%23d7b56d' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 22h5l-5 5h5' stroke-width='1.8'/%3E%3Cpath d='M10 13h7l-7 7h7' stroke-width='2.1'/%3E%3Cpath d='M20 1.5h8.5l-8.5 8.5h8.5' stroke-width='2.4'/%3E%3C/svg%3E") center / contain no-repeat;
        animation: toz-spi-z 2.5s ease-out .8s;
    }
    /* Scena „Zrobione!” po ostatniej sprawie: piesek kładzie się od razu, a oddech i „z” czekają, aż scena zejdzie ze
       strony (gdyby skrypt sceny się nie wczytał, piesek i tak leży - śpi nieruchomo). */
    body:has(.swieto) p.pusto-spi::before { animation-play-state: running, paused; }
    body:has(.swieto) p.pusto-spi::after { animation-play-state: paused; }
    @keyframes toz-spi-oddech { 50% { transform: scale(1.03, 1.09); } }
    @keyframes toz-spi-z {
        0%   { opacity: 0; clip-path: inset(70% 70% 0 0); transform: translate(0, 4px) scale(.8); }
        12%  { opacity: 1; }
        30%  { clip-path: inset(70% 70% 0 0); }
        40%  { clip-path: inset(38% 38% 0 0); }
        58%  { clip-path: inset(38% 38% 0 0); }
        68%  { clip-path: inset(0 0 0 0); }
        82%  { opacity: 1; }
        100% { opacity: 0; clip-path: inset(0 0 0 0); transform: translate(6px, -10px) scale(1.1); }
    }
}

/* --- "Na górę" na długich listach (na-gore.js; przegląd przejść 04.10.2026) ------------------------- */
.na-gore {
    position: fixed; right: max(16px, var(--toz-margines)); bottom: 20px; z-index: 35;
    width: 46px; height: 46px; border: 0; border-radius: 999px; cursor: pointer;
    background: linear-gradient(135deg, #4a68ba, var(--toz-granat-ciemny));
    box-shadow: 0 6px 18px rgba(44, 67, 129, .3), 0 0 0 3px rgba(215, 181, 109, .35);
}
.na-gore::before {
    content: ''; position: absolute; left: 50%; top: 54%; width: 12px; height: 12px;
    border-top: 3px solid #fff; border-left: 3px solid #fff; transform: translate(-50%, -50%) rotate(45deg);
}
.na-gore:hover { box-shadow: 0 8px 22px rgba(44, 67, 129, .38), 0 0 0 3px rgba(215, 181, 109, .6); }
/* Przy otwartym panelu "Kolumny" (na telefonie przyklejonym do dołu ekranu) przycisk zasłaniał jego róg (T28). */
body:has(details.wybor-kolumn[open]) .na-gore { display: none; }
/* Fokus jak wszędzie (--toz-fokus) - złota obwódka miała na jasnym tle 1,78:1 (audyt 08.10.2026, J202). */
.na-gore:focus-visible { outline: 3px solid var(--toz-fokus); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
    .na-gore:not([hidden]) { animation: toz-zjaw .2s ease-out; }
}
@media print { .na-gore { display: none; } }

/* --- Okazje (App\Okazje, okazje.js; właściciel, 04.10.2026: "przygotuj system graficznie na jakieś święta") ---
   Ozdoby za treścią w swoje dni: śnieg i gwiazdki (Boże Narodzenie), iskry (Sylwester, Nowy Rok), pisanki
   i kwiatki (Wielkanoc), serca (Dzień Wolontariusza), łapki (Światowy Dzień Zwierząt). Te same kształty
   bierze powitanie dnia (scena .swieto). Tylko po zalogowaniu; nie łapią kliknięć; na wydruku ich nie ma. */
.swieto-snieg          { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7M12 5.5L9.6 3.1M12 5.5l2.4-2.4M12 18.5l-2.4 2.4M12 18.5l2.4 2.4M5.6 8.3l-3.2.9M5.6 8.3L4.7 5.1M18.4 15.7l3.2-.9M18.4 15.7l.9 3.2M5.6 15.7l-3.2-.9M5.6 15.7l-.9 3.2M18.4 8.3l3.2.9M18.4 8.3l.9-3.2' fill='none' stroke='%239fb0dc' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-snieg-jasny    { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7M12 5.5L9.6 3.1M12 5.5l2.4-2.4M12 18.5l-2.4 2.4M12 18.5l2.4 2.4M5.6 8.3l-3.2.9M5.6 8.3L4.7 5.1M18.4 15.7l3.2-.9M18.4 15.7l.9 3.2M5.6 15.7l-3.2-.9M5.6 15.7l-.9 3.2M18.4 8.3l3.2.9M18.4 8.3l.9-3.2' fill='none' stroke='%23c3cdea' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-gwiazda        { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l2.9 6.6 7.1.6-5.4 4.7 1.6 7L12 17.3l-6.2 3.6 1.6-7L2 9.2l7.1-.6z' fill='%23d7b56d'/%3E%3C/svg%3E"); }
.swieto-iskra-granat   { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5l2.4 7.1 7.1 2.4-7.1 2.4L12 20.5l-2.4-7.1-7.1-2.4 7.1-2.4z' fill='%237d8fd0'/%3E%3C/svg%3E"); }
.swieto-pisanka        { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 30'%3E%3Cellipse cx='12' cy='16' rx='9.5' ry='12.5' fill='%23d7b56d'/%3E%3Cpath d='M3.6 13.5l2.9-2.4 2.9 2.4 2.9-2.4 2.9 2.4 2.9-2.4 2.9 2.4' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M3.2 19.5h17.6' stroke='%23fff' stroke-width='1.3'/%3E%3C/svg%3E"); }
.swieto-pisanka-granat { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 30'%3E%3Cellipse cx='12' cy='16' rx='9.5' ry='12.5' fill='%237d8fd0'/%3E%3Cpath d='M3.6 13.5l2.9-2.4 2.9 2.4 2.9-2.4 2.9 2.4 2.9-2.4 2.9 2.4' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M3.2 19.5h17.6' stroke='%23fff' stroke-width='1.3'/%3E%3C/svg%3E"); }
.swieto-kwiat          { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%23e3c47e'%3E%3Ccircle cx='12' cy='6' r='4'/%3E%3Ccircle cx='17.7' cy='10.2' r='4'/%3E%3Ccircle cx='15.5' cy='17' r='4'/%3E%3Ccircle cx='8.5' cy='17' r='4'/%3E%3Ccircle cx='6.3' cy='10.2' r='4'/%3E%3C/g%3E%3Ccircle cx='12' cy='12' r='3.2' fill='%233a57a2'/%3E%3C/svg%3E"); }
.swieto-serce-granat   { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21s-7.5-4.6-9.6-9.2C.9 8.4 3 4.5 6.8 4.5c2.1 0 3.6 1.1 5.2 3 1.6-1.9 3.1-3 5.2-3 3.8 0 5.9 3.9 4.4 7.3C19.5 16.4 12 21 12 21z' fill='%237d8fd0'/%3E%3C/svg%3E"); }
/* Dni "zwierzęce" (16.10.2026): kocie łapki i sylwetki, liście i ślady saren, pszczoły, kości - w barwach marki. */
.swieto-kocia-lapa       { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%233a57a2'%3E%3Ccircle cx='11.5' cy='20.5' r='4.6'/%3E%3Ccircle cx='19.6' cy='12' r='4.9'/%3E%3Ccircle cx='28.4' cy='12' r='4.9'/%3E%3Ccircle cx='36.5' cy='20.5' r='4.6'/%3E%3Cpath d='M24 23c-6.2 0-11.2 5.4-11.2 10.4 0 3.5 2.7 5.4 5.7 5.4 2.2 0 3.6-1.2 5.5-1.2s3.3 1.2 5.5 1.2c3 0 5.7-1.9 5.7-5.4C35.2 28.4 30.2 23 24 23z'/%3E%3C/svg%3E"); }
.swieto-kocia-lapa-zloto { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23d7b56d'%3E%3Ccircle cx='11.5' cy='20.5' r='4.6'/%3E%3Ccircle cx='19.6' cy='12' r='4.9'/%3E%3Ccircle cx='28.4' cy='12' r='4.9'/%3E%3Ccircle cx='36.5' cy='20.5' r='4.6'/%3E%3Cpath d='M24 23c-6.2 0-11.2 5.4-11.2 10.4 0 3.5 2.7 5.4 5.7 5.4 2.2 0 3.6-1.2 5.5-1.2s3.3 1.2 5.5 1.2c3 0 5.7-1.9 5.7-5.4C35.2 28.4 30.2 23 24 23z'/%3E%3C/svg%3E"); }
.swieto-kot              { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%237d8fd0' d='M7.2 2.8l2.1 3.1a5.1 5.1 0 0 1 5.4 0l2.1-3.1.7 5a5 5 0 0 1-.6 4.3c1.9 1.5 3 3.9 3 6.4 0 1.9-1.1 3.2-3 3.2H8.4c-.9 0-1.4-.6-1.4-1.2 0-.8.6-1.2 1.4-1.2h.5a6.3 6.3 0 0 1-.9-3.3c0-1.5.5-2.9 1.4-4a5 5 0 0 1-1.6-3.9z'/%3E%3Cpath d='M17.8 21.2c2.4.2 4-1.3 3.8-3.8' fill='none' stroke='%237d8fd0' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-kot-zloto        { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23d7b56d' d='M7.2 2.8l2.1 3.1a5.1 5.1 0 0 1 5.4 0l2.1-3.1.7 5a5 5 0 0 1-.6 4.3c1.9 1.5 3 3.9 3 6.4 0 1.9-1.1 3.2-3 3.2H8.4c-.9 0-1.4-.6-1.4-1.2 0-.8.6-1.2 1.4-1.2h.5a6.3 6.3 0 0 1-.9-3.3c0-1.5.5-2.9 1.4-4a5 5 0 0 1-1.6-3.9z'/%3E%3Cpath d='M17.8 21.2c2.4.2 4-1.3 3.8-3.8' fill='none' stroke='%23d7b56d' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-lisc             { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23d7b56d' d='M20.5 3C10.5 3 4 8.6 4 15.6c0 1.5.3 2.9.8 4.1L3 21.6 4.4 23l1.9-1.9c1.2.6 2.7.9 4.2.9 7.6 0 10.9-7.4 10-19z'/%3E%3Cpath d='M6.5 20.5c3.6-5.2 7.6-9.2 12-12.4' fill='none' stroke='%23b8933f' stroke-width='1.1' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-lisc-granat      { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%237d8fd0' d='M20.5 3C10.5 3 4 8.6 4 15.6c0 1.5.3 2.9.8 4.1L3 21.6 4.4 23l1.9-1.9c1.2.6 2.7.9 4.2.9 7.6 0 10.9-7.4 10-19z'/%3E%3Cpath d='M6.5 20.5c3.6-5.2 7.6-9.2 12-12.4' fill='none' stroke='%233a57a2' stroke-width='1.1' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-trop-sarny       { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%237d8fd0'%3E%3Cpath d='M8.3 3.3C5.8 4.6 4.6 8.4 4.8 12.6c.2 3.6 1.7 6.4 3.7 7.4 1.6.8 2.7-.4 2.7-2.6V5.5c0-1.8-1.3-3-2.9-2.2z'/%3E%3Cpath d='M15.7 3.3c2.5 1.3 3.7 5.1 3.5 9.3-.2 3.6-1.7 6.4-3.7 7.4-1.6.8-2.7-.4-2.7-2.6V5.5c0-1.8 1.3-3 2.9-2.2z'/%3E%3C/svg%3E"); }
.swieto-pszczola         { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cellipse cx='9.5' cy='8' rx='4.2' ry='3' transform='rotate(-25 9.5 8)' fill='%23dfe5f6' stroke='%237d8fd0' stroke-width='.8'/%3E%3Cellipse cx='14.5' cy='8' rx='4.2' ry='3' transform='rotate(25 14.5 8)' fill='%23dfe5f6' stroke='%237d8fd0' stroke-width='.8'/%3E%3Cellipse cx='11' cy='14.5' rx='7' ry='5' fill='%23e3c47e'/%3E%3Cpath d='M9 10v9M12.6 9.6v9.8' stroke='%233a57a2' stroke-width='1.9'/%3E%3Ccircle cx='18.6' cy='14' r='2.7' fill='%233a57a2'/%3E%3C/svg%3E"); }
.swieto-kosc             { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23d7b56d'%3E%3Cg transform='rotate(-35 12 12)'%3E%3Crect x='6' y='10' width='12' height='4' rx='1.5'/%3E%3Ccircle cx='6' cy='9.7' r='2.7'/%3E%3Ccircle cx='6' cy='14.3' r='2.7'/%3E%3Ccircle cx='18' cy='9.7' r='2.7'/%3E%3Ccircle cx='18' cy='14.3' r='2.7'/%3E%3C/g%3E%3C/svg%3E"); }
.swieto-kosc-jasna       { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%237d8fd0'%3E%3Cg transform='rotate(-35 12 12)'%3E%3Crect x='6' y='10' width='12' height='4' rx='1.5'/%3E%3Ccircle cx='6' cy='9.7' r='2.7'/%3E%3Ccircle cx='6' cy='14.3' r='2.7'/%3E%3Ccircle cx='18' cy='9.7' r='2.7'/%3E%3Ccircle cx='18' cy='14.3' r='2.7'/%3E%3C/g%3E%3C/svg%3E"); }

/* ZA treścią (właściciel, 04.10.2026: "nie na pierwszym planie. Mogą biegać sobie po wolnych polach poza obszarem
   roboczym") - nad samą poświatą tła, pod każdą kartą, napisem i belką. okazje.js stawia drobiny tylko w wolnych polach
   (marginesy, odstępy między kartami, miejsce pod treścią); gdy strona się przewinie, drobina chowa się za kartą. */
.okazja-tlo { position: fixed; inset: 0 0 auto; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none; overflow: hidden; }
.okazja-czastka, .okazja-trop {
    position: absolute; left: var(--x); top: var(--y); width: var(--rozmiar); height: var(--rozmiar);
    margin: calc(var(--rozmiar) / -2) 0 0 calc(var(--rozmiar) / -2); opacity: 0;
    background-position: center; background-size: contain; background-repeat: no-repeat;
}
.okazja-trop { transform: rotate(var(--obrot)); }
@media (prefers-reduced-motion: no-preference) {
    .okazja-opad      { animation: toz-okazja-opad var(--czas) linear; }
    .okazja-wzlot     { animation: toz-okazja-wzlot var(--czas) ease-in-out; }
    .okazja-migotanie { animation: toz-okazja-migotanie var(--czas) ease-in-out; }
    /* Pszczoła okrąża półtora razy punkt w wolnym polu (promień z okazje.js) i odlatuje - bez pętli. */
    .okazja-krazenie  { animation: toz-okazja-krazenie var(--czas) linear; }
    /* Ślad łapki odciska się, chwilę stoi i blednie; następny pojawia się o krok dalej (opóźnienie z okazje.js). */
    .okazja-trop      { animation: toz-okazja-trop 1.6s ease-out var(--opoznienie) backwards; }
    @keyframes toz-okazja-opad {
        from { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg); }
        20%, 75% { opacity: .85; }
        to   { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) rotate(160deg); }
    }
    @keyframes toz-okazja-wzlot {
        from { opacity: 0; transform: translate3d(0, 0, 0) rotate(-10deg); }
        20%, 75% { opacity: .85; }
        to   { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) rotate(10deg); }
    }
    @keyframes toz-okazja-krazenie {
        from     { opacity: 0; transform: rotate(0deg) translateX(var(--promien)) rotate(0deg); }
        12%, 82% { opacity: .9; }
        to       { opacity: 0; transform: rotate(540deg) translateX(var(--promien)) rotate(-540deg); }
    }
    @keyframes toz-okazja-migotanie {
        0%, 100% { opacity: 0; transform: scale(.5) rotate(0deg); }
        50%      { opacity: .9; transform: scale(1) rotate(45deg); }
    }
    @keyframes toz-okazja-trop {
        0%   { opacity: 0; transform: rotate(var(--obrot)) scale(.6); }
        12%  { opacity: .9; transform: rotate(var(--obrot)) scale(1); }
        50%  { opacity: .75; }
        100% { opacity: 0; transform: rotate(var(--obrot)) scale(1); }
    }
}
/* Pasek okazji pod belką menu - lampki na Boże Narodzenie, iskry na Sylwestra i Nowy Rok, pisanki na Wielkanoc,
   serca i łapki w swoje dni, w barwach marki. Ma tło belki, więc jest jej dolnym brzegiem: przewijana treść chowa
   się pod nim, jak pod belką, zamiast mieć na sobie kropki. Nie łapie kliknięć. */
body[data-okazja] .topbar::after {
    content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 10px; pointer-events: none;
    background-color: var(--toz-belka); background-repeat: repeat-x; background-size: 28px 10px;
    box-shadow: 0 8px 12px -8px rgba(44, 67, 129, .18);
}
/* Pasek wisi pod belką, więc belka musi być jego punktem odniesienia także tam, gdzie nie jest przyklejona (do 760 px,
   menu rozwinięte, strona bez skryptów) - inaczej pasek stawał na dole pierwszego ekranu, w poprzek treści. */
@media (max-width: 760px) {
    body[data-okazja] .topbar { position: relative; }
}
/* Przyklejony nagłówek tabeli staje tuż pod paskiem, a nie pod nim schowany (belka jest przyklejona od 761 px). */
@media (min-width: 761px) {
    body[data-okazja] .tabela-z-naglowkiem > .naglowek-kopia { top: calc(var(--toz-belka-wysokosc, 0px) + 10px); }
}
body[data-okazja="boze-narodzenie"] .topbar::after {
    background-image: radial-gradient(circle at 7px 5px, #d7b56d 0 2.6px, transparent 3px),
        radial-gradient(circle at 21px 5px, #7d8fd0 0 2.6px, transparent 3px),
        linear-gradient(transparent 4.5px, rgba(58, 87, 162, .25) 4.5px 5.5px, transparent 5.5px);
}
body[data-okazja="sylwester"] .topbar::after, body[data-okazja="nowy-rok"] .topbar::after {
    background-image: radial-gradient(circle at 7px 5px, #e3c47e 0 1.8px, transparent 2.4px),
        radial-gradient(circle at 21px 3px, #7d8fd0 0 1.4px, transparent 2px),
        radial-gradient(circle at 15px 8px, #d7b56d 0 1.2px, transparent 1.8px);
}
body[data-okazja="wielkanoc"] .topbar::after {
    background-image: radial-gradient(ellipse 3px 4px at 7px 5px, #d7b56d 98%, transparent),
        radial-gradient(ellipse 3px 4px at 21px 5px, #7d8fd0 98%, transparent);
}
body[data-okazja="dzien-wolontariusza"] .topbar::after, body[data-okazja="dzien-zwierzat"] .topbar::after,
body[data-okazja="dzien-kota"] .topbar::after, body[data-okazja="dzien-przyrody"] .topbar::after,
body[data-okazja="dzien-pszczol"] .topbar::after, body[data-okazja="dzien-psa"] .topbar::after,
body[data-okazja="dzien-kundelka"] .topbar::after {
    background-image: radial-gradient(circle at 7px 5px, #d7b56d 0 2.2px, transparent 2.8px),
        radial-gradient(circle at 21px 5px, rgba(125, 143, 208, .8) 0 2.2px, transparent 2.8px);
}
@media (prefers-reduced-motion: no-preference) {
    /* Lampki i iskry delikatnie mrugają. */
    body[data-okazja="boze-narodzenie"] .topbar::after, body[data-okazja="sylwester"] .topbar::after,
    body[data-okazja="nowy-rok"] .topbar::after { animation: toz-okazja-lampki 2.4s ease-in-out infinite alternate; }
    @keyframes toz-okazja-lampki { from { opacity: .55; } to { opacity: 1; } }
}
@media print { .okazja-tlo, body[data-okazja] .topbar::after { display: none; } }

/* Treść punktu sprawy ogólnej na liście spraw uchwały (04.10.2026) - pod tematem, z podziałem na akapity. */
.tresc-punktu { display: block; margin-top: 4px; white-space: pre-line; overflow-wrap: anywhere; }

/* "±" przy kwocie faktury - minus dla faktury korygującej na telefonie (audyt 04.10.2026, F08). */
.znak-kwoty { margin-top: 6px; min-width: 44px; font-size: 1rem; }

/* --- Listy i karty w ruchu (właściciel, 27.10.2026: „działaj” - grafika nr 21, 22, 24, 25) ----------------------------
   Strefa plików budzi się, gdy plik wjedzie w okno; czerwień zaległości gaśnie złotem; napis z wiersza przelatuje
   w tytuł karty; plakietka stanu odwraca się na nowy kolor. Zasady „Efektów wizualnych” jak wszędzie (pilnuje ich
   unit-efekty): ruch tylko w bloku prefers-reduced-motion, raz po działaniu człowieka, nic nad treścią; barwy tylko
   granat i złoto marki, czerwień tylko jako dawny stan, który blednie. Tryb ciemny z ciemny-arkusz.py. */

/* Strefa plików (grafika nr 21; przeciagnij-pliki.js): gdy plik wjedzie w okno przeglądarki, każda widoczna strefa
   „budzi się” (strefa-zrzutu-czuwa) - przerywaną ramkę na czas przeciągania zastępuje pierścień z granatu w złoto
   (przerywana ramka nie przyjmie spadku barwy, więc pierścień to maska na ::after), a za napisami strefy czeka duża,
   blada łapa z rozczapierzonymi palcami. Strefa pod kursorem (strefa-zrzutu-aktywna) świeci mocniej. Łapa stoi ZA
   napisami: strefa jest wtedy osobną warstwą (isolation), łapa pod jej treścią. Bez ruchu w systemie pierścień i łapa
   też się zapalają - to znak, gdzie wolno upuścić plik; biegnie tylko światło. Na telefonie pliku się nie przeciąga. */
@property --strefa-swiatlo { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.strefa-zrzutu-czuwa, .strefa-zrzutu-lapie { isolation: isolate; }
.strefa-zrzutu-czuwa { border-color: transparent; }
.strefa-zrzutu-czuwa::after {
    content: ''; position: absolute; inset: -2px; padding: 2px; border-radius: inherit; pointer-events: none;
    background: conic-gradient(from var(--strefa-swiatlo), var(--toz-granat), #6f86c9 18%, var(--toz-zloto) 32%, var(--toz-granat) 52%,
        #6f86c9 74%, var(--toz-zloto) 88%, var(--toz-granat));
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor; mask-composite: exclude;
}
.strefa-zrzutu-czuwa::before {
    content: ''; position: absolute; inset: 6px; z-index: -1; pointer-events: none; opacity: .13;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cdefs%3E%3ClinearGradient id='g' gradientUnits='userSpaceOnUse' x1='4' y1='4' x2='44' y2='44'%3E%3Cstop offset='0' stop-color='%233a57a2'/%3E%3Cstop offset='1' stop-color='%23d7b56d'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='url(%23g)'%3E%3Cellipse cx='7.6' cy='19' rx='4.3' ry='6' transform='rotate(-32 7.6 19)'/%3E%3Cellipse cx='17.6' cy='9.6' rx='4.6' ry='6.6' transform='rotate(-12 17.6 9.6)'/%3E%3Cellipse cx='30.4' cy='9.6' rx='4.6' ry='6.6' transform='rotate(12 30.4 9.6)'/%3E%3Cellipse cx='40.4' cy='19' rx='4.3' ry='6' transform='rotate(32 40.4 19)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
}
.strefa-zrzutu-czuwa.strefa-zrzutu-aktywna::before { opacity: .24; }
.strefa-zrzutu-czuwa.strefa-zrzutu-aktywna::after { inset: -3px; padding: 3px; }
@media (max-width: 640px) {
    .strefa-zrzutu-czuwa::before, .strefa-zrzutu-czuwa::after { display: none; }
}
@media (prefers-reduced-motion: no-preference) {
    /* Światło biegnie dookoła strefy tyle, ile trwa przeciąganie (jak kreska wczytywania); łapa wychodzi raz. */
    .strefa-zrzutu-czuwa::after { animation: toz-strefa-swiatlo 2.4s linear infinite; }
    .strefa-zrzutu-czuwa::before { animation: toz-strefa-lapa-czeka .3s ease-out; }
    /* Plik złapany (upuszczony albo wklejony; strefa-zrzutu-lapie na 0,8 s): łapa za napisami zaciska palce i gaśnie,
       a strefa raz błyska złotem - bez lecących ikonek nad treścią. */
    .strefa-zrzutu-lapie { animation: toz-strefa-blysk .7s ease-out; }
    .strefa-zrzutu-lapie::before {
        content: ''; position: absolute; inset: 6px; z-index: -1; pointer-events: none; opacity: 0;
        background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cdefs%3E%3ClinearGradient id='g' gradientUnits='userSpaceOnUse' x1='4' y1='4' x2='44' y2='44'%3E%3Cstop offset='0' stop-color='%233a57a2'/%3E%3Cstop offset='1' stop-color='%23d7b56d'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='url(%23g)'%3E%3Cellipse cx='13.2' cy='22.4' rx='4' ry='4.8' transform='rotate(-18 13.2 22.4)'/%3E%3Cellipse cx='19.6' cy='16.6' rx='4.2' ry='5' transform='rotate(-6 19.6 16.6)'/%3E%3Cellipse cx='28.4' cy='16.6' rx='4.2' ry='5' transform='rotate(6 28.4 16.6)'/%3E%3Cellipse cx='34.8' cy='22.4' rx='4' ry='4.8' transform='rotate(18 34.8 22.4)'/%3E%3Cpath d='M24 23.5c-6.4 0-11.8 5.8-11.8 11.3 0 3.6 2.7 5.5 5.8 5.5 2.4 0 3.9-1.1 6-1.1s3.6 1.1 6 1.1c3.1 0 5.8-1.9 5.8-5.5 0-5.5-5.4-11.3-11.8-11.3z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
        animation: toz-strefa-lapa-lapie .7s ease-out;
    }
    @keyframes toz-strefa-swiatlo { to { --strefa-swiatlo: 360deg; } }
    @keyframes toz-strefa-lapa-czeka { from { opacity: 0; transform: scale(.82); } }
    @keyframes toz-strefa-lapa-lapie {
        from { opacity: .3; transform: scale(1.08); }
        35%  { opacity: .32; transform: scale(.86); }
        to   { opacity: 0; transform: scale(.9); }
    }
    @keyframes toz-strefa-blysk {
        from { background-color: rgba(215, 181, 109, .3); box-shadow: 0 0 0 0 rgba(215, 181, 109, .55); }
        to   { box-shadow: 0 0 0 12px rgba(215, 181, 109, 0); }
    }
}

/* Czerwone gaśnie złotem (grafika nr 22; App\Historia\ZaleglosciZdjete): na pierwszym widoku listy po zapisie, który
   zdjął zaległość, przez wiersz od lewej przebiega złota smuga - komórka po komórce, a przy zbiorczym „Zapłacono dnia”
   wiersze gasną po kolei, falą z góry na dół (data-gasnie: kolej w fali, dalsze razem z dwunastym). Ruch zaczyna się od
   złota: dawna czerwień tylko blednie w tle (wyroki, teczki, pisma) albo w dacie „po terminie” (faktury - tam wiersz
   nie miał czerwonego tła). Ok. 1,5 s, raz. Animuje się samo tło i barwa komórek, bez przesunięć i bez „zostaje”.
   Wiersz, z którego weszło się w kartę (wiersz-ostatni z ulatwienia.js), dostaje ten ruch zamiast zwykłego błysku -
   jeden ruch, nie dwa; złota kreska z lewej zostaje. */
@media (prefers-reduced-motion: no-preference) {
    .table tbody tr.wiersz-gasnie[data-gasnie] > td {
        background-image: linear-gradient(90deg, rgba(215, 181, 109, 0), rgba(215, 181, 109, .55), rgba(215, 181, 109, 0));
        background-size: 60% 100%; background-repeat: no-repeat; background-position: -150% 0;
        animation: toz-gasnie-smuga .55s ease-out calc(var(--gasnie-wiersz, 0s) + var(--gasnie-kolumna, 0s));
    }
    .table tbody tr.wiersz-gasnie-tlo[data-gasnie] > td {
        animation: toz-gasnie-smuga .55s ease-out calc(var(--gasnie-wiersz, 0s) + var(--gasnie-kolumna, 0s)),
            toz-gasnie-tlo 1.5s ease-out var(--gasnie-wiersz, 0s) backwards;
    }
    .table tbody tr.wiersz-gasnie[data-gasnie] > td.termin-gasnie {
        animation: toz-gasnie-smuga .55s ease-out calc(var(--gasnie-wiersz, 0s) + var(--gasnie-kolumna, 0s)),
            toz-gasnie-data 1.5s ease-out var(--gasnie-wiersz, 0s) backwards;
    }
    tr.wiersz-gasnie[data-gasnie="2"] { --gasnie-wiersz: .08s; }
    tr.wiersz-gasnie[data-gasnie="3"] { --gasnie-wiersz: .16s; }
    tr.wiersz-gasnie[data-gasnie="4"] { --gasnie-wiersz: .24s; }
    tr.wiersz-gasnie[data-gasnie="5"] { --gasnie-wiersz: .32s; }
    tr.wiersz-gasnie[data-gasnie="6"] { --gasnie-wiersz: .4s; }
    tr.wiersz-gasnie[data-gasnie="7"] { --gasnie-wiersz: .48s; }
    tr.wiersz-gasnie[data-gasnie="8"] { --gasnie-wiersz: .56s; }
    tr.wiersz-gasnie[data-gasnie="9"] { --gasnie-wiersz: .64s; }
    tr.wiersz-gasnie[data-gasnie="10"] { --gasnie-wiersz: .72s; }
    tr.wiersz-gasnie[data-gasnie="11"] { --gasnie-wiersz: .8s; }
    tr.wiersz-gasnie[data-gasnie="12"] { --gasnie-wiersz: .88s; }
    tr.wiersz-gasnie > td:nth-child(2) { --gasnie-kolumna: .05s; }
    tr.wiersz-gasnie > td:nth-child(3) { --gasnie-kolumna: .1s; }
    tr.wiersz-gasnie > td:nth-child(4) { --gasnie-kolumna: .15s; }
    tr.wiersz-gasnie > td:nth-child(5) { --gasnie-kolumna: .2s; }
    tr.wiersz-gasnie > td:nth-child(6) { --gasnie-kolumna: .25s; }
    tr.wiersz-gasnie > td:nth-child(7) { --gasnie-kolumna: .3s; }
    tr.wiersz-gasnie > td:nth-child(8) { --gasnie-kolumna: .35s; }
    tr.wiersz-gasnie > td:nth-child(9) { --gasnie-kolumna: .4s; }
    tr.wiersz-gasnie > td:nth-child(10) { --gasnie-kolumna: .45s; }
    tr.wiersz-gasnie > td:nth-child(n+11) { --gasnie-kolumna: .5s; }
    @keyframes toz-gasnie-smuga { from { background-position: -150% 0; } to { background-position: 250% 0; } }
    @keyframes toz-gasnie-tlo { from { background-color: #f6e6d8; } 30% { background-color: rgba(215, 181, 109, .26); } }
    @keyframes toz-gasnie-data { from { color: #b97880; } }
}

/* Napis z wiersza przelatuje w tytuł karty i wraca (grafika nr 24; przejscie-wiersza.js nazywa po jednym elemencie
   na obu stronach i daje nowej stronie kierunek): komórka z napisem (data-napis-wiersza w szablonie listy) albo zdjęcie
   z galerii płynie i rośnie w tytuł karty, a reszta karty wchodzi lekko z prawej - w głąb. Po powrocie lista wchodzi
   z lewej, a tytuł kurczy się w swój wiersz (gdy stoi na pierwszym ekranie). Całość ok. 0,26 s (najwyżej 0,3 s, decyzja
   04.10.2026). Obraz napisu skaluje się po wysokości, bez rozciągania. Wiersz, który przyjmuje tytuł, nie wchodzi falą
   (wiersz-przyjmuje) - tytuł ląduje w wierszu, który już stoi. Starsza przeglądarka - jak dotąd. */
@media (prefers-reduced-motion: no-preference) {
    html.przejscie-dalej::view-transition-new(root) { animation: toz-przejscie-z-prawej .26s cubic-bezier(.2, .8, .2, 1) both; }
    html.przejscie-wstecz::view-transition-new(root) { animation: toz-przejscie-z-lewej .26s cubic-bezier(.2, .8, .2, 1) both; }
    ::view-transition-group(napis-wiersza) { animation-duration: .26s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
    ::view-transition-old(napis-wiersza), ::view-transition-new(napis-wiersza) { height: 100%; width: auto; }
    .table-wrap-ewidencja .table tbody tr.wiersz-przyjmuje:nth-child(n), ul.galeria-adopcji > li.wiersz-przyjmuje { animation-name: none; }
    @keyframes toz-przejscie-z-prawej { from { opacity: 0; transform: translateX(28px); } }
    @keyframes toz-przejscie-z-lewej { from { opacity: 0; transform: translateX(-28px); } }
}

/* Plakietka odwraca się na nowy kolor (grafika nr 25). W wierszu listy (w-wierszu.js): stara plakietka obraca się jak
   tabliczka wokół poziomej osi do połowy, nowa dokręca się do końca w nowym kolorze, razem z zielonym pierścieniem
   potwierdzenia. Na karcie składek po „Dodaj wpłatę” (App\Zarzad\SwiezoOplacone, _skladki-miesiace.php) miesiące
   opłacone tą wpłatą odwracają się po kolei z „brak” albo „jeszcze nie” na „zapłacona”, jak kartki kalendarza -
   najwyżej dwanaście, co 0,08 s (całość do 1,2 s). Obie strony to te same plakietki stanów, więc ciemny wygląd ma je
   od razu; dawna strona jest tylko dla oka (aria-hidden) i bez ruchu w systemie jej nie ma. */
.odwrotka { display: inline-grid; }
.odwrotka > .stan { grid-area: 1 / 1; justify-self: end; }
.odwrotka-stara { display: none; }
@media (prefers-reduced-motion: no-preference) {
    button.stan.w-wierszu-odwraca { animation: toz-plakietka-odwraca .15s ease-in forwards; }
    button.stan.w-wierszu-dokreca { animation: toz-plakietka-dokreca .15s ease-out, toz-w-wierszu-zapisane .7s ease-out; }
    /* Przycisk zmiany w wierszu, który nie jest plakietką (ikona flagi na liście maili, 10.11.2026), odwraca się tak samo. */
    button.w-wierszu:not(.stan).w-wierszu-odwraca { animation: toz-plakietka-odwraca .15s ease-in forwards; }
    button.w-wierszu:not(.stan).w-wierszu-dokreca { animation: toz-plakietka-dokreca .15s ease-out, toz-w-wierszu-zapisane .7s ease-out; }
    .odwrotka-stara { display: inline-block; animation: toz-odwrotka-stara .15s ease-in var(--odwrotka-zwloka, 0s) forwards; }
    .odwrotka-nowa { animation: toz-plakietka-dokreca .15s ease-out calc(var(--odwrotka-zwloka, 0s) + .15s) backwards; }
    .odwrotka[data-odwrotka="2"] { --odwrotka-zwloka: .08s; }
    .odwrotka[data-odwrotka="3"] { --odwrotka-zwloka: .16s; }
    .odwrotka[data-odwrotka="4"] { --odwrotka-zwloka: .24s; }
    .odwrotka[data-odwrotka="5"] { --odwrotka-zwloka: .32s; }
    .odwrotka[data-odwrotka="6"] { --odwrotka-zwloka: .4s; }
    .odwrotka[data-odwrotka="7"] { --odwrotka-zwloka: .48s; }
    .odwrotka[data-odwrotka="8"] { --odwrotka-zwloka: .56s; }
    .odwrotka[data-odwrotka="9"] { --odwrotka-zwloka: .64s; }
    .odwrotka[data-odwrotka="10"] { --odwrotka-zwloka: .72s; }
    .odwrotka[data-odwrotka="11"] { --odwrotka-zwloka: .8s; }
    .odwrotka[data-odwrotka="12"] { --odwrotka-zwloka: .88s; }
    @keyframes toz-plakietka-odwraca { to { transform: perspective(240px) rotateX(90deg); } }
    @keyframes toz-plakietka-dokreca { from { transform: perspective(240px) rotateX(-90deg); } }
    @keyframes toz-odwrotka-stara { to { transform: perspective(240px) rotateX(90deg); visibility: hidden; } }
}

/* --- Dostępność i telefon (audyt 04.10.2026, seria F) -------------------------------------------- */
/* Napis zależny od wskaźnika: "przeciągnij" tylko przy myszy, na dotyku "wybierz albo zrób zdjęcie" (F51). */
.tylko-dotyk { display: none; }
@media (hover: none) and (pointer: coarse) {
    .tylko-mysz { display: none; }
    .tylko-dotyk { display: inline; }
}
/* Gwiazdka przy nazwisku wyróżnionego członka (F35) - złota, jak wyróżnienie w całym systemie. */
.znak-wyroznienia { color: var(--toz-uwaga); margin-right: 4px; }
/* Grupa pól bez ramki - sama nazwa dla czytnika (wybór metody logowania dwuetapowego, F15). */
fieldset.bez-ramki { border: 0; padding: 0; margin: 0; }
/* Tryb wysokiego kontrastu (Windows): wybór tak/nie i "dziś" w kalendarzu niosą wyróżnienie
   kolorami systemu, a nie własnym tłem, które ten tryb zdejmuje (F34). */
@media (forced-colors: active) {
    .przelacznik-tak-nie input:checked + label { forced-color-adjust: none; background: Highlight; color: HighlightText; }
    .kalendarz-dzis { outline: 3px solid Highlight; outline-offset: -3px; }
    .zakladka.aktywna, .btn-strona-aktywna { text-decoration: underline; }
    /* Pismo "do realizacji": czerwone tło znika, a słowo jest tylko dla czytnika - znak w barwie systemu (J205). */
    .table tbody tr.wiersz-do-realizacji > td:first-child, .table tbody tr.wiersz-zalega > td:first-child { border-left: 4px solid Highlight; }
    /* Lista zmiany w wierszu: pozycję spod strzałek oznacza tło i cień, które ten tryb zdejmuje; wiersz zmieniony
       na żywo - tak samo (audyt 23.10.2026, T17, WCAG 2.4.7). */
    .w-wierszu-lista [role="option"].aktywna { outline: 2px solid Highlight; outline-offset: -2px; }
    tr.na-zywo-zmiana > td:first-child { border-left: 4px solid Highlight; }
}
/* Safari na iPhonie wysyła stuknięcie tylko do elementu, który wygląda na klikalny - plakietka
   "kto i kiedy" i treść strony (zamykanie menu i list stuknięciem obok) dostają wskaźnik (F36). */
@media (hover: none) and (pointer: coarse) {
    [data-kto-i-kiedy], main#tresc { cursor: pointer; }
    /* Bez szarego błysku całej treści przy każdym stuknięciu (Safari). */
    main#tresc { -webkit-tap-highlight-color: transparent; }
}
/* Pola z mniejszym pismem też mają 16 px na dotyku - inaczej Safari przybliża stronę (F39, F43). */
@media (pointer: coarse) {
    .zbiorczo textarea, .kopiuj-adresy textarea { font-size: 16px; }
    /* Nazwy zdarzeń w kalendarzu łamią się zamiast ucinać - na dotyku nie ma dymka (F30). */
    .zdarzenie { white-space: normal; }
}
@media (max-width: 640px) {
    /* Wiersz załącznika: przyciski schodzą pod opis, opis ma całą szerokość (F40). */
    .zalaczniki li, .materialy li { flex-wrap: wrap; }
    .zalaczniki li .zalacznik-opis, .materialy li .zalacznik-opis { flex: 1 1 calc(100% - 80px); }
    /* Długie napisy na przyciskach w kartach łamią się, zamiast wychodzić poza kartę (F41). */
    .card .btn { white-space: normal; max-width: 100%; }
    .card .table .btn { white-space: nowrap; }
}
/* Telefon trzymany poziomo (niski ekran) - belka i pasek zapisu nieprzyklejone, jak na wąskim (F52). Na końcu
   arkusza, żeby wygrać z regułami bazowymi; belka "relative", nie "static" - od niej liczy się panel zwiniętego
   menu i pasek okazji (przegląd napraw 04.10.2026). */
@media (max-height: 500px) {
    .topbar { position: relative; }
    .pasek-zapisu { position: static; backdrop-filter: none; }
}

/* Ikony plików przy dokumentach (właściciel, 07.10.2026: "Nie pisz przy dokumentach w systemie, czy to jest
   dokument Worda, czy PDF, czy jakiś inny, po prostu zastosuj odpowiednią ikonę pasującą do określonego dokumentu").
   Klasa "plik plik-<rodzaj>" (helper plik_klasa()) - ikona przed napisem przycisku albo odnośnika; "plik-sam" -
   sama ikona (plakietka wzoru, kafelek pliku). Barwy stałe, w obu trybach te same - ikona to znak, nie tło. */
.plik::before { content: ''; flex: 0 0 auto; display: inline-block; width: 1.3em; height: 1.3em; margin-right: .45em;
    background: center / contain no-repeat; vertical-align: -.28em; }
.plik-sam::before { margin-right: 0; width: 26px; height: 26px; }
.material-pdf.plik-sam::before { width: 46px; height: 46px; }
.zalacznik-podglad.plik-sam::before { width: 36px; height: 36px; }
.plik-docx::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%232b579a' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%232b579a' stroke-width='1.3' stroke-linejoin='round'/%3E%3Crect x='1.5' y='11' width='11' height='9' rx='1.6' fill='%232b579a'/%3E%3Ctext x='7.0' y='18.2' font-family='Arial,Helvetica,sans-serif' font-size='7.6' font-weight='700' fill='%23fff' text-anchor='middle'%3EW%3C/text%3E%3C/svg%3E"); }
.plik-xlsx::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%231e7145' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%231e7145' stroke-width='1.3' stroke-linejoin='round'/%3E%3Crect x='1.5' y='11' width='11' height='9' rx='1.6' fill='%231e7145'/%3E%3Ctext x='7.0' y='18.2' font-family='Arial,Helvetica,sans-serif' font-size='7.6' font-weight='700' fill='%23fff' text-anchor='middle'%3EX%3C/text%3E%3C/svg%3E"); }
.plik-pdf::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%23c8312b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%23c8312b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Crect x='1.5' y='11' width='15' height='9' rx='1.6' fill='%23c8312b'/%3E%3Ctext x='9.0' y='18.2' font-family='Arial,Helvetica,sans-serif' font-size='5.6' font-weight='700' fill='%23fff' text-anchor='middle'%3EPDF%3C/text%3E%3C/svg%3E"); }
.plik-zip::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%236b6f7b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%236b6f7b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Crect x='11' y='3.0' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='12.5' y='4.6' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='11' y='6.2' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='12.5' y='7.8' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='11' y='9.4' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='12.5' y='11.0' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='11' y='12.6' width='1.5' height='1.1' fill='%236b6f7b'/%3E%3Crect x='10.6' y='14.4' width='3.8' height='5' rx='1' fill='%236b6f7b'/%3E%3Crect x='11.7' y='16.6' width='1.6' height='1.6' rx='.4' fill='%23fff'/%3E%3C/svg%3E"); }
.plik-csv::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%230f766e' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%230f766e' stroke-width='1.3' stroke-linejoin='round'/%3E%3Crect x='7.5' y='9.5' width='9.5' height='9.5' fill='none' stroke='%230f766e' stroke-width='1.1'/%3E%3Cpath d='M7.5 12.7h9.5M7.5 15.8h9.5M10.7 9.5v9.5M13.9 9.5v9.5' stroke='%230f766e' stroke-width='1.1'/%3E%3C/svg%3E"); }
.plik-inny::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 1.75h8.25L19.5 7v14.25a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2.75a1 1 0 0 1 1-1z' fill='%23fff' stroke='%236b6f7b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M14.25 1.75V7h5.25' fill='none' stroke='%236b6f7b' stroke-width='1.3' stroke-linejoin='round'/%3E%3Cpath d='M8 10h8M8 13h8M8 16h5.5' stroke='%236b6f7b' stroke-width='1.3' stroke-linecap='round'/%3E%3C/svg%3E"); }
/* Rodzaj pliku dla czytnika ekranu - tekst zastępczy ikony (składnia content: '' / 'opis'), na ekranie nic się nie zmienia
   (zasada: bez formatu w napisach). Przeglądarka bez tej składni pomija deklarację i zostaje sama ikona (audyt 08.10.2026, J206). */
.plik-docx::before { content: '' / 'dokument Word, '; }
.plik-pdf::before { content: '' / 'dokument PDF, '; }
.plik-xlsx::before { content: '' / 'arkusz, '; }
.plik-csv::before { content: '' / 'zestawienie wpisów, '; }
.plik-zip::before { content: '' / 'paczka plików, '; }

/* Adres konta systemu Google na karcie oddziału (kopia do arkusza, 25.10.2026) - długi adres zawija się na telefonie,
   zamiast uciekać poza kartę; na komputerze stoi w jednej linii, gdy się mieści. */
.adres-konta { overflow-wrap: anywhere; }

/* Ikony czynności w wierszach tabel (właściciel, 25.10.2026: "dało by się na listach zmienić te przyciski które tam są
   na jakieś ładne ikony ?" - wybrany wariant B, same ikony). Przycisk "btn btn-maly btn-ikona" z title (dymek pod myszą),
   wnętrze daje helper ikona_czynnosci(napis): ikona i ten sam napis dla czytnika ekranu. Ikona to maska w kolorze
   napisu przycisku - działa w obu trybach; kosz zawsze czerwony. Rysunki własne (SVG w arkuszu, jak ikony plików). */
.ikona { display: inline-block; flex: 0 0 auto; width: 18px; height: 18px; background-color: currentColor;
    -webkit-mask: var(--ikona) center / contain no-repeat; mask: var(--ikona) center / contain no-repeat; }
.btn.btn-ikona { width: 34px; min-width: 34px; padding: 0; }
.btn-ikona .ikona-usun { background-color: var(--toz-blad); }
.btn-ikona:has(.ikona-usun) { --fala: rgba(165, 40, 52, .4); }
.btn.btn-ikona:not(.btn-primary):not(.btn-danger):not(.btn-link):not(.btn-strona-aktywna):has(.ikona-usun) { border-color: rgba(165, 40, 52, .35); }
.btn.btn-ikona:not(.btn-primary):not(.btn-danger):not(.btn-link):not(.btn-strona-aktywna):not(:disabled):has(.ikona-usun):hover {
    border-color: rgba(165, 40, 52, .6); box-shadow: 0 2px 10px rgba(165, 40, 52, .16);
}
/* Tryb wysokiego kontrastu (Windows) zastępuje tła - maska bez tego znikałaby razem z ikoną. */
@media (forced-colors: active) { .ikona, .btn-ikona .ikona-usun { forced-color-adjust: none; background-color: ButtonText; } }
.ikona-otworz { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 12s3.5-6.5 9.5-6.5S21.5 12 21.5 12s-3.5 6.5-9.5 6.5S2.5 12 2.5 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); } /* oko - Otwórz, Pokaż */
.ikona-edytuj { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20h4.5L19.3 9.2a2.1 2.1 0 0 0 0-3l-1.5-1.5a2.1 2.1 0 0 0-3 0L4 15.5V20z'/%3E%3Cpath d='M13.5 6l4.5 4.5'/%3E%3C/svg%3E"); } /* ołówek - Edytuj, Popraw, Uzupełnij */
.ikona-usun { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16'/%3E%3Cpath d='M9.5 7V4.5h5V7'/%3E%3Cpath d='M6.5 7l1 13h9l1-13'/%3E%3Cpath d='M10 11v5.5M14 11v5.5'/%3E%3C/svg%3E"); } /* kosz - Usuń, Usuń bezpowrotnie */
.ikona-odepnij { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3.5h6'/%3E%3Cpath d='M10 3.5v5L7 12v2h10v-2l-3-3.5v-5'/%3E%3Cpath d='M12 14v6.5'/%3E%3Cpath d='M4 4l16 16'/%3E%3C/svg%3E"); } /* przekreślona pinezka - Odepnij */
.ikona-przypnij { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3.5h6'/%3E%3Cpath d='M10 3.5v5L7 12v2h10v-2l-3-3.5v-5'/%3E%3Cpath d='M12 14v6.5'/%3E%3C/svg%3E"); } /* pinezka - Przypnij */
.ikona-przywroc { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 12a7.5 7.5 0 1 0 2.2-5.3L4.5 9'/%3E%3Cpath d='M4.5 4v5h5'/%3E%3C/svg%3E"); } /* strzałka zawracająca - Przywróć */
.ikona-kopiuj { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='9' y='9' width='11' height='11' rx='2'/%3E%3Cpath d='M5 15h-.5A1.5 1.5 0 0 1 3 13.5v-9A1.5 1.5 0 0 1 4.5 3h9A1.5 1.5 0 0 1 15 4.5V5'/%3E%3C/svg%3E"); } /* dwie kartki - Skopiuj */
.ikona-przeslij { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 2 11 13'/%3E%3Cpath d='M22 2 15 22l-4-9-9-4 20-7z'/%3E%3C/svg%3E"); }
.stopka-podglad { padding: .75rem; border: 1px solid var(--linia, #d8dde3); border-radius: 6px; overflow-wrap: anywhere; }
.stopka-podglad img { max-width: 100%; height: auto; }
.ikona-odpowiedz { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 7 4 12l5 5'/%3E%3Cpath d='M4 12h10a6 6 0 0 1 6 6v1'/%3E%3C/svg%3E"); }
.ikona-przekaz { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 7 5 5-5 5'/%3E%3Cpath d='M20 12H10a6 6 0 0 0-6 6v1'/%3E%3C/svg%3E"); }
.ikona-gwiazdka { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5l2.6 5.6 6.1.7-4.5 4.2 1.2 6-5.4-3-5.4 3 1.2-6-4.5-4.2 6.1-.7z'/%3E%3C/svg%3E"); } /* gwiazdka - mail bez gwiazdki */
.ikona-gwiazdka-pelna { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5l2.6 5.6 6.1.7-4.5 4.2 1.2 6-5.4-3-5.4 3 1.2-6-4.5-4.2 6.1-.7z'/%3E%3C/svg%3E"); background-color: var(--toz-uwaga-tekst, var(--toz-uwaga)); } /* pełna bursztynowa gwiazdka - mail z gwiazdką */
.ikona-dokosza { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.5v6'/%3E%3Cpath d='M9.2 5.8 12 8.6l2.8-2.8'/%3E%3Cpath d='M4.5 11.5h15'/%3E%3Cpath d='M6.5 11.5l1 9h9l1-9'/%3E%3C/svg%3E"); } /* strzałka do kosza - przeniesienie do kosza w skrzynce, da się cofnąć (07.11.2026) */
.ikona-spam { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8.2 3h7.6L21 8.2v7.6L15.8 21H8.2L3 15.8V8.2z'/%3E%3Cpath d='M12 7.5v5.5'/%3E%3Cpath d='M12 16.5h.01'/%3E%3C/svg%3E"); } /* ośmiokąt z wykrzyknikiem - do spamu (07.11.2026) */
/* Flaga przy mailu: znak stanu, nie czynność, więc bez gestu pod myszą; kolor z klasy flaga-kod (Poczekalnia::FLAGI). */
.ikona-flaga-maila { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 21V4' fill='none'/%3E%3Cpath d='M5 4h13l-3 4.5 3 4.5H5z'/%3E%3C/svg%3E"); vertical-align: -3px; }
.flaga-czerwony { background-color: var(--flaga-czerwony); }
.flaga-niebieski { background-color: var(--flaga-niebieski); }
.flaga-zielony { background-color: var(--flaga-zielony); }
.flaga-szary { background-color: var(--flaga-szary); }
.flaga-brazowy { background-color: var(--flaga-brazowy); }
.flaga-turkusowy { background-color: var(--flaga-turkusowy); }
.flaga-pomaranczowy { background-color: var(--flaga-pomaranczowy); }
.flaga-fioletowy { background-color: var(--flaga-fioletowy); }
.flaga-blekitny { background-color: var(--flaga-blekitny); }
.flaga-zolty { background-color: var(--flaga-zolty); }
.flagi-wybor { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; max-width: 100%; }
.flagi-wybor .btn .ikona { margin-right: 0; }
.flagi-wybor .btn[aria-pressed="true"], .flagi-wybor .btn[aria-current="true"], .flaga-menu .btn[aria-pressed="true"] { border-color: var(--toz-granat-tekst, var(--toz-granat)); box-shadow: inset 0 0 0 1px var(--toz-granat-tekst, var(--toz-granat)); }
/* Wybór flagi w zakładce Maile > Z flagą (04.11.2026): pod szukaniem, odnośniki jak przyciski koloru przy fladze faktur; na telefonie kolory łamią się do następnej linii. */
.flagi-filtr { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 10px; max-width: 100%; }
/* Flaga w wierszu listy (właściciel, 02.11.2026): ikona pusta albo w kolorze maila, a klik otwiera okienko przeglądarki (popover). Tabela ma overflow, więc coś stojącego w niej zostałoby
   przycięte; okienko leży ponad wszystkim, nie rozpycha strony w bok i zamyka się kliknięciem obok, bez skryptu. Tam, gdzie miejsca przy ikonie arkusz nie umie podać, staje na środku ekranu. */
.ikona-flaga-pusta { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 21V4'/%3E%3Cpath d='M5 4h13l-3 4.5 3 4.5H5z'/%3E%3C/svg%3E"); vertical-align: -3px; color: var(--toz-muted); }
.flaga-wiersza { display: inline-flex; vertical-align: -4px; padding: 3px; margin: -3px 1px -3px -3px; border: 0; border-radius: 6px; background: none; color: inherit; font: inherit; line-height: 0; cursor: pointer; }
.flaga-wiersza:hover { background: var(--toz-granat-jasny); }
.flaga-wiersza .ikona { margin-right: 0; }
/* Na dotyku pole 32 px przy tej samej wysokości wiersza: chybione dotknięcie otwierałoby kartę maila (zasada z T07). Tutaj, bo reguła wyżej stoi w arkuszu po blokach pointer: coarse. */
@media (pointer: coarse) {
    .flaga-wiersza { padding: 7px; margin: -7px 1px -7px -7px; }
}
.table tbody tr[id^="mail-wiersz-"] { scroll-margin-top: 30vh; } /* po flagowaniu z menu lista wraca do wiersza: ponad nim zostaje belka, nagłówek tabeli i komunikat */
.flaga-menu { padding: 8px; border: 1px solid var(--toz-border); border-radius: var(--toz-promien); background: var(--toz-plyta); color: var(--toz-text); box-shadow: 0 8px 24px rgba(35, 38, 47, .22); }
.flaga-menu:popover-open { display: grid; grid-template-columns: repeat(5, 34px); gap: 4px; }
.flaga-menu .flaga-usun, .flaga-menu [data-dlugo-stan] { grid-column: 1 / -1; }
.flaga-menu [data-dlugo-stan] { margin: 4px 0 0; max-width: 186px; }
.flaga-menu .btn .ikona { margin-right: 0; }
@supports (position-area: bottom) {
    .flaga-menu { inset: auto; margin: 4px; position-area: bottom span-right; position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline; }
}
.ikona-zrobione { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E"); } /* ptaszek - Zrobione */
/* Kolumna "Zdjecia" listy interwencji (wlasciciel, 29.10.2026) - jedna ikona na sprawe, barwy systemu: granatowy aparat
   (zdjecia z interwencji), czerwony trojkat (falszywe od zglaszajacego), bursztynowy znak zapytania (niesprawdzone),
   zielony ptaszek w kole (prawdziwe), czerwony krzyzyk (brak zdjec). Opis w dymku (data-dymek) i dla czytnika. Barwy
   -tekst w ciemnym wygladzie (jasniejsze), w jasnym - zwykle. */
.kol-zdjecia { width: 1%; }
.kol-zdjecia abbr { text-decoration: none; cursor: help; }
/* Na papierze ikona też - przeglądarka bez "grafiki tła" nie drukuje maski na barwie tła (przegląd 29.10.2026). */
@media print { .kol-zdjecia .ikona { -webkit-print-color-adjust: exact; print-color-adjust: exact; } }
.kol-zdjecia .ikona { width: 20px; height: 20px; vertical-align: middle; }
.ikona-zdjecia-z-interwencji { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8h3l1.5-2.5h7L17 8h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E"); background-color: var(--toz-granat-tekst, var(--toz-granat)); }
.ikona-zdjecia-falszywe { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5l9.5 16.5h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Cpath d='M12 17.5h.01'/%3E%3C/svg%3E"); background-color: var(--toz-blad-tekst, var(--toz-blad)); }
.ikona-zdjecia-niesprawdzone { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.5 9.5a2.5 2.5 0 1 1 3.5 2.3c-.6.3-1 .9-1 1.6v.6'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E"); background-color: var(--toz-uwaga-tekst, var(--toz-uwaga)); }
.ikona-zdjecia-prawdziwe { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5l2.8 2.8L16.5 9.5'/%3E%3C/svg%3E"); background-color: var(--toz-ok-tekst, var(--toz-ok)); }
.ikona-zdjecia-brak { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12'/%3E%3Cpath d='M18 6L6 18'/%3E%3C/svg%3E"); background-color: var(--toz-blad-tekst, var(--toz-blad)); }

/* Znaczek "zaufany" przy nadawcy maila odebranego i adresacie wysłanego (właściciel, 05.11.2026: "czy przy odebranych mailach zaznaczamy gdzieś
   że to zaufane adresy?") - na listach maili, w mailach sprawy, w rozmowie i w metryczce karty. Mała granatowa plakietka z tarczą i ptaszkiem,
   rodzaj adresu w dymku (data-dymek) i dla czytnika ekranu. Nie łamie się w środku: na telefonie przechodzi cała do następnej linijki. */
.znak-zaufany { display: inline-flex; align-items: center; gap: 3px; margin-left: 2px; padding: 0 7px 0 5px; border: 1px solid #c5cfe8; border-radius: 999px;
    background: var(--toz-granat-jasny); color: var(--toz-granat-ciemny); font-size: .75rem; font-weight: 400; line-height: 1.5; white-space: nowrap; vertical-align: 1px; }
a.znak-zaufany { text-decoration: none; }
a.znak-zaufany:hover, a.znak-zaufany:focus-visible { border-color: var(--toz-fokus); color: var(--toz-granat-ciemny); text-decoration: none; }
.znak-zaufany .ikona { width: 12px; height: 12px; }
.ikona-tarcza-zaufany { --ikona: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.8l7.8 3v5.8c0 4.6-3.3 8.4-7.8 9.8-4.5-1.4-7.8-5.2-7.8-9.8V5.8z'/%3E%3Cpath d='M8.6 12.2l2.4 2.4 4.6-4.8'/%3E%3C/svg%3E"); } /* tarcza z ptaszkiem - zaufany adres */

/* Zapisana treść odczytu AI (J315) - długie linie się zawijają, bez przesuwania strony w bok. */
.tresc-odczytu {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: .875rem;
}

/* Stała strona błędu (gdy strony aplikacji nie da się złożyć albo po błędzie krytycznym) - bez układu i bez
   stylów w atrybutach, które blokuje CSP strony (audyt kontrolny 12.10.2026, K16). */
.strona-bledu-stala {
    max-width: 32rem;
    margin: 3rem auto;
    line-height: 1.5;
}

.strona-bledu-stala h1 {
    font-size: 1.4rem;
}

/* --- Fruwające rzeczy, tło i powitania (właściciel, 27.10.2026: „działaj” - grafika nr 15, 16, 17, 19, 29, 31, 32) ---
   Wszystko za treścią albo w wolnym polu, krótko i raz, w granacie i złocie; ruch tylko w bloku ruchu. Po zdarzeniu ozdoba
   jest na stronie jedna: scena święta (.swieto), „Witaj w TOZ” ([data-witaj]) albo pieczęć zamknięcia sprawy
   ([data-pieczec]) - złota łuna po zapisie wtedy się nie zapala, a fala pory roku czeka na następną stronę (okazje.js).
   Drobiny (okazja-*) rysuje okazje.js w warstwie .okazja-tlo z sekcji okazji. */

/* nr 19 - poświata według pory dnia (body[data-pora] z godziny wczytania, granice jak w powitaniu - App\Ozdoby::poraDnia):
   rano szampańskie złoto nisko, wieczorem miodowe złoto w dolnym rogu i granat u góry, nocą chłodniej. W jasnym wyglądzie
   zmienia się tylko odcień i położenie plam - siła ta sama co w dzień (szary napis stopki stoi wprost na tle); granat
   gęstnieje tylko w ciemnym wyglądzie (poprawki ręczne ciemny.css). W dzień - jak dotąd. */
body[data-pora="swit"] .tlo-zorza {
    background:
        radial-gradient(42% 38% at 8% 6%, rgba(96, 134, 214, .28), rgba(96, 134, 214, 0) 70%),
        radial-gradient(46% 36% at 30% 100%, rgba(227, 196, 126, .38), rgba(227, 196, 126, 0) 70%),
        radial-gradient(40% 34% at 92% 4%, rgba(58, 87, 162, .21), rgba(58, 87, 162, 0) 70%),
        radial-gradient(34% 30% at 88% 96%, rgba(227, 196, 126, .19), rgba(227, 196, 126, 0) 70%);
}
body[data-pora="zmierzch"] .tlo-zorza {
    background:
        radial-gradient(60% 34% at 50% 0%, rgba(58, 87, 162, .28), rgba(58, 87, 162, 0) 70%),
        radial-gradient(40% 36% at 96% 98%, rgba(201, 150, 74, .38), rgba(201, 150, 74, 0) 70%),
        radial-gradient(44% 40% at 6% 100%, rgba(96, 134, 214, .21), rgba(96, 134, 214, 0) 70%),
        radial-gradient(30% 28% at 70% 100%, rgba(201, 150, 74, .19), rgba(201, 150, 74, 0) 70%);
}
body[data-pora="noc"] .tlo-zorza {
    background:
        radial-gradient(46% 40% at 10% 4%, rgba(58, 87, 162, .28), rgba(58, 87, 162, 0) 70%),
        radial-gradient(40% 36% at 90% 0%, rgba(96, 134, 214, .3), rgba(96, 134, 214, 0) 70%),
        radial-gradient(48% 42% at 76% 100%, rgba(58, 87, 162, .21), rgba(58, 87, 162, 0) 70%),
        radial-gradient(28% 26% at 4% 94%, rgba(215, 181, 109, .19), rgba(215, 181, 109, 0) 70%);
}

/* nr 19 - we wzorze tła obok łapek mały motyw pory roku (body[data-pora-roku]): wiosną kwiatek, latem motyl, jesienią liść
   klonu z żołędziem, zimą płatek śniegu. Ten sam kafelek 200 px i ta sama siła co wzór (5,5%), w pustym miejscu kafelka. */
body[data-pora-roku] .tlo-zorza::before {
    content: ''; position: absolute; inset: 0;
    background: var(--toz-granat); opacity: .055;
    -webkit-mask-size: 200px 200px; mask-size: 200px 200px; -webkit-mask-repeat: repeat; mask-repeat: repeat;
}
body[data-pora-roku="wiosna"] .tlo-zorza::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 54) scale(.85)'%3E%3Ccircle cx='12' cy='6.4' r='3.6'/%3E%3Ccircle cx='17.3' cy='10.3' r='3.6'/%3E%3Ccircle cx='15.3' cy='16.5' r='3.6'/%3E%3Ccircle cx='8.7' cy='16.5' r='3.6'/%3E%3Ccircle cx='6.7' cy='10.3' r='3.6'/%3E%3C/g%3E%3Cg transform='translate(98 158) scale(.55)'%3E%3Ccircle cx='12' cy='6.4' r='3.6'/%3E%3Ccircle cx='17.3' cy='10.3' r='3.6'/%3E%3Ccircle cx='15.3' cy='16.5' r='3.6'/%3E%3Ccircle cx='8.7' cy='16.5' r='3.6'/%3E%3Ccircle cx='6.7' cy='10.3' r='3.6'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 54) scale(.85)'%3E%3Ccircle cx='12' cy='6.4' r='3.6'/%3E%3Ccircle cx='17.3' cy='10.3' r='3.6'/%3E%3Ccircle cx='15.3' cy='16.5' r='3.6'/%3E%3Ccircle cx='8.7' cy='16.5' r='3.6'/%3E%3Ccircle cx='6.7' cy='10.3' r='3.6'/%3E%3C/g%3E%3Cg transform='translate(98 158) scale(.55)'%3E%3Ccircle cx='12' cy='6.4' r='3.6'/%3E%3Ccircle cx='17.3' cy='10.3' r='3.6'/%3E%3Ccircle cx='15.3' cy='16.5' r='3.6'/%3E%3Ccircle cx='8.7' cy='16.5' r='3.6'/%3E%3Ccircle cx='6.7' cy='10.3' r='3.6'/%3E%3C/g%3E%3C/svg%3E");
}
body[data-pora-roku="lato"] .tlo-zorza::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 52) rotate(-12 12 12) scale(.9)'%3E%3Cellipse cx='7.6' cy='8.6' rx='5.2' ry='4.2' transform='rotate(-28 7.6 8.6)'/%3E%3Cellipse cx='16.4' cy='8.6' rx='5.2' ry='4.2' transform='rotate(28 16.4 8.6)'/%3E%3Cellipse cx='8.6' cy='15.6' rx='3.6' ry='2.9' transform='rotate(24 8.6 15.6)'/%3E%3Cellipse cx='15.4' cy='15.6' rx='3.6' ry='2.9' transform='rotate(-24 15.4 15.6)'/%3E%3Crect x='11.2' y='6.4' width='1.6' height='12.4' rx='.8'/%3E%3Cpath d='M11.6 6.8L9.6 3.2M12.4 6.8l2-3.6' fill='none' stroke='%23000' stroke-width='1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 52) rotate(-12 12 12) scale(.9)'%3E%3Cellipse cx='7.6' cy='8.6' rx='5.2' ry='4.2' transform='rotate(-28 7.6 8.6)'/%3E%3Cellipse cx='16.4' cy='8.6' rx='5.2' ry='4.2' transform='rotate(28 16.4 8.6)'/%3E%3Cellipse cx='8.6' cy='15.6' rx='3.6' ry='2.9' transform='rotate(24 8.6 15.6)'/%3E%3Cellipse cx='15.4' cy='15.6' rx='3.6' ry='2.9' transform='rotate(-24 15.4 15.6)'/%3E%3Crect x='11.2' y='6.4' width='1.6' height='12.4' rx='.8'/%3E%3Cpath d='M11.6 6.8L9.6 3.2M12.4 6.8l2-3.6' fill='none' stroke='%23000' stroke-width='1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
}
body[data-pora-roku="jesien"] .tlo-zorza::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(148 50) rotate(14 12 12) scale(.95)'%3E%3Cpath d='M12 1l1.6 4.2 2.8-1.4-.6 4.6 3.8-1.6-.8 3 3.8 1.2-3.2 2.4 1 2.2-5.2-.6-.8 2.2-1.8-1.4V22h-1.2v-6.2l-1.8 1.4-.8-2.2-5.2.6 1-2.2-3.2-2.4 3.8-1.2-.8-3 3.8 1.6-.6-4.6 2.8 1.4z'/%3E%3C/g%3E%3Cg transform='translate(176 74) rotate(-16 9 9) scale(.62)'%3E%3Crect x='8.3' y='.6' width='1.4' height='3.4' rx='.7'/%3E%3Cpath d='M2.6 7.4a6.4 4.2 0 0 1 12.8 0z'/%3E%3Cpath d='M4.4 8.4h9.2c0 4.4-2 7.8-4.6 9C6.4 16.2 4.4 12.8 4.4 8.4z'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(148 50) rotate(14 12 12) scale(.95)'%3E%3Cpath d='M12 1l1.6 4.2 2.8-1.4-.6 4.6 3.8-1.6-.8 3 3.8 1.2-3.2 2.4 1 2.2-5.2-.6-.8 2.2-1.8-1.4V22h-1.2v-6.2l-1.8 1.4-.8-2.2-5.2.6 1-2.2-3.2-2.4 3.8-1.2-.8-3 3.8 1.6-.6-4.6 2.8 1.4z'/%3E%3C/g%3E%3Cg transform='translate(176 74) rotate(-16 9 9) scale(.62)'%3E%3Crect x='8.3' y='.6' width='1.4' height='3.4' rx='.7'/%3E%3Cpath d='M2.6 7.4a6.4 4.2 0 0 1 12.8 0z'/%3E%3Cpath d='M4.4 8.4h9.2c0 4.4-2 7.8-4.6 9C6.4 16.2 4.4 12.8 4.4 8.4z'/%3E%3C/g%3E%3C/svg%3E");
}
body[data-pora-roku="zima"] .tlo-zorza::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 52) scale(.9)' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7M12 5.5L9.6 3.1M12 5.5l2.4-2.4M12 18.5l-2.4 2.4M12 18.5l2.4 2.4M5.6 8.3l-3.2.9M5.6 8.3L4.7 5.1M18.4 15.7l3.2-.9M18.4 15.7l.9 3.2M5.6 15.7l-3.2-.9M5.6 15.7l-.9 3.2M18.4 8.3l3.2.9M18.4 8.3l.9-3.2'/%3E%3C/g%3E%3Cg transform='translate(98 158) scale(.55)' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg transform='translate(150 52) scale(.9)' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7M12 5.5L9.6 3.1M12 5.5l2.4-2.4M12 18.5l-2.4 2.4M12 18.5l2.4 2.4M5.6 8.3l-3.2.9M5.6 8.3L4.7 5.1M18.4 15.7l3.2-.9M18.4 15.7l.9 3.2M5.6 15.7l-3.2-.9M5.6 15.7l-.9 3.2M18.4 8.3l3.2.9M18.4 8.3l.9-3.2'/%3E%3C/g%3E%3Cg transform='translate(98 158) scale(.55)' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M3.3 17L20.7 7'/%3E%3C/g%3E%3C/svg%3E");
}

/* Światło nad poświatą (layout.php: .tlo-swiatlo) - też za treścią i bez klikania. */
.tlo-swiatlo { position: fixed; inset: 0 0 auto; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none; }

/* nr 19 - gwiazdki nocą: kilkanaście drobnych złotych gwiazdek w marginesach i odstępach, tylko na pierwszej stronie po
   zalogowaniu (ta z powitaniem dnia - layout.php: .tlo-gwiazdy); raz przy wejściu mrugają, potem stoją. Jak samo
   powitanie i każda ozdoba tej sekcji - tylko w bloku ruchu; bez ruchu nocne tło zostaje bez gwiazdek (przegląd 27.10.2026). */
@media (prefers-reduced-motion: no-preference) {
    .tlo-gwiazdy::after {
        --gwiazda: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5l2.4 7.1 7.1 2.4-7.1 2.4L12 20.5l-2.4-7.1-7.1-2.4 7.1-2.4z' fill='%23d7b56d'/%3E%3C/svg%3E");
        content: ''; position: absolute; inset: 0; opacity: .85;
        background: var(--gwiazda) 1.2% 14% / 9px 9px no-repeat, var(--gwiazda) 98.6% 9% / 7px 7px no-repeat,
            var(--gwiazda) 1.6% 31% / 6px 6px no-repeat, var(--gwiazda) 98.9% 23% / 10px 10px no-repeat,
            var(--gwiazda) 1% 47% / 8px 8px no-repeat, var(--gwiazda) 98.4% 39% / 6px 6px no-repeat,
            var(--gwiazda) 1.8% 63% / 10px 10px no-repeat, var(--gwiazda) 98.8% 55% / 8px 8px no-repeat,
            var(--gwiazda) 1.1% 78% / 6px 6px no-repeat, var(--gwiazda) 98.5% 70% / 9px 9px no-repeat,
            var(--gwiazda) 1.5% 92% / 8px 8px no-repeat, var(--gwiazda) 98.7% 86% / 6px 6px no-repeat,
            var(--gwiazda) 34% 97% / 7px 7px no-repeat, var(--gwiazda) 66% 98% / 8px 8px no-repeat;
    }
}

/* nr 16 - udany zapis albo dodanie (body[data-zapis] z layout.php; po usunięciu i przy błędzie znaku nie ma): poświata
   za kartami raz jaśnieje ciepłym złotem - fala światła od góry w marginesy i odstępy, po ok. 1,5 s wraca do zwykłych
   barw. Karty zostają białe. Bez ruchu w systemie nic (łunę zapala tylko ruch). */
body[data-zapis] .tlo-swiatlo::before {
    content: ''; position: absolute; inset: 0; opacity: 0; transform-origin: 50% 0;
    background: radial-gradient(70% 58% at 50% 0%, rgba(227, 196, 126, .5), rgba(215, 181, 109, .2) 48%, rgba(215, 181, 109, 0) 78%);
}
/* ...i 6 złotych iskierek z ptaszka komunikatu - w jego lewym polu (46 px przy znaku), bez wchodzenia na tekst
   i poza ramkę. Same cienie jednej kropki w środku znaku. */
body[data-zapis] .main > .alert-success { position: relative; }
body[data-zapis] .main:has(.rozmowa-mail) > .alert-success { position: sticky; }
body[data-zapis] .main > .alert-success::after {
    content: ''; position: absolute; left: 24px; top: 22px; width: 4px; height: 4px; margin: -2px 0 0 -2px;
    border-radius: 50%; opacity: 0; pointer-events: none;
}
/* Większa ozdoba po zapisie (scena święta, „Witaj w TOZ”, pieczęć) zostaje sama - łuna i iskierki chowają się, zamiast
   czekać (scena znika po kilku sekundach, a łuna nie ma ruszyć po niej). */
body:has(.swieto, [data-witaj], [data-pieczec]) .tlo-swiatlo::before,
body:has(.swieto, [data-witaj], [data-pieczec]) .main > .alert-success::after { visibility: hidden; }

/* nr 17 - „Witaj w TOZ, Burek!” / „Witamy w TOZ!” (layout.php, [data-witaj]): biała pigułka z małym złotym sercem w miejscu
   powitania dnia, bez klikania, na ok. 3 s - zapala ją tylko ruch. Ślad łapek albo serduszka w marginesie - okazje.js. */
.witaj-w-toz {
    position: fixed; top: 66px; right: 16px; z-index: 15; pointer-events: none; opacity: 0;
    max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis;
    padding: 8px 16px 8px 40px; border-radius: 999px; background: #fff; color: var(--toz-granat-ciemny);
    font-weight: 600; box-shadow: 0 6px 18px rgba(44, 67, 129, .14), 0 0 0 2px rgba(215, 181, 109, .35); white-space: nowrap;
}
.witaj-w-toz::before {
    content: ''; position: absolute; left: 13px; top: 50%; width: 18px; height: 18px; margin-top: -9px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23d7b56d'%3E%3Cpath d='M12 21s-7.5-4.6-9.6-9.2C.9 8.4 3 4.5 6.8 4.5c2.1 0 3.6 1.1 5.2 3 1.6-1.9 3.1-3 5.2-3 3.8 0 5.9 3.9 4.4 7.3C19.5 16.4 12 21 12 21z'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (max-width: 760px) { .witaj-w-toz { top: 60px; right: 10px; max-width: calc(100vw - 20px); padding: 6px 12px 6px 34px; font-size: .92rem; } }

/* nr 15 i 29 - nowe drobiny okazje.js: płatki kwiatów (wiosna), motyle (lato), ptaki w kluczu (przeloty), świetliki
   (wieczór w ciemnym wyglądzie - ręczna część ciemny.css ustawia .okazja-tlo { --swietliki: 1 }; w jasnym nic). */
.swieto-platek        { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5c3.9 3.1 5.6 7.6 4.1 12-1.2 3.6-4.1 6.9-4.1 6.9s-2.9-3.3-4.1-6.9C6.4 10.1 8.1 5.6 12 2.5z' fill='%23e3c47e'/%3E%3Cpath d='M12 6.5v11' stroke='%23fff' stroke-opacity='.6' stroke-width='.9' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-platek-granat { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5c3.9 3.1 5.6 7.6 4.1 12-1.2 3.6-4.1 6.9-4.1 6.9s-2.9-3.3-4.1-6.9C6.4 10.1 8.1 5.6 12 2.5z' fill='%239fb0dc'/%3E%3Cpath d='M12 6.5v11' stroke='%23fff' stroke-opacity='.6' stroke-width='.9' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-motyl         { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%23d7b56d'%3E%3Cellipse cx='7.6' cy='8.6' rx='5.2' ry='4.2' transform='rotate(-28 7.6 8.6)'/%3E%3Cellipse cx='16.4' cy='8.6' rx='5.2' ry='4.2' transform='rotate(28 16.4 8.6)'/%3E%3C/g%3E%3Cg fill='%23e3c47e'%3E%3Cellipse cx='8.6' cy='15.6' rx='3.6' ry='2.9' transform='rotate(24 8.6 15.6)'/%3E%3Cellipse cx='15.4' cy='15.6' rx='3.6' ry='2.9' transform='rotate(-24 15.4 15.6)'/%3E%3C/g%3E%3Crect x='11.2' y='6.4' width='1.6' height='12.4' rx='.8' fill='%233a57a2'/%3E%3Cpath d='M11.6 6.8L9.6 3.2M12.4 6.8l2-3.6' fill='none' stroke='%233a57a2' stroke-width='1' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-motyl-granat  { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='%237d8fd0'%3E%3Cellipse cx='7.6' cy='8.6' rx='5.2' ry='4.2' transform='rotate(-28 7.6 8.6)'/%3E%3Cellipse cx='16.4' cy='8.6' rx='5.2' ry='4.2' transform='rotate(28 16.4 8.6)'/%3E%3C/g%3E%3Cg fill='%239fb0dc'%3E%3Cellipse cx='8.6' cy='15.6' rx='3.6' ry='2.9' transform='rotate(24 8.6 15.6)'/%3E%3Cellipse cx='15.4' cy='15.6' rx='3.6' ry='2.9' transform='rotate(-24 15.4 15.6)'/%3E%3C/g%3E%3Crect x='11.2' y='6.4' width='1.6' height='12.4' rx='.8' fill='%232c4381'/%3E%3Cpath d='M11.6 6.8L9.6 3.2M12.4 6.8l2-3.6' fill='none' stroke='%232c4381' stroke-width='1' stroke-linecap='round'/%3E%3C/svg%3E"); }
.swieto-ptak          { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.5 10.5c3.4-3.2 7-3.3 10.5 1 3.5-4.3 7.1-4.2 10.5-1-3.6-.5-7 .9-10.5 4.4-3.5-3.5-6.9-4.9-10.5-4.4z' fill='%233a57a2'/%3E%3C/svg%3E"); }
.swieto-swietlik      { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cdefs%3E%3CradialGradient id='s'%3E%3Cstop offset='0' stop-color='%23fff6d8'/%3E%3Cstop offset='.3' stop-color='%23e3c47e'/%3E%3Cstop offset='.6' stop-color='%23d7b56d' stop-opacity='.4'/%3E%3Cstop offset='1' stop-color='%23d7b56d' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Ccircle cx='12' cy='12' r='12' fill='url(%23s)'/%3E%3C/svg%3E"); }
/* Klucz ptaków przelatuje w poprzek wolnego pasa (okazje.js: --x, --y, --dx); ptaki stoją w nim w kształcie litery V. */
.okazja-klucz { position: absolute; left: var(--x); top: var(--y); width: 0; height: 0; opacity: 0; }
.okazja-ptak {
    position: absolute; left: var(--px); top: var(--py); width: 16px; height: 16px; margin: -8px 0 0 -8px;
    background-position: center; background-size: contain; background-repeat: no-repeat;
}

/* nr 31 - kot zza stopki (okazje.js: .kot-zaglada na początku stopki, raz dziennie na końcu długiej listy): okno nad
   kreską stopki po lewej, w pustym polu pod ostatnią kartą; granatowy łebek ze złotymi oczami wychyla się zza kreski.
   Tylko na komputerze i tylko z ruchem; w ciemnym wyglądzie jaśniejszy granat (poprawki ręczne ciemny.css). */
.kot-zaglada { display: none; }
.kot-zaglada-okno { position: absolute; left: 0; bottom: 15px; width: 56px; height: 40px; overflow: hidden; }
.kot-zaglada-glowa {
    position: absolute; left: 10px; bottom: 0; width: 36px; height: 34px; transform: translateY(100%); transform-origin: 50% 100%;
    background-color: var(--toz-granat);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 34'%3E%3Cpath d='M5 34V15.5C5 11.2 6 8.2 7.6 6.2L5.6 1l7.3 3.7a13.6 13.6 0 0 1 10.2 0L30.4 1l-2 5.2C30 8.2 31 11.2 31 15.5V34z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 34'%3E%3Cpath d='M5 34V15.5C5 11.2 6 8.2 7.6 6.2L5.6 1l7.3 3.7a13.6 13.6 0 0 1 10.2 0L30.4 1l-2 5.2C30 8.2 31 11.2 31 15.5V34z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.kot-zaglada-oczy {
    position: absolute; left: 8px; top: 15px; width: 20px; height: 6px;
    background: radial-gradient(circle at 3px 3px, var(--toz-zloto) 0 2.3px, rgba(215, 181, 109, 0) 2.8px),
        radial-gradient(circle at 17px 3px, var(--toz-zloto) 0 2.3px, rgba(215, 181, 109, 0) 2.8px);
}

/* Rezerwa nr 32 - świt za kartą logowania: raz przy wejściu za kartą wschodzi miękka złota łuna (ok. 1,5 s) i zostaje
   delikatna aureola, a po obwódce karty raz przebiega światło (kąt w @property, jak kółko przed wylogowaniem). Nocą łuna
   chłodniejsza. Bez łapy i znaku organizacji (ekran logowania nie mówi, czyj to system). Po nieudanej próbie (komunikat
   błędu) świt się nie powtarza. Przeglądarka bez @property pokazuje samą łunę. */
@property --swit-kat { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@media (prefers-reduced-motion: no-preference) {
    .karta-logowania { position: relative; }
    .main:not(:has(> .alert-danger)) > .karta-logowania::before {
        content: ''; position: absolute; left: 50%; top: 50%; z-index: -1; width: 150%; height: 140%; pointer-events: none;
        background: radial-gradient(closest-side, rgba(227, 196, 126, .5), rgba(215, 181, 109, .2) 58%, rgba(215, 181, 109, 0));
        animation: toz-swit 1.6s ease-out .4s both;
    }
    body[data-pora="noc"] .main:not(:has(> .alert-danger)) > .karta-logowania::before {
        background: radial-gradient(closest-side, rgba(147, 169, 230, .45), rgba(96, 134, 214, .18) 58%, rgba(96, 134, 214, 0));
    }
    @keyframes toz-swit {
        from { opacity: 0; transform: translate(-50%, -18%) scale(.55); }
        55%  { opacity: 1; }
        to   { opacity: .4; transform: translate(-50%, -50%) scale(1); }
    }
}
@media (prefers-reduced-motion: no-preference) and (max-width: 640px) {
    .main:not(:has(> .alert-danger)) > .karta-logowania::before { width: 110%; }
}
@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
    @media (prefers-reduced-motion: no-preference) {
        .main:not(:has(> .alert-danger)) > .karta-logowania::after {
            content: ''; position: absolute; inset: -1px; padding: 2px; border-radius: inherit; pointer-events: none; opacity: 0;
            background: conic-gradient(from var(--swit-kat), rgba(215, 181, 109, 0) 0deg, rgba(215, 181, 109, 0) 270deg,
                var(--toz-zloto) 330deg, rgba(255, 255, 255, .85) 346deg, rgba(215, 181, 109, 0) 360deg);
            -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
            mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
            animation: toz-swit-obwodka 1.8s ease-in-out .7s both;
        }
        @keyframes toz-swit-obwodka {
            from { opacity: 0; --swit-kat: 0deg; }
            12%, 82% { opacity: 1; }
            to   { opacity: 0; --swit-kat: 360deg; }
        }
    }
}

/* Ruch: łuna i iskierki po zapisie (nr 16), pigułka „Witaj” (nr 17), nowe drobiny (nr 15, 29), gwiazdki (nr 19), kot (nr 31). */
@media (prefers-reduced-motion: no-preference) {
    body[data-zapis] .tlo-swiatlo::before { animation: toz-luna 1.5s ease-out .45s; }
    body[data-zapis] .main > .alert-success::after { animation: toz-iskierki .55s ease-out .55s; }
    .witaj-w-toz { animation: toz-powitanie 3.8s ease-in-out 1.4s forwards; }
    .tlo-gwiazdy::after { animation: toz-gwiazdy 2.4s ease-in-out .5s backwards; }
    .okazja-motyl    { animation: toz-okazja-motyl var(--czas) ease-in-out; }
    .okazja-swietlik { animation: toz-okazja-swietlik var(--czas) ease-in-out; }
    .okazja-klucz    { animation: toz-okazja-klucz var(--czas) linear; }
    .okazja-ptak     { animation: toz-okazja-skrzydla .32s ease-in-out var(--opoznienie) 22 alternate; }
    .kot-zaglada { display: block; position: relative; height: 0; pointer-events: none; }
    .kot-zaglada-glowa { animation: toz-kot-glowa 2.6s ease-in-out both; }
    .kot-zaglada-oczy  { animation: toz-kot-oczy 2.6s linear both; }
    @keyframes toz-luna {
        from { opacity: 0; transform: scaleY(.35); }
        35%  { opacity: 1; }
        to   { opacity: 0; transform: scaleY(1.15); }
    }
    @keyframes toz-iskierki {
        from {
            opacity: 1;
            box-shadow: 0 0 0 0 #e3c47e, 0 0 0 0 #e3c47e, 0 0 0 0 #e3c47e, 0 0 0 0 #e3c47e, 0 0 0 0 #e3c47e, 0 0 0 0 #e3c47e;
        }
        to {
            opacity: 0;
            box-shadow: 12px 0 0 -1px #d7b56d, 6px -10px 0 -1px #d7b56d, -6px -10px 0 -1px #d7b56d,
                -12px 0 0 -1px #d7b56d, -6px 10px 0 -1px #d7b56d, 6px 10px 0 -1px #d7b56d;
        }
    }
    @keyframes toz-gwiazdy { from { opacity: 0; } 25% { opacity: .9; } 45% { opacity: .3; } 70% { opacity: 1; } }
    /* Motyl leci w górę zygzakiem (wychylenie 8 px - okazje.js zostawia na nie miejsce) i macha skrzydłami. */
    @keyframes toz-okazja-motyl {
        from { opacity: 0; transform: translate3d(0, 0, 0) scaleX(1); }
        12%  { opacity: .9; transform: translate3d(calc(var(--dx) * .12 + 6px), calc(var(--dy) * .12), 0) scaleX(.5); }
        25%  { transform: translate3d(calc(var(--dx) * .25 + 8px), calc(var(--dy) * .25), 0) scaleX(1); }
        37%  { transform: translate3d(calc(var(--dx) * .37), calc(var(--dy) * .37), 0) scaleX(.5); }
        50%  { transform: translate3d(calc(var(--dx) * .5 - 8px), calc(var(--dy) * .5), 0) scaleX(1); }
        62%  { transform: translate3d(calc(var(--dx) * .62), calc(var(--dy) * .62), 0) scaleX(.5); }
        75%  { transform: translate3d(calc(var(--dx) * .75 + 8px), calc(var(--dy) * .75), 0) scaleX(1); }
        85%  { opacity: .9; }
        to   { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) scaleX(.5); }
    }
    /* Świetlik unosi się łukiem i mruga nieregularnie 2-3 razy (czas każdego inny - okazje.js). */
    @keyframes toz-okazja-swietlik {
        from { opacity: 0; transform: translate3d(0, 0, 0) scale(.6); }
        14%  { opacity: .95; transform: translate3d(calc(var(--dx) * .1 + 4px), calc(var(--dy) * .14), 0) scale(1); }
        30%  { opacity: .3; }
        44%  { opacity: .95; transform: translate3d(calc(var(--dx) * .45 + 9px), calc(var(--dy) * .48), 0) scale(1); }
        58%  { opacity: .4; }
        72%  { opacity: .9; transform: translate3d(calc(var(--dx) * .8 + 5px), calc(var(--dy) * .8), 0) scale(.9); }
        to   { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) scale(.6); }
    }
    @keyframes toz-okazja-klucz {
        from { opacity: 0; transform: translate3d(0, 0, 0); }
        8%, 92% { opacity: .85; }
        to   { opacity: 0; transform: translate3d(var(--dx), -18px, 0); }
    }
    @keyframes toz-okazja-skrzydla { from { transform: scaleY(1); } to { transform: scaleY(.45); } }
    @keyframes toz-kot-glowa {
        from     { transform: translateY(100%) rotate(0deg); }
        16%, 58% { transform: translateY(0) rotate(0deg); }
        68%, 78% { transform: translateY(0) rotate(-12deg); }
        86%      { transform: translateY(0) rotate(0deg); }
        to       { transform: translateY(100%) rotate(0deg); }
    }
    @keyframes toz-kot-oczy { from, 27%, 33%, 41%, 47%, to { transform: scaleY(1); } 30%, 44% { transform: scaleY(.1); } }
}
@media print { .tlo-swiatlo, .witaj-w-toz, .kot-zaglada { display: none; } }

/* --- Telefon: mniej naraz na ekranie (właściciel, 15.10.2026: "za dużo danych jest na ekranie") -------------
   na-telefonie.js oznacza komórki i przełącza klasy; tu stoi, co znika do 640 px. Bez skryptu nic nie znika.
   .poza-telefonem - drugorzędny napis (część podsumowania, objaśnienie przy przycisku), na telefonie ukryty. */
.przycisk-filtrow,
.przelacznik-kolumn { display: none; }
/* Skrót do zdjęć pod tytułem zapisanej karty interwencji i zwierzaka (właściciel, 27.10.2026): na telefonie kafelki
   z plikami stoją kilka ekranów niżej, pod całym formularzem. Na komputerze go nie ma - tam jest spis części strony
   albo wszystko widać od razu. Cel skoku to .card[id] z zapasem na przyklejoną belkę (scroll-margin-top). */
.skrot-do-plikow { display: none; }
@media print { .skrot-do-plikow { display: none !important; } }

/* Kolumny list do wyboru na komputerze (uklad-list.js; właściciel, 16.10.2026). Kolumny dodatkowe (kol-dodatkowa) są w
   szablonie, ale widać je dopiero po "Dodaj" - także bez skryptu i na telefonie lista wygląda jak dotąd. */
.table .kol-dodatkowa:not(.kol-dodana), .table .kol-wybor-ukryta { display: none; }
.wybor-kolumn { position: relative; display: inline-block; margin: 0 0 10px; }
.wybor-kolumn > summary { list-style: none; cursor: pointer; }
.wybor-kolumn > summary::-webkit-details-marker { display: none; }
.wybor-kolumn > summary::after { content: ""; display: inline-block; margin-left: 8px; border: 4px solid transparent; border-top-color: currentColor; transform: translateY(2px); }
.wybor-kolumn[open] > summary::after { transform: translateY(-2px) rotate(180deg); }
.wybor-kolumn-panel {
    position: absolute; top: calc(100% + 4px); left: 0; z-index: 26;
    width: max-content; min-width: 18rem; max-width: min(28rem, calc(100vw - 32px));
    max-height: min(70vh, 34rem); overflow-y: auto;
    padding: 10px 12px; background: #fff; border: 1px solid var(--toz-border); border-radius: 10px;
    box-shadow: 0 12px 28px rgba(16, 20, 33, .18);
}
.wybor-kolumn-tytul { margin: 4px 0 6px; font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--toz-granat-ciemny); }
.wybor-kolumn-lista { list-style: none; margin: 0 0 8px; padding: 0; }
.wybor-kolumn-lista li {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 3px 6px; border-radius: 6px; font-size: .9rem;
}
.wybor-kolumn-lista li:hover { background: var(--toz-granat-jasny); }
.wybor-kolumn-lista li.schowana > label { color: var(--toz-muted); }
.wybor-kolumn-lista label { display: flex; align-items: center; gap: 6px; margin: 0; font-weight: 400; cursor: pointer; text-transform: none; letter-spacing: normal; }
.wybor-kolumn-akcje { display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.wybor-kolumn-akcje .btn-link { min-width: 26px; min-height: 26px; padding: 0 4px; font-size: 1rem; }
.wybor-kolumn-akcje .btn-link:disabled { opacity: .3; cursor: default; }
.wybor-kolumn-lista .btn-link { text-decoration: none; }
.wybor-kolumn-stopka { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-top: 8px; border-top: 1px solid var(--toz-border); }
.ustawienie-kolumn { margin-top: 10px; }
.ustawienie-kolumn .wybor-kolumn { margin: 0; }
/* Przeciąganie myszą w spisie kolumn: uchwyt z lewej, przenoszony wiersz przygaszony z kreską. */
.wybor-kolumn-lista li[draggable="true"] { cursor: grab; }
.wybor-kolumn-lista li.przenoszona { opacity: .55; background: var(--toz-granat-jasny); box-shadow: inset 3px 0 0 var(--toz-granat); }
.wybor-kolumn-uchwyt { flex: 0 0 auto; color: var(--toz-muted); letter-spacing: -2px; font-size: .9rem; user-select: none; }
.wybor-kolumn-lista li > label { flex: 1 1 auto; }
/* Od 20.10.2026 wybór kolumn także na tablecie i telefonie - osobny układ dla każdego rodzaju ekranu (własne widoki
   list). Karta z własnym układem ekranu nie ma przełącznika "pokaż wszystkie kolumny" (tabela ułożona po swojemu). */
[data-kolumny-wlasne] .przelacznik-kolumn { display: none !important; }
.table .kol-stala-ukryta { display: none; }
.table td.kol-stala-ukryta:has([data-otworz-wiersz]) {
    display: block; position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Ukryty odnośnik "Otwórz/Edytuj" pod kursorem klawiatury wychodzi na wierzch z obwódką - inaczej kursor ginął
   w każdym wierszu, także na laptopie z powiększeniem (audyt 23.10.2026, T03, WCAG 2.4.7). Tak samo niżej
   na telefonie i tablecie. */
.table td.kol-stala-ukryta:has([data-otworz-wiersz]:focus-visible) {
    width: auto; height: auto; margin: 0; padding: 4px; overflow: visible; clip: auto; z-index: 5; background: var(--toz-plyta);
}
[data-kolumny-wlasne] tbody tr:has([data-otworz-wiersz]) { cursor: pointer; }
@media (max-width: 640px) {
    .wybor-kolumn-panel { position: fixed; left: 16px; right: 16px; top: auto; bottom: 16px; width: auto; min-width: 0; max-width: none; max-height: 70vh; }
}
@media print { .wybor-kolumn { display: none; } }

/* Wykresy pod listami (App\Wykresy; właściciel, 16.10.2026) - SVG z serwera w barwach marki: granat to pierwsza seria,
   złoto druga. Pasek stanu ma kolor stanu w atrybucie fill - klasa serii go nie przykrywa. */
/* Najwyżej 3 wykresy w rzędzie (właściciel, 09.11.2026: "Upchane 4 wykresy obok siebie na monitorze 27" to za dużo. Nie da się na nich
   nic wyczytać", "3 wykresy na takim monitorze to wielkość optymalna"): kolumna ma co najmniej trzecią część szerokości (twardy limit
   trzech) i co najmniej 590 px - przy oknie 2560 px trzy (ok. 780 px), przy 1920 i 1366 px dwa (ok. 875 i 600 px; trzy przy 1920 byłyby
   po ok. 575 px - za ciasno), węższe - jeden. auto-fill: jeden albo dwa wykresy nie rozciągają się na całą kartę, tylko stoją
   w swoich kolumnach; wykres wypełnia kolumnę (bez dawnego max-width 760 px), proporcje trzyma viewBox. Napisy rysunku - PISMO
   w App\Wykresy (atrybut font-size na <svg>), arkusz daje im tylko barwę i grubość. Wykres poza siatką (karta zbiórki: „Jak
   rosła ta zbiórka”) zostaje przy dawnych 760 px - na całej szerokości karty rysunek byłby na pół ekranu (przegląd 09.11.2026). */
.wykresy-siatka { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, max(590px, (100% - 2 * 28px) / 3)), 1fr)); gap: 26px 28px; }
.wykres { margin: 0; min-width: 0; max-width: 760px; }
.wykresy-siatka .wykres, .okno-wykresu .wykres { max-width: none; }
.wykres figcaption { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-bottom: 8px; }
.wykres-tytul { font-weight: 600; font-size: 1.02rem; color: var(--toz-granat-ciemny); }
.wykres-opis { font-size: .875rem; }
.wykres-svg { display: block; width: 100%; height: auto; overflow: visible; }
.wykres-podzialka { stroke: var(--toz-border); stroke-width: 1; }
.wykres-os { fill: var(--toz-muted); }
.wykres-os-nazwa { fill: currentColor; }
.wykres-liczba { font-weight: 600; fill: var(--toz-granat-ciemny); }
.wykres-tor { fill: var(--toz-granat-jasny); }
.wykres-slupek:hover { opacity: .78; }
.wykres-seria-1:not([fill]) { fill: var(--toz-granat); }
.wykres-seria-2:not([fill]) { fill: var(--toz-zloto); }
.wykres-legenda { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 6px; font-size: .9rem; color: var(--toz-muted); }
.wykres-legenda-pozycja { display: inline-flex; align-items: center; gap: 7px; }
.wykres-znak { display: inline-block; flex: none; width: 14px; height: 14px; border-radius: 3px; }
.wykres-znak.wykres-seria-1 { background: var(--toz-granat); }
.wykres-znak.wykres-seria-2 { background: var(--toz-zloto); }
/* Więcej serii (27.10.2026: pisma według kategorii, kilka kas) - wciąż tylko odcienie granatu i złota (jednolite barwy),
   ostatnia ("pozostałe") przygaszona. */
.wykres-seria-3:not([fill]) { fill: #8fa3d6; }
.wykres-seria-4:not([fill]) { fill: #a8842f; }
.wykres-seria-5:not([fill]) { fill: #1d2d5c; }
.wykres-seria-6:not([fill]) { fill: #e6d3a3; }
.wykres-seria-7:not([fill]) { fill: var(--toz-przygaszone); }
.wykres-znak.wykres-seria-3 { background: #8fa3d6; }
.wykres-znak.wykres-seria-4 { background: #a8842f; }
.wykres-znak.wykres-seria-5 { background: #1d2d5c; }
.wykres-znak.wykres-seria-6 { background: #e6d3a3; }
.wykres-znak.wykres-seria-7 { background: var(--toz-przygaszone); }
/* Siatka natężenia (właściciel, 08.11.2026 - pod listą maili: kiedy przychodzą maile): komórka w granacie marki, moc z atrybutu
   fill-opacity (Wykresy::siatka), pusta - sam tor; liczba w ciemnej komórce jasna. */
.wykres-komorka { fill: var(--toz-granat); }
.wykres-komorka-pusta { fill: transparent; }
.wykres-komorka-liczba { font-weight: 600; fill: var(--toz-text); pointer-events: none; }
.wykres-komorka-liczba-jasna { fill: #fff; }
.wykres-znak.wykres-znak-siatka { width: 28px; background: linear-gradient(90deg, var(--toz-granat-jasny), var(--toz-granat)); }
/* Linie (stan kasy, stan środków 1,5%): kreska w barwie serii, punkty z dymkiem; znak w legendzie jako kreska. */
.wykres-linia { fill: none; stroke-width: 3; stroke-linejoin: round; stroke-linecap: round; }
.wykres-linia-1 { stroke: var(--toz-granat); }
.wykres-linia-2 { stroke: var(--toz-zloto); }
.wykres-linia-3 { stroke: #8fa3d6; }
.wykres-linia-4 { stroke: #a8842f; }
.wykres-linia-5 { stroke: #1d2d5c; }
.wykres-linia-6 { stroke: #e6d3a3; }
.wykres-punkt { stroke: var(--toz-plyta); stroke-width: 1.5; }
.wykres-znak.wykres-znak-linia { width: 16px; height: 4px; border-radius: 2px; }
/* Wykresy w świetle (właściciel 27.10.2026, „działaj” - wykresy nr 4): słupki prostych wykresów w spadku barwy - granat
   od ciemnego u dołu do jaśniejszego u góry, złoto od miodowego do jasnego (wzory z Wykresy::wzory, bez nich płaska
   barwa serii); przystanki biorą barwę z "color", więc ciemny wygląd przemaluje je generatorem. Na szczycie słupka
   cienka jasna kreska połysku, pod jedyną linią poświata, która blednie ku osi zera. Części słupków składanych (do
   siedmiu bliskich odcieni) i paski stanów (kolor = stan) zostają płaskie. */
.wykres-wzory { position: absolute; width: 0; height: 0; overflow: hidden; }
.wykres-wzory stop { stop-color: currentColor; }
.wykres-spadek-granat-dol { color: var(--toz-granat-ciemny); }
.wykres-spadek-granat-gora { color: #6f86c9; }
.wykres-spadek-zloto-dol { color: #a8842f; }
.wykres-spadek-zloto-gora { color: #e6d3a3; }
.wykres-slupki .wykres-seria-1:not([fill]) { fill: url(#wykres-spadek-granat) var(--toz-granat); }
.wykres-slupki .wykres-seria-2:not([fill]) { fill: url(#wykres-spadek-zloto) var(--toz-zloto); }
.wykres-ozdoba { pointer-events: none; }
.wykres-polysk { fill: rgba(255, 255, 255, .55); }
.wykres-poswiata-1 { color: var(--toz-granat); }
.wykres-poswiata-2 { color: var(--toz-zloto); }
.wykres-poswiata-3 { color: #8fa3d6; }
.wykres-poswiata-4 { color: #a8842f; }
.wykres-poswiata-5 { color: #1d2d5c; }
.wykres-poswiata-6 { color: #e6d3a3; }
.wykres-poswiata-mocna { stop-color: currentColor; stop-opacity: .3; }
.wykres-poswiata-slaba { stop-color: currentColor; stop-opacity: 0; }
/* Okres, który jeszcze trwa (wykresy nr 5): na słupku ukośne złote paseczki (wzór z Wykresy::wzory; składany - na całym),
   w legendzie ten sam znak; na linii pusta kropka, a złoty pierścień wokół niej widać tylko w ruchu - raz, gdy pióro
   dojdzie do punktu. Wąski złoty błysk przez paseczki (kreska wykres-smuga) też tylko w ruchu - poza nim przezroczysty
   (stroke-opacity, bo przygaszenie ozdób przy chmurce ustawia opacity). */
.wykres-paseczki { fill: url(#wykres-paseczki) none; }
.wykres-smuga { fill: none; stroke: var(--toz-zloto); stroke-opacity: 0; }
.wykres-paseczki-jasne { fill: rgba(255, 255, 255, .5); }
.wykres-paseczki-zlote { fill: var(--toz-zloto); }
.wykres-znak.wykres-znak-paseczki { background: repeating-linear-gradient(135deg, var(--toz-zloto) 0 2px, var(--toz-granat-jasny) 2px 4px); }
.wykres-znak.wykres-znak-trwa { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--toz-muted); background: var(--toz-plyta); }
.wykres-punkt-srodek { fill: var(--toz-plyta); }
.wykres-pierscien { fill: none; stroke: var(--toz-zloto); stroke-width: 2; opacity: 0; }
/* Złota gwiazdka nad najlepszym wynikiem serii, w której więcej znaczy lepiej (wykresy nr 3) - w wolnym pasie nad
   słupkiem, nic nie zasłania. */
.wykres-gwiazdka { fill: var(--toz-zloto); stroke: #a8842f; stroke-width: .6; stroke-linejoin: round; }
/* Ruch rysunku (wykresy nr 1, 2): słupek rośnie od osi razem z ozdobami (grupa wykres-stos - składany w całości), pasek
   stanu od lewej, kropki, pierścień i gwiazdka ze swojego środka. */
.wykres-stos, .wykres-paski .wykres-slupek, .wykres-punkt, .wykres-punkt-srodek, .wykres-pierscien, .wykres-gwiazdka { transform-box: fill-box; }
.wykres-stos { transform-origin: 50% 100%; }
.wykres-paski .wykres-slupek { transform-origin: 0 50%; }
.wykres-punkt, .wykres-punkt-srodek, .wykres-pierscien, .wykres-gwiazdka { transform-origin: center; }
/* Wykres czeka, aż wjedzie na ekran (ruchome.js daje wykres-czeka tylko przy ruchu, obserwatorze widoczności i nowym
   wejściu na stronę): słupki przy osi, linie, kropki i gwiazdka schowane. Tylko na ekranie - wydruk zawsze gotowy. */
@media screen and (prefers-reduced-motion: no-preference) {
    .wykres-czeka .wykres-stos { transform: scaleY(0); }
    .wykres-paski .wykres-czeka .wykres-slupek { transform: scaleX(0); }
    .wykres-czeka .wykres-linia, .wykres-czeka .wykres-punkt, .wykres-czeka .wykres-punkt-srodek, .wykres-czeka .wykres-poswiata,
    .wykres-czeka .wykres-gwiazdka { opacity: 0; }
}
/* ...i ożywa raz, gdy wjedzie (wykres-rosnie): słupki falą od lewej (opóźnienia z ruchome.js, razem do 0,45 s), linia
   rysuje się jak piórem (0,8 s, kilka linii po kolei), kropki zapalają się, gdy pióro do nich dojdzie, pierścień raz
   gaśnie, a gwiazdka zapala się, gdy słupki wyrosną - z błyskiem tylko przy nowym rekordzie. Wtedy też przez paseczki
   okresu, który jeszcze trwa, raz przebiega od dołu wąski złoty błysk (krótki odcinek kreski o długości pióra 1). */
@media (prefers-reduced-motion: no-preference) {
    .wykres-slupek { transition: opacity .15s ease; }
    .wykres-rosnie .wykres-stos { animation: toz-wykres-rosnie .3s ease-out backwards; }
    .wykres-paski .wykres-rosnie .wykres-slupek { animation: toz-wykres-w-bok .3s ease-out backwards; }
    .wykres-rosnie .wykres-linia { animation: toz-wykres-pioro .8s linear backwards; }
    .wykres-rosnie .wykres-punkt, .wykres-rosnie .wykres-punkt-srodek { animation: toz-wykres-punkt .25s ease-out backwards; }
    .wykres-rosnie .wykres-poswiata { animation: toz-zjaw .8s ease-out backwards; }
    .wykres-rosnie .wykres-pierscien { animation: toz-wykres-pierscien 1.6s ease-out; }
    .wykres-rosnie .wykres-gwiazdka { animation: toz-zjaw .25s ease-out .45s backwards; }
    .wykres-rosnie .wykres-gwiazdka-blysk { animation: toz-wykres-blysk .7s ease-out .45s backwards; }
    .wykres-rosnie .wykres-smuga { animation: toz-wykres-smuga .6s ease-in-out .45s; }
    @keyframes toz-wykres-rosnie { from { transform: scaleY(0); } }
    @keyframes toz-wykres-w-bok { from { transform: scaleX(0); } }
    @keyframes toz-wykres-pioro { from { stroke-dasharray: 1 2; stroke-dashoffset: 1.01; } to { stroke-dasharray: 1 2; stroke-dashoffset: 0; } }
    @keyframes toz-wykres-punkt { from { opacity: 0; transform: scale(0); } }
    @keyframes toz-wykres-pierscien { from { opacity: .9; transform: scale(1); } to { opacity: 0; transform: scale(2.6); } }
    @keyframes toz-wykres-blysk { 0% { opacity: 0; transform: scale(.2) rotate(-90deg); } 55% { opacity: 1; transform: scale(1.8) rotate(0deg); } }
    @keyframes toz-wykres-smuga { from { stroke-opacity: .9; stroke-dasharray: .15 2; stroke-dashoffset: .15; } to { stroke-opacity: .9; stroke-dasharray: .15 2; stroke-dashoffset: -1; } }
}
/* Wydruk płaski, jak dawniej: bez spadków, połysku i poświaty; paseczki i gwiazdka zostają - to informacja. */
@media print {
    .wykresy { break-inside: avoid; }
    .wykres-slupki .wykres-seria-1:not([fill]) { fill: var(--toz-granat); }
    .wykres-slupki .wykres-seria-2:not([fill]) { fill: var(--toz-zloto); }
    .wykres-polysk, .wykres-poswiata { display: none; }
}

/* Powrót do wiersza (ulatwienia.js; 16.10.2026): wiersz, z którego weszło się we wpis, ma złotą kreskę z lewej
   i krótki błysk - tylko komórki, bez ruchu wiersza (wiersze listy mają własne wejście). */
.table tbody tr.wiersz-ostatni > td:first-child { box-shadow: inset 4px 0 0 var(--toz-zloto); }
/* To samo przy wierszu, do którego lista wraca kotwicą po czynności w wierszu ("Odepnij" na liście postów, 25.10.2026) -
   komunikat stoi nad listą, a podświetlenie mówi, przy którym poście coś się stało. */
.tabela-postow tbody tr:target > td:first-child { box-shadow: inset 4px 0 0 var(--toz-zloto); }
@media (prefers-reduced-motion: no-preference) {
    .table tbody tr.wiersz-ostatni > td { animation: toz-wiersz-ostatni 2.4s ease-out .2s; }
    .tabela-postow tbody tr:target > td, .table tbody tr[id^="mail-wiersz-"]:target > td { animation: toz-wiersz-ostatni 2.4s ease-out .2s; }
    @keyframes toz-wiersz-ostatni { 0%, 30% { background-color: rgba(215, 181, 109, .32); } }
}

@media (max-width: 640px) {
    .poza-telefonem { display: none !important; }
    /* Skrót do zdjęć pod tytułem karty (interwencja, zwierzak; 27.10.2026) - zwykły odnośnik do kotwicy. */
    .card-head .skrot-do-plikow { display: block; margin-top: 8px; }

    /* Filtry: samo pole z data-na-telefonie i przyciski; reszta po "Więcej filtrów". */
    .przycisk-filtrow { display: inline-flex; }
    .filtry-zwijane:not(.filtry-rozwiniete) > :not([data-na-telefonie]):not(.filters-action) { display: none; }
    .filtry-zwijane:not(.filtry-rozwiniete) .filters-action > fieldset { display: none; }
    .filtry-zwijane [data-na-telefonie] { grid-column: 1 / -1; }

    /* Kolumny: same najważniejsze, aż do "pokaż wszystkie kolumny". Bez kolumny zaznaczania pasek działań
       na zaznaczonych nie ma czego zbierać, więc znika razem z nią. */
    .przelacznik-kolumn { display: inline-flex; margin-bottom: 10px; font-size: .82rem; padding: 3px 9px; }
    .kolumny-skrocone:not(.kolumny-wszystkie) .kol-poza-telefonem,
    .kolumny-skrocone:not(.kolumny-wszystkie) [data-zbiorcze] { display: none; }
    /* Komórka z odnośnikiem do wpisu znika z oczu, ale zostaje dla czytnika ekranu - inaczej w wierszu nie ma czym
       wejść do wpisu (audyt kontrolny 15.10.2026, L51). */
    .kolumny-skrocone:not(.kolumny-wszystkie) td.kol-poza-telefonem:has([data-otworz-wiersz]) {
        display: block; position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
    .kolumny-skrocone:not(.kolumny-wszystkie) td.kol-poza-telefonem:has([data-otworz-wiersz]:focus-visible) {
        width: auto; height: auto; margin: 0; padding: 4px; overflow: visible; clip: auto; z-index: 5; background: var(--toz-plyta);
    }
    /* Zostające kolumny mieszczą się w szerokości ekranu: plakietki i napisy się zawijają, zamiast rozpychać
       tabelę (plakietka stanu bez zawijania miała 186 px). Tak samo przy własnym układzie kolumn ekranu - chowanie
       kolumn zostaje przy .kolumny-skrocone, dopasowanie do ekranu obejmuje oba (audyt 23.10.2026, T10); :is() trzyma
       wagę reguł bez zmian. */
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table-wrap .table { width: 100%; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje),
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table th:not(.kol-akcje) { min-width: 0; max-width: none; }
    /* Długi ciąg bez spacji (adres strony, numer) łamie się gdziekolwiek; plakietka tylko między słowami. */
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje),
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje) * { white-space: normal; overflow-wrap: anywhere; }
    /* ...ale nie w kolumnie wąskiej jak słowo. Dawniej 5,75rem na każdą komórkę - przy czterech kolumnach tabela
       wychodziła za ekran i ostatnia była ucięta (przegląd telefonu 15.10.2026, M18). Data i kwota stoją w jednej
       linijce - "08.05.202 / 6" łamało się w środku (M10). */
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje):not(.kol-zaznacz):not(.kol-znaki) { min-width: 4rem; }
    /* Kolumna znaczków przy imieniu (podopieczni) zostaje wąska, a bez żadnego znaczka na stronie znika - pusta
       zabierała piątą część szerokości i łamała imiona w środku słowa (audyt 23.10.2026, T09). Warunek na całej karcie,
       nie na tabeli: przyklejona kopia nagłówka to osobna tabela bez wierszy i chowała swój nagłówek znaczków, choć
       tabela go pokazywała - napisy nad kolumnami jechały o jedną w lewo (kontrola przed wgraniem 23.10.2026). */
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]):not(:has(td.kol-znaki *)) .kol-znaki { display: none; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.kol-data,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.kol-data * { overflow-wrap: normal; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.liczba,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.liczba * { white-space: nowrap; overflow-wrap: normal; }
    /* Przyciski w kolumnie akcji jeden pod drugim - obok siebie rozpychały Terminarz za ekran (M14). */
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.kol-akcje { white-space: normal; }
    /* Kolumna kilku przycisków (sprawy uchwały: Popraw, strzałki, Usuń) zawija się w każdej tabeli - w jednej
       linii wypychała tabelę za ekran i ściskała treść do kilku słów w wierszu (przegląd telefonu, M21). */
    .table td.kol-akcje { white-space: normal; }
    .table td.kol-akcje .btn + .inline, .table td.kol-akcje .inline + .inline { margin-left: 0; }
    .table td.kol-akcje > * { margin: 2px 2px 2px 0; }
    /* Odnośnik, który otwiera wpis, zastępuje dotknięcie wiersza - w kolumnie akcji zostaje dla czytnika ekranu,
       a na ekranie tylko przyciski robiące coś innego (Terminarz: samo „Zrobione”). */
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz] {
        position: absolute; width: 1px; min-width: 0; height: 1px; padding: 0; margin: -1px; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz]:focus-visible {
        position: static; width: auto; height: auto; margin: 0; padding: 0 12px; overflow: visible; clip: auto;
    }
    /* Ikona (btn-ikona) przy fokusie z klawiatury wraca jako kwadrat, nie prostokąt z napisem. */
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz].btn-ikona:focus-visible { width: 34px; min-width: 34px; padding: 0; }
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz] + .inline { margin-left: 0; }
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje .btn + .inline,
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje .inline + .inline { display: block; margin: 6px 0 0; }

    /* Listy ze zdjęciami: komórka ze zdjęciem trzymała 12-16rem, a pusty prostokąt stał także bez zdjęcia -
       tabela nie mieściła się na ekranie (M15, M16; właściciel 15.10.2026: "w listach, gdzie są zdjęcia, tabele
       na komórce się nie mieszczą"). */
    .zbiorka-z-miniatura, .post-z-miniatura, .podopieczny-z-miniatura { min-width: 0; gap: 4px 8px; flex-wrap: wrap; }
    span.miniatura-zbiorki, span.miniatura-posta, span.miniatura-podopiecznego { display: none; }
    img.miniatura-zbiorki { flex-basis: 44px; width: 44px; height: 24px; }
    img.miniatura-posta { flex-basis: 48px; width: 48px; height: 48px; }

    /* Tabele do wpisywania (wpłaty przy wyroku, pozycje raportu kasowego): wiersz jako pola jedno pod drugim,
       z nazwą pola nad każdym - w tabeli kolumny wychodziły za ekran (M13, M17). */
    .tabela-wierszami { min-width: 0; }
    .tabela-wierszami thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .tabela-wierszami, .tabela-wierszami tbody { display: block; width: 100%; }
    .tabela-wierszami tr { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px 10px; padding: 12px 0;
                           border-bottom: 1px solid var(--toz-border); }
    .tabela-wierszami td { display: block; padding: 0; border: 0; min-width: 0 !important; width: auto !important;
                           max-width: none; text-align: left !important; }
    .tabela-wierszami td[data-etykieta]::before { content: attr(data-etykieta); display: block; margin-bottom: 3px;
                                                 font-size: .78rem; font-weight: 600; color: var(--toz-muted); }
    .tabela-wierszami tr { grid-auto-flow: row dense; }
    .tabela-wierszami td.kol-uwaga, .tabela-wierszami td[data-etykieta="Treść"],
    .tabela-wierszami td[data-etykieta="Szczegóły"] { grid-column: 1 / -1; }
    .tabela-wierszami td[data-etykieta="Dowód"], [data-tabela-pozycji].tabela-wierszami td[data-etykieta="Kwota"] { grid-column: 2 / -1; }
    .tabela-wierszami .kwota-w-tabeli { width: 100%; }
    .tabela-wierszami td.kol-lp-lista { grid-column: 1 / 3; font-weight: 600; }
    .tabela-wierszami td.kol-lp-lista::before { display: inline; margin-right: 4px; }
    .tabela-wierszami td.kol-usun, .tabela-wierszami td.kol-akcje { grid-column: 3; grid-row: 1; align-self: end; width: auto; }
    .tabela-wierszami .form-control { width: 100%; min-width: 0; }

    /* Półka wzorów: przyciski pod opisem wzoru - obok niego kafelek miał 441 px przy ekranie 375 (M01). */
    .wzor { flex-wrap: wrap; }
    .wzor-tresc { flex-basis: calc(100% - 60px); }
    .wzor-akcje { flex: 1 1 100%; justify-content: flex-end; flex-wrap: wrap; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table th,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td { padding-left: 5px; padding-right: 5px; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .naglowek-dopisek { display: none; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .znacznik-niebezpieczny,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .znacznik-miejsca,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .stan,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .badge {
        overflow-wrap: normal; font-size: .7rem; letter-spacing: 0; padding: 0 6px; line-height: 1.35;
    }
    /* Wiersz otwiera dotknięcie (na-telefonie.js) - przycisk "Edytuj" w osobnej kolumnie zjadał ćwierć ekranu. */
    .kolumny-skrocone:not(.kolumny-wszystkie) tbody tr:has([data-otworz-wiersz]) { cursor: pointer; }
    /* Opis przy "Dodaj ..." nad listą ("Pełny formularz - z pozycjami...") - na telefonie sam przycisk. */
    .dodanie-faktury > span.muted { display: none; }

    /* Formularze (właściciel, 15.10.2026: "tak samo w edycjach, jest ogromna ilość danych i przestrzeni").
       Objaśnienie pod polem pokazuje się dopiero, gdy ktoś jest w tym polu - czytnik ekranu i tak je dostaje
       (aria-describedby czyta także ukryte). Tylko zwykłe objaśnienie (sama klasa "hint"): ostrzeżenia
       (hint-uwaga) i objaśnienia z treścią do pracy (np. lista niezgodności) zostają zawsze. */
    /* Bez czynności i komunikatów na żywo: objaśnienie z przyciskiem albo odnośnikiem ("Dodaj do miejsc opieki",
       "Otwórz w mapach") i wynik skryptu ("Weź z GPS") zostają zawsze (audyt kontrolny 15.10.2026, L04, L19). Ekrany
       logowania (card-narrow) i zdania o bezpieczeństwie konta (hint-zawsze) też (decyzja właściciela, L48). */
    .pole:not(:focus-within) > .hint[class="hint"]:not(:has(a, button)):not([aria-live]):not([role="status"]),
    .card:not(.card-narrow) > .hint[class="hint"]:not(:has(a, button)):not([aria-live]):not([role="status"]),
    .historia > .hint[class="hint"] { display: none; }
    /* Objaśnienie z odnośnikiem: odnośnik zawsze, tekst objaśnienia dopiero w polu (przegląd telefonu, M02). */
    .pole:not(:focus-within) .opis-po-dotknieciu { display: none; }
    /* Podgląd kolorów plakietek pod polem "Kolor" (22 plakietki, ok. 218 px) - tak samo dopiero w polu (T31). */
    .pole:not(:focus-within) > .hint.podglad-kolorow { display: none; }
    /* Pole GPS na całą szerokość i od lewej, jak reszta pól (M04). */
    .gps-wiersz .form-control.pole-gps { flex: 1 1 100%; width: 100%; text-align: left; }
    /* "Zabrane zwierzaki": pusta liczba kart nie stoi szarym kwadratem, krzyżyk przy imieniu, nie w osobnej linii (M03). */
    .powiazanie-zwierzak .zwierzak-ile:empty { display: none; }
    .powiazanie-zwierzak input[name="zwierzak_imie[]"] { order: 1; }
    .powiazanie-zwierzak .zwierzak-ile { order: 2; }
    .powiazanie-zwierzak .usun-pozycje { order: 3; }
    .powiazanie-zwierzak > :not(input[name="zwierzak_imie[]"]):not(.zwierzak-ile):not(.usun-pozycje) { order: 4; }
    /* Pasek zapisu: "Zapisz" na całą szerokość, reszta mniejsza, usuwanie z boku (M05). */
    .pasek-zapisu { gap: 8px; }
    .pasek-zapisu .btn-primary { flex: 1 1 100%; }
    .pasek-zapisu .btn:not(.btn-primary) { padding: 7px 10px; font-size: .85rem; flex: 1 1 auto; }
    .pasek-zapisu .pasek-prawa .btn:not(.btn-primary) { flex: 0 0 auto; }
    .pasek-zapisu .pasek-prawa { justify-content: flex-end; }
    .pasek-zapisu .pasek-prawa .btn { width: auto; flex: 0 0 auto; }
    /* Zakładki kategorii pism w jednym rzędzie przewijanym w bok - zawinięte zajmowały cztery rzędy (M11). */
    .zakladki { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
    .zakladki::-webkit-scrollbar { display: none; }
    .zakladka { flex: 0 0 auto; }
    .pola { gap: 12px 14px; }
    .sekcja { margin-bottom: 18px; }
    .sekcja + .sekcja { padding-top: 16px; }
    /* Pole opisu na telefonie rośnie z treścią (na-telefonie.js) - stała wysokość 16rem to pół ekranu. */
    .pole-opis .form-control { min-height: 6rem; }
    .pole-opis-duze .form-control { min-height: 9rem; }
    /* Na telefonie pliku nie da się przeciągnąć - zostaje sam wybór pliku, bez ramki strefy. */
    .strefa-zrzutu { border: 0; padding: 0; margin-bottom: 10px; }
    .pusto { padding: 12px; }
    p.pusto::before { display: none; }
}

/* Tablet (641-1024 px; właściciel, 16.10.2026: "Więcej kolumn niż na telefonie"): kolumny z na-telefonie albo
   na-tablecie, reszta po "pokaż wszystkie kolumny"; wiersz otwiera dotknięcie (na-telefonie.js). Tabela 1,5-2,5 raza
   szersza niż ekran tabletu chowała z prawej kolumnę z "Edytuj". */
@media (min-width: 641px) and (max-width: 1024px) {
    .przelacznik-kolumn { display: inline-flex; margin-bottom: 10px; font-size: .82rem; padding: 3px 9px; }
    .tablet-bez-ukrytych .przelacznik-kolumn { display: none; }
    .kolumny-skrocone:not(.kolumny-wszystkie) .kol-poza-tabletem { display: none; }
    .kolumny-skrocone:not(.kolumny-wszystkie) td.kol-poza-tabletem:has([data-otworz-wiersz]),
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz] {
        display: block; position: absolute; width: 1px; min-width: 0; height: 1px; padding: 0; margin: -1px; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
    .kolumny-skrocone:not(.kolumny-wszystkie) td.kol-poza-tabletem:has([data-otworz-wiersz]:focus-visible) {
        width: auto; height: auto; margin: 0; padding: 4px; overflow: visible; clip: auto; z-index: 5; background: var(--toz-plyta);
    }
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz]:focus-visible {
        display: inline-flex; position: static; width: auto; height: auto; margin: 0; padding: 0 12px; overflow: visible; clip: auto;
    }
    .kolumny-skrocone:not(.kolumny-wszystkie) .table td.kol-akcje a[data-otworz-wiersz].btn-ikona:focus-visible { width: 34px; min-width: 34px; padding: 0; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table-wrap .table { width: 100%; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje),
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table th:not(.kol-akcje) { min-width: 0; max-width: none; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td:not(.kol-akcje) { white-space: normal; overflow-wrap: anywhere; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.kol-data,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td.liczba { white-space: nowrap; overflow-wrap: normal; }
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .badge,
    :is(.kolumny-skrocone:not(.kolumny-wszystkie), [data-kolumny-wlasne]) .table td .stan { overflow-wrap: normal; }
    .kolumny-skrocone:not(.kolumny-wszystkie) tbody tr:has([data-otworz-wiersz]) { cursor: pointer; }
    .zbiorka-z-miniatura, .post-z-miniatura { min-width: 0; }
    .table td.kol-akcje { white-space: normal; }
}

/* Pasek zapisu na ekranie dotykowym do 1024 px (tablet) - jak na telefonie: na końcu formularza, a nie przy dole
   ekranu, gdzie przy podniesionej klawiaturze zasłaniał wypełniane pole (właściciel, 16.10.2026). */
@media (max-width: 1024px) and (hover: none) and (pointer: coarse) {
    .pasek-zapisu {
        position: static; background: transparent; border-top: 0;
        padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0;
    }
}

/* ==========================================================================
   Ruchome elementy (właściciel, 16.10.2026: "jakie można ruchome rzeczy wprowadzić na taką stronę?" - zlecenie
   dane/zlecenie-ruchome-elementy.md i -2.md). Te same zasady co wyżej: ruch tylko dla tych, którzy go nie wyłączyli,
   nic nad treścią, każdy efekt raz, karta/treść/wiersz/komórka bez przesunięć; pilnuje tests/unit-efekty.php.
   ========================================================================== */

/* p. 1 - mapy: pinezki i chorągiewki opadają po kolei przy pierwszym wczytaniu (opóźnienie z mapa-*.js, razem
   najwyżej ok. 0,4 s, klikalne od razu), pinezka sprawy, z której się wróciło, 3 razy pulsuje. Przesuwanie mapy
   ręką rysuje je bez tych klas. */
@media (prefers-reduced-motion: no-preference) {
    .pin.pin-opada, .flaga.flaga-opada, .znak-urzedu.flaga-opada { animation: toz-mapa-opada .25s cubic-bezier(.3, 1.35, .5, 1) var(--opoznienie, 0s) backwards; }
    .pin.pin-puls { animation: toz-pin-puls .7s ease-out 3; transform-origin: 50% 100%; }
    @keyframes toz-mapa-opada {
        from { opacity: 0; transform: translateY(-18px); }
        to   { opacity: 1; transform: none; }
    }
    @keyframes toz-pin-puls {
        0%, 100% { transform: none; filter: none; }
        40%      { transform: scale(1.35); filter: drop-shadow(0 0 6px rgba(215, 181, 109, .95)); }
    }
}

/* p. 3 - pasek celu zbiórki (pasek_celu() w helpers.php): cienki pasek pod kwotą z procentem obok; od 100% pełny
   w złocie marki. Zwykły <progress> - bez skryptu stoi od razu napełniony, ruchome.js napełnia go przy wejściu. */
.pasek-celu { display: flex; align-items: center; gap: 6px; margin-top: 3px; justify-content: flex-end; }
dd .pasek-celu { justify-content: flex-start; max-width: 320px; }
.pasek-celu-postep {
    -webkit-appearance: none; appearance: none; flex: 1 1 auto; min-width: 48px; height: 6px; border: 0; border-radius: 999px;
    background: var(--toz-granat-jasny); overflow: hidden; color: var(--toz-granat);
}
.pasek-celu-postep::-webkit-progress-bar { background: var(--toz-granat-jasny); border-radius: 999px; }
.pasek-celu-postep::-webkit-progress-value { background: linear-gradient(90deg, #7d8fd0, var(--toz-granat)); border-radius: 999px; }
.pasek-celu-postep::-moz-progress-bar { background: linear-gradient(90deg, #7d8fd0, var(--toz-granat)); border-radius: 999px; }
.pasek-celu-pelny::-webkit-progress-value { background: linear-gradient(90deg, #e3c47e, var(--toz-zloto)); }
.pasek-celu-pelny::-moz-progress-bar { background: linear-gradient(90deg, #e3c47e, var(--toz-zloto)); }
.pasek-celu-procent { font-size: .8rem; color: var(--toz-muted); white-space: nowrap; }
@media print { .pasek-celu-postep { display: none; } }

/* p. 4 - miniatura zdjęcia rośnie w duży podgląd i wraca po zamknięciu (podglad-plikow.js: przejście wspólnego
   elementu "podglad-zdjecie"; przeglądarka bez przejść - podgląd jak dotąd). */
@media (prefers-reduced-motion: no-preference) {
    ::view-transition-group(podglad-zdjecie) { animation-duration: .32s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
    ::view-transition-old(podglad-zdjecie), ::view-transition-new(podglad-zdjecie) { height: 100%; object-fit: contain; }
}

/* p. 5 - szare paski w miejscu wyników, które przychodzą z serwera (window.TOZ.szkielet w ruchome.js; zapalają się
   po 0,3 s czekania). Połysk przesuwa się w bok, dopóki trwa czekanie - jak złota kreska wczytywania strony. */
.szkielet { display: grid; gap: 9px; padding: 12px 14px; }
.szkielet-pasek {
    display: block; height: 11px; border-radius: 6px;
    background: linear-gradient(90deg, #e6eaf3 0%, #f4f6fb 45%, #e6eaf3 90%) 0 0 / 220% 100%;
}
.szkielet-pasek:nth-child(2) { width: 82%; }
.szkielet-pasek:nth-child(3) { width: 64%; }
.szkielet-pasek:nth-child(4) { width: 76%; }
@media (prefers-reduced-motion: no-preference) {
    .szkielet-pasek { animation: toz-szkielet 1.3s ease-in-out infinite; }
    @keyframes toz-szkielet {
        from { background-position: 100% 0; }
        to   { background-position: -120% 0; }
    }
}

/* p. 6 - kropka "na żywo" przy osobie w pasku "kto ma kartę otwartą" (RownoczesnaEdycja::pasek, obecnosc.js): pulsuje
   3 razy, gdy osoba się pojawi (klasa .obecnosc-nowa tylko przy nowej); wpis osoby, która wyszła, łagodnie gaśnie. */
.obecnosc-kropka {
    display: inline-block; width: 8px; height: 8px; margin: 0 5px 1px 1px; border-radius: 50%;
    background: #1c7a45; vertical-align: middle;
}
@media (prefers-reduced-motion: no-preference) {
    .obecnosc-nowa .obecnosc-kropka { animation: toz-obecnosc-puls 1s ease-out 3; }
    .obecnosc-osoba.obecnosc-wychodzi { animation: toz-obecnosc-gasnie .45s ease-in forwards; }
    @keyframes toz-obecnosc-puls {
        from { box-shadow: 0 0 0 0 rgba(28, 122, 69, .55); }
        to   { box-shadow: 0 0 0 7px rgba(28, 122, 69, 0); }
    }
    @keyframes toz-obecnosc-gasnie { to { opacity: 0; } }
}

/* Zmiany na żywo (właściciel, 20.10.2026; na-zywo.js): pasek "kto zapisał" z przyciskiem w tej samej linii, a po
   samoczynnym przeładowaniu obwódka przy polach i tło wierszy, które się zmieniły - do pierwszego ruchu człowieka.
   Obwódka i kreska z lewej wiersza co najmniej 3:1 do tła w obu motywach - samo jasne tło było prawie niewidoczne
   (audyt 23.10.2026, T12, WCAG 1.4.11). Obwódka nie zmienia rozmiaru; mruga dwa razy tylko w bloku ruchu. */
.na-zywo .btn { margin-left: 6px; vertical-align: baseline; }
.na-zywo-zmiana { outline: 2px solid #a87200; outline-offset: 2px; border-radius: 4px; }
tr.na-zywo-zmiana { outline: none; }
tr.na-zywo-zmiana > td { background: #fff3bf; }
tr.na-zywo-zmiana > td:first-child { box-shadow: inset 4px 0 0 #a87200; }
@media (prefers-reduced-motion: no-preference) {
    .na-zywo-zmiana { animation: toz-na-zywo 1s ease-in-out 2; }
    @keyframes toz-na-zywo {
        50% { outline-color: rgba(168, 114, 0, .25); }
    }
}

/* Własne widoki list (właściciel, 20.10.2026; App\WidokiList): w menu zaraz pod swoją listą, z wcięciem i drobniejszą
   czcionką - widać, do której listy należą (bez ikon - wycofane 04.10.2026). Panel widoków na samym dole listy. */
.nav-rozwijane .nav-link.nav-widok { padding-left: 26px; font-size: .92em; }
.nav-rozwijane .nav-link.nav-widok::before {
    content: ""; display: inline-block; width: 8px; height: 1px; margin: 0 6px 4px -14px; background: currentColor; opacity: .45;
}
/* Na telefonie zwykłe pozycje grupy mają 28 px wcięcia - widok stoi głębiej, a kreska nie wystaje przed linię
   pozostałych pozycji (audyt 23.10.2026, T26). */
html.menu-zwiniete .nav-rozwijane .nav-link.nav-widok { padding-left: 42px; }
/* Nazwa widoku pod tytułem listy - tylko przy zwiniętym menu (telefon, wąskie okno), gdzie podświetlonej pozycji menu
   nie widać; na szerokim ekranie widok stoi podświetlony w menu (T32). */
.widok-podpis { display: none; margin: 2px 0 0; font-size: .875rem; color: var(--toz-muted); }
html.menu-zwiniete .widok-podpis { display: block; }
.widoki-listy .h5 { margin-top: 0; }
.widoki-listy-akcje, .widoki-listy-nowy { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 8px; }
.widoki-listy-akcje form { display: flex; align-items: center; gap: 6px; margin: 0; }
.widoki-listy-nazwa, .widoki-listy-nowy { gap: 6px; }
.widoki-listy-nazwa .form-control, .widoki-listy-nowy .form-control { width: 15rem; max-width: 100%; }
.widoki-listy-nowy label { margin: 0; }
.widoki-listy-moje a[aria-current="page"] { font-weight: 600; }
.widok-kopia { position: relative; display: inline-block; vertical-align: top; }
.widok-kopia > summary { list-style: none; }
.widok-kopia > summary::-webkit-details-marker { display: none; }
.widok-kopia-formularz {
    position: absolute; top: calc(100% + 4px); right: 0; z-index: 26;
    display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; width: max-content; min-width: 18rem; max-width: min(28rem, calc(100vw - 32px));
    padding: 10px 12px; background: var(--toz-plyta); border: 1px solid var(--toz-border); border-radius: 10px;
    box-shadow: 0 12px 28px rgba(16, 20, 33, .18); white-space: normal; text-align: left;
}

/* Zmiana w wierszu listy (właściciel, 20.10.2026; App\WWierszu, w-wierszu.js): plakietka stanu, statusu albo
   "do adopcji" jest przyciskiem - wygląda jak plakietka, z małą strzałką; lista pod nią to te same kolorowe plakietki.
   Pusta komórka (np. dokumenty "zbędne") - kreska w przerywanej ramce. */
button.stan.w-wierszu {
    font-family: inherit; font-weight: inherit; cursor: pointer; text-align: left;
}
/* Strzałka mówi, że plakietkę da się rozwinąć - pełnym kolorem napisu (przy .55 była za słaba, audyt 23.10.2026, T16). */
button.stan.w-wierszu::after {
    content: ""; display: inline-block; margin-left: 6px; vertical-align: middle;
    border-left: 3.5px solid transparent; border-right: 3.5px solid transparent; border-top: 4.5px solid currentColor;
    opacity: .9;
}
button.stan.w-wierszu:hover { filter: brightness(.96); box-shadow: 0 0 0 3px rgba(58, 87, 162, .12); }
button.stan.w-wierszu:hover::after, button.stan.w-wierszu[aria-expanded="true"]::after { opacity: 1; }
button.stan.w-wierszu:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 2px; }
button.stan.w-wierszu[aria-busy="true"] { opacity: .55; cursor: progress; }
/* Ramka pustej plakietki 3:1 do tła - inaczej pusta komórka wygląda na brak danych, nie na przycisk (T16, WCAG 1.4.11). */
.stan-pusty { background: transparent; border: 1px dashed var(--toz-pole-ramka); color: var(--toz-muted); }
.stan-pusty::before { display: none; }
.w-wierszu-lista {
    position: absolute; z-index: 60;
    min-width: 180px; max-width: calc(100vw - 16px); max-height: 20rem; overflow-y: auto;
    margin: 0; padding: 6px; list-style: none;
    display: flex; flex-direction: column; gap: 2px;
    background: var(--toz-plyta); border: 1px solid var(--toz-border); border-radius: 10px;
    box-shadow: 0 12px 28px rgba(16, 20, 33, .18);
    /* Przewinięcie do ostatniej pozycji nie przechodzi na stronę (T24). */
    overscroll-behavior: contain;
}
.w-wierszu-lista:focus { outline: none; }
.w-wierszu-lista [role="option"] {
    display: flex; align-items: center; gap: 10px;
    padding: 5px 8px; border-radius: 6px; cursor: pointer;
}
.w-wierszu-lista [role="option"]:hover, .w-wierszu-lista [role="option"].aktywna { background: var(--toz-granat-jasny); }
.w-wierszu-lista [role="option"].aktywna { box-shadow: inset 0 0 0 1px var(--toz-fokus); }
.w-wierszu-lista [role="option"][aria-selected="true"]::after {
    content: "✓"; margin-left: auto; padding-left: 8px; color: var(--toz-granat-ciemny); font-weight: 700;
}
.w-wierszu-komunikat { margin: 0 0 10px; }
/* Ikona w plakietce listy (kolory flagi maila, 10.11.2026) - flaga w swoim kolorze przed nazwą. */
.w-wierszu-lista .stan .ikona { width: 14px; height: 14px; margin-right: 5px; vertical-align: -2px; }
.flaga-wiersza.w-wierszu[aria-busy="true"] { opacity: .55; cursor: progress; }
.w-wierszu-komunikat .btn { margin-left: 6px; }
/* Odmowa albo brak zasięgu krótko przy samym przycisku - na telefonie zdanie nad tabelą jest poza ekranem (T08). */
.w-wierszu-uwaga { display: block; max-width: 16rem; margin-top: 4px; font-size: .8rem; line-height: 1.3; color: var(--toz-blad); white-space: normal; }
@media (max-width: 640px) {
    /* Kropka, napis i strzałka trzymają się razem - w wąskiej kolumnie plakietka rozpadała się na trzy linijki (T09). */
    button.stan.w-wierszu { display: inline-flex; align-items: center; }
}
@media (pointer: coarse) {
    .w-wierszu-lista [role="option"] { padding: 9px 10px; }
    /* Na dotyku plakietka-przycisk ma co najmniej 32 px wysokości - 17 px łatwo minąć, a chybione dotknięcie
       otwiera kartę (audyt 23.10.2026, T07). */
    button.stan.w-wierszu { min-height: 32px; display: inline-flex; align-items: center; }
}
@media (prefers-reduced-motion: no-preference) {
    button.stan.w-wierszu { transition: box-shadow .12s ease, filter .12s ease; }
    .w-wierszu-lista { animation: toz-w-wierszu-lista .12s ease-out; }
    .w-wierszu-zapisane { animation: toz-w-wierszu-zapisane .7s ease-out; }
    @keyframes toz-w-wierszu-lista { from { opacity: 0; transform: translateY(-4px); } }
    @keyframes toz-w-wierszu-zapisane {
        from { box-shadow: 0 0 0 0 rgba(31, 107, 69, .45); }
        to   { box-shadow: 0 0 0 8px rgba(31, 107, 69, 0); }
    }
}

/* p. 7 - po zapisaniu innego motywu (konto, "Wygląd") nowa strona odsłania nowe kolory kołem od przycisku zapisu
   (motyw-kolo.js: klasa .motyw-kolo na czas przejścia, środek koła w --motyw-x/--motyw-y). */
@media (prefers-reduced-motion: no-preference) {
    html.motyw-kolo::view-transition-old(root) { animation: none; }
    html.motyw-kolo::view-transition-new(root) { animation: toz-motyw-kolo .7s cubic-bezier(.4, 0, .2, 1); }
    @keyframes toz-motyw-kolo {
        from { clip-path: circle(0 at var(--motyw-x, 50%) var(--motyw-y, 50%)); }
        to   { clip-path: circle(150vmax at var(--motyw-x, 50%) var(--motyw-y, 50%)); }
    }
}

/* p. 8 i 14 - druga, mniejsza linia sceny święta (kamień milowy, ile zwierzak był w TOZ). */
.swieto-dopisek { display: block; margin-top: 4px; font-size: .5em; font-weight: 600; letter-spacing: 0; opacity: .85; }

/* p. 10 - kalendarz w Terminarzu: obwódka dzisiejszego dnia rysuje się raz przy wczytaniu, a po strzałce do sąsiedniego
   miesiąca sama siatka dni wjeżdża z właściwej strony (data-kierunek z adresu: dalej / wstecz, znacznik jednorazowy);
   karta kalendarza stoi w miejscu. */
@media (prefers-reduced-motion: no-preference) {
    .kalendarz-dzis { animation: toz-kalendarz-dzis .55s ease-out; }
    .kalendarz-dni[data-kierunek="dalej"]  { animation: toz-kalendarz-dalej .3s ease-out; }
    .kalendarz-dni[data-kierunek="wstecz"] { animation: toz-kalendarz-wstecz .3s ease-out; }
    @keyframes toz-kalendarz-dzis {
        from { border-color: transparent; box-shadow: inset 0 0 0 1px transparent, 0 0 0 0 rgba(215, 181, 109, 0); }
    }
    @keyframes toz-kalendarz-dalej  { from { opacity: 0; transform: translateX(28px); } }
    @keyframes toz-kalendarz-wstecz { from { opacity: 0; transform: translateX(-28px); } }
}

/* p. 11 - łapka drepcząca po złotej kresce wczytywania (efekty.js zapala kreskę po 0,16 s; łapka pojawia się dopiero,
   gdy wczytywanie trwa jeszcze sekundę, i idzie w takt światła na kresce; gaśnie razem z nią). Siedzi na samej kresce,
   bez klikania - belki menu nie zasłania. */
.postep-strony::after {
    content: ''; position: absolute; left: 0; top: 0; width: 13px; height: 13px; opacity: 0;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%233a57a2'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (prefers-reduced-motion: no-preference) {
    html.w-drodze .postep-strony::after {
        animation: toz-postep-lapka 1.05s linear infinite, toz-postep-lapka-zjaw .25s ease-out 1s forwards;
    }
    @keyframes toz-postep-lapka {
        from { transform: translateX(-16px) rotate(-14deg); }
        50%  { transform: translateX(50vw) rotate(14deg); }
        to   { transform: translateX(100vw) rotate(-14deg); }
    }
    @keyframes toz-postep-lapka-zjaw { to { opacity: 1; } }
}
@media print { .postep-strony::after { display: none; } }

/* p. 12 - rysunek na stronie błędu (error.php: piesek węszący przy 404, kotek za drzwiami przy 403, piesek z bandażem
   przy błędzie serwera; SVG w samym szablonie). Nos rusza się 3 razy, ogon merda 3 razy i stop. */
.blad-rysunek { display: block; width: 132px; height: 88px; margin: 0 auto 10px; }
.blad-ogon { transform-box: fill-box; transform-origin: 100% 100%; }
.blad-kotek .blad-ogon { transform-origin: 0 100%; }
@media (prefers-reduced-motion: no-preference) {
    .blad-nos  { animation: toz-blad-nos .45s ease-in-out 3; }
    .blad-ogon { animation: toz-blad-ogon .32s ease-in-out 6 alternate; }
    @keyframes toz-blad-nos  { 50% { transform: translate(1.6px, -1.2px); } }
    @keyframes toz-blad-ogon { to { transform: rotate(22deg); } }
}
@media print { .blad-rysunek { display: none; } }

/* p. 13 - "nic nie pasuje do ustawionych filtrów" inaczej niż pusta lista: zamiast łapy nos węszący nad lupą
   (p.pusto-filtr - szablon dokłada klasę przy gałęzi "nie pasuje"); nos węszy 2 razy. Napisy bez zmian. */
p.pusto-filtr::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Ccircle cx='20' cy='28' r='11' fill='none' stroke='%23b9c3de' stroke-width='4'/%3E%3Cpath d='M29 37l12 9' stroke='%23b9c3de' stroke-width='5' stroke-linecap='round'/%3E%3Cellipse cx='24' cy='9' rx='7.5' ry='5.2' fill='%237d8fd0'/%3E%3Cellipse cx='21' cy='9.5' rx='1.6' ry='2' fill='%23fff'/%3E%3Cellipse cx='27' cy='9.5' rx='1.6' ry='2' fill='%23fff'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: no-preference) {
    p.pusto-filtr::before { animation: toz-wesz .5s ease-in-out .1s 2; }
    @keyframes toz-wesz { 50% { transform: translateX(3px) rotate(-8deg); } }
}

/* p. 15 - powitanie według pory dnia (layout.php, App\Powitanie): u góry z prawej, w wolnym polu pod belką, bez
   klikania; słońce (dzień) albo księżyc (wieczór) z arkusza. Napis zapala i gasi tylko ruch - bez ruchu nic. */
.powitanie-dnia {
    position: fixed; top: 66px; right: 16px; z-index: 15; pointer-events: none; opacity: 0;
    padding: 8px 16px 8px 42px; border-radius: 999px; background: #fff; color: var(--toz-granat-ciemny);
    font-weight: 600; box-shadow: 0 6px 18px rgba(44, 67, 129, .14); white-space: nowrap;
}
.powitanie-dnia::before {
    content: ''; position: absolute; left: 12px; top: 50%; width: 22px; height: 22px; margin-top: -11px;
    background: center / contain no-repeat;
}
.powitanie-dzien::before   { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='none' stroke='%23d7b56d' stroke-width='4' stroke-linecap='round'%3E%3Ccircle cx='24' cy='24' r='9' fill='%23d7b56d'/%3E%3Cpath d='M24 4v6M24 38v6M4 24h6M38 24h6M9.9 9.9l4.2 4.2M33.9 33.9l4.2 4.2M9.9 38.1l4.2-4.2M33.9 14.1l4.2-4.2'/%3E%3C/svg%3E"); }
.powitanie-wieczor::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%233a57a2'%3E%3Cpath d='M30 4a18 18 0 1 0 14 29A16 16 0 0 1 30 4z'/%3E%3Ccircle cx='10' cy='12' r='1.6' fill='%23d7b56d'/%3E%3Ccircle cx='17' cy='6' r='1.2' fill='%23d7b56d'/%3E%3C/svg%3E"); }
@media (prefers-reduced-motion: no-preference) {
    .powitanie-dnia { animation: toz-powitanie 4.2s ease-in-out .35s forwards; }
    @keyframes toz-powitanie {
        0%   { opacity: 0; transform: translateY(-8px); }
        12%  { opacity: 1; transform: none; }
        82%  { opacity: 1; }
        100% { opacity: 0; }
    }
}
@media print { .powitanie-dnia { display: none; } }
@media (max-width: 760px) { .powitanie-dnia { top: 60px; right: 10px; padding: 6px 12px 6px 36px; font-size: .92rem; } }

/* p. 17 - potwierdzenia: w komunikacie o udanym zapisie ptaszek rysuje się raz (obrazek z własnym ruchem tylko
   w bloku ruchu; bez ruchu stoi ten sam znak co dotąd), a przy przycisku kopiowania na 1,5 s dymek "Skopiowano ✓"
   (window.TOZ.dymek w ruchome.js; przy błędzie "Nie udało się") - nad przyciskiem, bez klikania. */
.toz-skopiowano {
    position: fixed; z-index: 70; pointer-events: none; padding: 4px 10px; border-radius: 8px;
    background: var(--toz-granat-ciemny); color: #fff; font-size: .85rem; font-weight: 600; white-space: nowrap;
    box-shadow: 0 4px 12px rgba(44, 67, 129, .22);
}
.toz-skopiowano::after {
    content: ''; position: absolute; left: 50%; bottom: -5px; width: 10px; height: 10px; margin-left: -5px;
    background: inherit; transform: rotate(45deg);
}
.toz-skopiowano-pod::after { bottom: auto; top: -5px; }
.toz-skopiowano-blad { background: #a52834; }
@media (prefers-reduced-motion: no-preference) {
    .main > .alert-success {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cstyle%3Epath%7Bstroke-dasharray:13;stroke-dashoffset:13;animation:r .4s ease-out .2s forwards%7D@keyframes r%7Bto%7Bstroke-dashoffset:0%7D%7D%3C/style%3E%3Ccircle cx='10' cy='10' r='9' fill='%231f6b45'/%3E%3Cpath d='M5.8 10.4l2.8 2.8 5.6-6' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    }
    .toz-skopiowano { animation: toz-skopiowano .18s ease-out; }
    @keyframes toz-skopiowano { from { opacity: 0; transform: translateY(4px) scale(.96); } }
}
@media print { .toz-skopiowano { display: none; } }

/* p. 18 - przy ostrzeżeniu o wylogowaniu (sesja-wygasa.js) kółko, które powoli się opróżnia aż do chwili wylogowania
   (--od: ile zostało z dziesięciu minut, czas animacji = czas do końca). Tylko w bloku ruchu - bez ruchu sam tekst
   z minutami, jak dotąd. Przeglądarka bez @property pokazuje kółko bez ubywania. */
@property --sesja-reszta { syntax: '<number>'; inherits: false; initial-value: 100; }
.sesja-kolko { display: none; }
@media (prefers-reduced-motion: no-preference) {
    .sesja-kolko {
        display: inline-block; width: 16px; height: 16px; margin: 0 4px 0 8px; vertical-align: -3px; border-radius: 50%;
        background: conic-gradient(var(--toz-zloto) calc(var(--sesja-reszta) * 1%), rgba(201, 160, 74, .18) 0);
        animation-name: toz-sesja-kolko; animation-timing-function: linear; animation-fill-mode: both;
    }
    @keyframes toz-sesja-kolko {
        from { --sesja-reszta: var(--od); }
        to   { --sesja-reszta: 0; }
    }
}

/* p. 19 - zaraz po wylogowaniu przyciskiem nad formularzem logowania łapka macha dwa razy z napisem „Do zobaczenia!”
   (LoginController: znak w nowej sesji, raz). Tylko w bloku ruchu - bez ruchu został sam komunikat „Wylogowano.”. */
.do-zobaczenia { display: none; }
@media (prefers-reduced-motion: no-preference) {
    .do-zobaczenia {
        display: flex; align-items: center; justify-content: center; gap: 10px; margin: 0 0 14px;
        font-weight: 700; color: var(--toz-granat-ciemny); animation: toz-zjaw .3s ease-out;
    }
    .do-zobaczenia-lapka {
        display: inline-block; width: 30px; height: 30px; transform-origin: 50% 90%;
        background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%23d7b56d'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
        animation: toz-machanie .32s ease-in-out .25s 4 alternate;
    }
    @keyframes toz-machanie { from { transform: rotate(-16deg); } to { transform: rotate(16deg); } }
}

/* p. 20 - pasek postępu przy wysyłaniu plików w tle (dlugie-wysylanie.js): "Wysyłanie… 45%" pod formularzem; zdanie
   dla czytnika zostaje w [data-dlugo-stan]. */
.wysylanie-postep { display: flex; align-items: center; gap: 10px; margin: 8px 0 0; font-size: .9rem; color: var(--toz-granat-ciemny); }
.wysylanie-postep[hidden] { display: none; }
.wysylanie-postep progress {
    flex: 1 1 auto; max-width: 320px; height: 8px; border: 0; border-radius: 999px; background: #e6eaf3; overflow: hidden;
    -webkit-appearance: none; appearance: none;
}
.wysylanie-postep progress::-webkit-progress-bar { background: #e6eaf3; border-radius: 999px; }
.wysylanie-postep progress::-webkit-progress-value { background: var(--toz-zloto); border-radius: 999px; }
.wysylanie-postep progress::-moz-progress-bar { background: var(--toz-zloto); border-radius: 999px; }
@media (prefers-reduced-motion: no-preference) {
    .wysylanie-postep progress::-webkit-progress-value { transition: width .2s ease-out; }
}

/* p. 22 - płynne dokładanie wierszy w polach powtarzalnych (wiersze.js: klasa .wiersz-wchodzi na chwilę). Wiersz
   formularza pojaśnia i rozwija się od góry; w tabeli rusza się tylko zawartość komórek (tr i td bez przesunięć). */
@media (prefers-reduced-motion: no-preference) {
    .wiersz-wchodzi:not(tr) { transform-origin: 50% 0; animation: toz-wiersz-wchodzi .2s ease-out; }
    tr.wiersz-wchodzi > td > * { animation: toz-wiersz-wchodzi-tresc .2s ease-out; }
    @keyframes toz-wiersz-wchodzi { from { opacity: 0; transform: scaleY(.6); } }
    @keyframes toz-wiersz-wchodzi-tresc { from { opacity: 0; transform: translateY(-4px); } }
}

/* p. 24 - licznik zaznaczonych wierszy lekko podskakuje przy każdej zmianie zaznaczenia (zaznaczanie.js: klasa przy
   zmianie, nie przy wczytaniu). Pasek działań zbiorczych stoi jak dotąd - nie chowa się, więc nie wysuwa. */
@media (prefers-reduced-motion: no-preference) {
    .zbiorcze-licznik { display: inline-block; }
    .zbiorcze-licznik-skok { animation: toz-licznik-skok .28s ease-out; }
    @keyframes toz-licznik-skok { 40% { transform: translateY(-3px) scale(1.06); } }
}

/* p. 25 - chmurka z wartością na wykresach (ruchome.js): nad słupkiem miesiąc i liczba, pozostałe słupki przygasają;
   słupki dostępne tabulatorem. Chmurka przesuwa się między słupkami tylko w bloku ruchu. */
.wykres { position: relative; }
.wykres-chmurka {
    position: absolute; z-index: 5; pointer-events: none; padding: 3px 8px; border-radius: 6px;
    background: var(--toz-granat-ciemny); color: #fff; font-size: .875rem; font-weight: 600; white-space: nowrap;
    box-shadow: 0 4px 12px rgba(44, 67, 129, .2);
}
.wykres-chmurka[hidden] { display: none; }
.wykres-svg.wykres-wybrany .wykres-slupek:not(.wykres-aktywny) { opacity: .45; }
/* Ozdoby przygasłego słupka (połysk, paseczki) przygasają razem z nim (27.10.2026). */
.wykres-svg.wykres-wybrany .wykres-stos:not(:has(.wykres-aktywny)) > .wykres-ozdoba { opacity: .45; }
.wykres-slupek:focus { outline: none; }
.wykres-slupek:focus-visible { stroke: var(--toz-granat-ciemny); stroke-width: 2px; }
/* Siatka natężenia (przegląd 08.11.2026): moc koloru to sama treść mapy, więc wskazanie nie przygasza reszty komórek (blade
   komórki gubiłyby liczby i obraz, kiedy przychodzi najwięcej maili) - wskazaną komórkę znaczy obwódka w złocie marki. */
.wykres-siatka .wykres-svg.wykres-wybrany .wykres-slupek:not(.wykres-aktywny),
.wykres-siatka .wykres-slupek:hover { opacity: 1; }
.wykres-siatka .wykres-slupek.wykres-aktywny,
.wykres-siatka .wykres-slupek:hover { stroke: var(--toz-zloto); stroke-width: 2px; }
@media (prefers-reduced-motion: no-preference) {
    .wykres-chmurka { transition: left .15s ease-out, top .15s ease-out; }
}
/* Powiększenie wykresu (właściciel, 09.11.2026: "Nie da się na nich nic wyczytać. Trzeba sie bardzo przyglądać";
   powiekszenie-wykresu.js): przycisk „Powiększ” przy tytule (z klawiatury) i kliknięcie myszą w rysunek otwierają okno
   aplikacji (okno pytania: kreska marki, szyba za oknem) z tym samym wykresem na całą szerokość okna, a pod nim jego tabela
   liczb - ta sama co dla czytnika ekranu, tu widoczna. Rysunek nie wyższy niż ok. dwie trzecie ekranu, żeby tabela zaczynała
   się na nim; okno przewija się w sobie. Bez skryptu nie ma przycisku ani okna. Na wydruku przycisku nie ma. Przycisk stoi
   w figurze za podpisem (treść podpisu to nazwa wykresu dla czytnika ekranu - bez „Powiększ” w niej), w rzędzie tytułu
   z prawej; podpis zostawia mu miejsce (przegląd 09.11.2026). */
.wykres-powiekszalny > figcaption { padding-right: 7rem; }
.wykres-powiekszalny > .wykres-powieksz { position: absolute; top: -4px; right: 0; }
.wykres-powiekszalny .wykres-svg { cursor: zoom-in; }
/* Przewijanie okna nie przechodzi na stronę pod szybą, a szeroka tabela liczb przewija się sama, bez okna (przegląd telefonu 10.11.2026, T3-10). */
.okno-pytania.okno-wykresu { width: calc(100% - 32px); max-width: calc(100% - 32px); max-height: calc(100% - 32px); overflow: hidden auto; overscroll-behavior: contain; }
.okno-wykresu .okno-pytania-tresc { padding: clamp(16px, 2vw, 28px); }
.okno-wykresu-pasek { display: flex; justify-content: flex-end; margin: 0 0 4px; }
.okno-wykresu .wykres-powieksz { display: none; }
.okno-wykresu .wykres-powiekszalny > figcaption { padding-right: 0; }
.okno-wykresu .wykres-tytul { font-size: 1.2rem; }
.okno-wykresu .wykres-opis { font-size: .95rem; }
.okno-wykresu .wykres-svg { cursor: auto; max-height: 66vh; }
.okno-wykresu .wykres-legenda { font-size: 1rem; }
.okno-wykresu .wykres table.sr-only {
    position: static; display: block; width: auto; max-width: 100%; height: auto; margin: 20px 0 0; overflow: auto hidden; clip: auto; white-space: normal;
    border-collapse: collapse; font-size: .95rem; font-variant-numeric: tabular-nums;
}
/* Podpis tabeli to tytuł wykresu, który stoi tuż nad nią - dla oka zbędny, czytnik ekranu dalej go ma. */
.okno-wykresu .wykres table.sr-only caption {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* Wyrównanie jak w tabelach systemu: liczby i kwoty w prawo, okresy (daty) na środek, nazwy pasków w lewo. */
.okno-wykresu .wykres table.sr-only th,
.okno-wykresu .wykres table.sr-only td { padding: 6px 14px; border-bottom: 1px solid var(--toz-border); text-align: right; white-space: nowrap; }
.okno-wykresu .wykres table.sr-only th[scope="row"],
.okno-wykresu .wykres table.sr-only thead th:first-child { text-align: center; font-weight: 600; }
.okno-wykresu .wykres-paski table.sr-only th[scope="row"] { text-align: left; white-space: normal; }
.okno-wykresu .wykres table.sr-only thead th { color: var(--toz-granat-ciemny); border-bottom: 2px solid var(--toz-border); }
.okno-wykresu .wykres table.sr-only tbody tr:hover { background: var(--toz-granat-jasny); }
/* Na wydruku pismo rysunku z serwera (Wykresy::PISMO): powiekszenie-wykresu.js liczy je z szerokości kolumny na ekranie,
   a przy druku rysunek ma szerokość kartki - styl z ekranu dałby drobne napisy (przegląd 09.11.2026). */
@media print {
    .wykres-powieksz { display: none; }
    .wykres-powiekszalny > figcaption { padding-right: 0; }
    .wykres-powiekszalny .wykres-svg { cursor: auto; }
    .wykres-svg { font-size: 14px !important; }
}

/* p. 26 - tropy łapek raz przechodzą przez tło strony logowania (auth/login.php): za treścią (z-index ujemny), bez
   klikania, po kolei pojawiają się i gasną; tylko w bloku ruchu, na telefonie trzy, na wydruku nic. */
.logowanie-tropy { display: none; }
@media (prefers-reduced-motion: no-preference) {
    .logowanie-tropy { display: block; position: fixed; inset: 0 0 auto; height: 100vh; height: 100lvh; z-index: -1; pointer-events: none; overflow: hidden; }
    .logowanie-tropy span {
        position: absolute; width: 26px; height: 26px; opacity: 0; transform: rotate(var(--obrot, -25deg));
        background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='%237d8fd0'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
        animation: toz-trop 1.8s ease-in-out both;
    }
    .logowanie-tropy span:nth-child(1) { left: 6%; top: 86%; --obrot: -30deg; animation-delay: 0.25s; }
    .logowanie-tropy span:nth-child(2) { left: 14%; top: 74%; --obrot: -22deg; animation-delay: 0.57s; }
    .logowanie-tropy span:nth-child(3) { left: 23%; top: 66%; --obrot: -30deg; animation-delay: 0.89s; }
    .logowanie-tropy span:nth-child(4) { left: 33%; top: 55%; --obrot: -22deg; animation-delay: 1.21s; }
    .logowanie-tropy span:nth-child(5) { left: 68%; top: 40%; --obrot: -30deg; animation-delay: 1.53s; }
    .logowanie-tropy span:nth-child(6) { left: 79%; top: 29%; --obrot: -22deg; animation-delay: 1.85s; }
    .logowanie-tropy span:nth-child(7) { left: 90%; top: 17%; --obrot: -30deg; animation-delay: 2.17s; }
    @keyframes toz-trop { 0% { opacity: 0; } 25% { opacity: .38; } 70% { opacity: .3; } 100% { opacity: 0; } }
}
@media (prefers-reduced-motion: no-preference) and (max-width: 760px) {
    .logowanie-tropy span:nth-child(n+4) { display: none; }
}
@media print { .logowanie-tropy { display: none; } }

/* p. 27 - pasek "Brak internetu" (ruchome.js): u góry w miejscu belki, nad nią - nie na polach formularza ani pasku
   zapisu; po powrocie sieci zielony "Połączenie wróciło ✓" na 2,5 s. Wsuwa się tylko w bloku ruchu. */
.brak-sieci {
    position: fixed; left: 0; right: 0; top: 0; z-index: 46; padding: 12px 16px; text-align: center; font-weight: 600;
    background: #fff4dc; color: #6b4c0c; border-bottom: 1px solid #e7cf94; box-shadow: 0 6px 18px rgba(44, 67, 129, .14);
}
.brak-sieci[hidden] { display: none; }
.brak-sieci-wrocila { background: var(--toz-tlo-ok); color: var(--toz-ok); border-bottom-color: #b6ddc8; }
@media (prefers-reduced-motion: no-preference) {
    .brak-sieci { animation: toz-brak-sieci .25s ease-out; }
    @keyframes toz-brak-sieci { from { transform: translateY(-100%); } }
}
@media print { .brak-sieci { display: none; } }

/* p. 28 - "Weź z GPS": okrąg dokładności wokół pinezki (mapa-punktu.js, promień = dokładność w skali mapy, opis "±25 m"
   pod pinezką), bez klikania; kurczy się płynnie przy dokładniejszych odczytach, a pinezka przy pierwszym odczycie ląduje
   z lekkim odbiciem - ruch tylko w bloku ruchu. */
.mapa-dokladnosc {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
    background: rgba(58, 87, 162, .13); border: 1.5px solid rgba(58, 87, 162, .55); box-sizing: border-box;
}
.mapa-dokladnosc[hidden] { display: none; }
.mapa-dokladnosc span {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, 8px); padding: 1px 6px; border-radius: 6px;
    background: #fff; color: var(--toz-granat-ciemny); font-size: .75rem; font-weight: 600; white-space: nowrap;
}
@media (prefers-reduced-motion: no-preference) {
    .mapa-dokladnosc { transition: width .4s ease-out, height .4s ease-out; }
    .mapa-pin.mapa-pin-laduje { animation: toz-pin-laduje .45s cubic-bezier(.3, 1.6, .5, 1); }
    @keyframes toz-pin-laduje { from { transform: translateY(-16px); } }
}

/* p. 29 - kropka niezapisanych zmian przy przycisku zapisu na pasku (pilnuj-zmian.js): złota kropka i napis "Masz
   niezapisane zmiany" (na telefonie sama kropka, napis zostaje dla czytnika); jedno pulsowanie przy zapaleniu. */
.niezapisane { display: inline-flex; align-items: center; gap: 6px; font-size: .85rem; color: var(--toz-granat-ciemny); }
.niezapisane-kropka { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--toz-zloto); }
@media (max-width: 760px) {
    .niezapisane-napis { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (prefers-reduced-motion: no-preference) {
    .niezapisane-kropka { animation: toz-niezapisane .8s ease-out; }
    @keyframes toz-niezapisane {
        from { box-shadow: 0 0 0 0 rgba(215, 181, 109, .7); }
        to   { box-shadow: 0 0 0 8px rgba(215, 181, 109, 0); }
    }
}
@media print { .niezapisane { display: none; } }

/* p. 30 - pole, które uzupełnił albo poprawił skrypt (adres z podpowiedzi, wielkie litery, data z wpływu, status z dat,
   kwota ze stawki), krótko rozbłyskuje tłem w barwie marki (TOZ.rozblysk w ruchome.js). Tylko w bloku ruchu. */
@media (prefers-reduced-motion: no-preference) {
    .pole-poprawione { animation: toz-pole-poprawione .7s ease-out; }
    @keyframes toz-pole-poprawione { from { background-color: rgba(215, 181, 109, .45); } }
}

/* p. 31 - widoczne skróty klawiszowe (ulatwienia.js): po "/" pole szukania raz rozbłyskuje obwódką, po Ctrl+S przycisk
   zapisu na moment "wciska się" (klik idzie od razu). Tylko w bloku ruchu. */
@media (prefers-reduced-motion: no-preference) {
    .skrot-szukaj { animation: toz-skrot-szukaj .5s ease-out; }
    .skrot-wcisniety { animation: toz-skrot-wcisniety .22s ease-out; }
    @keyframes toz-skrot-szukaj { from { box-shadow: 0 0 0 4px rgba(215, 181, 109, .75); } }
    @keyframes toz-skrot-wcisniety { 40% { transform: scale(.95); filter: brightness(.9); } }
}

/* p. 32 - wpis historii z zapisu tej osoby sprzed chwili raz rozbłyskuje (_historia.php, App\Historia\SwiezyWpis):
   złota kreska z lewej i jasne tło komórek, jak powrót do wiersza na liście; tr i td bez przesunięć. */
.table tbody tr.wpis-swiezy > td:first-child { box-shadow: inset 4px 0 0 var(--toz-zloto); }
@media (prefers-reduced-motion: no-preference) {
    .table tbody tr.wpis-swiezy > td { animation: toz-wiersz-ostatni 2.4s ease-out .2s; }
}

/* p. 33 - przy przejściu do innej zakładki pism złota kreska otwartej zakładki przesuwa się z poprzedniej pod nową
   (przejście między stronami: wspólny element "zakladka-znak"; przeglądarka bez przejść - jak dotąd). Belki menu nie
   dotyczy. */
@media (prefers-reduced-motion: no-preference) {
    .zakladka-znak { view-transition-name: zakladka-znak; }
    ::view-transition-group(zakladka-znak) { animation-duration: .3s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
}

/* p. 35 - oś czasu u góry karty interwencji i podopiecznego (ruchome.js, [data-os-czasu]): linia z kropkami w miejscu
   dat, opis po najechaniu albo fokusie, kliknięcie przewija do pola. Rysuje się raz od lewej (tylko w bloku ruchu);
   na telefonie jej nie ma. */
.os-czasu { position: relative; margin: 0 0 18px; padding: 0 12px; height: 46px; }
.os-czasu[hidden] { display: none; }
.os-czasu-linia { position: absolute; left: 12px; right: 12px; top: 22px; height: 2px; border-radius: 2px; background: var(--toz-granat-jasny); }
.os-czasu-punkty { position: absolute; left: 12px; right: 12px; top: 0; height: 46px; margin: 0; padding: 0; list-style: none; }
.os-czasu-punkty li { position: absolute; top: 14px; }
.os-kropka {
    position: relative; display: block; width: 18px; height: 18px; margin-left: -9px; padding: 0; border: 3px solid #fff;
    border-radius: 50%; background: var(--toz-granat); box-shadow: 0 0 0 1px var(--toz-granat-jasny); cursor: pointer;
}
span.os-kropka { cursor: default; }
.os-kropka.os-dzis { background: var(--toz-zloto); }
.os-opis {
    display: none; position: absolute; left: 50%; bottom: calc(100% + 6px); transform: translateX(-50%); z-index: 6;
    padding: 3px 8px; border-radius: 6px; background: var(--toz-granat-ciemny); color: #fff; font-size: .78rem; font-weight: 600;
    white-space: nowrap; pointer-events: none;
}
.os-kropka:hover .os-opis, .os-kropka:focus-visible .os-opis { display: block; }
.os-czasu-punkty li:first-child .os-opis { left: 0; transform: none; }
.os-czasu-punkty li:last-child .os-opis { left: auto; right: 0; transform: none; }
@media (prefers-reduced-motion: no-preference) {
    .os-czasu-pierwszy .os-czasu-linia { transform-origin: 0 50%; animation: toz-os-linia .6s ease-out; }
    .os-czasu-pierwszy .os-czasu-punkty li { animation: toz-zjaw .25s ease-out backwards; animation-delay: var(--opoznienie, 0s); }
    @keyframes toz-os-linia { from { transform: scaleX(0); } }
}
@media print { .os-czasu { display: none; } }

/* p. 36 - spis sekcji długiej karty (ruchome.js): od 1440 px karta z data-spis-sekcji zostawia z prawej wolny pas
   (od pierwszego rysowania - bez skoku po skrypcie), a w nim stoi przyklejony spis nazw sekcji; sekcja na ekranie
   podświetlona. Węższy ekran, telefon, tablet i wydruk - bez spisu i bez pasa. */
.spis-sekcji { display: none; }
@media screen and (min-width: 1440px) {
    .main:has([data-spis-sekcji]:not([data-spis-sekcji="warunkowo"])):not(.bez-spisu-sekcji),
    .main.z-spisem-sekcji { padding-right: calc(var(--toz-margines) + 220px); }
    .spis-sekcji {
        display: block; position: fixed; top: 92px; right: var(--toz-margines); width: 200px; z-index: 4;
        max-height: calc(100vh - 120px); overflow-y: auto; font-size: .85rem;
        /* Własne tło - ozdoby tła strony (łapki) nie prześwitują pod napisami (17.10.2026). */
        padding: 8px 6px 8px 0; background: var(--toz-plyta); border-radius: var(--toz-promien); box-shadow: var(--toz-cien);
    }
    .spis-sekcji[hidden] { display: none; }
    .spis-sekcji ol { margin: 0; padding: 0; list-style: none; border-left: 2px solid var(--toz-border); }
    .spis-sekcji button {
        display: block; width: 100%; padding: 5px 0 5px 12px; margin: 0 0 0 -2px; border: 0; border-left: 2px solid transparent;
        background: none; color: var(--toz-muted); font: inherit; text-align: left; cursor: pointer;
    }
    .spis-sekcji button:hover { color: var(--toz-granat-ciemny); }
    .spis-sekcji button.spis-biezaca { color: var(--toz-granat-ciemny); font-weight: 600; border-left-color: var(--toz-zloto); }
}
@media (prefers-reduced-motion: no-preference) {
    .spis-sekcji button { transition: color .2s ease, border-color .2s ease; }
}
@media print { .spis-sekcji { display: none !important; } .main:has([data-spis-sekcji]) { padding-right: 0; } }

/* p. 37 - podgląd stanu przed zapisem (ruchome.js): przy tytule karty interwencji plakietka „Stan u nas” w kolorach
   istniejących klas stanów; po wyborze innego stanu zmienia się płynnie (tylko w bloku ruchu) i dostaje „po zapisie”. */
.stan-naglowek { margin: 4px 0 0; color: var(--toz-muted); }
.stan-po-zapisie[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
    [data-stan-podglad] { transition: background-color .3s ease, border-color .3s ease, color .3s ease; }
}

/* p. 38 - liczba ustawionych ukrytych filtrów jako plakietka na zwiniętym przycisku „Więcej filtrów” (telefon;
   na-telefonie.js); po zmianie liczby raz podskakuje (tylko w bloku ruchu). Zero - bez plakietki. */
.filtry-liczba {
    display: inline-block; min-width: 1.4em; padding: 0 6px; border-radius: 999px; background: var(--toz-granat);
    color: #fff; font-size: .78rem; font-weight: 700; line-height: 1.5; text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
    .filtry-liczba-zmiana { animation: toz-licznik-skok .32s ease-out; }
}

/* p. 39 - po zmianie kierunku sortowania tej samej kolumny strzałka na nowej stronie obraca się o 180° z poprzedniego
   kierunku (ulatwienia.js: klasa .sort-obrot z pamięci karty). Tylko w bloku ruchu. */
@media (prefers-reduced-motion: no-preference) {
    .sort-znak.sort-obrot { display: inline-block; animation: toz-sort-obrot .35s ease-out; }
    @keyframes toz-sort-obrot { from { transform: rotate(180deg); } }
}


/* p. 41 - „Przygotowuję dokument…” (ruchome.js): przycisk albo odnośnik, który składa dokument na serwerze, na czas
   składania dostaje napis i cienką złotą kreskę u dołu (bez procentów); gdy plik pójdzie - na 2 s „✓ Gotowe”. Kreska
   stoi w obrysie przycisku, nic nie zasłania. Światło po kresce tylko w bloku ruchu. */
.przygotowuje { position: relative; cursor: progress; }
.przygotowuje::after {
    content: ''; position: absolute; left: 6px; right: 6px; bottom: 2px; height: 2px; border-radius: 2px; pointer-events: none;
    background-color: var(--toz-zloto);
    background-image: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .9) 50%, rgba(255, 255, 255, 0));
    background-repeat: no-repeat; background-size: 30% 100%; background-position: -45% 0;
}
.przygotowane:not(.btn) { color: var(--toz-ok); }
@media (prefers-reduced-motion: no-preference) {
    .przygotowuje::after { animation: toz-postep 1.05s linear infinite; }
}
@media print { .przygotowuje::after { display: none; } }

/* p. 42 - plakietki „Nowość” przy nowych funkcjach (App\Nowosci, ruchome.js): mała plakietka w granacie marki przy
   elemencie; opis w podpowiedzi od razu. Raz przy wejściu na stronę przebiega po niej delikatny połysk (tylko w bloku
   ruchu); w pasku menu sama plakietka, bez ruchu. Znika po pierwszym kliknięciu - nigdy z upływem czasu. */
.nowosc {
    display: inline-block; margin: 0 0 0 .45em; padding: 0 .55em; border: 0; border-radius: 999px;
    background-color: var(--toz-granat); color: #fff; font: inherit; font-size: .72rem; font-weight: 700; line-height: 1.6;
    letter-spacing: .02em; vertical-align: .12em; white-space: nowrap; cursor: pointer;
    background-image: linear-gradient(100deg, rgba(255, 255, 255, 0) 35%, rgba(255, 255, 255, .55) 50%, rgba(255, 255, 255, 0) 65%);
    background-repeat: no-repeat; background-size: 250% 100%; background-position: 150% 0;
}
.nowosc[hidden] { display: none; }
.nowosc-grupa { cursor: inherit; }
button.nowosc:focus-visible { outline: 2px solid var(--toz-zloto); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
    .nowosc { animation: toz-nowosc-polysk 1.4s ease-in-out .6s backwards; }
    .nav .nowosc { animation: none; }
    @keyframes toz-nowosc-polysk { from { background-position: -150% 0; } to { background-position: 150% 0; } }
}
@media print { .nowosc { display: none !important; } }

/* --- Wykresy zbiórek, postów i Zarządu (właściciel, 27.10.2026: „działaj” - wykresy nr 6, 8, 10, 11, 13, 35, 36) -----
   Miesiąc z niepełną sumą (zbiórki miesiąc po miesiącu) - słupek jaśniejszy, w chmurce „*”, jak w tabeli obok. Na karcie
   zbiórki przerywana granatowa kreska celu z podpisem; przerywanie stoi w atrybucie rysunku, bo kreskę przerywaną
   w arkuszu ma tylko pióro rysujące linię (wykresy nr 2). Dni postów z linkiem do zbiórki - granatowe kropki na osi.
   Barwy marki ze zmiennych - ciemny wygląd z generatora. */
.wykres-niepelny { fill-opacity: .5; }
.wykres-cel { stroke: var(--toz-granat); stroke-width: 1.5; }
.wykres-cel-podpis { fill: var(--toz-granat); font-weight: 600; }
.wykres-znacznik { fill: var(--toz-granat); stroke: var(--toz-plyta); stroke-width: 1.5; }
.wykres-znak.wykres-znak-znacznik { width: 10px; height: 10px; border-radius: 50%; }

/* --- Wykresy rok po roku i ten rok na tle zeszłego (właściciel, 27.10.2026: „działaj” - wykresy nr 7, 9, 37) ---------
   Części zapłaconych faktur (z 1,5%, z dotacji, z innych środków) zostają płaskie jak słupki składane - spadek barwy
   zatarłby granice części. Zeszły rok stoi w tle: cienka, przerywana, przygaszona granatowa linia (kreski w jednostkach
   długości pióra 1 - linia ma zawsze cały rok, więc kreska ok. 7 px), ten rok grubą złotą; w legendzie te same znaki.
   Punkt "więcej niż w całym zeszłym roku" większy, z białą obwódką; nad ostatnim punktem tego roku podpis "dziś" - czeka
   razem z linią i zapala się, gdy pióro dojdzie do bieżącego miesiąca. Linia w tle nie rysuje się piórem (kreski
   pióra zgubiłyby przerywanie) - pojaśnia raz. */
.wykres-slupki .wykres-czesc.wykres-seria-2:not([fill]) { fill: var(--toz-zloto); }
.wykres-linia.wykres-linia-tlo { stroke-width: 2; stroke-dasharray: .012 .01; opacity: .6; }
.wykres-punkt.wykres-linia-tlo { opacity: .6; }
.wykres-linia.wykres-linia-gruba { stroke-width: 4.5; }
.wykres-znak.wykres-znak-linia.wykres-linia-tlo { height: 2px; background: repeating-linear-gradient(90deg, var(--toz-granat) 0 4px, transparent 4px 7px); opacity: .6; }
.wykres-znak.wykres-znak-linia.wykres-linia-gruba { height: 5px; }
.wykres-punkt-wyrozniony { stroke-width: 2; }
.wykres-dzis { font-size: .9em; font-weight: 600; fill: var(--toz-granat-ciemny); }
@media screen and (prefers-reduced-motion: no-preference) {
    .wykres-czeka .wykres-dzis { opacity: 0; }
}
@media (prefers-reduced-motion: no-preference) {
    .wykres-rosnie .wykres-linia-tlo { animation: toz-zjaw .8s ease-out backwards; }
    .wykres-rosnie .wykres-dzis { animation: toz-zjaw .25s ease-out .8s backwards; }
}

/* --- Grafika przy pracy (właściciel, 27.10.2026: „działaj” - pięć drobnych rzeczy z listy grafiki) -------------------
   Ikony w wierszach robią swój gest, zdjęcia wyłaniają się z mgiełki, za oknem pytania stoi granatowa matowa szyba,
   miejsce pisania świeci, a przełączniki zalewają się kolorem. Zasady „Efektów wizualnych” jak wszędzie (pilnuje ich
   unit-efekty): ruch tylko w bloku prefers-reduced-motion, raz na wejście albo po działaniu człowieka, nic nad treścią
   i nic w kółko; barwy tylko granat i złoto marki, czerwień tylko przy usuwaniu. Tryb ciemny z ciemny-arkusz.py. */

/* Ikony czynności w wierszach robią pod myszą jeden krótki gest, zgodny z tym, co przycisk zrobi (grafika nr 4): oko
   mruga, ołówek dwa razy przechyla się jak przy kreśleniu, kosz chwieje się na boki (gest to sam obrót - kosz zostaje
   czerwony), „Skopiuj” lekko się odbija, ptaszek „Zrobione” dorysowuje się od lewej (ikona to maska, więc przycięciem
   clip-path, a nie rysowaniem linii), strzałka „Przywróć” obraca się raz dookoła, pinezka „Odepnij” podskakuje. Rusza
   się sam rysunek (.ikona), nigdy przycisk - jak godło w belce (.brand:hover img), więc nic pod kursorem nie ucieka.
   Raz przy wejściu kursora (i przy fokusie z klawiatury), bez powtarzania w kółko; wyłączony przycisk stoi. Tylko tam,
   gdzie jest mysz (hover: hover) - na telefonie palec nie ma „najechania”. */
@media (prefers-reduced-motion: no-preference) {
    @media (hover: hover) {
        .btn-ikona:not(:disabled):hover .ikona-otworz, .btn-ikona:focus-visible .ikona-otworz { animation: toz-ikona-oko .45s ease-in-out; }
        .btn-ikona:not(:disabled):hover .ikona-edytuj, .btn-ikona:focus-visible .ikona-edytuj {
            transform-origin: 18% 82%; animation: toz-ikona-olowek .6s ease-in-out;
        }
        .btn-ikona:not(:disabled):hover .ikona-usun, .btn-ikona:focus-visible .ikona-usun {
            transform-origin: 50% 90%; animation: toz-ikona-kosz .55s ease-in-out;
        }
        .btn-ikona:not(:disabled):hover .ikona-kopiuj, .btn-ikona:focus-visible .ikona-kopiuj { animation: toz-ikona-kopiuj .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-zrobione, .btn-ikona:focus-visible .ikona-zrobione { animation: toz-ikona-ptaszek .4s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-przywroc, .btn-ikona:focus-visible .ikona-przywroc { animation: toz-ikona-przywroc .6s ease-in-out; }
        .btn-ikona:not(:disabled):hover .ikona-odepnij, .btn-ikona:focus-visible .ikona-odepnij { animation: toz-ikona-pinezka .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-przypnij, .btn-ikona:focus-visible .ikona-przypnij { animation: toz-ikona-pinezka .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-przeslij, .btn-ikona:focus-visible .ikona-przeslij { animation: toz-ikona-przeslij .5s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-odpowiedz, .btn-ikona:focus-visible .ikona-odpowiedz { animation: toz-ikona-odpowiedz .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-przekaz, .btn-ikona:focus-visible .ikona-przekaz { animation: toz-ikona-przekaz .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-gwiazdka, .btn-ikona:focus-visible .ikona-gwiazdka { animation: toz-ikona-gwiazdka .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-gwiazdka-pelna, .btn-ikona:focus-visible .ikona-gwiazdka-pelna { animation: toz-ikona-gwiazdka .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-dokosza, .btn-ikona:focus-visible .ikona-dokosza { animation: toz-ikona-kopiuj .45s ease-out; }
        .btn-ikona:not(:disabled):hover .ikona-spam, .btn-ikona:focus-visible .ikona-spam { animation: toz-ikona-gwiazdka .45s ease-out; }
    }
    @keyframes toz-ikona-oko { 30% { transform: scaleY(1); } 45% { transform: scaleY(.1); } 62% { transform: scaleY(1); } }
    @keyframes toz-ikona-olowek { 20%, 60% { transform: rotate(-15deg); } 40%, 80% { transform: rotate(3deg); } }
    @keyframes toz-ikona-kosz { 18% { transform: rotate(-12deg); } 42% { transform: rotate(10deg); } 66% { transform: rotate(-6deg); } 86% { transform: rotate(3deg); } }
    @keyframes toz-ikona-kopiuj { 35% { transform: translateY(-3px); } 60% { transform: translateY(0); } 78% { transform: translateY(-1px); } }
    @keyframes toz-ikona-ptaszek { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
    @keyframes toz-ikona-przywroc { to { transform: rotate(-360deg); } }
    @keyframes toz-ikona-odpowiedz { 45% { transform: translateX(-3px); } 70% { transform: translateX(0); } }
    @keyframes toz-ikona-gwiazdka { 45% { transform: scale(1.25) rotate(12deg); } 75% { transform: scale(1) rotate(0); } }
    @keyframes toz-ikona-przekaz { 45% { transform: translateX(3px); } 70% { transform: translateX(0); } }
    @keyframes toz-ikona-przeslij { 45% { transform: translate(3px, -3px); } 70% { transform: translate(0, 0); } }
    @keyframes toz-ikona-pinezka { 30% { transform: translateY(-4px); } 55% { transform: translateY(0); } 72% { transform: translateY(-1.5px); } }
}

/* Zdjęcia wyłaniają się z mgiełki (grafika nr 12; zdjecia-mgielka.js, wczytywany tylko na stronach z obrazkami
   wczytywanymi leniwie). Obrazek, który w chwili wczytania strony jeszcze nie doszedł, czeka z rysunkiem przesuniętym
   poza ramkę - tło i ramka obrazka zostają, a przeglądarka nie pokazuje zdjęcia kawałkami. Po dojściu w ok. 0,3 s
   przechodzi z lekkiego rozmycia do ostrości; miniatury 40 px przy imionach tylko się pojaśniają (rozmycie na takim
   kwadraciku nic nie daje). Połysk w miejscu zdjęcia (jasny granat, jak szare paski z p. 5) tylko wtedy, gdy zdjęcie
   stoi na ekranie i wczytuje się dłużej niż 0,3 s; gaśnie z dojściem albo błędem, a w galerii pod spodem dalej leży
   złota łapa. Zdjęcia, które przeglądarka już ma, skrypt pomija - stoją od razu. Animuje się sam obrazek, nigdy
   komórka ani wiersz. Galeria do adopcji wchodzi krótką falą jak wiersze list: pierwsze kafelki po kolei, reszta
   razem z ostatnim z fali, całość do 0,45 s; sama przezroczystość. */
@media (prefers-reduced-motion: no-preference) {
    img.zdjecie-czeka { object-position: -9999px -9999px; }
    img.zdjecie-polysk {
        background-image: linear-gradient(100deg, rgba(147, 169, 230, 0) 25%, rgba(147, 169, 230, .38) 50%, rgba(147, 169, 230, 0) 75%);
        background-size: 220% 100%; background-repeat: no-repeat;
        animation: toz-szkielet 1.3s ease-in-out infinite;
    }
    img.zdjecie-wylania { animation: toz-zdjecie-wylania .3s ease-out; }
    img.miniatura-podopiecznego.zdjecie-wylania { animation-name: toz-zdjecie-pojasnia; }
    @keyframes toz-zdjecie-wylania { from { opacity: .25; filter: blur(4px); } }
    @keyframes toz-zdjecie-pojasnia { from { opacity: .25; } }

    .galeria-adopcji > li:nth-child(1) { animation: toz-zjaw .2s ease-out backwards; }
    .galeria-adopcji > li:nth-child(2) { animation: toz-zjaw .2s ease-out .016s backwards; }
    .galeria-adopcji > li:nth-child(3) { animation: toz-zjaw .2s ease-out .032s backwards; }
    .galeria-adopcji > li:nth-child(4) { animation: toz-zjaw .2s ease-out .048s backwards; }
    .galeria-adopcji > li:nth-child(5) { animation: toz-zjaw .2s ease-out .064s backwards; }
    .galeria-adopcji > li:nth-child(6) { animation: toz-zjaw .2s ease-out .08s backwards; }
    .galeria-adopcji > li:nth-child(7) { animation: toz-zjaw .2s ease-out .096s backwards; }
    .galeria-adopcji > li:nth-child(8) { animation: toz-zjaw .2s ease-out .112s backwards; }
    .galeria-adopcji > li:nth-child(9) { animation: toz-zjaw .2s ease-out .128s backwards; }
    .galeria-adopcji > li:nth-child(10) { animation: toz-zjaw .2s ease-out .144s backwards; }
    .galeria-adopcji > li:nth-child(11) { animation: toz-zjaw .2s ease-out .16s backwards; }
    .galeria-adopcji > li:nth-child(12) { animation: toz-zjaw .2s ease-out .176s backwards; }
    .galeria-adopcji > li:nth-child(13) { animation: toz-zjaw .2s ease-out .192s backwards; }
    .galeria-adopcji > li:nth-child(14) { animation: toz-zjaw .2s ease-out .208s backwards; }
    .galeria-adopcji > li:nth-child(15) { animation: toz-zjaw .2s ease-out .224s backwards; }
    .galeria-adopcji > li:nth-child(n+16) { animation: toz-zjaw .2s ease-out .24s backwards; }
}

/* Granatowa matowa szyba za oknem pytania i podglądem (grafika nr 14; kolory szyby i sceny podglądu - w sekcjach
   okna pytania i podglądu). Okno pytania dostaje u góry tę samą kreskę marki co karty (granat w złoto), a przy pytaniu
   o usunięcie (opcja „groźna” w pytanie.js - przycisk btn-danger) czerwoną, jak karta pytania przed usunięciem. Strona
   za oknem lekko się rozmywa tylko poza telefonem: na telefonie podgląd zajmuje cały ekran, a okno pytania ma sam
   granatowy odcień. Przeglądarka bez rozmycia pokazuje sam odcień; szyba pojawia się płynnie jak dawne przyciemnienie
   (toz-zjaw na ::backdrop w sekcji „Ruch”). */
.okno-pytania {
    background-image: linear-gradient(90deg, var(--toz-granat), #6f86c9 45%, var(--toz-zloto));
    background-size: 100% 4px; background-repeat: no-repeat; background-position: 0 0;
}
.okno-pytania:has(.btn-danger) { background-image: linear-gradient(90deg, var(--toz-blad), #d4707b 55%, rgba(212, 112, 123, .4)); }
@media (min-width: 641px) {
    .okno-pytania::backdrop, .podglad::backdrop { -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
}

/* Miejsce pisania świeci (z rezerwy listy grafiki 27.10.2026). Kursor tekstowy w polach w granacie marki (w ciemnym
   wyglądzie złoty - poprawka ręczna w ciemny.css), a poświata obramowania rozchodzi się łagodnie (z wnętrza ramki na
   zewnątrz, z przezroczystości) - na telefonie tylko to. Poza telefonem etykieta pola, w którym się pisze, ciemnieje
   do granatu, pod polem rysuje się od lewej cienka kreska z granatu w złoto - raz na wejście w pole (przejście tylko
   przy wejściu; przy wyjściu kreska znika od razu) - i zapala się na złoto znak przy tytule części formularza, w której
   się pisze.
   Kreska to warstwa tła samego pola (bez nowych elementów i bez przesunięcia układu), więc tylko pola do pisania -
   lista wyboru ma w tej warstwie swoją strzałkę. Pole tylko do odczytu ma własne tło (bez kreski). Kreska przez
   przejście, a nie animację: pole z błędem drga po odrzuconym zapisie (toz-drgnienie) i kursor staje w nim od razu -
   animacja przy wejściu zabrałaby mu to drgnięcie. Pionowej złotej krawędzi na całą wysokość części nie ma: pola stoją
   w części tuż przy jej lewym brzegu, więc kreska albo dotykałaby pól, albo wymagała przesunięcia części. */
.form-control { caret-color: var(--toz-granat); }
@media (min-width: 641px) {
    .pole:focus-within > .label { color: var(--toz-granat-ciemny); }
    .form-control:where(input:not([type="file"]):not([type="checkbox"]):not([type="radio"]), textarea) {
        background-image: linear-gradient(90deg, var(--toz-granat), var(--toz-zloto));
        background-repeat: no-repeat; background-position: 0 100%; background-size: 0% 2px;
    }
    .form-control:where(input:not([type="file"]):not([type="checkbox"]):not([type="radio"]), textarea):focus { background-size: 100% 2px; }
    .sekcja:focus-within > legend::before {
        background: var(--toz-zloto); box-shadow: 0 0 0 2px rgba(215, 181, 109, .22), 0 0 9px rgba(215, 181, 109, .75);
    }
}
@media (prefers-reduced-motion: no-preference) {
    .pole > .label { transition: color .2s ease-out; }
    .sekcja > legend::before { transition: box-shadow .25s ease-out; }
    .form-control:where(input:not([type="file"]):not([type="checkbox"]):not([type="radio"]), textarea) { outline-color: transparent; outline-offset: -3px; }
    .form-control:where(input:not([type="file"]):not([type="checkbox"]):not([type="radio"]), textarea):focus {
        transition: background-color .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease,
            background-size .3s cubic-bezier(.2, .8, .2, 1), outline-color .25s ease-out, outline-offset .25s ease-out;
    }
}

/* Przełączniki zalewają się kolorem (z rezerwy listy grafiki 27.10.2026) - tylko po kliknięciu: efekty.js dokłada polu
   klasę „klikniete” dopiero przy zmianie ręką (także klawiszem), więc przy wczytaniu strony z przełącznikiem
   ustawionym wcześniej nic się nie rusza. Pigułka (.przelacznik): jasny granat zaznaczenia rozlewa się z kwadracika
   na całą pigułkę (0,25 s), po odznaczeniu zbiega z powrotem - warstwa pod napisem (::before) przycięta rosnącym kołem.
   Przełącznik ostrzegawczy (czerwony) bez zalewania. Przełącznik dwustronny (.przelacznik-tak-nie: „Część faktury”,
   „Przypnij”, „Dodać czy odjąć?”, tak/nie w raporcie): granatowa połówka przechodzi pod drugą etykietę - stara gaśnie
   ku wspólnej krawędzi, a nowa w tym samym tempie rośnie od niej, więc granat płynie jak jeden suwak, bez mierzenia
   połówek skryptem. Stara gaśnie tylko wtedy, gdy była wybrana: kliknięta wcześniej albo wybrana od wczytania
   (:default) - przy pierwszym wyborze bez ustawienia na start („Dodać czy odjąć?”) granat tylko wpływa w wybraną. */
@media (prefers-reduced-motion: no-preference) {
    .przelacznik:not(.przelacznik-ostrzegawczy):has(input.klikniete) { position: relative; isolation: isolate; }
    .przelacznik:not(.przelacznik-ostrzegawczy):has(input.klikniete)::before {
        content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
        background: linear-gradient(180deg, #f4f6fd, #e3e9f7);
        clip-path: circle(0 at 17px 50%);
    }
    .przelacznik:not(.przelacznik-ostrzegawczy):has(input.klikniete:checked) { background: #fff; }
    .przelacznik:not(.przelacznik-ostrzegawczy):has(input.klikniete:checked)::before {
        clip-path: circle(150% at 17px 50%); animation: toz-przelacznik-zalew .25s ease-out;
    }
    .przelacznik:not(.przelacznik-ostrzegawczy):has(input.klikniete:not(:checked))::before { animation: toz-przelacznik-zbieg .2s ease-in; }
    @keyframes toz-przelacznik-zalew { from { clip-path: circle(0 at 17px 50%); } }
    @keyframes toz-przelacznik-zbieg { from { clip-path: circle(150% at 17px 50%); } }

    .przelacznik-tak-nie:has(input.klikniete) label { transition: color .22s ease-out; }
    /* Kliknięta prawa połówka rośnie od lewej (wspólnej) krawędzi, lewa - jeśli była wybrana - gaśnie ku niej. */
    .przelacznik-tak-nie > label + input.klikniete:checked + label { animation: toz-polowka-od-lewej .22s ease-out; }
    .przelacznik-tak-nie:has(> label + input.klikniete:checked) > input.klikniete:first-child + label,
    .przelacznik-tak-nie:has(> label + input.klikniete:checked) > input:default:first-child + label { animation: toz-polowka-do-prawej .22s ease-out; }
    /* Kliknięta lewa - lustrzanie. */
    .przelacznik-tak-nie > input.klikniete:first-child:checked + label { animation: toz-polowka-od-prawej .22s ease-out; }
    .przelacznik-tak-nie:has(> input.klikniete:first-child:checked) > label + input.klikniete + label,
    .przelacznik-tak-nie:has(> input.klikniete:first-child:checked) > label + input:default + label { animation: toz-polowka-do-lewej .22s ease-out; }
    @keyframes toz-polowka-od-lewej {
        from { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 0 0 / 0% 100% no-repeat transparent; }
        to   { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 0 0 / 100% 100% no-repeat transparent; }
    }
    @keyframes toz-polowka-od-prawej {
        from { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 100% 0 / 0% 100% no-repeat transparent; }
        to   { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 100% 0 / 100% 100% no-repeat transparent; }
    }
    @keyframes toz-polowka-do-prawej {
        from { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 100% 0 / 100% 100% no-repeat transparent; }
        to   { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 100% 0 / 0% 100% no-repeat transparent; }
    }
    @keyframes toz-polowka-do-lewej {
        from { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 0 0 / 100% 100% no-repeat transparent; }
        to   { background: linear-gradient(var(--toz-granat), var(--toz-granat)) 0 0 / 0% 100% no-repeat transparent; }
    }
}

/* --- Kółko z inicjałami przy osobie -------------------------------------------
   Właściciel, 27.10.2026: "Kółko z inicjałami przy osobach. Przy „kto i kiedy” w historii zmian, w dzienniku zdarzeń
   i przy plikach stoi dziś samo nazwisko. Kółko z inicjałami w barwach systemu pozwala szybciej wyłapać, kto co zrobił."
   Znacznik rysuje osoba_z_kolkiem() / kolko_osoby() (helpers.php), litery i odcień liczy App\Auth\PodpisKonta::kolko() -
   ta sama osoba ma wszędzie te same litery i ten sam odcień. Litery stoją w atrybucie data-inicjaly i wypisuje je
   ::before: zaznaczone i skopiowane nazwisko nie łapie liter z kółka, a czytnik ekranu czyta samo nazwisko.
   Sześć odcieni wyłącznie z barw marki - granat i złoto, każde w trzech jasnościach (jasne jak w seriach wykresów; ciemne złoto #8c6d2c ciemniejsze od wykresowego #a8842f - dopiero ono daje białym literom 4,5:1), napis
   o kontraście co najmniej 4,8:1. Barwy idą przez własne zmienne kółka, więc arkusz ciemny (ciemny-arkusz.py) ich
   nie przelicza: granat i złoto zostają sobą, a ciemny napis nie jaśnieje na złotym tle. Kółko małe (ok. 20 px, na
   telefonie mniej) - wysokość linijki w tabeli zostaje, a nazwisko zawija się obok kółka, nie pod nim. */
.osoba-z-kolkiem { display: inline-flex; align-items: baseline; gap: .4em; max-width: 100%; }
.kolko-osoby {
    --kolko-tlo: var(--toz-granat);
    --kolko-napis: #fff;
    display: inline-flex; flex: none; align-self: flex-start; align-items: center; justify-content: center;
    width: 2em; height: 2em; vertical-align: middle;
    /* Przezroczysta ramka: w trybie wysokiego kontrastu przeglądarka ją rysuje i kółko zostaje kółkiem. */
    border: 1px solid transparent; border-radius: 999px;
    background: var(--kolko-tlo); color: var(--kolko-napis);
    box-shadow: inset 0 0 0 1px rgba(29, 45, 92, .12);
    font-size: .64rem; font-weight: 700; font-style: normal; line-height: 1; letter-spacing: 0;
}
.kolko-osoby::before { content: attr(data-inicjaly); white-space: nowrap; }
/* Kolejne konta dostają kolejne odcienie: barwa na przemian, jasność co dwa. */
.kolko-osoby-1 { --kolko-tlo: var(--toz-granat); --kolko-napis: #fff; }
.kolko-osoby-2 { --kolko-tlo: var(--toz-zloto); --kolko-napis: #1d2d5c; }
.kolko-osoby-3 { --kolko-tlo: var(--toz-granat-ciemny); --kolko-napis: var(--toz-zloto); }
.kolko-osoby-4 { --kolko-tlo: #e6d3a3; --kolko-napis: var(--toz-granat-ciemny); }
.kolko-osoby-5 { --kolko-tlo: #8fa3d6; --kolko-napis: #1d2d5c; }
.kolko-osoby-6 { --kolko-tlo: #8c6d2c; --kolko-napis: #fff; }
@media (max-width: 640px) {
    .kolko-osoby { font-size: .6rem; }
}
/* Na papierze tła się nie drukują - zostałyby same litery przed nazwiskiem. */
@media print {
    .kolko-osoby { display: none; }
}
/* Samo kółko w miejscu adresu (właściciel, 13.11.2026, dziennik zdarzeń: "nie pokazywać maila, tylko samo kółeczko
   z inicjałami, tylko to kółeczko musi być klikalne") - App\Auth\PodpisKonta::kolkoZPodpisem(). Opakowanie ma rozmiar
   kółka, więc obszar kliknięcia to całe kółko; podpis "Imię N." pokazuje od razu dymek (dymek.js) i czyta czytnik ekranu.
   Odnośnik do karty konta: ręka po najechaniu. Obrys przy fokusie okrągły i odsunięty poza złoty pierścień własnego
   kółka (3,5 px, efekt kolko-ja) - mieści się w odstępie komórki tabeli (8 px). Na dotyku pole kliknięcia odnośnika
   większe o 6 px z każdej strony, wygląd ten sam (cele dotykowe, C180). Na papierze zamiast kółka sam podpis. */
.kolko-z-podpisem { display: inline-flex; vertical-align: middle; border-radius: 999px; line-height: 1; text-decoration: none; }
a.kolko-z-podpisem, a.kolko-z-podpisem:hover { cursor: pointer; text-decoration: none; }
.kolko-z-podpisem:focus-visible { outline: 2px solid var(--toz-fokus); outline-offset: 5px; }
/* Kółko bez odnośnika na ekranie dotykowym: dotknięcie pokazuje dymek z "Imię N.", drugie go chowa (dymek.js; decyzja
   właściciela z 13.11.2026, pytanie 45) - dwa dotknięcia po sobie nie przybliżają przy tym strony. */
span.kolko-z-podpisem { touch-action: manipulation; }
@media print {
    .kolko-z-podpisem::after { content: attr(aria-label); }
}

/* --- Galeria do adopcji (właściciel, 27.10.2026: "Osobny widok obok listy, tylko w systemie: duże zdjęcia
   z imieniem, wiekiem i gatunkiem") - szablon podopieczni/galeria.php. Kafelek to jeden odnośnik do karty: kwadratowe
   zdjęcie przycięte do środka, pod nim imię, gatunek z wiekiem i (przy kilku oddziałach) oddział. Siatka sama dobiera
   liczbę kolumn - na komputerze kilka, na telefonie dwie, na bardzo wąskim ekranie jedna; kolumny mogą się zwęzić
   (minmax 0), a długie imię łamie się w środku, więc strona nie ucieka w bok. Pod zdjęciem leży łapa w złocie marki:
   widać ją, zanim zdjęcie dojdzie (loading="lazy"), gdy się nie wczyta i przy kafelku bez zdjęcia. Same zmienne barw
   i tła jak kafelki pulpitu (granat w złoto) - tryb ciemny bierze je z ciemny-arkusz.py. Pod kursorem kafelek stoi
   w miejscu (unit-efekty: nic pod kursorem nie ucieka) - zmienia się ramka, cień i lekko przybliża samo zdjęcie. */
.galeria-adopcji {
    list-style: none; margin: 0 0 20px; padding: 0;
    display: grid; gap: 18px;
    grid-template-columns: repeat(auto-fill, minmax(min(210px, 100%), 1fr));
}
.galeria-adopcji > li { display: flex; min-width: 0; }
.galeria-kafelek {
    display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0;
    border: 1px solid var(--toz-border); border-radius: var(--toz-promien); overflow: hidden;
    background: var(--toz-plyta); color: inherit; text-decoration: none;
    box-shadow: var(--toz-cien);
}
.galeria-kafelek:hover, .galeria-kafelek:focus-visible {
    border-color: var(--toz-fokus); text-decoration: none;
    box-shadow: 0 6px 20px rgba(44, 67, 129, .14);
}
.galeria-zdjecie {
    position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden;
    background: var(--toz-granat-jasny);
}
.galeria-zdjecie::before {
    content: ''; position: absolute; inset: 30%;
    background: var(--toz-zloto); opacity: .55;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cellipse cx='9.5' cy='20' rx='4.4' ry='6' transform='rotate(-22 9.5 20)'/%3E%3Cellipse cx='18.4' cy='11' rx='4.6' ry='6.6' transform='rotate(-8 18.4 11)'/%3E%3Cellipse cx='29.6' cy='11' rx='4.6' ry='6.6' transform='rotate(8 29.6 11)'/%3E%3Cellipse cx='38.5' cy='20' rx='4.4' ry='6' transform='rotate(22 38.5 20)'/%3E%3Cpath d='M24 22.5c-6.9 0-12.8 6.3-12.8 12.2 0 3.9 2.9 5.9 6.3 5.9 2.6 0 4.2-1.2 6.5-1.2s3.9 1.2 6.5 1.2c3.4 0 6.3-2 6.3-5.9 0-5.9-5.9-12.2-12.8-12.2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.galeria-zdjecie img { position: relative; display: block; width: 100%; height: 100%; object-fit: cover; }
.galeria-opis {
    display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0;
    padding: 10px 12px 12px; border-top: 1px solid var(--toz-border);
    background-image: linear-gradient(135deg, rgba(58, 87, 162, .05), rgba(215, 181, 109, .09));
}
.galeria-kafelek:hover .galeria-opis, .galeria-kafelek:focus-visible .galeria-opis { background-color: var(--toz-granat-jasny); }
.galeria-imie { font-size: 1.05rem; font-weight: 700; line-height: 1.25; color: var(--toz-granat-ciemny); overflow-wrap: anywhere; }
.galeria-imie.muted { font-weight: 400; color: var(--toz-muted); }
.galeria-cechy { font-size: .9rem; color: var(--toz-text); overflow-wrap: anywhere; }
.galeria-oddzial { font-size: .8rem; color: var(--toz-muted); overflow-wrap: anywhere; }
@media (max-width: 640px) {
    .galeria-adopcji { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .galeria-opis { padding: 8px 10px 10px; }
    .galeria-imie { font-size: .98rem; }
    .galeria-cechy { font-size: .85rem; }
}
@media (max-width: 340px) {
    .galeria-adopcji { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: no-preference) {
    .galeria-kafelek { transition: border-color .15s ease-out, box-shadow .15s ease-out; }
    .galeria-zdjecie img { transition: transform .3s ease-out; }
    .galeria-kafelek:hover .galeria-zdjecie img { transform: scale(1.04); }
}
@media print {
    .galeria-adopcji { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
    .galeria-kafelek { box-shadow: none; break-inside: avoid; }
    .galeria-zdjecie::before { display: none; }
}

/* Panel kosztów usługi AI w Ustawieniach (właściciel, 30.10.2026): nagłówek ze stanem połączenia, trzy kafelki, stopka z odnośnikami.
   Kafelek nie jest tu odnośnikiem, więc nie reaguje na najechanie. */
.koszty-ai-naglowek { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px; }
.koszty-ai-stan { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.koszty-ai-stan form { margin: 0; }
.kafelek-staly:hover { background: var(--toz-plyta) linear-gradient(135deg, rgba(58, 87, 162, .07), rgba(215, 181, 109, .11)); border-color: var(--toz-border); border-left-color: var(--toz-granat); }
.kafelek-staly .kafelek-opis { order: -1; margin-bottom: 6px; }
.koszty-ai-zakres { font-size: 1.25rem; line-height: 1.5; }
.koszty-ai-stopka { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--toz-border); }
.koszty-ai-stopka .hint { margin: 0; flex: 1 1 280px; }

/* Uprawnienia połączone na ekranach nadawania (właściciel, 30.10.2026): zdanie pod nazwą uprawnienia. */
.uprawnienie-polaczone { display: block; font-size: .8rem; color: var(--toz-muted); }
.uprawnienie-polaczone[hidden], [data-grupa="deny"] .uprawnienie-polaczone { display: none; }

/* --- Przegląd ekranów na telefonie 10.11.2026 (seria T) -------------------------------------------------------- */
/* Długie słowa bez spacji (powód pilności od AI, nazwy plików z maila, adresy e-mail urzędów, treść programu z PDF)
   łamią się w ramce, zamiast wychodzić za kartę (T2-01, T2-06, T2-07, T4-01, T4-02, T4-10). */
.poczekalnia-ai .stan { white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
.poczekalnia-pliki { min-width: 0; }
.poczekalnia-pliki .przelacznik { max-width: 100%; overflow-wrap: anywhere; }
.poczekalnia-pliki .przelacznik > span { min-width: 0; }
.poczekalnia-do-sprawy p, .okno-pytania-tekst { overflow-wrap: anywhere; }
.urzedy-wlasciwe, .program-wyciag, .program-tekst { overflow-wrap: anywhere; }
/* Podgląd stopki: tabela o stałej szerokości ze skopiowanego podpisu przewija się w ramce podglądu (T4-10). */
.stopka-podglad { overflow-x: auto; }
.stopka-podglad table { max-width: 100%; }
/* Opis przycisku w drugiej linijce - tylko na dotyku, gdzie dymka (title) nie ma: której pozycji z maila dotyczy
   "Przepisz pozycję", co pójdzie do usługi AI, dokąd przejdzie mail po "Wyślij i zakończ" (T2-02, T2-12). */
.przycisk-opis { display: none; }
@media (hover: none) and (pointer: coarse) {
    .btn:has(> .przycisk-opis) { flex-direction: column; white-space: normal; padding-top: 6px; padding-bottom: 6px; }
    .przycisk-opis { display: block; margin-top: 2px; font-size: .8125rem; font-weight: 400; line-height: 1.3; overflow-wrap: anywhere; }
}
/* Plakietka pod nazwą w wierszu - tylko przy skróconych kolumnach, gdy jej kolumna znika: "bez celu" w zbiórkach na telefonie
   i tablecie (T3-03), "brak programu" w urzędach na telefonie (T4-08). */
.pod-nazwa-tablet, .pod-nazwa-telefon { display: none; }
@media (max-width: 1024px) {
    .kolumny-skrocone:not(.kolumny-wszystkie) .pod-nazwa-tablet { display: block; width: fit-content; margin-top: 4px; }
}
@media (max-width: 640px) {
    .kolumny-skrocone:not(.kolumny-wszystkie) .pod-nazwa-telefon { display: block; width: fit-content; margin-top: 4px; }
}
/* Ramka "Nowa zbiórka bez celu" nad listą zwinięta na telefonie - przycisk "Wybierz cel" otwiera okno (T3-01). */
.wybor-celu-otworz { display: none; }
/* Pod palec: kolory flagi, liczba-odnośnik i sprawa w wierszu maila, drobne przyciski pisania, sterowanie mapą, pole
   strony faktury, wyniki szukania w oknie mapy; 16 px w polu stopki (T1-04, T1-05, T2-13, T2-14, T4-09, T4-11). */
@media (pointer: coarse) {
    .flagi-wybor { gap: 8px; }
    .flagi-wybor .btn-maly, .flaga-menu .btn-maly { min-height: 44px; }
    .flagi-wybor .btn.btn-ikona, .flaga-menu .btn.btn-ikona { width: 44px; min-width: 44px; }
    .flaga-menu:popover-open { grid-template-columns: repeat(5, 44px); gap: 8px; }
    .flaga-menu [data-dlugo-stan] { max-width: 252px; }
    .table a.licznik { padding-top: 5px; padding-bottom: 5px; margin-top: -4px; margin-bottom: -4px; }
    .table a.odnosnik-sprawy-wiersza { display: inline-block; padding: 6px 0; margin: -6px 0; }
    [data-odpowiedz-wstaw].btn-maly, [data-propozycja-przycisk].btn-maly, [data-odpowiedz-wszystkim].btn-maly,
    .odpowiedz-organizacje.btn-maly, .maile-podpis .btn-maly, .okno-organizacji-wybrane .btn-maly { min-height: 44px; }
    .maile-kopie > summary, .maile-nad-polem > summary { padding: 12px 0; }
    .mapa-wynik { min-height: 44px; }
    input[type="checkbox"][name="czesci[]"] { width: 22px; height: 22px; }
    .pole-caly-wiersz > .stopka-kod { font-size: 16px; }
    .mapa-sterowanie { gap: 6px; }
    .mapa-sterowanie .btn { min-width: 40px; min-height: 40px; }
    /* Dymek zostawia z prawej miejsce na dwie kolumny po 40 px (wyżej 32 px). */
    .mapa-zgloszen .mapa-dymek { width: min(320px, calc(100% - 124px)); }
}
@media (pointer: coarse) and (max-width: 480px) {
    /* Trzy rzędy po 40 px z odstępami kończą się ok. 140 px od góry mapy. */
    .mapa-zgloszen .mapa-dymek { width: auto; max-height: calc(100% - 42px - 152px); }
}
/* Tablet: nazwa zbiórki z miniaturą bez 12rem najmniejszej szerokości - na 768 px kolumny kwot zabierały resztę (T3-04). */
@media (min-width: 641px) and (max-width: 1024px) {
    .zbiorka-z-miniatura { min-width: 0; gap: 4px 8px; flex-wrap: wrap; }
}
@media (max-width: 640px) {
    .wybor-celu-zwiniety > :not(.card-head):not(.facts) { display: none; }
    .wybor-celu-zwiniety > .facts > div:not(:first-child) { display: none; }
    .wybor-celu-zwiniety .wybor-celu-otworz { display: inline-flex; margin-top: 8px; }
    /* Dane zbiórki w oknie wyboru celu w dwóch kolumnach - pierwszy wybór bliżej góry (T3-07). */
    .wybor-celu .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Pole Stan w liście celów węższe - nazwa pozycji ma więcej miejsca (T3-05). */
    select.form-control.wybor-stanu:not([multiple]):not([size]) { padding-left: 8px; padding-right: 24px; background-position: right 6px center; }
    /* Okno porównania: pola o stałej wysokości, przyciski przyklejone do dołu okna (T2-05). */
    .okno-porownania-pola textarea { height: 9rem; }
    .okno-porownania .okno-pytania-przyciski { position: sticky; bottom: 0; z-index: 1; margin: 0 -20px -20px; padding: 12px 20px;
        border-top: 1px solid var(--toz-border); background: var(--toz-plyta); }
    /* Wcięcie list z adresami i z wyciągiem programu - mniej niż domyślne 40 px (T4-01, T4-02). */
    .urzedy-wlasciwe, .program-wyciag { padding-left: 20px; }
    /* Objaśnienia pod przełącznikami zostają: Safari na iPhonie nie daje fokusu polu wyboru po dotknięciu, więc
       "objaśnienie dopiero w polu" nie pokazałoby ich nigdy (T4-04). */
    .pole:has(> .przelacznik, > .przelaczniki) > .hint[class="hint"]:not(:has(a, button)):not([aria-live]):not([role="status"]) { display: block; }
    /* Objaśnienia kolumn znikają razem z kolumnami, a po "pokaż wszystkie kolumny" wracają (T4-06). */
    .kolumny-skrocone:not(.kolumny-wszystkie) > .hint-kolumn { display: none; }
    /* Objaśnienie pod grupą pól (kod TERYT) - po wejściu w pole tej części (T4-13). */
    .sekcja:not(:focus-within) > .hint .opis-po-dotknieciu { display: none; }
    /* Tabele sum pod listą zbiórek przy jednym oddziale stoją pionowo: okres i kwota w jednej linijce (T3-09). */
    .tabela-zebrano-pionowo, .tabela-zebrano-pionowo tfoot, .tabela-zebrano-pionowo tbody { display: block; width: 100%; }
    .tabela-zebrano-pionowo thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .tabela-zebrano-pionowo tr { display: block; padding: 4px 0 8px; }
    .tabela-zebrano-pionowo td { display: flex; justify-content: flex-end; align-items: baseline; padding: 6px 0; min-width: 0 !important; }
    .tabela-zebrano-pionowo td:first-child { display: block; border-bottom: 2px solid var(--toz-border); }
    .tabela-zebrano-pionowo td[data-etykieta]::before { content: attr(data-etykieta); margin-right: auto; padding-right: 12px; font-weight: 400; white-space: normal; text-align: left; color: var(--toz-muted); }
}
