/* RadarAI - system wizualny: cztery jasne motywy nad jednym silnikiem.
 *
 * Spec: docs/superpowers/specs/2026-08-07-radar-motywy-design.md
 * (opisuje wersje z trzema osiami; osie zdjete 2026-08-09, patrz nizej)
 *
 * ============================================================================
 * ARCHITEKTURA W JEDNYM ZDANIU
 * ============================================================================
 * Reguly strukturalne (ponizej, sekcja SILNIK) NIE ZAWIERAJA ANI JEDNEJ
 * WARTOSCI BARWY - siegaja wylacznie po `var()`. Motyw podmienia zetony.
 * Dzieki temu cztery motywy kosztuja tyle, co jeden, a piaty bedzie kosztowal
 * tyle, co lista zmiennych. Pilnuje tego `test_reguly_nie_maja_wartosci_barw`.
 *
 * JEDNA os na <html>:
 *   data-motyw  sygnal | kartoteka | gesty | duzy   - caly wyglad w jednym slowie
 *
 * Do 2026-08-09 osie byly TRZY (motyw x akcent x jasny/ciemny), co dawalo 24
 * kombinacje. Nikt nie obejrzal ich wszystkich i dwie mialy niewidoczne liczby
 * na pulpicie. Teraz kazdy motyw ma jedna, gotowa postac - wybor jest z czterech
 * rzeczy przemyslanych, a nie z dwudziestu czterech policzonych.
 *
 * ============================================================================
 * BARWY SEMANTYCZNE NIE SA DO WYBORU
 * ============================================================================
 * Trzy role o stalym znaczeniu, w kazdym motywie i trybie:
 *
 *   --sem-brak     nie potwierdzilismy strony      (kolumna Strona, chip, plik)
 *   --sem-uwaga    ostrzezenie, slaby dowod, blad  (slaba nisza, przerwany przebieg)
 *   --sem-dobrze   potwierdzone, zrobione
 *
 * Uzytkownik przestawia MOTYW, nigdy ich. Powod jest zmierzony
 * doswiadczeniem tej tabeli: przy 1500 wierszach barwa dziala TYLKO dlatego,
 * ze jest rzadka i znaczy jedno. Akcent na czerwono skasowalby sygnal w calej
 * aplikacji, a jedynym objawem byloby to, ze handlowiec przestaje zauwazac,
 * ktorych firm nie sprawdzilismy.
 *
 * Dlatego akcenty trzymaja sie o >=30 stopni odcienia od kazdej roli
 * semantycznej. Najciasniejsza para: magenta Kartoteki (330) wobec czerwieni
 * sygnalu (8) - 38 stopni. Pilnuje `test_akcent_daleko_od_semantyki`.
 *
 * ============================================================================
 * DWIE POPRAWKI WOBEC KANWY - swiadome, obie z tego samego powodu
 * ============================================================================
 * W „1a Radar" limonka byla naraz tlem przycisku i werdyktem „potwierdzone".
 * W „1c Sygnal" zolty byl naraz tlem przycisku i ostrzezeniem.
 *
 * Regula: gdy akcent z kanwy wpada w odcien roli semantycznej, ROLA ZOSTAJE,
 * a AKCENT SIE PRZESUWA. Znaczenia nie da sie pokazac niczym innym niz barwa;
 * „to sie klika" da sie pokazac wypelnieniem.
 * ========================================================================== */

/* --- Kroje. W repozytorium, nie na CDN: panel stoi na 127.0.0.1 i ma dzialac
 * bez internetu - ta sama zasada, przez ktora HTMX lezy obok.
 *
 * `latin-ext` NIE JEST OZDOBA. Sprawdzone: 16 z 18 polskich znakow siedzi
 * wlasnie tam (tylko ó i Ó sa w `latin`). Bez tego podzbioru „Piaseczynski",
 * „ZABOWSKA" i „Srodmiescie" lamia sie w polowie slowa na krój zastepczy -
 * a to sa nazwy stojace w kazdym wierszu tej aplikacji. --- */

@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url("/static/fonty/Sora-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url("/static/fonty/Sora-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url("/static/fonty/Archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url("/static/fonty/Archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fira Code"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("/static/fonty/FiraCode-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fira Code"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("/static/fonty/FiraCode-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Roboto Mono"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("/static/fonty/RobotoMono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Roboto Mono"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("/static/fonty/RobotoMono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   MOTYWY - komplet zetonow na kazdy. Brak jednego znaczy ciche dziedziczenie
   po poprzednim motywie, czyli usterke widoczna w jednej kombinacji i w zadnej
   innej. Pilnuje `test_kazdy_motyw_ma_komplet_zetonow`.
   ========================================================================== */

/* --- CZTERY MOTYWY, WSZYSTKIE JASNE. --------------------------------------
 *
 * Do 2026-08-09 stalo tu 24 kombinacje: trzy motywy x jasny/ciemny x trzy
 * akcenty. Nikt nigdy nie obejrzal ich wszystkich, a dwie mialy niewidoczne
 * liczby na pulpicie - akcent byl kluczowany po motywie, ale NIE po trybie,
 * wiec przy przelaczeniu tlo sie odwracalo, a on zostawal na miejscu.
 * Decyzja Andreia: zostaja CZTERY gotowe wyglady, kazdy w jednej postaci.
 * Bez wyboru akcentu, bez jasny/ciemny, bez rozmiaru pisma.
 *
 * Kazdy blok definiuje KOMPLET zetonow - pilnuje tego
 * `test_kazdy_motyw_ma_komplet_zetonow`. Zapomniany zeton daje element, ktory
 * w jednym motywie wyglada obco i w zadnym innym, a patrzac na blok, ktory go
 * nie ma, nie sposob tego zobaczyc.
 *
 * Barwy nie sa dobrane na oko. Kazda para tekst/tlo przechodzi WCAG AA
 * (`test_kontrast_wcag_na_kazdym_motywie`), a kazdy akcent stoi >=30 stopni
 * od kazdej roli semantycznej w CALYM arkuszu (`test_akcent_daleko_od_semantyki`),
 * zeby akcent nigdy nie udawal sygnalu.
 * --------------------------------------------------------------------- */

/* --- SYGNAL (domyslny): plaskie bloki, ciezkie czarne linie, jasny papier,
 * zero zaokraglen, duze liczby. Zolty jest OSTRZEZENIEM, nie przyciskiem.
 * Akcent to blekit - czern zwolnila sie dla Duzego. --- */
:root,
:root[data-motyw="sygnal"] {
  --font-tekst: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-naglowek: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-cyfry: "Fira Code", ui-monospace, Consolas, monospace;

  --tlo: #f2f1ec;
  --tlo-2: #e6e5de;
  --tlo-3: #ebeae4;
  --tekst: #10120f;
  --tekst-2: #3d443c;
  --tekst-3: #626860;
  --linia: #10120f;
  --linia-2: #c9d6cd;

  --akcent: #1f5fd0;
  --na-akcencie: #ffffff;
  --pierscien: rgba(31, 95, 208, .25);

  /* Kanwa dawala tu `#a33232`, czyli odcien 0 - a to DOKLADNIE 29,8 stopnia od
   * magenty Kartoteki, czyli o wlos pod progiem 30. Przesuwam czerwien o osiem
   * stopni w cieplo zamiast obnizac prog: prog jest regula, ta wartosc jest
   * jedna z wielu. */
  --sem-brak: #a63a29;
  --sem-brak-tlo: transparent;
  /* Ciemniejsze niz kanwowe `#8a6a00`, bo ta rola JEDYNA maluje sie na wlasnym
   * zetonie, a nie na tle strony: `.stan-przerwane` i `.stan-blad` to
   * `--sem-uwaga` na `--sem-uwaga-tlo`. Zolty zeton jest jasny, wiec para
   * dawala 3,51:1 przy progu 4,5. */
  --sem-uwaga: #745900;
  --sem-uwaga-tlo: #ffd23f;
  --sem-dobrze: #0c5f3c;
  --sem-dobrze-tlo: #d6f2e5;

  /* Stan pracy handlowca - patrz komentarz przy `.praca-*`. Rampa tintow
   * BLEKITU, `odpada` neutralnie i nizej. */
  --praca-nowy-tlo: #dbdbd6;
  --praca-odpada-tlo: #c0af8e;

  --r-mala: 0;
  --r-srednia: 0;
  --r-duza: 0;
  --r-pigulka: 0;
  --grubosc-linii: 2px;
  --kreska-kolumny: 0;
  --wiersz-y: 11px;
  --wiersz-x: 14px;
  --ts-baza: 14px;
  --ts-mikro: 11px;
  --ts-nazwa: 14px;
  --ts-marka: 16px;
  --ts-duza: 30px;
  --waga-nazwa: 600;
  --waga-marka: 700;
  --tracking-marka: -.01em;
  --case-chip: uppercase;
  --tracking-chip: .06em;
  --cien-karta: none;
  --cien-popup: none;
  --czas-poswiaty: 4.0s;
  /* Przyciemnienie pod okienkiem modalnym. Stoi TYLKO tutaj, a nie w kazdym
   * motywie z osobna: zaslona jest czarna w kazdym z nich, bo ma odsunac
   * strone, a nie ubrac ja w barwe.
   *
   * Wartosc wlasna, bo domyslna przegladarki to ZMIERZONE `rgb(0 0 0 / .1)` -
   * przy tym arkuszu, gdzie tlo strony i tlo okienka roznia sie o wlos, dziesiec
   * procent czerni nie oddziela niczego. A okienko strzeze dzialania
   * nieodwracalnego. */
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* --- KARTOTEKA: cieply papier, przestronnie, pigulki, magenta. --- */
:root[data-motyw="kartoteka"] {
  --font-tekst: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-naglowek: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-cyfry: "Roboto Mono", ui-monospace, Consolas, monospace;

  --tlo: #faf7f3;
  --tlo-2: #f0e7dc;
  --tlo-3: #f5efe7;
  --tekst: #1b1a19;
  --tekst-2: #5c554d;
  --tekst-3: #6e665f;
  --linia: #e6ded3;
  --linia-2: #efe8de;

  --akcent: #cf2e7e;
  --na-akcencie: #ffffff;
  --pierscien: rgba(207, 46, 126, .22);

  --sem-brak: #a8321f;
  --sem-brak-tlo: transparent;
  /* O wlos ciemniejsze niz w Sygnale: papier Kartoteki (`--tlo-2: #f0e7dc`)
   * jest cieplejszy i ciemniejszy, wiec ta sama barwa dawala tam 4,43:1. */
  --sem-uwaga: #866015;
  --sem-uwaga-tlo: transparent;
  --sem-dobrze: #3f6b33;
  --sem-dobrze-tlo: #e9f2e4;

  /* Tinty MAGENTY, `odpada` neutralnie. */
  --praca-nowy-tlo: #e4e1dd;
  --praca-odpada-tlo: #c4b596;

  --r-mala: 4px;
  --r-srednia: 10px;
  --r-duza: 12px;
  --r-pigulka: 99px;
  --grubosc-linii: 1px;
  --kreska-kolumny: 0;
  --wiersz-y: 14px;
  --wiersz-x: 16px;
  --ts-baza: 15px;
  --ts-mikro: 12px;
  --ts-nazwa: 15px;
  --ts-marka: 17px;
  --ts-duza: 30px;
  --waga-nazwa: 600;
  --waga-marka: 800;
  --tracking-marka: -.02em;
  --case-chip: none;
  --tracking-chip: 0;
  --cien-karta: 0 1px 2px rgba(27, 26, 25, .05), 0 8px 24px rgba(27, 26, 25, .05);
  --cien-popup: 0 2px 4px rgba(27, 26, 25, .08), 0 10px 28px rgba(27, 26, 25, .10);
  --czas-poswiaty: 4.0s;
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* --- GESTY: maksimum wierszy na ekranie. Dla kogos, kto przerabia dluga
 * liste i woli zobaczyc szescdziesiat firm niz dwadziescia piec.
 *
 * Wiersz 6px zamiast 11, pismo 13px zamiast 14, wlosowe linie zamiast
 * czarnych belek Sygnalu. Zeton `--tekst-3` jest tu CIEMNIEJSZY niz
 * w Kartotece, mimo ze motyw wyglada lzej: przy 10px prog kontrastu jest ten
 * sam, a pola na blad mniej - drobny szary tekst oblewa pierwszy.
 *
 * Akcent to gleboka petrol (odcien 192). Nie zywy blekit Sygnalu i nie zielen:
 * przy tej gestosci barwa ma sie nie wybijac, a od najblizszej roli
 * semantycznej dzieli ja 42 stopnie zapasu. --- */
:root[data-motyw="gesty"] {
  --font-tekst: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-naglowek: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-cyfry: "Fira Code", ui-monospace, Consolas, monospace;

  --tlo: #f3f4f5;
  --tlo-2: #e6e9eb;
  --tlo-3: #edeff1;
  --tekst: #14171a;
  --tekst-2: #3a4045;
  --tekst-3: #5d6261;
  --linia: #c3c9ce;
  --linia-2: #dde1e4;

  --akcent: #0b4b5b;
  --na-akcencie: #ffffff;
  --pierscien: rgba(11, 75, 91, .25);

  --sem-brak: #b03a26;
  --sem-brak-tlo: transparent;
  --sem-uwaga: #85610f;
  --sem-uwaga-tlo: transparent;
  --sem-dobrze: #2f6b3f;
  --sem-dobrze-tlo: transparent;

  /* Tinty MORSKIEGO, `odpada` neutralnie. */
  --praca-nowy-tlo: #dddedf;
  --praca-odpada-tlo: #c2b291;

  --r-mala: 2px;
  --r-srednia: 3px;
  --r-duza: 4px;
  --r-pigulka: 99px;
  --grubosc-linii: 1px;
  --kreska-kolumny: 0;
  --wiersz-y: 6px;
  --wiersz-x: 10px;
  --ts-baza: 13px;
  /* 11 px, nie 10. Gestosc tego motywu siedzi w odstepach wiersza, a nie
   * w mikrotekscie: zmierzone 2026-08-10, podniesienie z 10 kosztuje JEDEN
   * wiersz w oknie (18 -> 17), a zdejmuje z aplikacji najdrobniejsze pismo,
   * jakie w niej bylo. Prog pilnuje `test_zaden_motyw_nie_schodzi_ponizej
   * _progu_czytelnosci`. */
  --ts-mikro: 11px;
  --ts-nazwa: 13px;
  --ts-marka: 15px;
  --ts-duza: 24px;
  --waga-nazwa: 600;
  --waga-marka: 700;
  --tracking-marka: -.01em;
  --case-chip: uppercase;
  --tracking-chip: .05em;
  --cien-karta: none;
  --cien-popup: 0 2px 4px rgba(20, 23, 26, .08), 0 10px 26px rgba(20, 23, 26, .12);
  --czas-poswiaty: 4.0s;
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* --- DUZY: godziny nad tabela, slabszy wzrok, wieksza odleglosc od ekranu.
 * Wchlania usunieta opcje "Rozmiar pisma: Duzy" - dlatego nic nie przepadlo,
 * gdy zniknela z Ustawien.
 *
 * Pismo 17px i wiersz 16px, czyli o polowe wiecej powietrza niz Sygnal.
 * Akcent jest ATRAMENTOWY, nie barwny, i to nie jest ubostwo: motyw, ktorego
 * celem jest czytelnosc, zyskuje na tym, ze kolor NIE konkuruje z tekstem.
 * Czern zwolnila sie, bo Sygnal przeszedl na blekit. Straznik odleglosci od
 * semantyki pomija ja jako achromatyczna - i slusznie, bo nie niesie odcienia,
 * ktory moglby udawac sygnal. --- */
:root[data-motyw="duzy"] {
  --font-tekst: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-naglowek: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-cyfry: "Roboto Mono", ui-monospace, Consolas, monospace;

  --tlo: #fbfaf7;
  --tlo-2: #eeebe4;
  --tlo-3: #f4f2ec;
  --tekst: #101010;
  --tekst-2: #33322f;
  --tekst-3: #616766;
  --linia: #101010;
  --linia-2: #d8d4cb;

  --akcent: #141414;
  --na-akcencie: #fbfaf7;
  --pierscien: rgba(20, 20, 20, .22);

  --sem-brak: #a3301f;
  --sem-brak-tlo: transparent;
  --sem-uwaga: #7a5a00;
  --sem-uwaga-tlo: transparent;
  --sem-dobrze: #2c5f38;
  --sem-dobrze-tlo: transparent;

  /* Akcent Duzego jest niemal czarny, wiec cala rampa wychodzi SZARA - cztery
   * stany rozjezdzaja sie tu wylacznie jasnoscia, i to jest w porzadku:
   * to motyw dla slabszego wzroku, gdzie roznica jasnosci niesie wiecej niz
   * roznica barwy. `odpada` lekko cieple, zeby nie bylo czwartym szczeblem
   * tej samej drabiny. */
  --praca-nowy-tlo: #e4e3e0;
  --praca-odpada-tlo: #c6b799;

  --r-mala: 3px;
  --r-srednia: 5px;
  --r-duza: 6px;
  --r-pigulka: 99px;
  --grubosc-linii: 2px;
  --kreska-kolumny: 0;
  --wiersz-y: 16px;
  --wiersz-x: 18px;
  --ts-baza: 17px;
  --ts-mikro: 13px;
  --ts-nazwa: 17px;
  --ts-marka: 19px;
  --ts-duza: 36px;
  --waga-nazwa: 700;
  --waga-marka: 800;
  --tracking-marka: -.01em;
  --case-chip: none;
  --tracking-chip: 0;
  --cien-karta: none;
  --cien-popup: none;
  --czas-poswiaty: 4.0s;
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* --- KSIEGA: ksiega rachunkowa na ekranie. Krój o stalej szerokosci NIE tylko
 * na danych, ale na wszystkim - na nawigacji, naglowkach i etykietach. Do tego
 * pionowe kreski miedzy kolumnami, ktorych nie ma zaden inny motyw.
 *
 * Kierunek podpowiedzial Google Stitch (2026-08-09, model 3.1 Pro). Jego wersja
 * stala na JetBrains Mono; przeszlismy na Fira Code, bo ta juz lezy
 * w repozytorium z subsettingiem `latin-ext` - nowy krój to dwa kolejne pliki
 * woff2 do pobrania przy kazdym wejsciu, a panel ma dzialac bez internetu.
 *
 * Akcent jest cieply, prawie czarny (#1c1a17) - atrament, nie barwa. Duzy ma
 * czern neutralna (#141414); roznica jest ledwie widoczna i to nie szkodzi,
 * bo te dwa motywy rozroznia sie krojem i gestoscia, nie akcentem.
 *
 * Czerwien `--sem-brak` stoi na 8 stopniach, a nie na 0, mimo ze Stitch
 * proponowal czyste `#e53e3e`. Odcien 0 to DOKLADNIE 30 stopni od magenty
 * Kartoteki, czyli na styku progu - dokladnie ta pulapka, ktora opisuje
 * komentarz przy Sygnale. 8 stopni daje 38 zapasu. --- */
:root[data-motyw="ksiega"] {
  --font-tekst: "Fira Code", ui-monospace, Consolas, monospace;
  --font-naglowek: "Fira Code", ui-monospace, Consolas, monospace;
  --font-cyfry: "Fira Code", ui-monospace, Consolas, monospace;

  --tlo: #f9f9f9;
  --tlo-2: #ececec;
  --tlo-3: #f3f3f3;
  --tekst: #1a1c1c;
  --tekst-2: #4a4d4d;
  --tekst-3: #616464;
  --linia: #1a1c1c;
  --linia-2: #d1d1d1;

  --akcent: #1c1a17;
  --na-akcencie: #f9f9f9;
  --pierscien: rgba(28, 26, 23, .22);

  --sem-brak: #c52d16;
  --sem-brak-tlo: transparent;
  --sem-uwaga: #846500;
  --sem-uwaga-tlo: transparent;
  --sem-dobrze: #2f6b3f;
  --sem-dobrze-tlo: transparent;

  /* To samo, co w Duzym: akcent Ksiegi jest niemal czarny, wiec rampa jest
   * szara, a `odpada` odchodzi od niej cieplem. */
  --praca-nowy-tlo: #e3e3e3;
  --praca-odpada-tlo: #c5b698;

  --r-mala: 0;
  --r-srednia: 0;
  --r-duza: 0;
  --r-pigulka: 0;
  --grubosc-linii: 1px;
  --kreska-kolumny: 1px;
  --wiersz-y: 8px;
  --wiersz-x: 12px;
  --ts-baza: 13px;
  --ts-mikro: 11px;
  --ts-nazwa: 13px;
  --ts-marka: 15px;
  --ts-duza: 28px;
  --waga-nazwa: 700;
  --waga-marka: 700;
  --tracking-marka: 0;
  --case-chip: uppercase;
  --tracking-chip: .04em;
  --cien-karta: none;
  --cien-popup: none;
  --czas-poswiaty: 4.0s;
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* --- PLAN: bialy rysunek techniczny na chlodnym tle, blekit, cienka kreska.
 *
 * Drugi kierunek Andreia z Claude Design (2026-08-10). Odwraca wszystko, co
 * pozostale motywy maja wspolne: tlo jest CIEMNIEJSZE od kart, kreska cienka
 * i jasna, rogi zaokraglone. Reszta panelu nie wie o tym ani jednej reguly -
 * to jest ta wlasnosc, dla ktorej silnik nie zna wartosci barw ani promieni.
 *
 * `--tlo` chlodniejsze i ciemniejsze niz `--tlo-2`/`--tlo-3`, bo tu karty maja
 * odcinac sie BIELA od plaszczyzny, a nie stac na niej ciemniejszym prostokatem.
 * Wszystkie strazniki kontrastu licza od faktycznego tla, wiec ta zamiana
 * niczego nie omija - sprawdza sie sama.
 *
 * Czerwien jest ciemniejsza niz w kanwie: tam „1 204" swieci na bialym jako
 * wielka liczba, u nas ta sama rola maluje takze drobny tekst w tabeli. --- */
:root[data-motyw="plan"] {
  --font-tekst: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-naglowek: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-cyfry: "Roboto Mono", ui-monospace, Consolas, monospace;

  --tlo: #eef1f7;
  --tlo-2: #ffffff;
  --tlo-3: #ffffff;
  --tekst: #12183a;
  --tekst-2: #3f4767;
  --tekst-3: #5a6280;
  --linia: #d5dceb;
  --linia-2: #e4e9f3;

  --akcent: #2436c9;
  --na-akcencie: #ffffff;
  --pierscien: rgba(36, 54, 201, .25);

  --sem-brak: #b32218;
  --sem-brak-tlo: transparent;
  --sem-uwaga: #6b4e00;
  --sem-uwaga-tlo: #ffe08a;
  --sem-dobrze: #0a5a38;
  --sem-dobrze-tlo: #d8f0e4;

  /* Plan to jedyny motyw, w ktorym `--tlo-2` i `--tlo-3` sa OBA czystym bielem -
   * czyli ten, przez ktory rampa musi miec wlasne zetony zamiast skladac sie
   * z gotowych powierzchni. */
  --praca-nowy-tlo: #d8dbe4;
  --praca-odpada-tlo: #c0af8e;

  --r-mala: 6px;
  --r-srednia: 8px;
  --r-duza: 10px;
  --r-pigulka: 999px;
  --grubosc-linii: 1px;
  --kreska-kolumny: 0;
  --wiersz-y: 12px;
  --wiersz-x: 14px;
  --ts-baza: 14px;
  --ts-mikro: 11px;
  --ts-nazwa: 14px;
  --ts-marka: 16px;
  --ts-duza: 30px;
  --waga-nazwa: 600;
  --waga-marka: 700;
  --tracking-marka: -.02em;
  --case-chip: none;
  --tracking-chip: 0;
  --cien-karta: none;
  --cien-popup: 0 2px 4px rgba(18, 24, 58, .08), 0 12px 32px rgba(18, 24, 58, .14);
  --czas-poswiaty: 4.0s;
  --przyciemnienie: rgb(0 0 0 / .45);
}

/* ==========================================================================
   SILNIK - ponizej NIE MA ANI JEDNEJ WARTOSCI BARWY.
   ========================================================================== */

* { box-sizing: border-box; }

body {
  margin: 0;
  /* Kolumna na wysokosc okna. Dzieki temu `.uklad` bierze CALA reszte i rail
   * bocznego menu siega dolu takze na krotkim ekranie - bez tego jego kreska
   * urywala sie na ostatniej pozycji (zmierzone: 231 px przy oknie 1080 px)
   * i uklad wygladal jak prostokat rzucony w lewy gorny rog.
   *
   * ZADNEGO odejmowania wysokosci paska - patrz dluzszy komentarz przy
   * `body:has(.ekran.pelne-okno)` nizej. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--tlo);
  color: var(--tekst);
  font-family: var(--font-tekst);
  font-size: var(--ts-baza);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--pierscien);
  border-radius: var(--r-mala);
}

/* Wiersz wynikow ma `tabindex`, wiec MUSI byc widac, gdzie stoi klawiatura.
 * Regula wyzej tu nie wystarcza: tabela stoi na `border-collapse: collapse`,
 * a przy zwinietych krawedziach `box-shadow` na `<tr>` sie nie maluje - fokus
 * byloby wiec ustawiony, lecz niewidoczny, czyli gorzej niz brak fokusu.
 * `outline` z ujemnym offsetem rysuje sie po komorkach i dziala mimo zwiniecia. */
.wyniki tbody tr:focus-visible {
  outline: 2px solid var(--akcent);
  outline-offset: -2px;
  box-shadow: none;
}

/* --- Pasek gorny --- */

/* Rozmiar pisma byl tu czwarta osia (`data-pismo="duze"`, trzy zetony w gore).
   Zniknal 2026-08-09 razem z wyborem akcentu i trybu - jego role przejal motyw
   DUZY, ktory podnosi nie tylko litery, ale i wiersz, i kontrast, i grubosc
   linii. Sama wieksza litera w gestym ukladzie i tak nie rozwiazywala problemu,
   dla ktorego powstala. */

.pasek {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 20px;
  border-bottom: var(--grubosc-linii) solid var(--linia);
  background: var(--tlo);
  position: sticky;
  top: 0;
  z-index: 10;
  /* Ten sam sufit co tresc - inaczej marka stoi metr w lewo od menu, ktore
   * rzekomo opisuje, a kreska pod paskiem konczy sie gdzie indziej niz
   * kolumna pod nia. */
  width: 100%;
  max-width: 1760px;
  margin-inline: auto;
}
.pasek .marka {
  font-family: var(--font-naglowek);
  font-size: var(--ts-marka);
  font-weight: var(--waga-marka);
  letter-spacing: var(--tracking-marka);
}
.pasek .marka:hover { text-decoration: none; }
.pasek .meta { color: var(--tekst-2); font-size: var(--ts-mikro); }
.pasek .rozpychacz { margin-left: auto; }

/* --- Przyciski. Hierarchia z WYPELNIENIA, nie z barwy: glowny zalany
 * akcentem, poboczny obrysowany. --- */

.btn {
  font: inherit;
  font-family: var(--font-tekst);
  font-size: var(--ts-mikro);
  padding: 7px 14px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-mala);
  background: var(--tlo-3);
  color: var(--tekst);
  cursor: pointer;
  white-space: nowrap;
  transition: background 140ms ease, border-color 140ms ease;
}
.btn:hover { background: var(--tlo-2); text-decoration: none; }
.btn.glowny {
  background: var(--akcent);
  border-color: var(--akcent);
  color: var(--na-akcencie);
  font-weight: 600;
}

/* --- Filtry. Chip jest ODNOSNIKIEM, nie przyciskiem - filtry skladaja sie
 * przez adres, wiec dzialaja takze bez JavaScriptu. --- */

.filtry {
  display: flex;
  /* `flex-start`, nie `center`: przycisk eksportu ma stac przy GORNEJ krawedzi
   * paska niezaleznie od tego, ile linii zajma pigulki. Przy `center` wedrowal
   * w pionie za kazdym razem, gdy filtr zmienil liczbe zawinietych linii. */
  align-items: flex-start;
  gap: 8px;
  /* BEZ `flex-wrap` na tym poziomie. Zawija sie `.chipy` w srodku, a przycisk
   * jest jego rodzenstwem i do zawijania nie wchodzi - dzieki temu stoi zawsze
   * w tym samym rogu. Do 20.08 byl ostatnim elementem TEGO ciagu, z
   * `margin-left:auto`, wiec ladowal na koncu ostatniej linii pigulek
   * i przeskakiwal przy kazdej zmianie filtru. */
  padding: 11px 20px;
  border-bottom: var(--grubosc-linii) solid var(--linia);
  background: var(--tlo-3);
  /* Przyklejony do gory - i tu przyklejenie DZIALA, w odroznieniu od naglowka
   * tabeli. `.filtry` jest dzieckiem `.ekran`, a ani `.ekran`, ani `.uklad` nie
   * maja `overflow`, wiec przewija sie cala strona i `top` liczy sie wzgledem
   * OKNA. Naglowek tabeli siedzi w `.lewa`, ktora ma `overflow-x: auto` i przez
   * to jest kontenerem przewijania - patrz dlugi komentarz przy `.wyniki th`.
   * Sprawdzone przed napisaniem tej reguly, nie po.
   *
   * `top: 49px` to wysokosc gornego paska. `z-index` wyzszy niz naglowek tabeli
   * (2) i niz przyklejona kolumna Status, bo pasek ma je przykrywac, a nie
   * przeswitywac spod nich. */
  position: sticky;
  top: 49px;
  z-index: 3;
}

/* Okienko - JEDNO dla usuwania przebiegu i dla wyboru kolumn eksportu.
 *
 * Zastapilo zwijana sekcje usuwania (2026-08-10). Tamta byla nie do
 * znalezienia: `display: inline-block` na `<summary>` kasuje trojkat
 * rozwijania, wiec zostawal napis 11 px w kolorze `--tekst-2`, czytany jak
 * podpis nad tabela. Zmierzone: stal 103 px od gory i nikt go nie widzial.
 *
 * Zaslona idzie z zetonu `--przyciemnienie`, a nie z wartosci wpisanej tutaj:
 * ponizej SILNIKA nie ma ani jednej barwy. Domyslna zaslona przegladarki
 * (zmierzone `rgb(0 0 0 / .1)`) byla za slaba - tlo strony i tlo okienka
 * roznia sie w tym arkuszu o wlos. */
.okienko {
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-srednia);
  background: var(--tlo-2);
  color: var(--tekst);
  padding: 4px 26px 22px;
  width: min(560px, calc(100% - 40px));
}

.okienko::backdrop { background: var(--przyciemnienie); }

/* Kolumna akcji na Pulpicie: tyle, ile trzeba na przycisk, i ani piksela
 * wiecej - szerokosc jest w tej tabeli potrzebna kolumnie „Obszar". */
.wiersz-akcje { width: 1%; white-space: nowrap; }

/* Ptaszki kolumn eksportu w dwoch slupkach: dziewietnascie pozycji w jednym
 * nie miesci sie w oknie laptopa, a okienko nie ma sie przewijac - wybor,
 * ktorego nie widac w calosci, przestaje byc wyborem. */
/* Zestawy NAD ptaszkami i wysylka POD nimi - z tego ukladu widac, ze zestaw
 * jest skrotem do zaznaczenia, a nie druga droga do pliku. */
.zestawy { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 16px; }
.akcje-okienka { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 4px; }

/* Wysylka gasnie przy zerze zaznaczonych kolumn - patrz skrypt w `rama.html`. */
.btn:disabled { opacity: .45; cursor: not-allowed; }

.kolumny { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 18px; }
/* Selektor ZLOZONY, nie samo `.ptaszek` - inaczej przegrywa specyficznoscia
 * z `.formularz label` (0,1,1 wobec 0,1,0) i etykiety wychodza wersalikami
 * z odstepami miedzy literami. Zmierzone okiem na zywym okienku: „NAZWA
 * FIRMY" zamiast „Nazwa firmy". */
.formularz .ptaszek {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--ts-mikro);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}

/* Dociaganie albo pager - jedno miejsce pod tabela, dwa mozliwe wypelnienia. */
.pager {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 14px var(--wiersz-x);
}
.pager-przerwa { color: var(--tekst-3); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--ts-mikro);
  letter-spacing: var(--tracking-chip);
  text-transform: var(--case-chip);
  /* Scisniete 20.08 z `5px 11px` i odstepu 6px. Jedenascie pigulek zawijalo sie
   * przy otwartej karcie na TRZY linie, a pasek uroslo do 132 px - Andrei
   * poprosil, zeby „sie miescila". Zmierzone: te cztery piksele na pigulke
   * i dwa na odstep to razem ~64 px, czyli akurat tyle, ile brakowalo do
   * zejscia na dwie linie przy 1280 px. Ponizej tego pigulka zaczyna byc
   * mniejsza od wygodnego celu dotykowego. */
  padding: 4px 9px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-pigulka);
  color: var(--tekst-2);
  background: var(--tlo);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.chip:hover { background: var(--tlo-2); color: var(--tekst); text-decoration: none; }
.chip.on { background: var(--akcent); border-color: var(--akcent); color: var(--na-akcencie); }
.chip .ile { font-variant-numeric: tabular-nums; font-family: var(--font-cyfry); opacity: .75; }

/* Kreska miedzy WYMIARAMI filtru. Jedenascie pigulek w jednym ciagu czyta
 * sie jak jedna lista wyborow, a nie jest: wewnatrz wymiaru chipy sie
 * WYKLUCZAJA (klik w drugi zastepuje pierwszy - patrz `_po_przelaczeniu`),
 * miedzy wymiarami SKLADAJA. To jedyne miejsce, w ktorym ta zasada jest
 * widoczna, zanim ktos kliknie.
 *
 * Wlos, nie separator z wlasnym kolorem - `--linia` i `--grubosc-linii`
 * jak kazda inna kreska w arkuszu. Ponizej SILNIKA nie ma tu ani jednej
 * barwy wpisanej wprost.
 *
 * `align-self: stretch` z `min-height` zamiast stalej wysokosci: pasek jest
 * `flex-wrap`, wiec kreska ma dorownac pigulkom takze wtedy, gdy urosna od
 * dluzszej etykiety albo od wiekszego stopnia pisma w motywie. */
/* Pigulki zawijaja sie WEWNATRZ swojego kontenera, a nie w pasku.
 * `min-width: 0` jest tu warunkiem dzialania, nie ozdoba: element `flex`
 * domyslnie nie kurczy sie ponizej swojej najwezszej zawartosci, wiec bez tego
 * dlugi ciag pigulek rozpycha pasek i wypycha przycisk poza ekran zamiast
 * zawinac. */
.chipy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  flex: 1 1 auto;
  min-width: 0;
}

.chipy-przerwa {
  width: var(--grubosc-linii);
  align-self: stretch;
  min-height: 1.4em;
  margin: 0 4px;
  background: var(--linia);
}

/* --- Pasek przebiegu. Jedyna animacja w arkuszu: mowi „ten przebieg jeszcze
 * oddycha", a tego nie da sie przekazac inaczej przy kilku godzinach. --- */

.przebieg {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 11px;
  padding: 9px 20px;
  background: var(--tlo-2);
  border-bottom: var(--grubosc-linii) solid var(--linia);
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
}
/* Tor jest POJEMNIKIEM na segmenty, a nie jednym wypelnieniem: w fazie rekordow
 * stoja w nim dwa (`zaklasyfikowane`, `odrzucone`), w spisie jedno.
 *
 * Nietkniete NIE MA wlasnego elementu - jest tlem, ktore zostalo. To nie jest
 * oszczednosc znacznikow: kolejka to brak wyniku, a nie trzeci wynik, i pasek
 * ma to powiedziec sam z siebie. Stad prazki zamiast plaskiej barwy - plaskie
 * tlo czytalo sie jak kolejny segment.
 *
 * 10 px zamiast dawnych 4 px, bo przy 4 px trzy segmenty i granica miedzy nimi
 * byly kreska, a nie informacja. */
.tor {
  display: flex;
  position: relative;
  height: 26px;
  /* Kolejka bierze `--tlo`, czyli papier STRONY, a nie `--tlo-3`, czyli tlo
   * planszy. Na `--tlo-3` tor zlewal sie z plansza pod nim i mial krawedz
   * tylko tam, gdzie akurat wypadl prazek - zmierzone w przegladarce, oba
   * zetony oddawaly `rgb(235, 234, 228)`. Papier strony rozni sie od kazdej
   * powierzchni, na ktorej ten pasek stoi: od planszy w duzym widoku i od
   * `--tlo-2` w gornym pasku. */
  background-color: var(--tlo);
  background-image: repeating-linear-gradient(
    -45deg, var(--linia-2) 0 4px, transparent 4px 11px
  );
  border-radius: var(--r-pigulka);
  overflow: hidden;
}
.tor i { height: 100%; background: var(--akcent); transition: width 600ms ease; }
/* Odsiane ida ATRAMENTEM PRZYGASZONYM, nie druga barwa. Odrzucona firma to
 * wykonana praca o wyniku „nie" - `DESIGN.md` mowi, ze roznice ma niesc slowo,
 * a nowa barwa wymaga uzasadnienia. Tu go nie ma: legenda stoi obok. */
.tor i.odsiane { background: var(--tekst-3); }
/* Granica przetworzone/kolejka. Czolo pracy, czyli miejsce, w ktorym cos sie
 * teraz dzieje - jedyny punkt paska, ktory ma prawo przyciagac oko. */
.granica {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--tekst);
}

/* Poswiata sunaca po torze. Cykl przychodzi ze ZMIENNEJ ustawianej z TEMPA
 * przebiegu - szybciej, gdy leci, wolniej, gdy zwalnia, i stoi, gdy stanal.
 * To jest cala jej racja bytu: bez zwiazku z danymi bylaby ozdoba, a `DESIGN.md`
 * mowi „semantyka niesie znaczenie, nie ozdobe".
 *
 * Serwer kwantyzuje cykl do dziesiatych sekundy, bo zmiana `animation-duration`
 * restartuje animacje - plynna wartosc kazalaby poswiacie drgac przy kazdym
 * odczycie, czyli naprawa zamienilaby sie w usterke.
 *
 * Zmienna siedzi na STABILNEJ otoczce `#postep`, nie na tym elemencie:
 * wnetrze jest wymieniane co 2 s i zabraloby animacje ze soba.
 *
 * Poswiata zostaje JEDYNA animacja toru. Do 2026-08-11 pulsowalo pod nia
 * jeszcze wypelnienie (`oddech`) - dwa ruchy o tym samym znaczeniu, a od
 * podzialu toru na segmenty ten drugi zaczal klamac: przezroczystosc na jednym
 * z trzech kubelkow czyta sie jak stan tego kubelka, nie calego przebiegu. */
.tor.zywy::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 34%;
  border-radius: var(--r-pigulka);
  background: linear-gradient(90deg, transparent, var(--akcent), transparent);
  opacity: .45;
  animation: poswiata var(--czas-poswiaty) linear infinite;
}
@keyframes poswiata { from { transform: translateX(-100%) } to { transform: translateX(400%) } }

/* --- Legenda segmentow. Bez niej pasek jest ladny i nieczytelny: barwa mowi
 * „te sa inne", a nie „te odpadly", i nie podaje ani jednej liczby. --- */
.legenda {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 22px;
  margin-top: 16px;
  font-size: var(--ts-baza);
  color: var(--tekst-2);
}
.legenda span { display: flex; align-items: center; gap: 7px; }
.legenda b {
  font-family: var(--font-cyfry);
  font-variant-numeric: tabular-nums;
  font-weight: var(--waga-nazwa);
  color: var(--tekst);
}
/* Ksztalt raz, barwa osobno - ten sam wzorzec, co pod pigulkami stanow. Znaczki
 * biora barwy DOKLADNIE z segmentow toru; rozjazd tutaj to legenda, ktora
 * opisuje inny pasek niz ten obok. */
.legenda-klas, .legenda-odrz, .legenda-kolejka {
  width: 11px;
  height: 11px;
  border-radius: var(--r-pigulka);
}
.legenda-klas { background: var(--akcent); }
.legenda-odrz { background: var(--tekst-3); }
.legenda-kolejka { background: var(--tlo); border: 1px solid var(--linia-2); box-sizing: border-box; }

/* Podpis pod paskiem: mowi, CZYM ten ksztalt nie jest. Pasek proporcji wyglada
 * jak spis firm i ktos policzylby z niego pojedyncze rekordy. */
.postep-skala {
  margin-top: 12px;
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
}

/* --- Mala nisza: jedna firma = jeden kwadrat.
 *
 * Przy 36 firmach (fryzjer/Otwock) pasek proporcji jest przesada - liczba nad
 * nim i tak da sie przeliczyc wzrokiem, a kwadraty mowia to samo BEZ skali,
 * ktorej trzeba zaufac. Powyzej `PROG_KWADRACIKOW` zamieniaja sie w szum
 * i wraca pasek. Trzy grupy, nie jeden ciag: kolejnosc w grupie nic nie znaczy,
 * wiec przemieszane kwadraty udawalyby porzadek, ktorego nie ma. --- */
.kwadraciki { display: flex; flex-wrap: wrap; gap: 10px 24px; }
.kwadraciki div { display: flex; flex-wrap: wrap; gap: 5px; }
.kwadraciki i { width: 16px; height: 16px; border-radius: var(--r-mala); }

@keyframes bicie {
  0%, 100% { opacity: .35; transform: scale(.85) }
  50% { opacity: 1; transform: scale(1) }
}

/* --- Duzy widok postepu.
 *
 * Przez caly spis obszaru tabela pokazuje samo zdanie o braku dopasowan,
 * a chipy same zera - wiec postep jest JEDYNA trescia na ekranie i dostawal
 * pasek 4 px przy gornej krawedzi. Dla Warszawy ta faza trwala 49 minut.
 *
 * Znika przy pierwszym wyniku: od tej chwili miejsce nalezy sie liscie,
 * po ktorej sie pracuje. Stad brak jakiegokolwiek przelacznika - o tym,
 * ktory ksztalt ma sens, rozstrzyga stan przebiegu, a nie ustawienie. --- */
.postep-duzy {
  max-width: 720px;
  margin: 10vh auto 0;
  /* Plansza, a nie tresc rozsypana na tle. Ten ekran ma jedna rzecz do
   * pokazania i przez godzine nic wiecej sie na nim nie dzieje - ramka mowi,
   * gdzie ta jedna rzecz sie zaczyna i konczy. Ten sam jezyk form, co kafle
   * pulpitu: `--linia` o grubosci motywu, tlo `--tlo-3`, promien z zetonu. */
  padding: clamp(20px, 4vw, 40px);
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-duza);
  background: var(--tlo-3);
  box-shadow: var(--cien-karta);
}
/* Naglowek planszy: po lewej CO sie dzieje, po prawej JAK DLUGO i JAK SZYBKO.
 * Do 2026-08-11 czas i tempo staly pod paskiem, czyli najdalej od liczby,
 * ktorej dotycza. */
.postep-glowa {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 24px;
}
.postep-faza {
  font-size: var(--ts-mikro);
  letter-spacing: var(--tracking-chip);
  text-transform: var(--case-chip);
  color: var(--tekst-2);
}
.postep-etap {
  margin-top: 4px;
  font-family: var(--font-naglowek);
  font-size: var(--ts-marka);
  font-weight: var(--waga-nazwa);
}
.postep-liczba {
  margin-top: clamp(24px, 5vw, 44px);
  font-family: var(--font-tekst);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-align: center;
}
/* Krotnosc `--ts-duza`, a nie wlasna liczba pikseli: to ta sama rola co liczba
 * w kaflu pulpitu, tylko jedyna na ekranie - wiec ma isc za motywem (Duzy
 * podnosi zeton) zamiast obok niego. */
.postep-liczba b {
  font-size: clamp(var(--ts-duza), 9vw, calc(var(--ts-duza) * 2));
  font-weight: var(--waga-nazwa);
}
.postep-liczba span {
  font-size: clamp(var(--ts-baza), 5vw, calc(var(--ts-duza) * 1.1));
  color: var(--tekst-2);
  margin-left: 10px;
}
/* Podpis mowi, CO liczy licznik. W spisie ta sama cyfra znaczy „tyle znalazlem",
 * w fazie rekordow „tyle odhaczylem z kolejki" - patrz `PODPIS_SPIS`. */
.postep-podpis {
  margin-top: 12px;
  margin-bottom: clamp(24px, 5vw, 40px);
  font-size: var(--ts-baza);
  color: var(--tekst-2);
  text-align: center;
}
.postep-fakty {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
}
/* Znak zycia. Nie ozdoba: w fazie spisu jest jedynym sygnalem, ktory odroznia
 * prace od zaciecia - bije, dopoki przychodzi puls z silnika.
 *
 * Ksztalt i ruch w JEDNEJ regule. Rozbite na dwie sa zderzeniem nazw, ktorego
 * nie widac w kodzie - pilnuje tego `test_zadna_klasa_nie_jest_definiowana_dwa_razy`
 * i zlapal mnie na tym przy pisaniu tego widoku. */
.puls {
  width: 7px;
  height: 7px;
  border-radius: var(--r-pigulka);
  background: var(--akcent);
  animation: bicie 1.8s ease-in-out infinite;
}

/* --- Uklad --- */

.plotno { display: flex; align-items: flex-start; }
.lewa { flex: 1; min-width: 0; overflow-x: auto; }

/* --- Ekran wynikow wypelnia okno i przewija sie W SRODKU ---
 *
 * Powod jest jeden: naglowek tabeli. `position: sticky` liczy `top` wzgledem
 * najblizszego KONTENERA PRZEWIJANIA, a `.lewa` jest nim od zawsze, bo ma
 * `overflow-x: auto` (CSS ustawia wtedy `overflow-y` rowniez na `auto`).
 * Tyle ze `.lewa` nigdy nie przewijala sie w pionie - przewijala sie cala
 * strona - wiec naglowek nie mial sie do czego przykleic i po prostu odjezdzal
 * z reszta. Zmierzone 2026-08-09 przy 250 wierszach: po przewinieciu o 3000 px
 * `th` byl na -2723 px, czyli daleko poza ekranem.
 *
 * Nie da sie tego naprawic samym `top`: dopoki przewija sie strona, a nie
 * `.lewa`, przyklejenie nie ma czego trzymac. Trzeba oddac `.lewa` wlasna
 * wysokosc i wlasne przewijanie - dokladnie to, co `.prawa` ma od poczatku.
 * Stad ta sekcja i klasa wstrzykiwana przez `wyniki.html`: zaden inny ekran
 * nie ma powodu przestac przewijac sie normalnie.
 *
 * `min-height: 0` NIE jest ozdoba - domyslne `auto` nie pozwala elementowi
 * zmalec ponizej tresci, wiec bez tego kolumna rosnie w dol razem z tabela
 * i wewnetrzne przewijanie nie wystepuje wcale.
 *
 * ZADNEGO `calc(100vh - <wysokosc paska>)`. Kusi, bo trzy reguly w tym pliku
 * juz tak robia - i wszystkie trzy zgaduja 49px, podczas gdy pasek ma
 * ZMIERZONE 52px, a przy motywie „Duzy" bedzie mial jeszcze wiecej, bo rosnie
 * z krojem pisma. Przy takim odejmowaniu strona dostawala 3px nadmiaru
 * i przewijala sie o te 3px - dosc, zeby przyklejenie zaczelo drgac, za malo,
 * zeby ktokolwiek nazwal to bledem. Zamiast zgadywac, oddajemy rachunek
 * ulozeniu: `body` jest kolumna na wysokosc okna, a `.uklad` bierze to,
 * co zostalo po pasku - ile by ten pasek nie mierzyl.
 *
 * `:has()` zamiast klasy na `<body>`, bo widok nie ma jak jej tam dopisac -
 * ta sama sztuczka co przy `.ekran:has(> .logowanie)` nizej. */
/* Od 2026-08-10 kolumnowe ulozenie `body` i `flex: 1` na `.uklad` stoja
 * w regulach BAZOWYCH - potrzebuje ich kazdy ekran, zeby rail menu siegal
 * dolu. Temu ekranowi zostaje wiec jedna roznica: `height` zamiast
 * `min-height`, czyli zakaz rosniecia. To ona sprawia, ze przewija sie
 * `.lewa`, a nie strona. */
body:has(.ekran.pelne-okno) { height: 100vh; }
.ekran.pelne-okno { display: flex; flex-direction: column; min-height: 0; padding-bottom: 0; }
.ekran.pelne-okno .plotno { flex: 1; min-height: 0; align-items: stretch; }
.ekran.pelne-okno .lewa { height: 100%; overflow: auto; }
/* Ten ekran jest kolumna flex, wiec kazde dziecko rozciaga sie na cala
 * szerokosc - przycisk „Usun ten przebieg" wychodzil pasem przez caly ekran
 * z napisem na srodku. Dotyczy tylko przyciskow stojacych wprost w ekranie;
 * te w paskach i formularzach maja swoich rodzicow.
 *
 * Margines przeniesiony z `.usuwanie { margin: 14px 0 0 }`, ktore ten przycisk
 * zastapil - bez niego trzy obramowane bloki (pasek postepu, przycisk, pasek
 * filtrow) stykaly sie krawedziami, czyli szescioma liniami bez ani jednego
 * piksela przerwy. Zgloszone przez Andreia 2026-08-10. */
.ekran.pelne-okno > .btn { align-self: flex-start; margin: 14px 0; }
/* Wewnatrz kolumny o ustalonej wysokosci przyklejanie jest juz zbedne -
 * `.prawa` stoi tam, gdzie ma stac, sama z siebie. */
.ekran.pelne-okno .prawa { position: static; top: auto; height: 100%; }

@media (max-width: 900px) {
  /* Na waskim ekranie menu przenosi sie NAD tresc i zjada wysokosc, ktorej
   * tabela potrzebuje bardziej. Wracamy do przewijania cala strona - dojscie
   * do akcji zalatwia tam przyklejony pasek filtrow. */
  body:has(.ekran.pelne-okno) { height: auto; display: block; }
  .ekran.pelne-okno { display: block; padding-bottom: 24px; }
  .ekran.pelne-okno .lewa { height: auto; }
  .ekran.pelne-okno .prawa { position: sticky; top: 49px; height: calc(100vh - 49px); }
}
.prawa {
  width: 310px;
  flex-shrink: 0;
  border-left: var(--grubosc-linii) solid var(--linia);
  background: var(--tlo-3);
  padding: 16px 18px;
  position: sticky;
  top: 49px;
  height: calc(100vh - 49px);
  overflow-y: auto;
  box-shadow: var(--cien-karta);
}

/* --- Tabela --- */

table.wyniki { width: 100%; border-collapse: collapse; }
.wyniki th {
  text-align: left;
  font-size: var(--ts-mikro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  /* Pelny ciemny pas, nie szary napis nad kreska (2026-08-10, za kanwa).
   *
   * Barwy z `--tekst` i `--tlo`, a NIE z `--linia` i bieli: te dwie sa juz
   * para tekst/tlo w kazdym motywie, wiec odwrocone przechodza kontrast
   * z definicji. `--linia` bywa w motywach jasniejsza i wlasnie tam bialy
   * napis by sie posypal - w jednej kombinacji z pieciu, czyli tak, jak psuja
   * sie rzeczy w tym arkuszu.
   *
   * Samo TLO stoi nizej, przy `position: sticky` - tam, gdzie stalo od zawsze,
   * bo przyklejony naglowek musi byc kryjacy. Dopisanie drugiego `background`
   * tutaj nic by nie dalo: ta sama regula, dalsza deklaracja wygrywa. */
  color: var(--tlo);
  padding: 9px var(--wiersz-x);
  /* `top: 0`, a NIE 49px pod gornym paskiem - i to nie jest drobiazg.
   *
   * `.lewa` ma `overflow-x: auto`, a CSS ustawia wtedy `overflow-y` rowniez na
   * `auto`. Robi to z niej kontener przewijania, wiec `top` przyklejonego
   * naglowka liczy sie wzgledem NIEJ, nie wzgledem okna. `.lewa` nigdy nie
   * przewija sie w pionie (przewija sie cala strona), wiec 49px nie „omijalo
   * gornego paska" - po prostu spychalo naglowek 49px w glab tabeli, na stale,
   * prosto na pierwsze wiersze. Zmierzone 2026-08-09: `thead` na -113,
   * `th` na -64, pierwszy wiersz na -77. Naglowek siedzial na wierszu.
   *
   * Zeby naglowek NAPRAWDE zostawal na ekranie przy przewijaniu listy, `.lewa`
   * musialaby dostac wlasna wysokosc i wlasne przewijanie w pionie - tak jak
   * `.prawa`. To osobna zmiana ukladu, nie poprawka jednej liczby. */
  position: sticky;
  top: 0;
  /* Kryjace, bo pod przyklejonym naglowkiem przejezdzaja wiersze. Od
   * 2026-08-10 kryje CIEMNYM - to jest ten pelny pas z kanwy. */
  background: var(--tekst);
  /* Naglowek WOLNO zlamac na dwie linie - patrz `.wyniki td:not(:first-child)`
   * nizej. Danym nadal nie wolno. */
  /* Naglowek MUSI byc nad kazda komorka tabeli. `thead` stoi w dokumencie
   * przed `tbody`, wiec przy rownym z-indeksie wygrywalaby komorka - a odkad
   * kolumna Status jest przyklejona, jest ona komorka POZYCJONOWANA i wjezdza
   * naglowkowi na wierzch. Jawna warstwa zamiast polegania na kolejnosci. */
  z-index: 2;
}
.wyniki td {
  padding: var(--wiersz-y) var(--wiersz-x);
  border-bottom: 1px solid var(--linia-2);
  vertical-align: middle;
}
/* Nazwa firmy dostaje minimum, inaczej „MOLENDA-SYSTEMY BEZPIECZENSTWA MOLENDA
 * GRZEGORZ" lamie sie w czterowierszowy slupek i wiersze przestaja byc rowne.
 * Reszta kolumn nie zawija wcale - telefon zlamany w pol jest nieczytelny,
 * a `.lewa` przewija sie w bok. */
.wyniki th:first-child, .wyniki td:first-child { min-width: 230px; }
/* Nowrap dotyczy DANYCH, nie naglowkow.
 *
 * Naglowek, ktory nie moze sie zlamac, dyktuje szerokosc kolumny nawet wtedy,
 * gdy jest od niej znacznie szerszy niz jej tresc. Zmierzone: „Strona
 * potwierdzona" zajmowala 192 px przy danych szerokich na 52 px, bo sam napis
 * ma 165 px. Tabela wystawala przez to poza `.lewa` o 151 px, a przyklejona
 * kolumna Status parkuje przy prawej krawedzi i ZASLANIA to, co pod nia
 * wjezdza - stad „WIARYGODNOSC" czytana jako „WIARYGO". Objaw padal wiec
 * o dwie kolumny od przyczyny.
 *
 * Zlamany naglowek zdejmuje z tego 58 px i nie kosztuje nic: rzad naglowka
 * jest jeden na tabele, a wiersz danych powtarza sie 1900 razy - dlatego dane
 * zostaja w jednej linii (telefon zlamany w pol jest nieczytelny). */
.wyniki td:not(:first-child) { white-space: nowrap; }
/* Pionowe kreski miedzy kolumnami - sygnatura KSIEGI i jedynego motywu, ktory
 * je ma. Pozostale cztery ustawiaja `--kreska-kolumny: 0`, wiec ta regula nic
 * u nich nie rysuje. Silnik nadal nie zna zadnej wartosci barwy: szerokosc
 * przychodzi z zetonu, kolor z `--linia`. */
.wyniki th:not(:last-child), .wyniki td:not(:last-child) {
  border-right: var(--kreska-kolumny) solid var(--linia);
}
/* WASKIE OKNO: slowo znika, liczba zostaje.
 *
 * Zmierzone 2026-08-09: przy oknie 1500 px z otwarta karta firmy (310 px stalej
 * szerokosci) tabela nie miesci sie w kontenerze w ZADNYM motywie - Gesty
 * wystaje o 66 px, Duzy o 316.
 *
 * POWOD, DLA KTOREGO TA REGULA POWSTALA, ZNIKNAL 2026-08-20: przyklejona
 * kolumna Status parkowala przy prawej krawedzi i zaslaniala to, co pod nia
 * wjezdzalo. Kolumny juz nie ma, a tabela jest o jej 165 px wezsza. Regula
 * zostaje, bo drugi czlon uzasadnienia dziala dalej - przy waskim oknie tabela
 * nadal sie nie miesci, a slowo obok liczby nie niesie nic ponad nia.
 *
 * „Wiarygodnosc" nie jest jednak osobna kolumna - to podpis w TEJ SAMEJ
 * komorce co punktacja (`_wiersz.html`). A slowo jest wprost wyliczone
 * z liczby obok (`score.label_for`), wiec jego zniknieciem nie ginie zadna
 * informacja: „74" i „wysoka" mowia to samo, tylko drugie zajmuje 90 px.
 *
 * UCZCIWIE: to zmniejsza kolizje, nie usuwa jej. Motyw Duzy wystaje o 316 px
 * i po tej zmianie nadal wystaje - tabela ma przewijanie w bok i tak ma byc.
 * Zysk jest tam, gdzie brakowalo kilkudziesieciu pikseli. */
@media (max-width: 1600px) {
  .wyniki td.num .pod { display: none; }
}
/* Najechanie maluje WIERSZ, nie komorki - i to jest cala ochrona barw, ktore
 * cos znacza. Tlo komorki maluje sie NAD tlem wiersza, wiec komorka z wlasna
 * barwa zachowuje ja sama z siebie, bez wyliczania w regule, ktore to sa.
 *
 * Zgloszone z produkcji 2026-08-11: `tr:hover td` (0,2,3) bilo
 * `td:has(> .stan-trwa)` (0,2,1), wiec najechanie podmienialo tlo i nie
 * ruszalo koloru tekstu - zostawal `--na-akcencie` (bialy) na jasnym tle.
 * Zmierzone: 1,00:1 w Planie, 1,05-1,21:1 w reszcie motywow.
 *
 * Straznik kontrastu tego nie widzi i mowi o tym wprost: para byla rozbita
 * na dwie reguly - tekst u potomka, tlo u przodka.
 *
 * Pierwsza poprawka wykluczala komorki stanu z reguly najechania. Ta jest
 * prostsza i przezyje nastepna barwna komorke, ktorej nikt nie dopisze
 * do wyjatku. */
.wyniki tbody tr {
  cursor: pointer;
  background: var(--tlo);
  transition: background 120ms ease;
}
.wyniki tbody tr:hover { background: var(--tlo-3); }
.wyniki tbody tr.wybrany td { background: var(--tlo-2); }
/* Znacznik zaznaczenia RAZ, przy lewej krawedzi wiersza - nie przy kazdej
 * komorce. Do 2026-08-09 `box-shadow` siedzial na `td`, wiec przy szesciu
 * kolumnach malowal szesc paskow zamiast jednego. Przy calym widocznym wierszu
 * czytalo sie to jeszcze jak kreski dzielace kolumny, ale gdy wiersz wjezdzal
 * pod przyklejony naglowek, zostawal z nich rzad niebieskich kresek wiszacy
 * pod naglowkiem i nieznaczacy juz nic. */
.wyniki tbody tr.wybrany td:first-child { box-shadow: inset 3px 0 0 var(--akcent); }
.wyniki .nazwa {
  font-family: var(--font-naglowek);
  font-weight: var(--waga-nazwa);
  font-size: var(--ts-nazwa);
}
.wyniki .pod { font-size: var(--ts-mikro); color: var(--tekst-2); }
.num { font-variant-numeric: tabular-nums; font-family: var(--font-cyfry); }

.obciete {
  padding: 9px var(--wiersz-x);
  border-bottom: var(--grubosc-linii) solid var(--linia);
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
}
.obciete a { text-decoration: underline; }

/* Zakres rejestru pod lista. Ten sam glos, co `.obciete` - oba mowia, czego
 * na ekranie NIE MA - tylko bez kreski, bo nie oddziela niczego od niczego.
 * `max-width` w `ch`, bo to jedyne zdanie ciagle na tym ekranie: pelna
 * szerokosc tabeli daje linijke, ktorej oko nie wraca na poczatek. */
.zakres-listy {
  margin: 0;
  padding: 12px var(--wiersz-x) 18px;
  max-width: 78ch;
  font-size: var(--ts-mikro);
  color: var(--tekst-3);
}

/* --- SYGNAL. Trzy role, kazda o jednym znaczeniu, w kazdym motywie. --- */

.strona-brak,
.lista-niepelna {
  font-size: var(--ts-mikro);
  font-weight: 700;
  letter-spacing: .05em;
  color: var(--sem-brak);
  background: var(--sem-brak-tlo);
  border-radius: var(--r-mala);
  white-space: nowrap;
}
.strona-jest { font-size: var(--ts-mikro); color: var(--sem-dobrze); }
.strona-slaba { font-size: var(--ts-mikro); color: var(--sem-uwaga); }

/* --- Stan pracy: POSTEP, nie sygnal. Cztery stany czytane WYPELNIENIEM:
 * pusty krazek, polowa, pelny, zblakly. Barwy tu nie ma, bo stan pracy stoi
 * w tych samych wierszach co ocena strony - a tam barwa juz cos znaczy.
 * Kolejnosc wypelnien niesie przy tym cos, czego cztery barwy nie niosly:
 * postep ma kierunek. --- */

/* Stany przebiegu jako PIGULKI, nie jako szary tekst - tak jak na kanwie.
   Kazda barwa jest tu ta sama, ktora te slowa znacza w calej aplikacji:
   zielen „potwierdzone, zrobione", bursztyn „ostrzezenie", akcent „to zyje".
   Zadna nie jest ozdoba - dlatego wolno ich tu uzyc. */
.stan, .stan-zrobione, .stan-trwa, .stan-przerwane, .stan-blad {
  display: inline-block;
  padding: 2px 9px;
  border-radius: var(--r-pigulka);
  font-size: var(--ts-mikro);
  font-weight: 600;
  white-space: nowrap;
}

.stan { color: var(--tekst-2); background: var(--tlo-2); }
.stan-zrobione { color: var(--sem-dobrze); background: var(--sem-dobrze-tlo); }
.stan-trwa { color: var(--na-akcencie); background: var(--akcent); }
.stan-przerwane { color: var(--sem-uwaga); background: var(--sem-uwaga-tlo); }
.stan-blad {
  color: var(--sem-uwaga);
  background: var(--sem-uwaga-tlo);
  font-weight: 700;
  letter-spacing: .05em;
}

/* --- Stan PRACY handlowca: cztery role, ZERO nowych zetonow.
 *
 * SAM ATRAMENT, ZADNEJ BARWY SEMANTYCZNEJ - i to nie jest ostroznosc, tylko
 * decyzja, ktora stoi tu przede mna. `test_stan_pracy_nie_jest_kolorem` mowi
 * ja wprost: stan pracy to POSTEP, nie sygnal, a barwa na tym ekranie jest
 * zarezerwowana dla jedynej rzeczy, ktora zmienia decyzje handlowca - jakosci
 * leada. Zielone „wyslana" obok czerwonego „BRAK strony" zabieraloby ten
 * sygnal, a bursztynowy tint zderzalby sie z „strona niepewna"
 * w sasiedniej kolumnie (pilnuje tego `test_bursztyn_nie_znaczy_naraz...`).
 *
 * Stany maja sie jednak ODROZNIAC, i to jest prosba Andreia z 2026-08-11.
 * Roznica idzie wiec glebia atramentu, ktorej nikt nie rezerwuje: `nowy`
 * spokojny, `wyslana` ciemniejsza (rzecz ruszona), `odpada`
 * wyblakle - ma sie COFAC, a nie walczyc o uwage. Kropka niesie postep dalej;
 * atrament sie do niej doklada.
 *
 * Jedna klasa dla DWOCH powierzchni: pigulki w tabeli i przycisku w karcie -
 * mapowania nie trzeba sie uczyc dwa razy. Stoi PO `.btn` i po `.stan`, wiec
 * przy rownej specyficznosci wygrywa kolejnoscia.
 *
 * SAM ATRAMENT TO ZA MALO - zmierzone 1,30:1 miedzy „nowy" a „odpada"
 * w Kartotece, czyli roznica, ktorej przy przewijaniu listy nie widac. Gotowe
 * tla tez nie wystarcza: w Planie `--tlo-2` i `--tlo-3` to OBA czysty biel.
 *
 * Stad KAZDY stan ma wlasny zeton tla (prosba Andreia z 2026-08-11). Zetony,
 * a nie wartosci w tej regule, bo inaczej szesc motywow dostaje jedna palete,
 * a `plan` i `kartoteka` stoja na zupelnie innym papierze.
 *
 * Barwy sa TINTAMI AKCENTU, nie rolami semantycznymi - i to jest ta roznica,
 * ktorej pilnuje `DESIGN.md`. Akcent stoi >=30 stopni od `--sem-brak`,
 * `--sem-uwaga` i `--sem-dobrze` w kazdym motywie (`test_akcent_daleko_od_semantyki`),
 * wiec wyslana NIE MOZE zabrzmiec jak „potwierdzone" ani jak
 * „uwaga". Czerwien i bursztyn zostaja przy jakosci leada, tak jak byly.
 *
 *   nowy        - najjasniejsza pigulka, bez barwy: stan domyslny wiekszosci
 *                 wierszy, ma NIE rzucac sie w oczy
 *   wyslana     - PELNY akcent, jasny napis, grubsze pismo: domkniete.
 *                 Jedyna odwrocona biegunowosc w tabeli - patrz nizej
 *   odpada      - cieply neutral, o pol drabinki nizej niz wyslana:
 *                 brak barwy akcentu przy stanach w toku jest tu znaczeniem
 *
 * Pierwsze podejscie (2026-08-11) dobralo te cztery tla NA OKO i wyszly za
 * blade: zmierzone potem w przegladarce 1,02-1,09 pigulki do tla wiersza,
 * czyli cztery pigulki nie do odroznienia od wiersza ani od siebie.
 * Rownie zle wypadlo rozsuwanie ich sama BARWA - w Duzym i Ksiedze akcent
 * jest niemal czarny, wiec jego tint jest szary i barwa nie rozsuwa niczego.
 * Dzisiejsze wartosci sa policzone: kazda pigulka >=1,22 do wiersza, kazda
 * para >=1,14 do siebie, kazdy napis >=4,5:1. Dobierajac nowa - policz,
 * nie ogladaj (skrypt liczacy to samo: `scratchpad/dobierz_tla_statusow.py`).
 *
 * Kropka niesie ten sam postep ksztaltem (pusty krazek, polowa, pelny,
 * zblakly) i zostaje bez barwy - patrz `test_stan_pracy_nie_jest_kolorem`.
 * Dwie drogi do tej samej informacji, bo przy 1900 wierszach jedna nie
 * wystarcza nikomu, kto barw nie rozroznia. --- */
/* WSZYSTKIE cztery napisy pelnym atramentem. Arkusz roznicowal je glebia
 * atramentu (`--tekst-2` na „nowy", `--tekst-3` na „odpada"), bo wtedy to
 * atrament niosl stan. Teraz niesie go TLO, a przygaszony atrament na napisie
 * 11 px daje juz tylko gorzej czytelny napis - w Kartotece i Ksiedze schodzil
 * pod 7:1. Stan czyta sie tlem, ksztaltem kropki i slowem; atrament ma byc
 * po prostu czytelny. */
.praca-nowy { color: var(--tekst); background: var(--praca-nowy-tlo); }
/* JEDYNY stan z odwrocona biegunowoscia: jasny napis na pelnym akcencie.
 *
 * Dwie proby poszly w liczbe i obie byly zle. Najpierw 4,61-4,82:1 (prog WCAG
 * to podloga, nie cel), potem 7,19-8,67:1 - i Andrei DALEJ zglosil „ciemny
 * tekst na ciemnym tle". Bo wzor WCAG liczy wylacznie JASNOSC: granat
 * `#12183a` na blekicie `#9aa3e6` to ta sama barwa, tylko ciemniejsza, wiec
 * 7,19 mowilo „czytelne", a oko widzialo jednolita plame. Kontrastu odcienia
 * ten wzor nie mierzy i zadna wieksza liczba w TEJ SAMEJ barwie tego nie
 * naprawi.
 *
 * Odwrocenie biegunowosci naprawia - i nie wymaga nowego zetonu: `--akcent`
 * pod `--na-akcencie` to para, ktora arkusz juz niesie (`.btn.glowny`,
 * `.chip.on`, `.stan-trwa`) i ktorej pilnuje `test_kontrast_wcag_na_kazdym_motywie`.
 * Przy okazji rampa stanow czyta sie mocniej: trzy pigulki jasne, jedna
 * zalana - „domkniete" widac z drugiego konca tabeli. */
.praca-wyslana {
  color: var(--na-akcencie);
  background: var(--akcent);
  border: 1px solid var(--akcent);
  font-weight: 700;
}
/* `odpada` jest CIEPLE, nie neutralnie szare - i to nie jest ozdoba. Neutralna
 * szarosc rozni sie od `wyslana` glownie odcieniem, a w Duzym i Ksiedze akcent
 * jest niemal czarny, wiec `wyslana` TEZ wychodzi szara i odcienia nie ma.
 * Cieplo jest tam jedynym wymiarem, ktory zostaje. */
.praca-odpada { color: var(--tekst); background: var(--praca-odpada-tlo); }

/* NAJECHANIE NIE MOZE SKASOWAC BARWY STANU.
 *
 * `.btn:hover` ma specyficznosc (0,2,0) - pseudoklasa liczy sie jak klasa -
 * a `.praca-*` tylko (0,1,0). Przy najechaniu tlo wracalo wiec do `--tlo-2`,
 * a `color` zostawal ten ze stanu. Dopoki wszystkie cztery stany mialy ciemny
 * napis, nie bylo tego widac. Od chwili, gdy „wyslana" dostala napis
 * `--na-akcencie`, najechanie dawalo BIALY NAPIS NA JASNYM TLE - zgloszone
 * przez Andreia na Kartotece, 2026-08-11.
 *
 * `.btn.glowny` chroni sie przed tym samym mechanizmem sama: ma rowna
 * specyficznosc (0,2,0) i stoi w arkuszu PO `.btn:hover`, wiec wygrywa
 * kolejnoscia. Stany pracy nie moga skorzystac z tej sztuczki, bo ta sama
 * klasa maluje takze pigulke w tabeli, gdzie `.btn` nie ma.
 *
 * Sprzezenie zwrotne przy najechaniu niesie `filter`, nie barwa: przyciemnia
 * to, co jest, zamiast to zastepowac - wiec dziala na kazdym z czterech stanow
 * i nie trzeba go dobierac osobno. */
.btn.praca-nowy:hover { background: var(--praca-nowy-tlo); }
.btn.praca-wyslana:hover { background: var(--akcent); }
.btn.praca-odpada:hover { background: var(--praca-odpada-tlo); }
.btn.praca-nowy:hover, .btn.praca-wyslana:hover,
.btn.praca-odpada:hover { filter: brightness(.93); }

/* KTORY stan jest ustawiony. Do 2026-08-11 szablon dokladal `wybrany`, a arkusz
 * nie mial dla tej klasy ani jednej reguly - cztery przyciski w karcie
 * wygladaly identycznie i nie dalo sie odczytac, ktory stan firma ma teraz.
 * Barwe niesie `.praca-*`, ta klasa niesie wylacznie „to jest ten". */
.btn.wybrany { border-color: var(--akcent); font-weight: 700; }

/* CALA KOMORKA stanu zalana barwa, nie pigulka w jej srodku (2026-08-10,
 * za kanwa). To nie jest ozdoba i nie lamie reguly „semantyka niesie
 * znaczenie": stan przebiegu JEST trescia tej komorki, wiec zalanie jej mowi
 * to samo, co pigulka, tylko glosniej. Przy liscie przebiegow chodzi
 * dokladnie o to, zeby „PRZERWANE" bilo w oczy katem oka.
 *
 * `:has()` zamiast klasy na `<td>`: klasa pigulki niesie `display:
 * inline-block`, a komorka z `inline-block` wypada z algorytmu ukladu tabeli
 * i rozciaga kolumne - zmierzone 2026-08-09, rozrzut 51 px w jednej kolumnie.
 * Ta sama pulapka, drugie podejscie.
 *
 * Pigulka w srodku traci wtedy wlasne tlo, zeby nie bylo barwy na barwie.
 *
 * ZAWEZONE 2026-08-11 do przebiegu, ktory ZYJE. Zalanie weszlo, gdy w tabeli
 * stal jeden przebieg; przy szesciu pieciokrotnie powtorzona zielen przestaje
 * cokolwiek mowic - to samo niesie spokojne slowo w kazdym wierszu - a przy
 * okazji KASUJE KRESKI miedzy wierszami: `--linia-2` na `--sem-dobrze-tlo`
 * to zmierzone 1,01:1 w Planie, czyli piec wierszy zlewa sie w jeden ksztalt.
 * Na `--akcent` ta sama kreska ma 7,05:1, wiec tam zalanie krawedzi nie zjada.
 *
 * Barwa zostaje wiec tam, gdzie niesie UWAGE, a nie tam, gdzie powtarza slowo.
 * Stany koncowe wracaja do pigulek - maja wlasne tla z regul wyzej. */
.wyniki td:has(> .stan-trwa) { background: var(--akcent); }
.wyniki td:has(> .stan-trwa) > .stan-trwa {
  background: transparent;
  padding-left: 0;
  padding-right: 0;
}

/* --- Karta firmy --- */

.karta h3 {
  font-family: var(--font-naglowek);
  font-size: calc(var(--ts-baza) + 3px);
  line-height: 1.25;
  margin: 0 0 3px;
}
.karta .nip { font-size: var(--ts-mikro); color: var(--tekst-2); margin-bottom: 16px; }
.pole { margin-bottom: 13px; }
.pole .etykieta {
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-weight: 600;
  color: var(--tekst-3);
  margin-bottom: 3px;
}
.pole .wartosc { font-size: var(--ts-baza); }
.pole .zrodlo { font-size: var(--ts-mikro); color: var(--tekst-3); }
/* SIATKA 2x2, nie zawijany rzad. Przyciski dobieraly szerokosc do napisu, wiec
 * przy szerokosci karty miescily sie trzy, a „odpada" spadalo w drugi rzad samo
 * i wezsze od pozostalych - cztery rownorzedne wybory wygladaly jak trzy plus
 * dopisek. Stale dwie kolumny zamiast `auto-fit`: `auto-fit` przy niektorych
 * szerokosciach karty daje 3+1, czyli dokladnie ten sam krzywy uklad. */
.statusy {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5px;
  margin-top: 6px;
}
textarea.notatka {
  width: 100%;
  min-height: 72px;
  font: inherit;
  font-family: var(--font-tekst);
  font-size: var(--ts-mikro);
  padding: 9px 10px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-mala);
  background: var(--tlo);
  color: var(--tekst);
  resize: vertical;
}
.zapisane { animation: mrugniecie 900ms ease-out; }
@keyframes mrugniecie { 0% { background: var(--tlo-2); } 100% { background: transparent; } }

/* --- Formularze --- */

/* Kolumna formularza jest WASKA celowo - pole rozciagniete na 1900px jest
 * nieczytelne, oko gubi poczatek linii. Ale 640px na szerokim monitorze
 * czytalo sie jak „strona sie nie rozciagnela", a nie jak decyzja: przy dwoch
 * polach w rzedzie (rodzaj obszaru + obszar) robilo sie ciasno, a po prawej
 * zostawal metr pustki. 820px miesci te dwa pola wygodnie i nadal trzyma
 * dlugosc linii w ryzach. */
.formularz { max-width: 820px; padding: 26px 0; }
.formularz label {
  display: block;
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .09em;
  font-weight: 600;
  color: var(--tekst-3);
  margin-bottom: 6px;
}
/* Typ pola trzeba tu DOPISAC. Pole spoza tej listy nie dostaje ani szerokosci,
 * ani obramowania, ani tla - zostaje golym prostokatem sklejonym z etykieta
 * i wyglada na zepsute, choc dziala. Tak bylo z `password` od chwili powstania
 * ekranu logowania (2026-08-07) do 2026-08-09: nikt tego nie widzial, bo panel
 * na serwerze stal jeszcze na wersji bez logowania. Dopisujac `email`, `number`
 * czy `date`, dopisz je rowniez tutaj. */
.formularz input[type="text"], .formularz input[type="password"], .formularz select {
  width: 100%;
  font: inherit;
  font-family: var(--font-tekst);
  padding: 10px 12px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-mala);
  background: var(--tlo-3);
  color: var(--tekst);
  margin-bottom: 16px;
}
.formularz .rzad { display: flex; gap: 14px; }
.formularz .rzad > * { flex: 1; }
.formularz .podpowiedz {
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
  margin: -12px 0 18px;
  padding-left: 11px;
  border-left: 2px solid var(--linia-2);
}

/* --- Podpowiedzi pod polem.
 *
 * Lista jest UNIESIONA nad formularzem (`position: absolute`), a nie wpycha
 * go w dol: inaczej przy kazdym nacisnieciu klawisza przycisk startu skakalby
 * o wysokosc listy - a to jest ten sam przycisk, ktory uruchamia kilkugodzinny
 * przebieg i pod ktorym stoi ocena niszy. --- */

.z-podpowiedzia { position: relative; }
.kotwica-podpowiedzi { position: absolute; left: 0; right: 0; z-index: 20; }
.podpowiedzi {
  list-style: none;
  margin: -13px 0 0;
  padding: 4px;
  background: var(--tlo);
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-srednia);
  /* WŁASNY żeton cienia, nie `--cien-karta`. Ta lista jest jedyną powierzchnią,
   * która ląduje NA KARCIE, więc sposób, w jaki motyw oddziela kartę od strony,
   * nie działa tu wcale. W Planie karta jest biała, strona chłodna i `--cien-karta`
   * jest `none` - świadomie, bo tam kartę wycina sam kolor. Lista położona na tej
   * karcie zostawała więc bez granicy: kreska ma 1,38:1 wobec białego.
   * Zgłoszone z produkcji 2026-08-11. Motywy z prawie czarną kreską mają tu `none`
   * - cień byłby w nich obcy, a granicę niesie linia. */
  box-shadow: var(--cien-popup);
  max-height: 260px;
  overflow-y: auto;
}
.podpowiedz-poz {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-family: var(--font-tekst);
  font-size: var(--ts-baza);
  padding: 7px 10px;
  border: 0;
  border-radius: var(--r-mala);
  background: transparent;
  color: var(--tekst);
  cursor: pointer;
}
.podpowiedz-poz:hover { background: var(--tlo-2); }
.podpowiedz-poz:focus-visible { background: var(--tlo-2); }

/* --- „Widać, że pracuje".
 *
 * Panel pokazywany przez htmx na czas zadania (`hx-indicator`). Domyslnie
 * niewidoczny; klasa `htmx-request` zapala go na czas lotu.
 *
 * Wymienia KROKI i CZAS, KTORY MINAL - nie udaje procentow. Tlumaczenie zawodu
 * na kod to jedno zapytanie do modelu, ktore nie melduje postepu w srodku, wiec
 * kazdy pasek „ile zostalo" bylby zmyslony. Zmierzone 2026-08-07: nowy zawod
 * ~8 s, zawod zapamietany ~2,7 s.
 *
 * To jedyna animacja dolozona do arkusza od czasu paska przebiegu, i podlega
 * tej samej zasadzie: ramie obraca sie DOPOKI trwa zadanie i gasnie razem
 * z nim, wiec mowi „to jeszcze leci" - czego inaczej nie da sie powiedziec. --- */

.pracuje {
  display: none;
  align-items: center;
  gap: 16px;
  margin: 4px 0 18px;
  padding: 14px 16px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-duza);
  background: var(--tlo-3);
}
.pracuje.htmx-request { display: flex; }

.omiatacz { width: 44px; height: 44px; flex: none; }
.omiatacz .tarcza { fill: none; stroke: var(--linia-2); stroke-width: 1.5; }
.omiatacz .tarcza.cichsza { stroke-dasharray: 2 4; }
.omiatacz .ramie {
  stroke: var(--akcent);
  stroke-width: 2.5;
  stroke-linecap: round;
  transform-origin: 24px 24px;
  animation: omiatanie 2.6s linear infinite;
}
@keyframes omiatanie { to { transform: rotate(360deg); } }

.pracuje-tytul { font-weight: 600; }
.pracuje-tytul .sekundy { color: var(--tekst-2); font-variant-numeric: tabular-nums; }
.pracuje-kroki {
  margin: 6px 0 0;
  padding-left: 18px;
  font-size: var(--ts-mikro);
  color: var(--tekst-3);
}
/* Pierwszy krok jest wyrozniony, bo to on trwa - reszta przelatuje w sekunde. */
.pracuje-kroki .dlugi { color: var(--tekst-2); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .omiatacz .ramie { animation: none; }
}

/* --- Ocena niszy --- */

/* --- Uklad z bocznym menu ---
   Pasek gorny mial siedem pozycji i przy 800 px nie miescil sie: „Nowe
   wyszukiwanie" bylo ucinane, a strona dostawala poziomy suwak. Kolumna rosnie
   w dol, wiec kolejna pozycja niczego nie wypycha. */
/* Kontener aplikacji. 1440 px, bo bez sufitu tresc szla do krawedzi okna:
   zmierzone na 1920 px slupek „E-mail i telefon" (9,8%) mial 1350 px toru,
   a kolumna „Zawod" 640 px na jedno slowo.

   `align-items: stretch` zamiast `flex-start` - rail bocznego menu ma siegac
   dolu okna, a nie konczyc sie na ostatniej pozycji. Do 2026-08-10 robil to
   wylacznie ekran wynikow (osobna regula w bloku `pelne-okno`), wiec kreska
   menu na Pulpicie urywala sie w polowie.

   1760 px, a nie 1440 - poszerzone tego samego dnia na prosbe Andreia
   („o jakies 200-400 px, wybierz sam"). Wybrana ta wartosc, bo jest
   ZMIERZONYM progiem, a nie srodkiem widelek: tabela wynikow potrzebuje
   1092 px i przy 1440 dostawala 867, czyli miala wlasny poziomy suwak.
   Przy 1760 dostaje 1187 i suwak znika - cena kontenera, przyjeta rano
   swiadomie, przestala byc potrzebna. */
.uklad {
  display: flex;
  align-items: stretch;
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 1760px;
  margin-inline: auto;
}

.menu {
  flex: 0 0 208px;
  padding: 12px 0;
  border-right: var(--grubosc-linii) solid var(--linia);
}

.menu-poz {
  display: block;
  padding: 9px 18px;
  color: var(--tekst-2);
  font-size: var(--ts-mikro);
  text-decoration: none;
  border-left: 3px solid transparent;
}

.menu-poz:hover { background: var(--tlo-2); color: var(--tekst); text-decoration: none; }

.menu-poz.aktywna {
  /* Wypelniona, nie podkreslona. Na kanwie to jest jedyny element nawigacji,
     ktory widac katem oka - a przy szesciu pozycjach o to wlasnie chodzi. */
  color: var(--na-akcencie);
  font-weight: 700;
  background: var(--akcent);
  border-left-color: var(--akcent);
}

/* Wylogowanie jest FORMULARZEM, a nie odnosnikiem, bo `GET /wyloguj` dalby sie
 * odpalic z obcej strony samym obrazkiem. Przycisk ma wiec wygladac jak pozycja
 * menu - to jedyne miejsce w tym arkuszu, gdzie o formie elementu przesadza
 * bezpieczenstwo, a nie uklad. Odsuniety linia, bo konczy liste, a nie
 * doklada sie do niej. */
.menu-stopka {
  margin-top: 12px;
  padding-top: 12px;
  border-top: var(--grubosc-linii) solid var(--linia);
}
.menu-stopka button {
  width: 100%;
  text-align: left;
  font-family: var(--font-tekst);
  font-size: var(--ts-mikro);
  /* Przegladarka daje przyciskom `line-height: normal`, a odnosnikom obok
     dziedziczy sie interlinia z tekstu. Bez tej linii „Wyloguj" jest o 3 px
     nizszy od kazdej innej pozycji menu - zmierzone, nie przewidziane. */
  line-height: inherit;
  background: none;
  border: 0;
  border-left: 3px solid transparent;
  cursor: pointer;
}

/* `min-width: 0` jest tu WARUNKIEM, nie ozdoba: bez niego element w zwijce
   nie schodzi ponizej szerokosci swojej najszerszej tabeli i to ona rozpycha
   caly uklad, zamiast dostac wlasny suwak.

   Nazwa `.ekran`, a NIE `.plotno`: ta druga jest juz zajeta przez dwukolumnowy
   uklad ekranu wynikow (`display: flex` z `.lewa` i `.prawa`). Zderzenie nazw
   ustawilo kafle, tabele i odnosnik w jednym rzedzie - i zaden straznik tego
   nie zlapal, bo on sprawdza, czy klasa ISTNIEJE w arkuszu, a ta istniala az
   za dobrze. */
.ekran {
  flex: 1 1 auto;
  min-width: 0;
  /* Margines boczny stoi TUTAJ, raz. Wczesniej nosil go kazdy ekran osobno
     (`.formularz`, `.powitanie`, `.pomoc`), wiec kazdy nowy o nim zapominal -
     i tak wlasnie tabela pulpitu dotknela prawej krawedzi okna.

     Gora dostala 18 px 2026-08-10, po zgloszeniu Andreia. Bylo zero: kafle
     i pasek postepu dotykaly dolnej krawedzi paska gornego, czyli dwie linie
     lezaly na sobie. Istnialo to od zawsze i nie bylo widac, dopoki pasek
     ciagnal sie przez cala szerokosc okna - po zamknieciu w kontenerze obie
     linie koncza sie w tym samym punkcie i robia rog.

     18 px, bo taki jest rytm WEWNATRZ tresci (kafle -> wykres -> tabela,
     zmierzone). Gora ma sie zgadzac z reszta, a nie byc czwarta wartoscia. */
  padding: 18px 20px 24px;
}

@media (max-width: 900px) {
  .uklad { display: block; }
  .menu {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 8px;
    border-right: 0;
    border-bottom: var(--grubosc-linii) solid var(--linia);
  }
  .menu-poz { border-left: 0; border-bottom: 3px solid transparent; padding: 8px 12px; }
  .menu-poz.aktywna { border-left-color: transparent; border-bottom-color: var(--akcent); }
}

/* --- Pulpit: kafle ---
   Cztery liczby, ktore odpowiadaja na pytanie „co ja tu mam", zanim ktokolwiek
   kliknie w tabele. Liczby ida Z BAZY, nie z licznikow w pamieci. */
/* Kafle stykaja sie krawedziami - JEDNA tasma, a nie cztery pudelka w rzedzie.
 *
 * To jest ta roznica wobec kanwy, ktora Andrei nazwal „u nas jakos za slabo"
 * (2026-08-10), a ktora nie byla o barwie: jezyk form mielismy ten sam (ostre
 * rogi, 2 px linii, zero cieni), tylko mowiony polglosem. Odstep miedzy
 * blokami rozbija je na osobne przedmioty; wspolna krawedz robi z nich jeden.
 *
 * Obramowanie nosi POJEMNIK, a komorki tylko kreske po lewej - inaczej
 * sasiadujace ramki sumowalyby sie do 4 px i tasma mialaby grubsza linie
 * w srodku niz na zewnatrz. */
.kafle {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0;
  border: var(--grubosc-linii) solid var(--linia);
  margin-bottom: 18px;
}
.kafel + .kafel { border-left: var(--grubosc-linii) solid var(--linia); }

.kafel {
  padding: 14px 16px;
  background: var(--tlo-3);
}

.kafel-nazwa {
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--tekst-2);
}

.kafel-liczba {
  /* Akcent, nie atrament. To sa cztery liczby na ekranie podsumowania, a nie
     tysiac wierszy tabeli - argument „barwa dziala, bo jest rzadka" dotyczy
     tabeli, nie kafla. Akcent trzyma sie >=30 stopni od kazdej roli
     semantycznej, wiec nie miesza sie z „brak/uwaga/dobrze". */
  color: var(--akcent);
  margin-top: 4px;
  font-family: var(--font-cyfry);
  font-size: var(--ts-duza);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.kafel-opis { margin-top: 2px; font-size: var(--ts-mikro); color: var(--tekst-3); }

/* --- Wykres „Kontakt w bazie". Pierwszy wykres w tej aplikacji, wiec ustala
 * wzorzec: slupki z elementow, a nie SVG.
 *
 * SVG wymagaloby wlasnego ukladu tekstu i wlasnego skalowania, a tu wszystko -
 * krój, rozmiar pisma, barwy z zetonow, zawijanie polskich nazw -
 * przychodzi z arkusza za darmo. Ta sama technika co pasek postepu (`.tor i`),
 * ktora w tym projekcie juz dziala.
 *
 * Cztery slupki sa PODZIALEM bazy, wiec wszystkie niosa te sama miare i ta sama
 * barwe. Rozny kolor na slupek sugerowalby rozne znaczenia. Wyjatkiem jest
 * nieobecnosc kontaktu - stlumiona, nie czerwona: rola semantyczna zostaje
 * przy swojej barwie i nie sluzy do zdobienia. --- */

.wykres {
  margin-bottom: 18px;
  padding: 14px 16px;
  border: var(--grubosc-linii) solid var(--linia);
  background: var(--tlo-3);
}

.wykres-tytul {
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--tekst-2);
  margin-bottom: 12px;
}

.wykres-wiersz {
  display: grid;
  /* Nazwa staloszerokosciowa, zeby slupki zaczynaly sie w jednej linii -
     inaczej „E-mail i telefon" przesuwalby caly rzad wzgledem „Tylko e-mail"
     i porownanie dlugosci, czyli caly sens wykresu, przestawaloby dzialac. */
  grid-template-columns: 148px 1fr 56px 52px;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
}

.wykres-nazwa { font-size: var(--ts-mikro); color: var(--tekst-2); }

.wykres-tor {
  height: 10px;
  background: var(--linia-2);
  border-radius: var(--r-pigulka);
  overflow: hidden;
}

.wykres-slupek {
  display: block;
  height: 100%;
  min-width: 2px;
  background: var(--akcent);
  border-radius: var(--r-pigulka);
  transition: width 600ms ease;
}

/* Nieobecnosc kontaktu. Stlumiona, bo to jedyna grupa, ktorej NIE chcemy -
   ale bez barwy semantycznej: „brak" znaczy w tym arkuszu werdykt o stronie
   firmy i nie moze zaczac znaczyc dwoch rzeczy naraz. */
.wykres-brak { background: var(--linia); opacity: .55; }

.wykres-liczba { text-align: right; }
.wykres-udzial { font-size: var(--ts-mikro); color: var(--tekst-3); text-align: right; }

/* Bez wlasnej reguly `prefers-reduced-motion` - na koncu tego arkusza stoi
   jedna, ktora gasi kazde przejscie i kazda animacje. Druga kopia tylko
   udawalaby, ze rzecz jest zalatwiona w dwoch miejscach. */

@media (max-width: 700px) {
  /* Nazwa nad slupkiem: przy 148px na nazwe i dwoch kolumnach liczb slupek
     schodzi na tym ekranie do kilkudziesieciu pikseli i przestaje cokolwiek
     pokazywac. */
  .wykres-wiersz { grid-template-columns: 1fr 56px 52px; }
  .wykres-nazwa { grid-column: 1 / -1; }
}

.ocena {
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-duza);
  background: var(--tlo-3);
  padding: 18px 20px;
  /* Gorny margines NIE jest kosmetyka: bez niego karta zaczynala sie dokladnie
     tam, gdzie konczyl sie przycisk „Sprawdz, czy warto" - zmierzone, odstep
     wynosil 0 px, wiec dwie ramki po 1 px siadaly na jednej linii i czytalo sie
     to jak nachodzenie elementow na siebie. */
  margin: 18px 0;
  box-shadow: var(--cien-karta);
}

/* --- Werdykt bramki ---
   Pierwsze zdanie odpowiada na pytanie, z ktorym ktos klikal („czy warto?"),
   zamiast zaczynac od kodu klasyfikacji.

   Trzy stany, bo trzy rozne odpowiedzi: jest z czego szukac, jest ale malo,
   nie ma nic. Czwarty - milczenie rejestru - zostaje przy `.blad`, bo jako
   jedyny znaczy „cos sie zepsulo", a nie „sprawdzilem i tyle z tego wyszlo". */
.werdykt {
  margin: 18px 0 0;
  padding: 14px 18px;
  border: var(--grubosc-linii) solid var(--linia);
  border-left-width: 5px;
  background: var(--tlo-3);
}

.werdykt-tytul {
  font-family: var(--font-naglowek);
  font-weight: 700;
  font-size: var(--ts-nazwa);
}

.werdykt-tresc {
  margin-top: 4px;
  color: var(--tekst-2);
  font-size: var(--ts-mikro);
}

.werdykt-liczba {
  font-family: var(--font-cyfry);
  font-size: var(--ts-duza);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.werdykt.jest { border-left-color: var(--sem-dobrze); }
.werdykt.jest .werdykt-liczba { color: var(--sem-dobrze); }
.werdykt.slabo { border-left-color: var(--sem-uwaga); }
.werdykt.slabo .werdykt-liczba { color: var(--sem-uwaga); }
/* Pusto NIE dostaje barwy semantycznej. „Sprawdzilem i nic tu nie ma" jest
   uczciwa odpowiedzia, a nie ostrzezeniem ani awaria - kolor robilby z niej
   jedno albo drugie. */
.werdykt.pusto { border-left-color: var(--linia-2); }
.ocena .slaba { color: var(--sem-uwaga); font-weight: 700; }
.ocena .uwaga { font-size: var(--ts-mikro); color: var(--tekst-2); margin-top: 10px; }

/* --- Komunikaty --- */

.pusto { padding: 40px 20px; color: var(--tekst-2); }
.blad {
  margin: 16px 20px;
  padding: 12px 15px;
  border: var(--grubosc-linii) solid var(--tekst);
  border-radius: var(--r-srednia);
  font-size: var(--ts-baza);
}

/* --- Ekran powitalny i pomoc. Tekst ciagly, wiec jedyne miejsce w tej
 * aplikacji, gdzie szerokosc jest ograniczona miara czytania (~65 znakow),
 * a nie szerokoscia okna. --- */

.powitanie, .pomoc { max-width: 68ch; padding: 34px 0 60px; }
/* Bez `.logowanie` - ten ekran nie ma juz naglowka. Nazwa aplikacji zniknela
   stamtad swiadomie (2026-08-09), wiec i regula, ktora by ja stylizowala. */
.powitanie h1, .pomoc h1 {
  font-family: var(--font-naglowek);
  font-size: calc(var(--ts-baza) + 12px);
  line-height: 1.15;
  letter-spacing: -.02em;
  margin: 0 0 12px;
  text-wrap: balance;
}
.pomoc h2 {
  font-family: var(--font-naglowek);
  font-size: calc(var(--ts-baza) + 3px);
  margin: 34px 0 10px;
  padding-bottom: 7px;
  border-bottom: var(--grubosc-linii) solid var(--linia);
}
.wiodacy { font-size: calc(var(--ts-baza) + 2px); color: var(--tekst-2); }
.powitanie p, .pomoc p { margin: 0 0 12px; }

/* --- Ekran logowania: jedno pole i jeden przycisk, na srodku okna.
 *
 * Do 2026-08-09 byla to waska kolumna dosunieta do lewej, pod paskiem
 * i naglowkiem - na szerokim monitorze czytalo sie to jak strona, ktora sie nie
 * rozciagnela. Teraz pasek i nawigacja sa zgaszone (patrz `zaloguj.html`),
 * wiec ekran jest pusty i jedyna tresc moze stanac tam, gdzie oko jej szuka.
 *
 * `min-height: 100vh` na samym `.logowanie`, a nie na rodzicu: `.uklad` stoi
 * na `align-items: flex-start`, wiec `.ekran` nie rozciagnie sie sam. Wysokosc
 * dziecka rozpycha go od srodka i wyrownanie w pionie zaczyna dzialac.
 *
 * Barwy zadnej wlasnej - ekran dostaje wszystkie piec motywow za darmo. --- */

.logowanie {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
/* `.ekran` niesie 24px dolnego dopelnienia dla wszystkich widokow. Przy
 * `min-height: 100vh` na logowaniu daje to 24px nadmiaru i suwak przewijania
 * na stronie, na ktorej nie ma czego przewijac. Zerujemy je TYLKO tutaj -
 * `:has()` zamiast klasy na `.ekran`, zeby `rama.html` nie musiala wiedziec,
 * ktory ekran akurat renderuje. */
.ekran:has(> .logowanie) { padding: 0; }
.logowanie-pole { width: 100%; max-width: 19rem; }
.logowanie-pole .formularz { max-width: none; padding: 0; }
.logowanie-pole .blad { margin: 0 0 18px; }
.powitanie-akcje { display: flex; gap: 10px; flex-wrap: wrap; margin: 22px 0 0; }
.powitanie-gotowosc {
  margin-top: 34px;
  padding-top: 18px;
  border-top: var(--grubosc-linii) solid var(--linia);
  font-size: var(--ts-mikro);
  color: var(--tekst-2);
}

.kroki { padding-left: 20px; margin: 0; }
.kroki li { margin-bottom: 12px; }
.slowniczek { margin: 0; }
.slowniczek dt {
  font-weight: 700;
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--tekst-3);
  margin-top: 16px;
}
.slowniczek dd { margin: 3px 0 0; }

/* --- Sprawdzenie gotowosci. Stan czyta sie ZNAKIEM I ZDANIEM, a barwa jest
 * tylko wzmocnieniem - ten ekran oglada sie raz i musi dzialac takze wtedy,
 * gdy ktos barw nie rozroznia. --- */

.kontrole { list-style: none; margin: 16px 0 0; padding: 0; }
.kontrola {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 11px 0;
  border-bottom: 1px solid var(--linia-2);
}
.kontrola .znak {
  flex: none;
  width: 16px; height: 16px;
  margin-top: 2px;
  border: 2px solid var(--tekst-3);
  border-radius: 50%;
}
.kontrola.dobrze .znak { border-color: var(--sem-dobrze); background: var(--sem-dobrze); }
.kontrola.zle .znak { border-color: var(--sem-uwaga); background: var(--sem-uwaga); }
.nazwa-kontroli { font-weight: 600; }
.kontrola .komunikat { font-size: var(--ts-mikro); color: var(--tekst-2); }
.kontrola.zle .komunikat { color: var(--sem-uwaga); }

/* --- Przelacznik motywu --- */

/* Etykieta dla czytnika ekranu. `display: none` zabralby ja takze czytnikowi,
 * a `title` na `select` nie jest etykieta - jest podpowiedzia. */
.tylko-dla-czytnika {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Cztery pary „etykieta nad polem". Wczesniej byl to jeden rzad w pasku
   u gory, gdzie etykiety byly schowane przed wzrokiem (`tylko-dla-czytnika`) -
   po przeniesieniu do Ustawien staly sie widoczne i lamaly sie w slupki miedzy
   polami. Siatka daje kazdej parze wlasna kolumne i zwija sie sama. */
.wyglad {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  align-items: end;
}

.wyglad label {
  display: block;
  font-size: var(--ts-mikro);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--tekst-2);
  margin-bottom: 4px;
}

.wyglad > div, .wyglad > span { min-width: 0; }
.wyglad select {
  font: inherit;
  font-family: var(--font-tekst);
  font-size: var(--ts-mikro);
  padding: 5px 8px;
  border: var(--grubosc-linii) solid var(--linia);
  border-radius: var(--r-mala);
  background: var(--tlo-3);
  color: var(--tekst);
  cursor: pointer;
}

/* --- Sprawdzenie bazy klienta -------------------------------------------- */
/* Drugi tryb produktu. Zadna z tych regul nie zawiera wartosci barwy - siegaja
   wylacznie po zetony, wiec dzialaja we wszystkich trzech motywach naraz. */

/* Wspolna czytelna kolumna: walidacja, odswiezanie, ustawienia i ekrany
 * ich wynikow. Do 2026-08-09 nazywala sie `.walidacja`, przez co Ustawienia
 * pozyczaly klase walidacji - i ich szerokosc wziela sie stamtad przypadkiem.
 * 760px zostawialo na szerokim monitorze metr pustki po prawej i czytalo sie
 * jak niedokonczony uklad; 1040px wypelnia ekran, nie rozciagajac przy tym
 * wierszy klucz-wartosc do nieczytelnej dlugosci. */
.kolumna { max-width: 1040px; padding: 26px 20px; }

.wgranie {
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
  margin: 20px 0;
  padding: 20px;
  border: var(--grubosc-linii) dashed var(--linia-2);
  border-radius: var(--r-mala);
  background: var(--tlo-2);
}

.wgranie input[type="file"] { flex: 1; min-width: 220px; font: inherit; }

.drobne { font-size: var(--ts-mikro); color: var(--tekst-2); }

/* CEL KLIKALNY ma miec co najmniej 24 px wysokosci (WCAG 2.2 AA, 2.5.8).
 * Zmierzone przed poprawka: 14 px („Co jest ustawione" na Pulpicie), 16-18 px
 * (nazwy w listach przebiegow, odswiezen i sprawdzen), 22 px (wybor pliku).
 *
 * Dotyczy odnosnikow SAMODZIELNYCH - takich, ktore sa cala trescia swojej
 * komorki albo akapitu. Odnosniki W ZDANIU norma zwalnia i my tez: powiekszanie
 * ich rozpychaloby akapit, a trafic w nie i tak latwo, bo sasiaduja z tekstem,
 * ktory nie jest celem.
 *
 * Wysokosc bierze `padding-block` na `inline-block`, bo `min-height` na
 * elemencie liniowym nie robi nic.
 *
 * Tabeli WYNIKOW to nie dotyka: jej wiersze nie maja ani jednego `<a>` -
 * klika sie caly wiersz, ktory ma 60 px. */
.wyniki td a,
.drobne a { display: inline-block; padding-block: 5px; }
input[type="file"] { padding-block: 5px; }

/* Etykieta obejmujaca pole wyboru JEST celem klikniecia - klikniecie w napis
 * przelacza pole - wiec to ona musi miec 24 px, a nie kwadracik w srodku.
 * Zmierzone: etykieta ciagnela sie przez 956 px szerokosci i miala 22 px
 * wysokosci, czyli o dwa za malo.
 *
 * Samo pole ma 13x13 i normy NIE lamie: rozmiar nadaje mu przegladarka,
 * a nie my, a to jest wprost wymienione zwolnienie w 2.5.8. Dlatego nie
 * powiekszam kwadracika - poprawiam to, w co sie faktycznie klika. */
.wybor {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 24px;
  margin-bottom: 6px;
}

/* Raport odswiezenia - tekst z silnika, kolumny wyrownane spacjami.
   Krój cyfrowy jest tu WARUNKIEM czytelnosci, a nie ozdoba: raport sklada
   `odswiez.format_raportu` i przy kroju proporcjonalnym liczby rozjezdzaja sie
   z opisami. Zadnych wartosci barw - tylko zetony, jak w kazdej regule
   strukturalnej. */
.raport {
  font-family: var(--font-cyfry);
  font-size: var(--ts-mikro);
  background: var(--tlo-3);
  border: var(--grubosc-linii) solid var(--linia);
  padding: 18px 20px;
  overflow-x: auto;
  white-space: pre;
}

.podsumowanie { width: 100%; border-collapse: collapse; }

.podsumowanie td {
  padding: 7px 0;
  border-bottom: var(--grubosc-linii) solid var(--linia);
}

.podsumowanie td:not(:first-child) {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-cyfry);
}

/* Waga wiersza niesie ZNACZENIE, nie ozdobe: klient ma zobaczyc na pierwszy
   rzut oka, co zyje, a co kosztuje go przy kazdej wysylce. Rola przy barwie,
   tak samo jak przy werdyktach na liscie firm. */
.wal-zyje td:first-child { color: var(--sem-dobrze); }
.wal-strata td:first-child { color: var(--sem-uwaga); font-weight: 700; }
.wal-uwaga td:first-child { color: var(--tekst-2); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
