/* Komponenty aplikacji. Żadnej wartości koloru ani odstępu wprost —
   wszystko z tokens.css, żeby motyw ciemny i kolor klienta były
   podmianą zmiennych, a nie drugim arkuszem. */
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
     font:var(--fs-base)/var(--lh) var(--font);-webkit-font-smoothing:antialiased}
h1,h2,h3{margin:0;font-weight:640;letter-spacing:-.011em}
h1{font-size:var(--fs-xl)} h2{font-size:var(--fs-lg)} h3{font-size:var(--fs-md)}
a{color:var(--accent);text-decoration:none}
button{font:inherit}

/* Pasek menu: 244 px zamiast 216. Lukasz, 03.09.2026: "ucina nazwe
   firmy, trzeba delikatnie dac szerszy ten pasek menu o kilkanascie
   pikseli, jest na to miejsce". Wgrane logo zajmuje w tym rzedzie
   miejsce, ktorego kwadracik z inicjalami nie zajmowal - nazwa firmy
   nie ma sie przez to lamac ani chowac za wielokropkiem. */
.shell{display:grid;grid-template-columns:244px 1fr;min-height:100vh}
.side{background:var(--surface-2);border-right:1px solid var(--line);
      display:flex;flex-direction:column;padding:var(--s4) var(--s3)}
/* Pasek marki ZAWIJA SIĘ, bo od 05.09.2026 logo jest dwa razy większe.
   Przy szerokim logotypie („serwis24" z napisem) w jednym rzędzie
   z tekstem zostawało na napisy dwadzieścia pikseli i pasek pokazywał
   „S… / Se…" — czyli ani logo, ani nazwy. Logo bierze cały rząd,
   nazwa programu staje pod nim i obie rzeczy są czytelne. */
.brandbar{display:flex;align-items:center;gap:10px;padding:4px 6px var(--s4);
  flex-wrap:wrap}
.logo{width:30px;height:30px;border-radius:8px;background:var(--accent);color:var(--accent-ink);
      display:grid;place-items:center;font-size:12px;font-weight:700;flex:none}
.brandtext{min-width:0}
.brandtext .t{font-weight:650;font-size:var(--fs-base);white-space:nowrap;
              overflow:hidden;text-overflow:ellipsis}
/* Nazwa programu pod spodem nie lamie sie na dwie linie - w rzedzie
   z logo wyglada to jak dwa osobne napisy, a nie jak podpis. */
.brandtext .s{font-size:var(--fs-xs);color:var(--ink-3);white-space:nowrap;
              overflow:hidden;text-overflow:ellipsis}
/* Kategoria i pozycje pod nia.
   Lukasz, 03.09.2026: "zlewa mi sie kategoria np. ZASOBY, a potem zaraz
   pod spodem Firmy jakos sie nie wyrozniaja - mozna zrobic tak, ze
   kategoria ma troche inniejszy kolor, bardziej widoczny, a nizej te
   podmenu sa delikatnie od lewej odsuniete o 3-4 pixele".
   Dokladnie tak: kategoria jasniejsza i z kreska, pozycje wciete
   i oparte o pionowa linie - widac, ze naleza do niej, a nie stoja
   obok. */
.side .grp{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.09em;
           color:var(--ink-2);font-weight:800;padding:18px 10px 7px;
           display:flex;align-items:center;gap:8px}
.side .grp::after{content:'';flex:1;height:1px;background:var(--line)}
.side button.nav{display:flex;align-items:center;gap:9px;padding:8px 10px 8px 16px;width:100%;
      border:0;border-left:2px solid var(--line);background:none;
      border-radius:0 var(--radius-sm) var(--radius-sm) 0;color:var(--ink-2);
      font-size:var(--fs-base);font-weight:520;cursor:pointer;text-align:left}
.side button.nav:hover{background:var(--surface);color:var(--ink);border-left-color:var(--g5)}
.side button.nav.on{background:var(--accent-soft);color:var(--accent);font-weight:640;
      border-left-color:var(--accent)}
.side .cnt{margin-left:auto;font-size:var(--fs-xs);color:var(--ink-3);
           font-variant-numeric:tabular-nums}
.sidefoot{margin-top:auto;padding:var(--s3) 10px 4px;border-top:1px solid var(--line);
          font-size:var(--fs-xs);color:var(--ink-3)}
.main{display:flex;flex-direction:column;min-width:0}
/* =====================================================================
   NAGLOWEK - trzy strefy, nie rzad guzikow.
   Siatka 1fr / auto / 1fr sprawia, ze zegar stoi POSRODKU paska
   niezaleznie od tego, ile rzeczy jest po prawej. Przy zwyklym flexie
   przesuwalby sie za kazdym razem, gdy przybywa jedna ikona.
   ===================================================================== */
/* WYSOKOŚĆ PASKA: 10 px → 16 px odstępu w pionie (razem ok. 62 → 74 px).
   Łukasz, 05.09.2026: „co sądzisz, żeby troszeczkę zrobić wyższy ten
   górny bar?".
   Sądzę, że tak — ale z innego powodu, niż wygląda na pierwszy rzut oka.
   NIE po to, żeby zrównać go z paskiem marki w kolumnie obok: ten ma
   teraz ze 140 px (logo urosło dwukrotnie), a pasek o takiej wysokości
   zabrałby dwa wiersze listy na KAŻDYM ekranie i to jest cena płacona
   codziennie za wyrównanie widoczne raz.
   Powód jest inny: najwyższą rzeczą w pasku jest blok „Zalogowany …"
   — twarz 38 px plus dwie linijki tekstu — i przy 10 px odstępu ten
   blok dotyka krawędzi. Sześć pikseli z góry i z dołu daje mu powietrze,
   a pasek przestaje wyglądać na wciśnięty pod logo. */
/* PROG POLICZONY, A NIE ZGADNIETY.
   Blad znaleziony 05.09.2026: przelaczenie ukladu stalo na 1640 px,
   liczbie wzietej z sufitu. Kolumny `1fr` sa ROWNE, wiec zeby zegar
   stanal posrodku, pasek musi zmiescic DWA RAZY szerokosc prawej strony
   (864 px zmierzone) plus sam zegar plus odstepy - okolo 1920 px. Do
   tego pasek jest o cale menu (244 px) wezszy od okna. Stad 2160 px.
   Przy oknie 1700 px stara regula dawala prawej stronie 612 px zamiast
   864; nadmiar wychodzil w LEWO i kladl sie na zegarze - pod plakietka
   czatu widac bylo date.
   Zapytanie kontenerowe byloby tu ladniejsze, ale element nie moze
   odpowiadac na wlasne `@container`, a postawienie kontenera na `.main`
   zrobiloby z niego blok zawierajacy dla `position:fixed` - czyli
   zepsuloby wszystkie okienka modalne w programie. */
.topbar{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
        align-items:center;gap:var(--s4);padding:16px var(--s6);
        border-bottom:1px solid var(--line);background:var(--surface)}
.topbar .sp{flex:1}
.top-lewo{display:flex;align-items:center;gap:var(--s4);min-width:0}
/* Szukajka oddaje miejsce jako pierwsza. Przy waskim oknie ma sie
   sciskac, a nie wchodzic na zegar stojacy w srodkowej kolumnie. */
.top-lewo .qs{flex:1 1 auto;min-width:0;max-width:460px}
.top-lewo .qs input{width:100%;min-width:0}
.top-tytul{display:flex;flex-direction:column;line-height:1.15;white-space:nowrap;
  min-width:0}
/* Nazwa ekranu USTĘPUJE MIEJSCA, zamiast wchodzić na zegar.
   Od 05.09.2026 tytuł bywa dwuczłonowy („Operator Internetu · Sesje
   abonentów") i przy `nowrap` bez ucinania kładł się wprost na godzinie.
   Ucięty tytuł da się doczytać z dymka; dwa napisy jeden na drugim
   są nie do odczytania w ogóle. */
.top-tytul h1{margin:0;font-size:var(--fs-xl);min-width:0;
  overflow:hidden;text-overflow:ellipsis}
/* ...ALE NIE WCZESNIEJ, NIZ TO KONIECZNE.
   Lukasz, 06.09.2026 - zrzut z „Baza wie..." przy oknie 1500 px, gdzie
   miejsca bylo az nadto. Winowajca: tytul mial `flex-shrink` domyslnie
   1 i sciskal sie ROWNO z szukajka, zamiast pozwolic jej oddac miejsce
   pierwszej. Teraz tytul nie kurczy sie w ogole - dostaje tyle, ile
   potrzebuje, do 340 px, a dopiero powyzej tej granicy ucina sie
   wielokropkiem. Szukajka ma wlasne `min-width` i to ona ustepuje. */
.top-tytul{flex:0 1 auto;min-width:150px;max-width:340px}
/* Kto ustepuje PIERWSZY. Sam `min-width` nie wystarczyl: przy `flex`
   domyslnym oba elementy kurczyly sie ROWNO, wiec tytul tracil litery
   w tym samym tempie, w ktorym szukajka traci piksele - a szukajka ma
   ich do oddania duzo wiecej bez szkody dla czytelnosci. Wspolczynnik
   3 znaczy „szukajka oddaje trzy razy szybciej niz tytul".
   Zamrozenie tytulu na `flex:0 0 auto` bylo GORSZE: grupa przestawala
   sie miescic i wchodzila na zegar. */
.top-lewo .qs{flex:1 3 auto}
/* Nazwa programu pod nazwa ekranu: razem czytaja sie jak "Serwis24
   Suite - Panel IT", ale nie zabieraja miejsca w jednej linii. */
.top-produkt{font-size:var(--fs-xs);color:var(--ink-3);letter-spacing:.03em}
.top-srodek{display:flex;justify-content:center}
.top-prawo{display:flex;align-items:center;justify-content:flex-end;gap:var(--s4);min-width:0}
/* Zegar potrzebuje powietrza z obu stron - inaczej data podchodzi pod
   plakietke czatu i oba napisy zlewaja sie w jeden. */
.top-srodek{padding:0 var(--s4)}

/* Zegar ma byc widoczny - wiec go NIE chowamy, tylko przestajemy
   trzymac na sile na srodku, gdy pasek zrobi sie ciasny. Siatka
   trzycolumnowa stawia go dokladnie posrodku tylko wtedy, gdy naprawde
   jest na to miejsce: kolumny 1fr sa ROWNE, wiec pasek musi zmiescic
   dwa razy szerokosc prawej strony (864 px) plus zegar. Ponizej pasek
   wraca do zwyklego rzedu, zegar staje za szukajka, a szukajka oddaje
   miejsce. Trzy rzeczy sciskane rowno konczylyby sie tym, ze zadna
   z nich nie jest czytelna. */
@media (max-width:2160px){
  .topbar{display:flex;flex-wrap:nowrap}
  .top-lewo{flex:1 1 auto;min-width:0}
  /* Szukajka ma dolna granice: ponizej niej przestaje byc polem
     do wpisywania, a staje sie ozdoba. */
  .top-lewo .qs{max-width:340px;min-width:190px}
  /* ...ale TYTUL tez ma granice. Bez niej przy 1400 px kurczyl sie do
     ZERA i ekran nie mial nazwy - a to jest jedyna rzecz w tym pasku,
     ktora mowi, gdzie sie jest. Skraca sie wielokropkiem do 150 px
     i dalej nie ustepuje.
     06.09.2026: przez chwile stalo tu `min-width:0` i tytul znikal
     calkowicie za szukajka. Ta wartosc NIE MOZE byc zerem. */
  .top-tytul{min-width:150px;max-width:300px}
  .top-srodek{flex:0 0 auto;padding:0 var(--s3)}
  .top-prawo{flex:0 0 auto}
}
/* Jeszcze ciasniej: plakietka czatu zostaje ikona z liczba. Sama
   liczba na czerwonym tle mowi dosc, a slowa wracaja, gdy jest miejsce.

   PROG PODNIESIONY Z 1380 NA 1560 (06.09.2026). Zmierzone: przy oknie
   1500 px prawa strona paska zajmowala 739 px - wiecej niz polowe
   calego paska - i lewa grupa wychodzila poza swoje miejsce wprost na
   zegar. Same slowa „8 rozmow, 21 nowych" kosztowaly 152 px, czyli
   wiecej, niz wynosilo nachodzenie. */
@media (max-width:1560px){
  .czatnik-opis{display:none}
  .czatnik{padding:0 10px;gap:6px}
  /* Szukajka schodzi do 150 px - tyle wystarczy, zeby zobaczyc, ze sie
     pisze. Nizej ustepuje juz tylko ona, bo tytul ekranu i godzina sa
     wazniejsze od szerokosci pola, ktore i tak rozwija sie po kliknieciu. */
  .top-lewo .qs{max-width:260px;min-width:150px}
  .zegar-czas{font-size:var(--fs-xl)}
}
/* PONIZEJ 1320 px SZUKAJKA ZNIKA - i to jest decyzja, nie brak pomyslu.
   Zmierzone przy 1240 px: lewa grupa potrzebuje 316 px (tytul 150 +
   szukajka 150 + odstep), zegar 180, prawa strona 587 - razem 1115 px
   na pasku szerokim 996. Czegos musi zabraknac.

   Odpada szukajka, bo jest jedyna rzecza w tym pasku, ktora ma zamiennik:
   kazdy ekran ma wlasne pole wyszukiwania. Tytul mowi, gdzie jestes,
   zegar jest po to, zeby na niego patrzec z drugiego konca pokoju,
   a prawa strona to wylacznie akcje. Wczesniej szukajka nie znikala,
   tylko wychodzila poza swoja grupe i kladla sie na zegarze - czyli
   psula dwie rzeczy zamiast ustapic. */
@media (max-width:1320px){
  .top-lewo .qs{display:none}
}

.zegar{text-align:center;line-height:1.15;white-space:nowrap}
.zegar-czas{font-size:var(--fs-2xl);font-weight:680;font-variant-numeric:tabular-nums;
  letter-spacing:.01em}
.zegar-dzien{font-size:var(--fs-sm);color:var(--ink-2)}

/* Ikony jednego rodzaju siedza w jednej ramce - widac, ze naleza do
   siebie i ze zadna z nich nie zmienia danych, tylko widok. */
.ikony{display:flex;align-items:center;gap:2px;padding:3px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}
.ikona{display:flex;align-items:center;justify-content:center;width:32px;height:32px;
  border:0;background:none;border-radius:var(--radius-sm);color:var(--ink-2);cursor:pointer}
.ikona:hover{background:var(--surface);color:var(--ink)}
.ikona:focus-visible{outline:none;box-shadow:var(--focus)}
.ikona.on{background:var(--accent-soft);color:var(--accent)}

/* Czat: dwa stany, nie jeden przycisk z liczba. Cisza jest szara,
   czekanie jest czerwone i podpisane slowem - liczba sama nie mowi,
   czego dotyczy. */
.czatnik{display:flex;align-items:center;gap:8px;height:38px;padding:0 14px;
  border:1px solid var(--line);border-radius:var(--radius-pill);
  background:var(--surface);color:var(--ink-2);font:inherit;font-size:var(--fs-sm);
  font-weight:600;cursor:pointer;white-space:nowrap}
.czatnik:hover{border-color:var(--g5);color:var(--ink)}
.czatnik.pilne{background:var(--bad-bg);border-color:var(--bad-border);color:var(--bad)}
.czatnik.pilne:hover{border-color:var(--bad)}
.czatnik-licznik{display:inline-flex;align-items:center;justify-content:center;
  min-width:22px;height:22px;padding:0 6px;border-radius:999px;
  background:var(--bad-solid);color:var(--bad-solid-ink);
  font-size:var(--fs-xs);font-weight:800;font-variant-numeric:tabular-nums}
.czatnik-opis{font-weight:650}

/* Kto jest zalogowany - z twarza i rola, a nie samo nazwisko szara
   czcionka gdzies miedzy guzikami. */
.top-ja{display:flex;align-items:center;gap:10px;padding-left:var(--s4);
  border-left:1px solid var(--line)}
/* Twarz rośnie razem z paskiem — inaczej wyższy pasek to sam odstęp,
   czyli pusta przestrzeń bez powodu. */
.ja-twarz{width:42px;height:42px;border-radius:50%;object-fit:cover;
  border:2px solid var(--line);background:var(--surface-2);flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-sm);font-weight:700;color:var(--accent)}
.ja-twarz.litery{background:var(--accent-soft);border-color:var(--accent-border)}
.ja-opis{display:flex;flex-direction:column;line-height:1.2;white-space:nowrap}
.ja-rola{font-size:var(--fs-xs);color:var(--ink-3)}
.ja-imie{font-size:var(--fs-base);font-weight:650}
.content{padding:var(--s5) var(--s6);overflow:auto}

.btn{height:var(--control-h);padding:0 14px;border-radius:var(--radius);
     border:1px solid var(--line);background:var(--surface);color:var(--ink);
     font-weight:600;font-size:var(--fs-base);cursor:pointer}
.btn:hover{border-color:var(--g5);background:var(--surface-2)}
.btn:focus-visible{outline:none;box-shadow:var(--focus)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.btn.sm{height:34px;padding:0 12px;font-size:var(--fs-sm)}
/* Kolor przycisku ma znaczyc to samo co swiatlo na skrzyzowaniu:
   zielony rusza, czerwony zatrzymuje, niebieski zapisuje. */
.btn.zielony{background:var(--ok-solid);border-color:var(--ok-solid);color:var(--ok-solid-ink)}
.btn.zielony:hover{background:var(--ok-solid-hover);border-color:var(--ok-solid-hover)}
.btn.czerwony{background:var(--bad-solid);border-color:var(--bad-solid);color:var(--bad-solid-ink)}
.btn.czerwony:hover{background:var(--bad-solid-hover);border-color:var(--bad-solid-hover)}
/* przycisk, ktory cos odbiera komus innemu - ostrzega, ale nie krzyczy */
.btn.ostrzega{border-color:var(--warn-border);background:var(--warn-bg);color:var(--warn)}
.btn.ostrzega:hover{border-color:var(--warn);background:var(--warn-bg)}
/* kasowanie - czerwona obwodka. Pelny czerwony zostawiamy dla "Stop",
   ktore klika sie kilkanascie razy dziennie i musi byc najlepiej widoczne. */
.btn.groznie{border-color:var(--bad-border);color:var(--bad);background:var(--surface)}
.btn.groznie:hover{border-color:var(--bad);background:var(--bad-bg)}
.btn:disabled{opacity:.5;cursor:default}

/* NIE jest przyciskiem: informacja, ze zlecenie juz jest moje.
   Wczesniej stal tu przycisk "Przejmij", ktory sugerowal, ze da sie
   przejac cos, co sie juz ma. */
.stan-przydzialu{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;
  border-radius:var(--radius);border:1px solid var(--ok-border);background:var(--ok-bg);
  color:var(--ok);font-size:var(--fs-sm);font-weight:650;white-space:nowrap}
.stan-przydzialu .kropka{width:8px;height:8px;border-radius:50%;background:var(--ok-solid);flex:none}
.input{height:var(--control-h);padding:0 12px;border:1px solid var(--line);
       border-radius:var(--radius);background:var(--surface);color:var(--ink);
       font:var(--fs-base)/1 var(--font);width:100%}
.input:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus)}
/* BLAD ZNALEZIONY 02.09.2026: `.input` narzucalo staly `height`, wiec KAZDY
   textarea w programie - notatka, tresc maila, opis protokolu - byl
   sciety do wysokosci jednego pola tekstowego. `rows={10}` w kodzie nie
   robilo nic, bo wysokosc z CSS wygrywa z atrybutem `rows`.
   Efekt: tresc szablonu maila widac bylo przez szpare na dwie linie. */
textarea.input{height:auto;min-height:84px;padding:10px 12px;line-height:1.5;
  resize:vertical;font:var(--fs-base)/1.5 var(--font)}
/* pole na dluzszy tekst - tresc maila, protokol */
textarea.input.duze{min-height:280px}

/* Podglad maila. Bialy prostokat z ramka - ma wygladac jak wiadomosc
   w skrzynce, a nie jak kolejne pole formularza. */
.haslo-blok{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line)}

.podglad{margin-top:var(--s4);border-top:1px solid var(--line);padding-top:var(--s3)}
.podglad-hd{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.podglad-hd .tytul{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.06em;
  color:var(--ink-3);font-weight:700}
.podglad-hd .rozpychacz{margin-left:auto}
.podglad-mail{background:var(--g0);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden}
.podglad-temat{padding:10px 14px;border-bottom:1px solid var(--line-soft);
  font-weight:660;background:var(--surface-2)}
.podglad-tresc{padding:14px;white-space:pre-wrap;line-height:1.55;max-height:420px;
  overflow-y:auto}

.card{background:var(--surface);border:1px solid var(--line);
      border-radius:var(--radius-lg);box-shadow:var(--shadow-1);margin-bottom:var(--s5)}
.card>.hd{padding:var(--s4) var(--pad-card);border-bottom:1px solid var(--line-soft);
          display:flex;align-items:center;gap:var(--s3)}
/* Pasek filtrów: własny wiersz pod wyszukiwarką. Filtry wciśnięte
   w jedną linię z resztą nagłówka zawijają się losowo i wyglądają
   na przypadkowe — a mają wyglądać na narzędzie. */
.filters{display:flex;flex-direction:column;gap:10px;padding:var(--s3) var(--pad-card);
         border-bottom:1px solid var(--line-soft);background:var(--surface-2)}
.filters .row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.filters select.input{width:auto;min-width:150px}
.card>.bd{padding:var(--pad-card)}
/* Pasek liczb. `auto-fit` zamiast `auto-fill`: przy osmiu kaflach
   i szerokim oknie kolumny rozkladaja sie rowno, zamiast zostawiac
   jeden kafel samotnie w drugim rzedzie obok pustych kolumn. */
.kpis{display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
      margin-bottom:var(--s4)}
.kpi{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);
     box-shadow:var(--shadow-1);padding:var(--s4) var(--s5)}
.kpi .l{font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.04em;
        color:var(--ink-2);font-weight:700}
.kpi .v{font-size:var(--fs-2xl);font-weight:660;letter-spacing:-.02em;margin-top:4px;
        line-height:1.1;font-variant-numeric:tabular-nums}
.kpi .d{font-size:var(--fs-sm);color:var(--ink-3);margin-top:4px}
.kpi.alert{border-color:var(--bad-border);background:var(--bad-bg)}
.kpi.alert .v{color:var(--bad)}
/* Kolor liczby ma ZNACZYC: zielone dziala, czerwone czeka na robote. */
.kpi .v.ton-ok{color:var(--ok)}
.kpi .v.ton-zle{color:var(--bad)}

/* stopka listy: wybor liczby wierszy */
.pager .na-stronie{margin-left:auto;display:flex;align-items:center;gap:6px;
  font-size:var(--fs-sm)}
.pager .na-stronie select.input{width:auto;height:28px;padding:0 6px}
/* Kafel, w ktory da sie kliknac, zeby zawezic liste pod spodem.
   Musi to po sobie pokazywac - kursorem i podniesieniem przy najechaniu,
   inaczej nikt nie zgadnie, ze jest czyms wiecej niz liczba. */
/* BLAD: kafel klikalny jest <button>, a przycisk NIE dziedziczy koloru
   tekstu od strony - dostawal czarny kolor przegladarki i w ciemnym
   motywie liczby byly praktycznie niewidoczne. `color:inherit` to
   naprawia; te same trzy slowa trzeba dopisac do kazdego przycisku,
   ktory udaje kawalek strony. */
.kpi-klik{text-align:left;font:inherit;color:inherit;cursor:pointer;width:100%;display:block}
.kpi-klik:hover{border-color:var(--g5);box-shadow:var(--shadow-2)}
.kpi-klik:focus-visible{outline:none;box-shadow:var(--focus)}
.kpi-klik.wybrany{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.kpi-klik.wybrany .l{color:var(--accent)}

/* [LAPTOP] / [PC] przed nazwa modelu. "Lenovo ThinkPad L14" nie mowi
   na pierwszy rzut oka, czy to sprzet przenosny. */
.znacznik{display:inline-block;padding:1px 5px;border-radius:var(--radius-sm);
  background:var(--surface-2);border:1px solid var(--line);color:var(--ink-3);
  font-size:var(--fs-xs);font-weight:700;letter-spacing:.03em;vertical-align:1px}

table{width:100%;border-collapse:collapse;font-size:var(--fs-base)}
thead th{text-align:left;font-size:var(--fs-sm);text-transform:uppercase;
         letter-spacing:.04em;color:var(--ink-2);font-weight:700;padding:11px 14px;
         background:var(--naglowek);
         border-bottom:1px solid var(--line);white-space:nowrap;cursor:pointer;user-select:none}
tbody td{padding:var(--pad-cell);border-bottom:1px solid var(--line-soft);height:var(--row-h)}
/* PASEK CO DRUGI WIERSZ. Ledwo widoczny — ma prowadzić oko przez
   kolumny, a nie robić z tabeli zebry. Najechanie jest mocniejsze,
   więc nie ginie na wierszu, który już ma pasek. */
tbody tr:nth-child(even){background:var(--pas)}
tbody tr:hover, tbody tr:nth-child(even):hover{background:var(--surface-2)}
.num{text-align:right;font-variant-numeric:tabular-nums}
.mono{font-family:var(--mono);font-size:var(--fs-sm)}
.muted{color:var(--ink-3)}
.clip{max-width:340px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.pill{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 11px;
      border-radius:var(--radius-pill);font-size:var(--fs-sm);font-weight:650;
      border:1px solid transparent;white-space:nowrap}
.pill.ok{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-border)}
.pill.warn{background:var(--warn-bg);color:var(--warn);border-color:var(--warn-border)}
.pill.bad{background:var(--bad-bg);color:var(--bad);border-color:var(--bad-border)}
.pill.info{background:var(--info-bg);color:var(--info);border-color:var(--info-border)}
.pill.mute{background:var(--surface-2);color:var(--ink-2);border-color:var(--line)}
/* Plakietka statusu na liscie: pierwsza kolumna, wiec musi byc widoczna
   z odleglosci. Stala szerokosc trzyma kolumne rowno - statusy roznej
   dlugosci robily z lewej krawedzi tabeli zabek. */
.pill.duza{height:30px;padding:0 14px;font-size:var(--fs-base);font-weight:660}
td.kol-status{width:1%}
td.kol-status .pill{min-width:132px;justify-content:center}
/* data w jednej linii - zawinieta na dwie robi z wiersza schodek */
td.kol-data{white-space:nowrap}
/* opis zgloszenia oddaje miejsce reszcie kolumn, zamiast rozpychac tabele */
.tblwrap table.karty td.clip{max-width:320px}

/* Ile zostalo do terminu. Kolor niesie pilnosc, nie ozdobe. */
.termin{font-variant-numeric:tabular-nums;white-space:nowrap}
.termin.pilne{color:var(--warn);font-weight:650}
.termin.po{color:var(--bad);font-weight:700}

.note{border:1px solid var(--line);border-left:3px solid var(--accent);
      background:var(--surface-2);border-radius:var(--radius);padding:12px 14px;
      color:var(--ink-2);margin-bottom:var(--s3);
      /* Komunikat o kilku zlych polach przychodzi jako kilka linii -
         bez tego skleja sie w jedno zdanie bez sensu. */
      white-space:pre-line}
.note b{color:var(--ink)}
.pager{display:flex;align-items:center;gap:10px;padding:var(--s3) var(--pad-card);
       border-top:1px solid var(--line-soft);color:var(--ink-3);font-size:var(--fs-sm)}
.login{min-height:100vh;display:grid;place-items:center;padding:var(--s5)}
.login .box{width:100%;max-width:380px}
.err{color:var(--bad);font-size:var(--fs-sm);margin-top:8px}
/* Szuflada karty zlecenia. Byla na 720 px i wszystko sie w niej lamalo
   do drugiej linii. Teraz: nigdy mniej niz 720 px, na duzym monitorze
   ~58% szerokosci, a i tak nie wiecej niz 94% ekranu. */
.drawer{position:fixed;inset:0 0 0 auto;width:min(94vw,max(860px,66vw));background:var(--surface);
        border-left:1px solid var(--line);box-shadow:var(--shadow-3);overflow:auto;
        padding:var(--s5) var(--s6);z-index:40}
.scrim{position:fixed;inset:0;background:rgba(20,18,14,.35);z-index:39}

/* Okienko decyzji na srodku ekranu. Uzywamy go tam, gdzie pytanie ma
   WLASNA tresc - `confirm()` przegladarki nie umie pokazac listy
   brakow ani przyjac notatki. */
.okienko{position:fixed;z-index:60;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(560px,92vw);max-height:86vh;overflow:auto;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-3);padding:var(--s5) var(--s6)}
.okienko .pasek-akcji{margin-top:var(--s5)}
.okienko.szerokie{width:min(760px,94vw)}
/* Okienko na jedną rzecz - zmiana hasła, potwierdzenie. Wąskie, bo
   trzy pola rozciągnięte na 700 px czyta się gorzej niż na 380. */
.okienko.waskie{width:min(420px,94vw)}

.lista-brakow{list-style:none;margin:0 0 var(--s4);padding:0;
  display:flex;flex-direction:column;gap:8px}
.lista-brakow li{display:flex;gap:10px;align-items:flex-start;
  padding:9px 12px;border-radius:var(--radius-sm);
  background:var(--surface-2);border:1px solid var(--line-soft)}
.lista-brakow li.wazne{background:var(--warn-bg);border-color:var(--warn-border)}
.lista-brakow .znak{flex:none;width:20px;height:20px;border-radius:50%;
  display:grid;place-items:center;font-weight:800;font-size:var(--fs-sm);
  background:var(--line);color:var(--ink-2)}
.lista-brakow li.wazne .znak{background:var(--warn);color:#fff}

/* Zamkniecie zlecenia to koniec roboty - przycisk ma to pokazywac. */
.btn.zamknij-zlecenie{margin-left:auto;font-weight:700}
.stan-przydzialu.zamkniete{border-color:var(--line);background:var(--surface);
  color:var(--ink-2)}
.stan-przydzialu.zamkniete .kropka{background:var(--ink-3)}
dl.kv{display:grid;grid-template-columns:190px 1fr;gap:6px 14px;margin:0 0 var(--s4)}
dl.kv dt{color:var(--ink-3);font-size:var(--fs-sm)}
dl.kv dd{margin:0}
/* Tabela zawsze przewija się w swoim pudełku, nigdy nie rozpycha strony.
   Bez tego na telefonie cała aplikacja jeździ w bok i nie da się jej używać. */
.tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.tblwrap table{min-width:720px}

/* KOLEJNOSC USTEPOWANIA MIEJSCA.
   Prawa strona paska potrzebuje 864 px i to ona wypycha wszystko inne.
   Zanim zaczniemy scinac tytul i szukajke do nieczytelnosci, oddaje
   miejsce to, co da sie oddac bez straty: PODPIS przy zdjeciu
   uzytkownika. Twarz zostaje, wiec nadal wiadomo, kto jest zalogowany,
   a pasek odzyskuje blisko dwiescie pikseli. */
@media (max-width:1800px){
  .top-ja .ja-opis{display:none}
  .top-ja{padding-left:var(--s3);border-left:1px solid var(--line-soft)}
}

@media (max-width:900px){
  .shell{grid-template-columns:1fr}
  /* =================================================================
     MENU JAKO SZUFLADA WYSUWANA OD LEWEJ
     =================================================================
     Łukasz, 09.09.2026: „to menu na mobilce jest nieakceptowalne
     w takiej formie, nie da się z tego korzystać i rozjeżdża wszystko
     — nie da rady zrobić, żeby np. wysuwało się od lewej strony
     w razie potrzeby?".

     Miał rację i warto nazwać, dlaczego poprzednie podejście musiało
     się nie udać. Menu było POZIOMYM PASKIEM, czyli próbą zmieszczenia
     w jednym rzędzie czegoś, co się w rzędzie nie mieści: nie ma tam
     miejsca na nagłówki grup („Zasoby", „Nadzór"), nie ma na podmenu
     operatora — a podmenu i tak się tam pchało i rozpychało pasek na
     330 px wysokości. Przewijanie palcem po kilkunastu kafelkach to
     nie jest nawigacja, tylko szukanie.

     Szuflada to DOKŁADNIE TO SAMO MENU, co na monitorze — pionowe,
     z grupami i podmenu — tylko schowane do czasu, aż będzie
     potrzebne. Zero osobnego kodu, zero drugiej listy do utrzymania.

     `transform` zamiast `left`, bo przesunięcie liczy karta graficzna
     — na telefonie to różnica między płynnym wysuwaniem a szarpaniem.
     ================================================================= */
  .side{position:fixed;top:0;left:0;bottom:0;z-index:90;
        width:min(320px,86vw);
        flex-direction:column;overflow-y:auto;overscroll-behavior:contain;
        padding:var(--s4) var(--s3) var(--s6);
        border-right:1px solid var(--line);border-bottom:0;
        box-shadow:8px 0 28px rgba(16,24,40,.18);
        transform:translateX(-100%);
        transition:transform .22s ease}
  .side.otwarte{transform:translateX(0)}
  /* Szuflada zasłania treść, więc pod nią musi być przyciemnienie —
     inaczej nie widać, że reszta ekranu czeka. */
  .scrim-menu{z-index:89}
  /* Pozycje wracają do postaci pionowej — czyli tej bazowej. */
  .side button.nav{white-space:normal;width:100%;min-height:44px}
  /* Na telefonie zostaje ciasno: tam każdy piksel wysokości jest
     droższy, bo ekran ma ich cztery razy mniej.

     UWAGA NA KOLEJNOŚĆ REGUŁ. Ta linijka przez długi czas ustawiała
     `grid-template-columns` — i nie robiła NIC, bo reguła dla ≤1640 px
     zdążyła wcześniej przestawić pasek na `display:flex`. Efekt był
     widoczny gołym okiem na telefonie: nazwa ekranu chowała się pod
     plakietką czatu, bo trzy elementy ściskały się w jednym rzędzie
     bez prawa do zawinięcia. Tu pasek MUSI zawijać. */
  .topbar{display:flex;flex-wrap:wrap;gap:8px;padding:10px var(--s4)}
  /* Nazwa ekranu bierze całą pierwszą linię, reszta układa się pod nią. */
  .top-lewo{flex:1 1 100%;order:1}
  .top-lewo .qs{flex:1 1 auto;max-width:none}
  .top-srodek{flex:0 0 auto;order:2;padding:0}
  .top-prawo{flex:1 1 auto;order:3;gap:var(--s3)}
  .ja-twarz{width:36px;height:36px}
  .topbar h1{font-size:var(--fs-lg)}
  .top-prawo{justify-content:space-between}
  .top-ja .ja-opis{display:none}
  .top-ja{padding-left:0;border-left:0}
  .topbar > div[style]{order:10;flex-basis:100%;max-width:none !important}
  .content{padding:var(--s4)}
  .card>.hd{flex-wrap:wrap}
  .card>.hd .input{max-width:none !important;width:100%}
  .filters select.input{min-width:0;flex:1 1 45%}
  .kpis{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
  .kpi{padding:var(--s3) var(--s4)}
  .kpi .v{font-size:var(--fs-xl)}
  .drawer{width:100vw;padding:var(--s4)}
  dl.kv{grid-template-columns:1fr}
  dl.kv dt{margin-top:6px}
}

/* Wiersz, który otwiera kartę. Kursor i podświetlenie muszą to mówić —
   tabela, w którą da się kliknąć bez żadnego sygnału, jest pułapką. */
tr.rowlink { cursor: pointer; }
/* podświetlenie wiersza jest już wyżej (tbody tr:hover) — tu tylko sygnał,
   że w wiersz da się kliknąć */
tr.rowlink:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.note.bad { border-color: var(--bad); color: var(--bad); }
.note.ok{border-left-color:var(--ok);color:var(--ok)}
.input.sm { padding: 4px 8px; font-size: var(--fs-sm); }

/* Siatka zdjęć. Kwadraty, bo fotki z telefonu mają różne proporcje,
   a lista o zmiennej wysokości jest nie do przejrzenia. */
.fotki{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(108px,1fr))}
.fotka{margin:0;display:flex;flex-direction:column;gap:6px}
.fotka-obraz{padding:0;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface-2);cursor:zoom-in;overflow:hidden;aspect-ratio:1;display:block;width:100%}
.fotka-obraz img{width:100%;height:100%;object-fit:cover;display:block}
.fotka-obraz .pdf{display:grid;place-items:center;height:100%;font-weight:600;color:var(--ink-2)}
.fotka figcaption{display:flex;gap:6px;align-items:center;flex-wrap:wrap;font-size:var(--fs-sm)}
.lightbox{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.82);
  display:grid;place-items:center;gap:12px;grid-template-rows:1fr auto;padding:24px;cursor:zoom-out}
.lightbox img{max-width:100%;max-height:80vh;object-fit:contain;border-radius:var(--radius)}
.lightbox-podpis{color:#fff;text-align:center}
/* etykieta udająca przycisk musi wyglądać na wyłączoną, gdy input jest disabled */
.btn.off{opacity:.55;pointer-events:none}

/* Rząd formularza na karcie: pola układają się w linii, a zawijają
   dopiero wtedy, gdy naprawdę brakuje miejsca. Bez tego `select`
   dziedziczy width:100% z .input i każdy rozwijak zjada całą linię. */
/* =====================================================================
   ODDECH MIĘDZY POLAMI — GLOBALNIE
   =====================================================================
   Łukasz, 08.09.2026: „na wszystkich ekranach poprawiaj te przytulone
   do siebie pola, w 70% przypadków ekranów w Suite tak to wygląda".
   Miał rację: 8 px między polem a przyciskiem wygląda jak sklejone
   przy 16-piksełowym tekście. Trzy zmiany naraz, wszędzie:
     • odstęp w poziomie 8 → 12 px,
     • odstęp w pionie przy zawijaniu (wcześniej ten sam co w poziomie,
       więc dwa rzędy pól stykały się bardziej niż pola w rzędzie),
     • odstęp MIĘDZY sąsiednimi paskami — dwa paski pod sobą nie mają
       prawa wyglądać jak jeden.
   Formularze zagnieżdżone w pasku (pole + przycisk, np. „numer klienta
   → Otwórz kartę") zostają ciaśniejsze w środku, bo to jedna całość —
   ale od sąsiadów odsuwają się już pełnym odstępem. */
.formrow{display:flex;gap:12px;row-gap:10px;flex-wrap:wrap;align-items:center}
.formrow + .formrow{margin-top:10px}
.formrow > form.formrow{gap:8px}
.formrow select.input{width:auto;min-width:120px;flex:0 0 auto}
.formrow .input.grow{flex:1 1 180px;min-width:140px}
.formrow .input.w-min{width:88px;flex:0 0 auto}
.formrow .input.w-cena{width:110px;flex:0 0 auto}
.formrow .btn{flex:0 0 auto}
.formrow label{white-space:nowrap}
@media (max-width:640px){
  /* na telefonie odwrotnie: jedno pod drugim, bo w linii i tak nic nie wejdzie */
  .formrow .input.grow,.formrow select.input{flex:1 1 100%;width:100%}
}

/* Pasek akcji karty zlecenia. Dwa osobne wiersze o STALEJ wysokosci:
   praca (przydzial + zegar) i zmiana statusu. Wczesniej wszystko siedzialo
   w jednym `formrow` i wybranie statusu doklejalo dwa nowe pola, ktore
   zawijaly sie do nowej linii - cala karta przeskakiwala o wiersz w dol. */
.pasek-zlecenia{display:flex;flex-direction:column;gap:10px;margin-bottom:var(--s4);
  padding:12px 14px;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius)}
.pasek-zlecenia .rzad{display:flex;gap:8px;flex-wrap:wrap;align-items:center;min-height:34px}
.pasek-zlecenia .rzad-status{padding-top:10px;border-top:1px solid var(--line)}
.pasek-zlecenia .etykieta-rzedu{font-size:var(--fs-sm);text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-2);font-weight:700;flex:0 0 auto}
.pasek-zlecenia select.input{width:auto;min-width:150px;flex:0 0 auto}
.pasek-zlecenia .input.powod{flex:1 1 220px;min-width:140px}
@media (max-width:640px){
  .pasek-zlecenia .input.powod{flex:1 1 100%}
  .pasek-zlecenia select.input{flex:1 1 100%;width:100%;min-width:0}
}

/* =====================================================================
   Kropka dostepnosci - jak w AnyDesku. Zielona zyje, czerwona nie
   odpowiada, pomaranczowa "chyba zyje" (monitoring odezwal sie kwadrans
   temu), szara "nie wiem" (monitoringu nie ma albo dane sa stare).
   Obwodka w kolorze tla odklei kropke od tekstu na kazdym tle.
   ===================================================================== */
.dostepnosc{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-size:var(--fs-sm);color:var(--ink-3)}
.dostepnosc .kropka{width:9px;height:9px;border-radius:50%;flex:none;
  box-shadow:0 0 0 2px var(--surface)}
.dostepnosc .stan{font-weight:600;color:var(--ink-2)}
.dostepnosc.online .kropka{background:var(--ok-solid)}
.dostepnosc.online .stan{color:var(--ok)}
.dostepnosc.chyba-online .kropka{background:var(--warn)}
.dostepnosc.chyba-online .stan{color:var(--warn)}
.dostepnosc.offline .kropka{background:var(--bad-solid)}
.dostepnosc.offline .stan{color:var(--bad)}
.dostepnosc.nieznany .kropka{background:var(--g5)}
/* Wersja na liste: kropka duzo wieksza, bo skanuje sie kilkadziesiat
   wierszy naraz i 9 px ginie. Zielona delikatnie oddycha - ruch mowi
   "to jest stan na teraz", nie "tak bylo zapisane". Czerwona nie rusza
   sie wcale i ma aureole: ma zatrzymac wzrok, a nie migac.
   Kto ma wylaczone animacje w systemie, dostaje sam kolor. */
.dostepnosc.duza .kropka{width:14px;height:14px;box-shadow:0 0 0 3px var(--surface)}
.dostepnosc.duza.online .kropka{
  background:var(--ok-solid);animation:tetno 2.4s ease-in-out infinite}
.dostepnosc.duza.offline .kropka{
  background:var(--bad-solid);box-shadow:0 0 0 3px var(--surface),0 0 0 5px var(--bad-bg)}
@keyframes tetno{
  0%,100%{box-shadow:0 0 0 3px var(--surface),0 0 0 3px hsl(152 72% 40% / .45)}
  50%    {box-shadow:0 0 0 3px var(--surface),0 0 0 8px hsl(152 72% 40% / 0)}
}
@media (prefers-reduced-motion:reduce){
  .dostepnosc.duza.online .kropka{animation:none}
}

/* Numer stanowiska: to jest to, po czym technik szuka w tej tabeli.
   Ma byc najmocniejsza rzecza w wierszu, a nie szarym monospace'em. */
.numer-stanowiska{font-size:var(--fs-md);font-weight:700;letter-spacing:-.01em;
  color:var(--ink);white-space:nowrap}
/* liczby nie maja sie lamac na dwie linie - "16 GB" w dwoch wierszach
   robi z tabeli drabine */
td.num,td.mono{white-space:nowrap}

/* w tabeli data ostatniego kontaktu tylko przy szerokim ekranie */
@media (max-width:1100px){ td .dostepnosc .kiedy{display:none} }

/* =====================================================================
   Karta zlecenia w dwoch kolumnach. Prawa strona byla pusta, a technik
   i tak potrzebuje tam stanowiska - inaczej musi go szukac na osobnym
   ekranie, zeby przepisac ID AnyDeska.
   Lamiemy sie na `flex-wrap`, a nie na media query, bo szuflada bywa
   wezsza niz okno i zapytanie o szerokosc ekranu tego nie widzi.
   ===================================================================== */
.karta-kolumny{display:flex;gap:var(--s5);align-items:stretch;flex-wrap:wrap;
  margin-bottom:var(--s4)}

/* Dwa bloki obok siebie: rozmowa i notatki. Oba sa waskie z natury,
   wiec ciagniete przez cala karte marnowaly pol szerokosci i wydluzaly
   strone o drugie tyle. Lamia sie na `flex-wrap`, nie na media query,
   bo szuflada bywa wezsza niz okno. */
.para-blokow{display:flex;gap:var(--s4);align-items:flex-start;flex-wrap:wrap}
.para-blokow > .lewa,.para-blokow > .prawa{flex:1 1 340px;min-width:0}
.para-blokow .blok{margin-bottom:var(--s4)}
/* w waskiej kolumnie czat nie ma sie dodatkowo zwezac */
.para-blokow .rozmowa{max-width:none}
.karta-kolumny > .lewa{flex:1 1 360px;min-width:0;display:flex}
.karta-kolumny > .lewa > .kafel{flex:1 1 auto}
.karta-kolumny > .prawa{flex:0 1 320px;min-width:280px;display:flex}
.karta-kolumny > .prawa > .kafel{flex:1 1 auto}
.karta-kolumny > .lewa dl.kv{grid-template-columns:132px 1fr;margin-bottom:0}
@media (max-width:640px){ .karta-kolumny > .lewa dl.kv{grid-template-columns:1fr} }

.kafel{background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius);padding:var(--s4);display:flex;flex-direction:column;gap:10px}
.kafel-hd{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.kafel-hd .nazwa{font-weight:660;font-size:var(--fs-md)}
/* numer stanowiska jest linkiem: klikniecie otwiera pelna karte */
.jak-link{background:none;border:0;padding:0;font:inherit;color:var(--accent);
  cursor:pointer;text-align:left}
.jak-link:hover{text-decoration:underline}
.kafel-fakty{display:grid;grid-template-columns:auto 1fr;gap:7px 14px;
  font-size:var(--fs-base);margin:0}
.kafel-fakty dt{color:var(--ink-3)}
.kafel-fakty dd{margin:0;min-width:0;overflow-wrap:anywhere}
.kafel-akcje{display:flex;flex-wrap:wrap;gap:6px;padding-top:10px;
  border-top:1px solid var(--line)}
.kafel-akcje .btn{flex:1 1 auto}
.kafel-uwaga{font-size:var(--fs-sm);color:var(--warn);background:var(--warn-bg);
  border:1px solid var(--warn-border);border-radius:var(--radius-sm);padding:6px 8px}
/* Sama tresc zgloszenia - to jest zdanie, ktore technik czyta pierwsze,
   wiec dostaje wieksza czcionke niz reszta faktow w kaflu. */
.tresc-zgloszenia{font-size:var(--fs-md);line-height:1.45;color:var(--ink);font-weight:500}
.kafel-fakty{font-size:var(--fs-base)}
.kafel-fakty dd.po-terminie{color:var(--bad);font-weight:650}

/* Notatki: pudelka jedno pod drugim, bez ogromnych odstepow.
   Wczesniej kazda byla `.note` z marginesem 8 px i wlasna gruba ramka. */
/* Linia do przepisania jeden do jednego - ma sie odcinac od zdania
   wokol niej, zeby nikt nie przepisal polowy. */
.blok-kodu{display:block;margin:8px 0;padding:8px 12px;background:var(--g0);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font-size:var(--fs-sm);overflow-x:auto;white-space:pre;user-select:all}

.notatki{display:flex;flex-direction:column;gap:8px}
.notatka{border-left:3px solid var(--accent);background:var(--surface-2);
  border-radius:var(--radius-sm);padding:8px 12px}
.notatka .meta{font-size:var(--fs-sm);margin-bottom:4px;
  display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.notatka .meta .rozpychacz{margin-left:auto}
/* Przyciski przy notatce wychodza dopiero przy najechaniu - inaczej
   kazda notatka wyglada jak formularz, a to jest przede wszystkim
   tekst do czytania. Na dotyku pokazujemy je zawsze, bo tam nie ma
   najechania. */
.notatka .meta .btn{opacity:0;transition:opacity .12s}
.notatka:hover .meta .btn,.notatka:focus-within .meta .btn{opacity:1}
@media (hover:none){ .notatka .meta .btn{opacity:1} }
.notatka.w-edycji{background:var(--surface);border:1px solid var(--accent-border);
  border-left:3px solid var(--accent)}

/* to samo w rozmowie */
.wiad .meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.wiad-akcje{margin-left:auto;display:flex;gap:10px;opacity:0;transition:opacity .12s}
.wiad:hover .wiad-akcje,.wiad:focus-within .wiad-akcje{opacity:1}
@media (hover:none){ .wiad-akcje{opacity:1} }
.jak-link.groznie{color:var(--bad)}
.notatka .tresc{white-space:pre-wrap}

/* =====================================================================
   BLOK - podstawowy widget wewnatrz karty.
   Decyzja 02.09.2026: karta zlecenia ciagnela sie w dol na kilka
   ekranow, bo kazda sekcja byla golym naglowkiem plus rozwinietym
   formularzem. Teraz kazda sekcja to zamkniete pudelko z paskiem
   tytulu; formularz "dopisz" siedzi w nim schowany i wychodzi
   dopiero, gdy technik go zawola.
   Oddzielenie robi RAMKA, nie pusta przestrzen - to samo, co dalo
   czytelnosc, przy polowie wysokosci.
   ===================================================================== */
.blok{background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow-1);
  margin-bottom:var(--s4);overflow:hidden}
.blok > .blok-hd{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:8px var(--s4);background:var(--surface-2);
  border-bottom:1px solid var(--line);min-height:44px}
.blok-hd .tytul{font-weight:660;font-size:var(--fs-base)}
.blok-hd .licznik{color:var(--ink-3);font-size:var(--fs-sm);
  font-variant-numeric:tabular-nums}
.blok-hd .rozpychacz{margin-left:auto}
.blok > .blok-bd{padding:var(--s3) var(--s4)}
/* tabela ma dochodzic do krawedzi bloku - wciecie pod ramka wyglada
   jak pomylka, a zjada 32 px szerokosci na kazdym wierszu */
.blok > .blok-bd.tabela{padding:0}
.blok > .blok-bd.tabela table{border-collapse:collapse}
.blok > .blok-bd.tabela tbody tr:last-child td{border-bottom:0}
.blok > .blok-bd.tabela thead th{padding-left:var(--s4)}
.blok > .blok-bd.tabela td:first-child,
.blok > .blok-bd.tabela th:first-child{padding-left:var(--s4)}
.blok > .blok-bd.tabela td:last-child,
.blok > .blok-bd.tabela th:last-child{padding-right:var(--s4)}
.blok .puste{padding:var(--s4);color:var(--ink-3);font-size:var(--fs-sm)}

/* Formularz w bloku: wysuwa sie pod paskiem tytulu, wiec od razu
   widac, ze nalezy do tej sekcji i skad sie wzial. */
.blok > .blok-form{padding:var(--s3) var(--s4);background:var(--surface-2);
  border-bottom:1px solid var(--line)}

/* Pola w jednej linii zamiast siatki pelnej szerokosci. Etykiety
   zostaja - bez nich nie wiadomo, co gdzie wpisac - ale pole ma
   szerokosc swojej zawartosci, a nie calej karty. */
/* FORMULARZE STOJA NA SIATCE, nie na doklejanych kafelkach.
   Lukasz, 03.09.2026: "te podpisy nad okienkami, wyrownac jakos? rowne
   odstepy".
   Wczesniej kazde pole bylo szerokie na tyle, na ile szeroka byla jego
   ETYKIETA - wiec "Powtarzaj co (dni)" stalo w waskiej kolumnie, a
   "Pierwsze przypomnienie po (dniach)" w dwa razy szerszej. Odstepy
   miedzy kratkami wychodzily za kazdym razem inne i caly formularz
   wygladal na poskladany z resztek.
   Teraz kolumny sa rowne, a odstepy zawsze te same. Etykieta nie
   decyduje juz o szerokosci niczego - tylko o tym, co pisze.
   Rownamy GORA, nie dolem.
   Dolem wygladalo dobrze, dopoki pola byly jednakowe. Ale pole
   z podpowiedzia pod spodem ("najpierw wybierz firme") jest wyzsze -
   i przy rownaniu do dolu WYPYCHALO swoja etykiete i kratke do gory
   ponad sasiadow. Lukasz, 03.09.2026: "troche sie rozjechalo
   formatowanie" - i to bylo dokladnie to.
   Gora etykiety stoja w jednej linii, kratki tez, a podpowiedz po
   prostu zwisa nizej, tam gdzie i tak jest miejsce. */
.pola.ciasne{display:grid;
  grid-template-columns:repeat(auto-fill,minmax(196px,1fr));
  gap:var(--s3) var(--s4);align-items:start}
.pola.ciasne > .pole{min-width:0}
/* pole "rosnie" (adres, e-mail, notatka) dostaje dwie kolumny zamiast
   rozpychania sie kosztem sasiadow */
.pola.ciasne > .pole.rosnie{grid-column:span 2}
@media (max-width:640px){ .pola.ciasne > .pole.rosnie{grid-column:span 1} }
.pola.ciasne .pole > label,.pola.ciasne .pole-etykieta{font-size:var(--fs-sm)}
.pola.ciasne .pole{gap:4px}
/* pole z samym przyciskiem: pusta etykieta trzyma go w jednej linii z reszta */
.pola.ciasne .pole .formrow{gap:14px;flex-wrap:nowrap;align-items:center;white-space:nowrap}
.pola.ciasne .pole .formrow .btn{flex:0 0 auto}
.pola.ciasne .input{height:36px}
.pola.ciasne .input.w-min{width:80px}
.pola.ciasne .input.w-cena{width:100px}
.pola.ciasne .input.w-ilosc{width:70px}
.blok-form .pasek-akcji{margin-top:10px;padding-top:10px}

/* Przeliczenie netto/brutto pod polami. Ma byc widoczne OD RAZU przy
   wpisywaniu, a nie dopiero w tabeli po zapisaniu - inaczej kazdy liczy
   VAT w glowie i co dziesiaty raz sie myli. */
.przeliczenie{display:flex;gap:var(--s5);flex-wrap:wrap;align-items:baseline;
  margin-top:10px;padding:8px 12px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font-size:var(--fs-sm);color:var(--ink-3)}
.przeliczenie strong{color:var(--ink);font-size:var(--fs-base);
  font-variant-numeric:tabular-nums}
.przeliczenie .razem{margin-left:auto}
.przeliczenie .razem strong{color:var(--accent)}

/* =====================================================================
   ROZMOWA. Czat rozciagniety na cala szerokosc karty czyta sie zle -
   oko wraca za daleko w lewo. Zwezamy do dlugosci, jaka ma kazdy inny
   komunikator, a przycisk "Wyslij" idzie TAM, gdzie go szukamy:
   po prawej stronie pola, w jednej linii z nim.
   ===================================================================== */
.rozmowa{max-width:740px}
.rozmowa .czat{margin-bottom:10px}
.czat-pisz{display:flex;gap:8px;align-items:flex-end}
.czat-pisz textarea.input{flex:1 1 auto;min-height:44px;resize:vertical;
  padding:10px 12px;line-height:1.4}
.czat-pisz .btn{flex:0 0 auto;height:44px;padding:0 20px}
.czat-stopka{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  margin-top:6px;font-size:var(--fs-sm);color:var(--ink-3)}
/* Podpowiedz przy ptaszku "powiadom mailem". Ptaszek jest domyslnie
   odklikniety, wiec to jedyne miejsce, ktore mowi technikowi, ze tamten
   czlowiek jeszcze nie wie o rozmowie. Klikniecie zaznacza ptaszek. */
.link-mini{background:none;border:0;padding:0;font:inherit;color:var(--warn);
  text-decoration:underline;cursor:pointer}
.link-mini:hover{color:var(--ink)}

/* Zdjecie przyslane przez klienta w rozmowie. Ograniczone rozmiarem,
   zeby zrzut ekranu z monitora 4K nie zajal calego okna - klikniecie
   otwiera oryginal. */
.wiad-zdjecie{display:block;margin-top:8px;max-width:340px}
.wiad-zdjecie img{display:block;width:100%;height:auto;max-height:260px;object-fit:cover;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2)}
.wiad-zdjecie:hover img{border-color:var(--accent)}

/* Nagłówek karty: numer, status i priorytet w jednej linii na monitorze,
   a na telefonie zawijają się, zamiast uciekać poza ekran. */
.kartahd{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:4px}
/* Numer zlecenia to nazwa tego ekranu - ma byc czytelny z drugiego konca
   biurka, bo podaje sie go przez telefon. */
.numer-zlecenia{font-size:var(--fs-xl);font-weight:700;letter-spacing:-.01em}
/* etykiety pol nie moga byc drobniejsze niz reszta o wiecej niz stopien */
.pole > label,.pole-etykieta{font-size:var(--fs-sm)}
.kartahd .zamknij{margin-left:auto}
.kartahd .btn{flex:0 0 auto}
@media (max-width:640px){ .kartahd .zamknij{margin-left:0} }

/* Panel „otwórz na telefonie” jest wąski — mieści kod QR i nic więcej. */
.drawer.waski{width:min(420px,94vw)}
.qr{display:grid;place-items:center;padding:14px;background:#fff;border:1px solid var(--line);
    border-radius:var(--radius);margin-top:10px}
.qr img{width:min(260px,70vw);height:auto;display:block}
.lista{margin:0 0 10px;padding-left:20px;color:var(--ink-2)}
.lista li{margin-bottom:6px}
.formrow .mono.grow{flex:1 1 auto;font-size:var(--fs-sm);word-break:break-all}

@media (max-width:640px){
  /* Tabela zgłoszeń zamienia się w listę kart. Sześć kolumn na ekranie
     390 px to przewijanie w bok i szukanie po omacku — a to jest ekran,
     na który technik patrzy w biegu, jedną ręką. */
  .tblwrap table.karty thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .tblwrap table.karty,.tblwrap table.karty tbody,.tblwrap table.karty tr,.tblwrap table.karty td{display:block;width:auto}
  .tblwrap table.karty tr{border:1px solid var(--line);border-radius:var(--radius);
    padding:10px 12px;margin-bottom:8px;background:var(--surface)}
  /* .clip ma nowrap i ucinanie — na karcie tekst ma się zawijać,
     inaczej opis wychodzi na wiersz niżej i nakłada się na etykietę */
  /* WYSOKOŚĆ WIERSZA MUSI ZNIKNĄĆ, INACZEJ KARTA MA POŁ EKRANU.
     Zmierzone 06.09.2026 na ekranie 390 px: KAŻDA komórka miała
     dokładnie 48 px, bo globalna reguła `tbody td{height:var(--row-h)}`
     wygrywała z tym blokiem — nadpisywaliśmy tu `padding` i `border`,
     ale nie wysokość. Dziewięć komórek × 48 px = 468 px na JEDNO
     zgłoszenie. Technik widział na ekranie mniej niż jedno.

     `height:auto` zbija to do wysokości treści. To jedna deklaracja,
     ale to ona decyduje, czy ten ekran nadaje się do pracy w terenie. */
  .tblwrap table.karty td{border:0;padding:1px 0;white-space:normal !important;
    overflow:visible;text-overflow:clip;line-height:1.35;height:auto;min-height:0}
  /* Etykieta tylko tam, gdzie sama wartość nie mówi, czym jest.
     Numer, firma, opis i status bronią się same. */
  .tblwrap table.karty td[data-label="Technik"]::before,
  .tblwrap table.karty td[data-label="Wpłynęło"]::before{
    content:attr(data-label) ": ";color:var(--ink-2)}
  .tblwrap table.karty td[data-label="Numer"]{font-weight:600;font-size:var(--fs-sm)}
  .tblwrap table.karty td[data-label="Firma"]{font-weight:600;margin-bottom:2px}
  .tblwrap table.karty td[data-label="Zgłoszenie"]{margin-bottom:6px}
  .tblwrap table.karty td[data-label="Technik"],
  .tblwrap table.karty td[data-label="Wpłynęło"]{display:inline-block;font-size:var(--fs-sm)}
  .tblwrap table.karty td[data-label="Wpłynęło"]{margin-left:10px}
  .tblwrap table.karty td[data-label="Status"]{margin-top:6px}
  /* PUSTA KOMÓRKA ZNIKA Z KARTY. Na monitorze kreska „—" trzyma
     wyrównanie kolumny i mówi „sprawdzone, nic tu nie ma". Na karcie
     w telefonie kolumn nie ma, więc kreska w osobnej linii jest samym
     hałasem — dwie takie zjadały 40 px z każdego zgłoszenia. */
  .tblwrap table.karty td.puste{display:none}

  /* Górny pasek na telefonie: zostawiamy to, czego się faktycznie używa. */
  .topbar .schowaj-na-telefonie{display:none}
}

/* Podpowiedzi przy szukaniu firmy — lista pod polem, klawiatura i mysz
   mają trafiać w to samo. */
.podpowiedzi{border:1px solid var(--line);border-radius:var(--radius);margin-top:4px;overflow:hidden}
/* Wiersz podpowiedzi: nazwa rosnie, miasto i etykieta trzymaja sie
   prawej krawedzi - dzieki temu etykiety stoja w jednej kolumnie i da
   sie je przeczytac jednym spojrzeniem po liscie, a nie po jednej. */
.podpowiedz{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:8px 12px;border:0;
  background:var(--surface);color:var(--ink);cursor:pointer;font:inherit}
.podpowiedz:hover,.podpowiedz:focus-visible{background:var(--surface-2);outline:none}
.podpowiedz+.podpowiedz{border-top:1px solid var(--line-soft)}

/* Ustawienia: sekcja na rodzaj zgłoszeń */
.seria{border:1px solid var(--line);border-radius:var(--radius);padding:12px;margin-bottom:10px}
.seria-edycja{margin-top:10px;padding-top:10px;border-top:1px solid var(--line-soft);
  display:flex;flex-direction:column;gap:8px}
.seria-edycja .note{margin:0}

/* Panel z widgetów. Siatka czterokolumnowa; widget deklaruje szerokość,
   a na wąskim ekranie wszystko schodzi do jednej kolumny. */
/* =====================================================================
   PANEL - centrum dowodzenia, a nie stos kart.

   Lukasz, 03.09.2026: "wyrownajmy jakos wszystkie ekrany na tym widoku
   bo wyglada to slabo takie niepoukladane (...) albo dajmy mozliwosc,
   zeby np. byly 4 duze widgety ktore dziela ekran na 4 czesci (...)
   niech to wyglada PRO".

   Klucz jest jeden: WYSOKOSC RZEDU JEST STALA, a nie wynika z tresci.
   Wczesniej kazdy panel byl tak wysoki, jak jego lista - wiec dwa
   sasiednie konczyly sie w dwoch roznych miejscach, a pod krotszym
   zostawala dziura. Teraz rzad ma swoja wysokosc, panel zajmuje tyle
   rzedow, ile ma zapisane, a lista w srodku przewija sie sama.

   Cztery kolumny + panele 2x2 daja dokladnie to, o co pytal: ekran
   podzielony na cztery rowne czesci.
   ===================================================================== */
/* `dense` zasypuje dziury.
   Lukasz, 04.09.2026: "moge zamieniac miejscami panele, ale np. jak
   wyskoczy mi taka konfiguracja, ze jest wolne miejsce na spokojnie
   jeszcze, to juz tam nie moge nic wcisnac".
   Bez `dense` siatka zostawia luke, gdy nastepny panel sie w nia nie
   miesci, i czeka na kolejny rzad. Z `dense` szuka dalej i wstawia
   pierwszy, ktory pasuje - czyli robi dokladnie to, czego probowal
   dokonac recznie. */
.panel{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  grid-auto-rows:172px;grid-auto-flow:row dense;gap:var(--s4);align-items:stretch}
.panel>.w4,.panel>.kpis.w4{grid-column:span 4}
.panel>.w3{grid-column:span 3}
.panel>.w2{grid-column:span 2}
.panel>.w1{grid-column:span 1}
.panel>.h1{grid-row:span 1}
.panel>.h2{grid-row:span 2}
.panel>.h3{grid-row:span 3}
.panel>.h4{grid-row:span 4}
/* Panel jest pudelkiem o zadanej wysokosci: naglowek stoi, tresc plynie
   i przewija sie w srodku. `min-height:0` jest tu obowiazkowe - bez
   niego element siatki nie chce sie skurczyc ponizej swojej tresci
   i cale ograniczenie wysokosci przestaje dzialac. */
.widget{margin:0;display:flex;flex-direction:column;min-height:0;overflow:hidden}
.widget > .hd{flex:0 0 auto}
.widget > .widget-tresc{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
  overflow:hidden;position:relative}
/* Wewnatrz owijki lista dostaje cala reszte miejsca. `overflow:hidden`,
   a nie `auto`: przycinamy ja teraz na CALYM wierszu i mowimy, ile
   schowalismy - przewijanie w srodku kafla nie ma tu czego dodac. */
.widget > .widget-tresc > *{min-height:0;overflow:hidden}
/* Pasek „...i jeszcze N". Stoi w normalnym ukladzie, a nie na tresci -
   napis polozony na ostatnim wierszu zaslanialby to, co mial opisywac. */
.widget-reszta{flex:0 0 auto;padding:6px 2px 0;margin-top:auto;
  font-size:var(--fs-xs);color:var(--ink-3);text-align:center;
  border-top:1px solid var(--line-soft)}
/* Kafle stoja poza siatka paneli (patrz Dashboard w app.tsx), wiec
   maja wlasny odstep od tego, co pod nimi. */
.kpis{margin-bottom:var(--s4)}

@media (max-width:1100px){
  .panel{grid-template-columns:repeat(2,minmax(0,1fr))}
  .panel>.w3,.panel>.w4,.panel>.kpis.w4{grid-column:span 2}
}
@media (max-width:640px){
  /* Na telefonie nie ma czego wyrownywac - jedna kolumna, a wysokosc
     niech wynika z tresci, bo przewijanie w przewijaniu na malym
     ekranie to najgorsze, co mozna komus zrobic. */
  .panel{grid-template-columns:1fr;grid-auto-rows:auto}
  .panel>.w2,.panel>.w3,.panel>.w4,.panel>.kpis.w4{grid-column:span 1}
  .panel>.h1,.panel>.h2,.panel>.h3,.panel>.h4{grid-row:auto}
  .widget{overflow:visible}
  .widget > .hd + *{overflow:visible}
}

/* =====================================================================
   LISTA W WIDGECIE PANELU.
   Siatka o STALYCH kolumnach, nie flex. Powod z zycia: przy `flex`
   kolumna czasu miala szerokosc swojej tresci, wiec "11:00" i
   "62 dni temu" zaczynaly sie w innym miejscu i cala lista jechala
   w lewo tym bardziej, im krotszy byl tekst. Trzy wiersze pod soba
   wygladaly jak trzy rozne tabele.
   Wiersz jest `display:contents`, wiec jego komorki naleza do siatki
   listy - tylko tak kolumny stoja rowno MIEDZY wierszami.
   ===================================================================== */
/* BLAD I POPRAWKA 02.09.2026:
   bylo `align-items:center` na calej siatce. Przy `display:contents`
   znaczy to, ze KAZDA komorka jest tak wysoka, jak jej wlasna tresc,
   i wisi na srodku wiersza. Skutek widac bylo golym okiem: linia pod
   "62 dni temu" konczyla sie wyzej niz linia pod opisem na dwie linie,
   a podswietlenie przy najechaniu obejmowalo tylko srodek wiersza.
   Komorki musza sie ROZCIAGAC na wysokosc wiersza (`stretch`), a tresc
   srodkuje sie juz w srodku komorki. */
/* Lista wypelnia panel i przewija sie w nim. Wlasny `max-height` nie ma
   juz sensu - o wysokosci decyduje rzad siatki, a nie liczba wierszy. */
.lista-widget{display:grid;align-items:stretch;align-content:start;
  overflow-y:auto;overflow-x:hidden}

.lista-widget .nagl{display:contents}
.lista-widget .nagl > span{position:sticky;top:0;z-index:1;
  padding:9px 14px;background:var(--surface-2);
  border-bottom:1px solid var(--line);
  font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-2);font-weight:700;white-space:nowrap}
/* czas jest wyrownany do prawej, zeby liczby konczyly sie rowno */
.lista-widget .nagl > span:first-child{text-align:right}

.lista-widget .wrs{display:contents}
.lista-widget .wrs > *{padding:11px 14px;border-bottom:1px solid var(--line-soft);
  min-width:0;background:var(--surface);
  /* tresc na srodku KOMORKI, a komorka na cala wysokosc wiersza */
  display:flex;flex-direction:column;justify-content:center}
.lista-widget .wrs:last-child > *{border-bottom:0}
.lista-widget .wrs.klik{cursor:pointer}
.lista-widget .wrs.klik:hover > *{background:var(--surface-2)}
.lista-widget .wrs:focus-visible > *{background:var(--accent-soft);outline:none}

.lista-widget .kiedy{align-items:flex-end;white-space:nowrap;
  color:var(--ink-2);font-size:var(--fs-sm);font-variant-numeric:tabular-nums}
.lista-widget .numer{align-items:flex-start;white-space:nowrap;
  font-size:var(--fs-sm);color:var(--ink)}
/* czas oczekiwania to zla wiadomosc - ma to po sobie pokazywac */
.lista-widget .kiedy.pilne{color:var(--bad);font-weight:700}
/* Opis dostaje dwie linie, a nie jedna uciecie. Polowa okna stala pusta,
   a technik i tak musial otwierac zlecenie, zeby przeczytac zdanie. */
.lista-widget .opis{gap:2px;min-width:0}
.lista-widget .opis .glowny{display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;line-height:1.35}
.lista-widget .opis .muted{font-size:var(--fs-sm);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
/* Plakietka nie moze BYC komorka siatki - komorka rozciaga sie na cala
   szerokosc kolumny i plakietka przestaje wygladac jak plakietka.
   Dlatego w kodzie siedzi w osobnej komorce `.stan`.

   BLAD I POPRAWKA 03.09.2026: `align-self:center` na plakietce
   ustawialo ja na SRODKU kolumny, a naglowek kolumny stoi przy lewej
   krawedzi. W waskiej kolumnie roznica byla o kilka pikseli, w szerokiej
   o kilkadziesiat - i to jest dokladnie to, co Lukasz widzial jako
   "kolumny i pozycje pod nimi sa rozjechane". Zdejmuje sie to jedna
   linijka, ale trzeba ja bylo najpierw znalezc: nowsza regula z dolu
   pliku ustawiala `align-items` na komorce, a `align-self` na dziecku
   bije `align-items` rodzica, wiec nowsza regula nic nie zmieniala. */
.lista-widget .stan{align-items:flex-start}
.lista-widget .stan .pill{align-self:flex-start}
.lista-widget .wrs.zalegle .kiedy{color:var(--bad);font-weight:700}

/* Puste miejsce, ktore TLUMACZY, czemu jest puste. "Brak danych" kaze
   zgadywac, czy program jest zepsuty, czy naprawde nic nie ma. */
/* =====================================================================
   POLE DO PODPISU. Uzywane i w panelu, i w portalu klienta.
   `touch-action:none` jest tu konieczne, nie ozdobne: bez tego palec
   ciagnacy po polu przewija strone zamiast rysowac.
   ===================================================================== */
.podpis-blok{border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s4);background:var(--surface-2);margin-top:var(--s4)}
.podpis-tytul{font-size:var(--fs-sm);font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-2);margin-bottom:6px}
.podpis-oswiadczenie{margin:0 0 10px;font-size:var(--fs-sm);color:var(--ink-2);
  line-height:1.5;max-width:70ch}
.podpis-info{font-size:var(--fs-sm);color:var(--warn);margin-top:8px}
.podpis-pole{position:relative;background:var(--g0);border:1px solid var(--line);
  border-radius:var(--radius-sm);height:190px;overflow:hidden}
.podpis-pole canvas{display:block;width:100%;height:100%;touch-action:none;cursor:crosshair}
.podpis-podpowiedz{position:absolute;inset:0;display:grid;place-items:center;
  color:var(--ink-3);font-size:var(--fs-md);pointer-events:none}
.podpis-linia{position:absolute;left:24px;right:24px;bottom:38px;
  border-bottom:1px dashed var(--g5);pointer-events:none}
.podpis-osadzony{margin-top:var(--s4)}

/* Pasek nad panelem: jedna czynnosc, ktora robi sie najczesciej. */
.pasek-glowny{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  margin-bottom:var(--s5)}
.pasek-glowny .muted{font-size:var(--fs-sm)}
.btn.duzy{height:52px;padding:0 26px;font-size:var(--fs-md);font-weight:700;
  border-radius:var(--radius)}

.puste-tlumaczenie{padding:var(--s6) var(--pad-card);text-align:center}
.puste-tlumaczenie .glowne{font-size:var(--fs-md);font-weight:600;
  color:var(--ink-2);margin-bottom:6px}
.puste-tlumaczenie .muted{font-size:var(--fs-sm);max-width:52ch;
  margin:0 auto;line-height:1.5}

.pasek-zaleglych{color:var(--bad);font-size:var(--fs-sm);font-weight:600;
  background:var(--bad-bg);border-bottom:1px solid var(--bad-border);
  padding:9px 14px}

/* Na waskim ekranie siatka o czterech kolumnach nie ma sensu - zwijamy
   do dwoch i chowamy naglowki, bo i tak nie ma czego wyrownywac. */
@media (max-width:900px){
  .lista-widget{grid-template-columns:96px minmax(0,1fr) !important}
  .lista-widget .nagl{display:none}
  .lista-widget .numer{grid-column:2;padding-top:0;padding-bottom:2px;
    border-bottom:0;color:var(--ink-3)}
  .lista-widget .opis{grid-column:2;padding-top:0}
  .lista-widget .stan{grid-column:2;padding-top:0;align-items:flex-start}
}

/* Ustawienia: menu sekcji z lewej, treść z prawej. */
.ustawienia{display:grid;grid-template-columns:220px minmax(0,1fr);gap:var(--s4);align-items:start}
.ust-menu{position:sticky;top:var(--s4)}
.ust-poz{display:block;width:100%;text-align:left;padding:7px 12px;border:0;border-radius:var(--radius);
  background:transparent;color:var(--ink);cursor:pointer;font:inherit}
.ust-poz:hover{background:var(--surface-2)}
.ust-poz.on{background:var(--accent-soft,var(--surface-2));color:var(--accent);font-weight:600}
.ust-poz.potem{color:var(--ink-2)}
/* SZEROKOŚĆ CZYTANIA W USTAWIENIACH.
   Bez tego na monitorze 2000 px treść rozciągała się na całą szerokość:
   opisy szły przez pół metra ekranu, a wszystko, co dosunięte do prawej
   (przełączniki, przyciski), odjeżdżało tak daleko od swojej etykiety,
   że przestawało z nią wyglądać na jedną rzecz. */
.ust-tresc{margin:0;max-width:1180px}
@media (max-width:900px){ .ustawienia{grid-template-columns:1fr} .ust-menu{position:static} }

/* Hasło jednorazowe — ma rzucać się w oczy, bo widać je tylko raz. */
.note.haslo{border-color:var(--accent);background:var(--surface-2)}
.mono.duze{font-size:1.4rem;letter-spacing:.06em;user-select:all}

/* Uprawnienia roli */
.uprawnienia{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:4px;margin-bottom:8px}
.upr{display:flex;gap:8px;align-items:baseline;padding:5px 8px;border-radius:var(--radius);cursor:pointer}
.upr:hover{background:var(--surface-2)}
.upr.on{background:var(--surface-2)}
.upr .mono{font-size:var(--fs-sm)}
tr.wylaczony td{opacity:.55}

/* Czat na karcie zgłoszenia */
.czat{display:flex;flex-direction:column;gap:8px;max-height:320px;overflow-y:auto;
  padding:10px;border:1px solid var(--line);border-radius:var(--radius);margin-bottom:8px}
.wiad{max-width:82%;padding:8px 10px;border-radius:var(--radius)}
.wiad .meta{font-size:var(--fs-sm);margin-bottom:2px}
.wiad .tresc{white-space:pre-wrap}
.wiad.od-nas{align-self:flex-end;background:var(--surface-2)}
.wiad.od-klienta{align-self:flex-start;background:var(--info-bg,var(--surface-2));
  border:1px solid var(--line-soft)}

/* Dzwonek czatu */
.dzwonek-blok{position:relative}
.btn.pilne{border-color:var(--bad);color:var(--bad);font-weight:600}
.dzwonek-lista{position:absolute;right:0;top:calc(100% + 6px);z-index:60;width:min(380px,80vw);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 8px 28px rgba(0,0,0,.16);max-height:60vh;overflow-y:auto}
.scrim.cichy{background:transparent}

/* =====================================================================
   FORMULARZE — od podstaw.
   
   Problem, który to naprawia (zgłoszony 02.09.2026): "wszystko się zlewa,
   muszę szukać, co się zmieniło na ekranie i gdzie co wpisać".
   
   Trzy przyczyny i trzy lekarstwa:
   
   1. POLA BEZ ETYKIET. Wszędzie były same podpowiedzi w środku pola.
      Znikają, gdy tylko coś wpiszesz — i po chwili nie wiadomo, co jest
      w którym polu. Teraz etykieta jest NAD polem i zostaje na miejscu.
      
   2. WSZYSTKO W JEDNEJ LINII. Cztery kontrolki obok siebie czyta się
      jako jedną plamę. Teraz pole to blok o własnej szerokości, a bloki
      układają się w siatkę i zawijają, gdy brakuje miejsca.
      
   3. JEDNAKOWE ODSTĘPY WSZĘDZIE. Skoro odległość między etykietą a polem
      była taka sama jak między dwiema sekcjami, oko nie miało po czym
      grupować. Teraz są trzy poziomy i tylko trzy:
         6 px   wewnątrz pola (etykieta ↔ pole ↔ podpowiedź)
        16 px   między polami tej samej grupy
        36 px   między sekcjami, dodatkowo z linią
   ===================================================================== */

/* --- pole: etykieta nad, podpowiedź pod --------------------------- */
.pole{display:flex;flex-direction:column;gap:6px;min-width:0}
.pole > label,.pole-etykieta{
  font-size:var(--fs-sm);font-weight:600;color:var(--ink-2);
  letter-spacing:.01em;line-height:1.2}
.pole-podpowiedz{font-size:var(--fs-sm);color:var(--ink-3);line-height:1.4}
.pole-blad{font-size:var(--fs-sm);color:var(--bad)}
/* pole rozciaga swoja kontrolke na pelna szerokosc - ale NIE ptaszka,
   bo checkbox na 100% szerokosci naježdža na sasiada */
.pole input,.pole select,.pole textarea{width:100%}
.pole input[type=checkbox],.pole input[type=radio]{width:auto}
.pole.waskie{max-width:120px}
.pole.srednie{max-width:220px}
.pole.szerokie{grid-column:1/-1}

/* --- siatka pól --------------------------------------------------- */
.pola{display:grid;gap:var(--s4);
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr));align-items:start}
.pola.dwie{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.pola.jedna{grid-template-columns:1fr}

/* --- sekcja: nagłówek bliżej swojej treści niż poprzedniej -------- */
.sekcja{margin-top:36px}
.sekcja:first-child{margin-top:0}
.sekcja > h3,.sekcja-tytul{
  margin:0 0 var(--s3);padding-top:var(--s4);
  border-top:1px solid var(--line);
  font-size:var(--fs-md);font-weight:650;letter-spacing:-.01em}
.sekcja:first-child > h3,.sekcja:first-child .sekcja-tytul{border-top:0;padding-top:0}
.sekcja-opis{margin:-6px 0 var(--s4);color:var(--ink-2);font-size:var(--fs-sm);max-width:70ch}

/* --- pasek akcji: zawsze na dole, oddzielony ---------------------- */
.pasek-akcji{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;
  margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line-soft)}
.pasek-akcji .rozpychacz{margin-left:auto}
.pasek-akcji .uwaga{color:var(--ink-3);font-size:var(--fs-sm);max-width:46ch}

/* =====================================================================
   PANEL EDYCJI — to, co się otwiera po kliknięciu „zmień".
   
   Wcześniej rozwijał się w miejscu, wyglądając jak reszta tabeli, więc
   trzeba było szukać wzrokiem, co się właściwie zmieniło. Teraz ma
   cztery sygnały naraz: inne tło, pasek akcentu z lewej, wcięcie
   i nagłówek mówiący WPROST, co się edytuje.
   ===================================================================== */
.panel-edycji{
  position:relative;margin:var(--s2) 0 var(--s4);
  padding:var(--s5) var(--s5) var(--s5) calc(var(--s5) + 4px);
  background:var(--surface-2);border:1px solid var(--line);
  border-left:4px solid var(--accent);border-radius:var(--radius);
  box-shadow:var(--shadow-1)}
.panel-edycji-tytul{
  display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap;
  margin:0 0 var(--s4);font-size:var(--fs-md);font-weight:650}
.panel-edycji-tytul .co{color:var(--ink-3);font-weight:500}
.panel-edycji .sekcja{margin-top:var(--s6)}
.panel-edycji .sekcja > h3{border-top-color:var(--line-soft)}

/* wiersz, z którego panel wyrasta — żeby było widać skąd */
tr.w-edycji > td{background:var(--surface-2)}
tr.w-edycji > td:first-child{box-shadow:inset 4px 0 0 var(--accent)}
td.komorka-panelu{padding:0 !important;background:var(--bg) !important}

/* --- karta pozycji na liście (rola, szablon, seria numeracji) ----- */
.pozycja{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);padding:var(--s4);margin-bottom:var(--s3)}
.pozycja-gora{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap}
.pozycja-gora .nazwa{font-weight:600}
.pozycja-gora .rozpychacz{margin-left:auto}
.pozycja-opis{margin-top:var(--s1);color:var(--ink-2);font-size:var(--fs-sm)}
.pozycja.otwarta{border-color:var(--accent-border);box-shadow:var(--shadow-1)}

/* --- grupa przełączników (uprawnienia) ---------------------------- */
.grupa-przelacznikow{margin-top:var(--s4)}
.grupa-przelacznikow > .naglowek{
  font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);font-weight:700;margin-bottom:var(--s2)}
.przelaczniki{display:grid;gap:var(--s1);
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.przelacznik{display:flex;gap:var(--s2);align-items:flex-start;
  padding:var(--s2) var(--s3);border:1px solid transparent;
  border-radius:var(--radius-sm);cursor:pointer;background:var(--surface)}
.przelacznik:hover{background:var(--g0);border-color:var(--line)}
.przelacznik.wybrany{background:var(--accent-soft);border-color:var(--accent-border)}
.przelacznik input{margin-top:3px;flex:0 0 auto}
.przelacznik .tresc{display:flex;flex-direction:column;gap:1px;min-width:0}
.przelacznik .kod{font-family:var(--mono);font-size:var(--fs-xs);color:var(--ink-3)}

/* --- pojedynczy przełącznik w linii (checkbox z opisem) ----------- */
/* Krzyzyk kasujacy wlasny wpis w kalendarzu - widoczny dopiero przy
   najechaniu na wiersz, zeby nie rozpraszal przy czytaniu planu dnia. */
.kasuj-wpis{margin-left:6px;opacity:0;font-size:15px;line-height:1;color:var(--ink-3)}
.wrs:hover .kasuj-wpis,.kasuj-wpis:focus-visible{opacity:1}
.kasuj-wpis:hover{color:var(--bad-solid,#d64545)}

/* =====================================================================
   DYMKI — podpowiedzi po najechaniu.
   Lukasz, 05.09.2026: "zeby ktos najezdzajac na jakas opcje dostawal
   od razu informacje, do czego to sluzy, prostym jezykiem".

   Jeden element na caly program, `position: fixed`, doklejony do body -
   dzieki temu nie obcina go zaden `overflow: hidden` (a tabel
   przewijanych w bok i szuflad jest tu kilkanascie).
   ===================================================================== */
.dymek{position:fixed;z-index:200;max-width:280px;pointer-events:none;
  padding:8px 10px;border-radius:8px;font-size:var(--fs-sm);line-height:1.45;
  background:var(--ink,#1b1f24);color:var(--surface,#fff);
  box-shadow:0 6px 20px rgba(0,0,0,.28);
  animation:dymek-wejscie .12s ease-out}
/* Strzalka pod dymkiem (dymek nad elementem) albo nad nim. */
.dymek::after{content:'';position:absolute;left:50%;margin-left:-5px;
  border:5px solid transparent;border-top-color:var(--ink,#1b1f24);top:100%}
.dymek.pod::after{top:auto;bottom:100%;border-top-color:transparent;
  border-bottom-color:var(--ink,#1b1f24)}
@keyframes dymek-wejscie{from{opacity:0;transform:translateY(2px)}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.dymek{animation:none}}

/* DOSTEP OSOBY DO PORTALU: tresc z lewej, kod QR z prawej. */
.dostep-portal{display:flex;gap:var(--s5);align-items:flex-start;flex-wrap:wrap}
.dostep-tresc{flex:1 1 420px;min-width:0}
.dostep-qr{flex:0 0 auto;display:flex;flex-direction:column;gap:6px;align-items:center}
.link-portalu{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.link-portalu .input{flex:1 1 320px;min-width:0;font-size:var(--fs-sm)}

/* LOGOWANIE DWUETAPOWE */
.kody-zapasowe{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));
  gap:6px;margin:var(--s3) 0;padding:var(--s3);border-radius:var(--radius);
  background:var(--surface-2);border:1px solid var(--line)}
.kody-zapasowe span{font-size:var(--fs-base);letter-spacing:.06em;text-align:center;
  padding:4px 0}
.kroki-2fa{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:var(--s4)}
.kroki-2fa li{padding-left:4px}
/* Kod QR na bialym tle ZAWSZE - czytnik telefonu nie odczyta jasnych
   kwadratow na ciemnym tle motywu nocnego. */
.qr-2fa{display:inline-block;margin:8px 0;padding:8px;background:#fff;
  border-radius:var(--radius);border:1px solid var(--line)}
.qr-2fa img{display:block;width:200px;height:200px}

.ptaszek{display:inline-flex;gap:var(--s2);align-items:flex-start;cursor:pointer}
.ptaszek input{margin-top:3px;flex:0 0 auto}
.ptaszek .tresc{display:flex;flex-direction:column;gap:1px}
.ptaszek .podpis{font-size:var(--fs-sm);color:var(--ink-3)}

/* Formularz „dopisz coś" na karcie zgłoszenia. Musi być widocznie
   oddzielony od listy nad nim — inaczej pola do wpisywania zlewają się
   z danymi już zapisanymi i nie wiadomo, co jest czym. */
.dopisz{margin-top:var(--s4);padding:var(--s4);background:var(--surface-2);
  border:1px solid var(--line);border-radius:var(--radius)}
.dopisz-tytul{font-size:var(--fs-sm);font-weight:650;color:var(--ink-2);
  text-transform:uppercase;letter-spacing:.04em;margin-bottom:var(--s3)}
.dopisz .pasek-akcji{margin-top:var(--s4);padding-top:var(--s3)}

/* Zakładki wewnątrz ekranu (lista / archiwum) */
.zakladki{display:flex;gap:var(--s1);margin-bottom:var(--s4);
  border-bottom:1px solid var(--line)}
.zakladki button{padding:var(--s3) var(--s4);border:0;background:transparent;
  color:var(--ink-2);font:inherit;font-weight:600;cursor:pointer;
  border-bottom:2px solid transparent;margin-bottom:-1px}
.zakladki button:hover{color:var(--ink)}
.zakladki button.on{color:var(--accent);border-bottom-color:var(--accent)}

/* Pasek potwierdzenia po udanej akcji — zostaje, dopóki go nie zamkniesz,
   bo przekierowanie w środku pracy jest gorsze niż informacja z wyborem. */
.note.pasek-sukcesu{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  border-color:var(--ok-border);background:var(--ok-bg)}
.note.pasek-sukcesu .rozpychacz{margin-left:auto}

/* Zdanie wyjaśniające pod nagłówkiem karty — bez ujemnych marginesów,
   bo te są zarezerwowane dla opisu tuż pod tytułem sekcji. */
.wyjasnienie{margin:0;padding:var(--s3) var(--pad-card);color:var(--ink-2);
  font-size:var(--fs-sm);max-width:80ch;border-bottom:1px solid var(--line-soft)}
/* ten sam tekst, ale pod naglowkiem sekcji w srodku karty - bez ramki
   i bez wcięcia, bo tam nie zaczyna sie zaden nowy pojemnik */
.wyjasnienie.luzem{padding:0 0 var(--s2);border-bottom:0}

/* WYJATEK: blok z tabela ma zdjete cale wciecie (`.blok-bd.tabela`),
   zeby wiersze dochodzily do ramki. Zdanie opisujace sekcje dziedziczylo
   po tym zero i przyklejalo sie do lewej krawedzi i do kreski nad soba.
   Lukasz, 03.09.2026: "brzydko to wyglada, takie przytulone do lewej
   strony i do gory". Wiec tu, i tylko tu, wciecie wraca - rowne temu,
   ktore ma pierwsza kolumna tabeli pod spodem, zeby tekst i tabela
   staly w jednej linii. */
.blok > .blok-bd.tabela > .wyjasnienie.luzem{
  padding:var(--s4) var(--s4) var(--s3);
  max-width:76ch;line-height:1.55}
/* Gdy pod opisem jest juz tabela, kreska pod nim porzadkuje przejscie
   - inaczej zdanie i naglowki kolumn zlewaja sie w jeden szary blok. */
.blok > .blok-bd.tabela > .wyjasnienie.luzem:not(:last-child){
  border-bottom:1px solid var(--line-soft);padding-bottom:var(--s4)}

/* --------------------------------------------------------------------
   Podglad portalu klienta w ustawieniach.
   Ramka jest widoczna celowo: ma byc jasne, ze to okno w okno, a nie
   ekran naszego programu.
   -------------------------------------------------------------------- */
.ramka-portalu{margin:var(--s4) 0 0;border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--surface-2)}
.ramka-portalu iframe{display:block;width:100%;height:760px;border:0;background:#fff}

/* --------------------------------------------------------------------
   Skrzynka rozmow. Kazda pozycja to trzy linie o stalej roli: kto,
   o czym, kiedy. Rozmowa czekajaca na odpowiedz ma pasek z lewej -
   widac ja katem oka, bez czytania.
   -------------------------------------------------------------------- */
.lista-rozmow{display:flex;flex-direction:column;gap:1px;background:var(--line-soft);
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.rozmowa-poz{display:block;width:100%;text-align:left;background:var(--surface);
  border:0;border-left:3px solid transparent;padding:12px 14px;cursor:pointer;
  font:inherit;color:inherit}
.rozmowa-poz:hover{background:var(--surface-2)}
.rozmowa-poz.czeka{border-left-color:var(--bad-solid)}
.rozmowa-poz .gora{display:flex;align-items:baseline;gap:6px;
  font-size:var(--fs-base);margin-bottom:3px}
.rozmowa-poz .tresc{font-size:var(--fs-sm);line-height:1.45;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rozmowa-poz .dol{font-size:var(--fs-xs);margin-top:4px}

/* --------------------------------------------------------------------
   Przebieg zgloszenia - jedna os czasu ze wszystkim, co przy zleceniu
   robiono. Znak rodzaju po lewej zamiast koloru tla: kolorowanie
   dziewieciu rodzajow naraz daje tecze, w ktorej nic nie widac.
   -------------------------------------------------------------------- */
.przebieg{list-style:none;margin:0;padding:0;position:relative}
.przebieg::before{content:'';position:absolute;left:11px;top:6px;bottom:6px;
  width:1px;background:var(--line)}
.przebieg .pz{display:grid;grid-template-columns:24px 132px 1fr;align-items:baseline;
  gap:10px;padding:7px 0;position:relative}
.przebieg .pz-znak{grid-column:1;justify-self:center;background:var(--surface);
  line-height:1;font-size:13px;z-index:1;padding:2px 0;color:var(--ink-2);
  min-width:20px;text-align:center}
.przebieg .pz-czas{grid-column:2;font-size:var(--fs-xs);white-space:nowrap}
.przebieg .pz-tresc{grid-column:3;min-width:0;display:flex;flex-direction:column;gap:2px}
.przebieg .pz-tytul{font-size:var(--fs-sm);line-height:1.4}
.przebieg .pz-opis{font-size:var(--fs-sm);line-height:1.5;color:var(--ink-2);
  white-space:pre-wrap;word-break:break-word}
/* Zmiana statusu to szkielet sprawy - jedyne zdarzenie z wyroznieniem. */
.przebieg .pz-status .pz-znak{color:var(--accent)}
.przebieg .pz-podpis .pz-znak,.przebieg .pz-protokol .pz-znak{color:var(--ok-solid)}
@media (max-width:700px){
  .przebieg .pz{grid-template-columns:24px 1fr}
  .przebieg .pz-czas{grid-column:2}
  .przebieg .pz-tresc{grid-column:2}
}

/* --------------------------------------------------------------------
   Strefa nieodwracalnego. Oddzielona linia i odsunieta od reszty, zeby
   nikt nie trafil w nia przypadkiem, przewijajac formularz.
   -------------------------------------------------------------------- */
.strefa-ryzyka{margin-top:var(--s5);padding-top:var(--s4);
  border-top:1px dashed var(--line)}
.strefa-ryzyka h4{margin:0 0 var(--s3);font-size:var(--fs-md)}
.strefa-ryzyka table{margin:var(--s3) 0;max-width:420px}

/* Rozwinieta strefa dostaje wlasne tlo w barwie ostrzezenia. Nie jest
   to ozdoba: ten sam formularz co wyzej, ale w innym kolorze, mowi
   "tu sie konczy poprawianie, a zaczyna kasowanie". */
/* Szerokosc trzymana krotko. Ta sama strefa siedzi tez w rozwinietym
   wierszu tabeli stanowisk, a tam kolumna ma ze dwa tysiace pikseli -
   bez tego zdanie ucieka poza ekran razem z przyciskiem "Anuluj". */
.strefa-ryzyka.otwarta{max-width:720px;margin-top:var(--s5);padding:var(--s4);
  border:1px solid var(--bad-border);border-radius:var(--radius);
  background:var(--bad-bg)}
.strefa-ryzyka.otwarta h4{color:var(--bad)}
.strefa-ryzyka.otwarta .note{background:transparent;border:0;padding:0;
  margin:0 0 var(--s3)}
.strefa-ryzyka.otwarta code{background:var(--surface);padding:1px 6px;
  border-radius:var(--radius-sm);font-family:var(--mono)}
.strefa-ryzyka .formrow{margin:0;flex-wrap:wrap}
.strefa-ryzyka .pola.ciasne{margin:var(--s3) 0}

/* Scalanie i przenoszenie NIE sa czerwone. To sa porzadki, nie
   kasowanie - a czerwone tlo przy czynnosci, ktora niczego nie niszczy,
   uczy ignorowac czerwony kolor tam, gdzie naprawde cos znaczy.
   Ramka i tlo sa spokojne; czerwony zostaje na samym przycisku
   "Scal firmy", bo tego jednego kroku nie cofnie sie klikiem. */
.strefa-ryzyka.otwarta.scalanie,
.strefa-ryzyka.otwarta.przenoszenie{
  max-width:760px;border-color:var(--line);background:var(--surface-2)}
.strefa-ryzyka.otwarta.scalanie h4,
.strefa-ryzyka.otwarta.przenoszenie h4{color:var(--ink)}

/* Dwie kolumny liczb obok siebie: co znika, co zostaje. Czlowiek ma
   zobaczyc na jednym ekranie, ktora firma jest ta "prawdziwa". */
.scalanie-tabela{width:100%;margin:var(--s3) 0;border-collapse:collapse;
  font-size:var(--fs-sm)}
.scalanie-tabela th{text-align:left;padding:6px 10px;color:var(--ink-2);
  font-weight:600;border-bottom:1px solid var(--line)}
.scalanie-tabela th:nth-child(n+2){text-align:right}
.scalanie-tabela td{padding:5px 10px;border-bottom:1px solid var(--line-soft)}
.scalanie-tabela td.num{text-align:right;font-variant-numeric:tabular-nums}
.scalanie-tabela tr:last-child td{border-bottom:0}

/* Wybor "co z historia" - dwa zdania z konsekwencjami, a nie dwa
   suche napisy. Zaznaczone ma byc widac bez wpatrywania sie w kropke. */
.wybor-historii{display:flex;flex-direction:column;gap:var(--s2);
  margin:var(--s4) 0}
.wybor-historii > label{display:flex;gap:10px;align-items:flex-start;
  padding:10px 12px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);cursor:pointer;line-height:1.45}
.wybor-historii > label.on{border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent)}
.wybor-historii > label input{margin-top:3px;flex:0 0 auto}
.wybor-historii > label > span{min-width:0}
.strefa-ryzyka .rozpychacz{margin-left:auto}

/* --------------------------------------------------------------------
   Zakladki karty firmy w grupach. Kilkanascie zakladek w jednym pasku
   to pasek, w ktorym nikt niczego nie znajduje - wiec sa rozbite na
   grupy z malymi, szarymi etykietami. Etykieta ma porzadkowac, a nie
   konkurowac z zakladka.
   -------------------------------------------------------------------- */
.zakladki-grupy{display:flex;flex-direction:column;gap:var(--s2);
  margin-bottom:var(--s4);padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
.grupa-zakladek{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.grupa-zakladek .etykieta-grupy{
  font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);min-width:96px;flex:0 0 auto}
.grupa-zakladek .zakladki{border-bottom:0;margin:0;flex-wrap:wrap;gap:2px}

/* Panel wysuwany w srodku zakladki - historia, przypisanie licencji. */
.okienko-tresc{margin-top:var(--s4);padding:var(--s4);
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}
.okienko-tresc .kartahd{margin-bottom:var(--s3)}
.lista-wyboru{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  gap:4px;max-height:340px;overflow-y:auto;margin:var(--s3) 0;
  padding:var(--s3);border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface)}

/* ---------------------------------------------------------------------
   Ucinanie dlugich nazw w komorkach tabeli.

   `max-width` na samym <td> nie wystarcza: przy `table-layout: auto`
   przegladarka i tak rozciaga kolumne do szerokosci najdluzszej
   nierozdzielnej tresci, wiec "Zespol Placowek Edukacyjno-Wychowawczych"
   rozpychal cala tabele w prawo i lista jechala poza ekran.

   Ograniczenie musi siedziec na elemencie BLOKOWYM w srodku komorki -
   wtedy `overflow: hidden` odcina tez wklad tresci do szerokosci
   kolumny. Pelna nazwa zostaje w `title`, wiec nic sie nie gubi.
   --------------------------------------------------------------------- */
/* Lista infrastruktury: kolumny stoja tam, gdzie stoja - niezaleznie
   od tego, jak dlugi model wpisal ktos przed chwila. */
.tabela-infra{table-layout:fixed;min-width:900px}
.tabela-infra td,.tabela-infra th{overflow:hidden}
.tabela-infra td .tnij{max-width:100%}
.tabela-infra td.rozwiniecie{overflow:visible}

.tnij{display:block;max-width:var(--tnij,240px);overflow:hidden;
      text-overflow:ellipsis;white-space:nowrap}
td .tnij.jak-link{text-align:left}

/* Bezpieczny Dom - opieka informatyczna nad osoba prywatna.
   Wlasny kolor, bo na liscie stoi obok firm i ma sie od nich odrozniac
   bez czytania: ta sama robota, inny rozmowca. */
.pill.dom{background:var(--dom-bg,#f3ecff);color:var(--dom,#5b3fa8);
          border-color:var(--dom-border,#ddd0f7)}
:root[data-theme="dark"] .pill.dom{--dom-bg:#2a2140;--dom:#c9b6f5;--dom-border:#3d3159}

/* ---------------------------------------------------------------------
   NASZA FIRMA I LOGO (ustawienia).
   Podglad logo na szachownicy, bo wiekszosc znakow ma przezroczyste tlo
   i na bialym polu nie widac, gdzie sie konczy plik, a gdzie zaczyna
   strona.
   --------------------------------------------------------------------- */
.ust-blok{padding:var(--s4)}
.siatka2{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:var(--s3) var(--s4);margin-bottom:var(--s3)}
.logo-podglad{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;
  padding:var(--s4);border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface-2);
  background-image:linear-gradient(45deg,var(--line-soft) 25%,transparent 25%),
                   linear-gradient(-45deg,var(--line-soft) 25%,transparent 25%),
                   linear-gradient(45deg,transparent 75%,var(--line-soft) 75%),
                   linear-gradient(-45deg,transparent 75%,var(--line-soft) 75%);
  background-size:16px 16px;
  background-position:0 0,0 8px,8px -8px,-8px 0}
.logo-podglad img{max-height:72px;max-width:280px;object-fit:contain}
.logo-podglad .formrow{background:var(--surface);padding:6px 8px;border-radius:var(--radius-sm)}

/* Wgrane logo w pasku bocznym i na ekranie logowania. Bierzemy
   wysokosc, nie szerokosc - znak poziomy i kwadratowy maja wygladac
   jak ten sam element, a nie jak dwa rozne naglowki. */
/* Logo w pasku bocznym stoi obok nazwy, wiec nie moze zjadac calej
   szerokosci. Kwadratowy znak i poziomy znak maja tu wygladac tak samo
   wysoko - stad ograniczenie wysokoscia, a nie szerokoscia. */
/* LOGO W PASKU BOCZNYM I NA EKRANIE LOGOWANIA — WIĘKSZE O 100%.
   Łukasz, 05.09.2026: „powiększymy rozmiar loga w tych miejscach
   o jakieś 100%?". `max-width` rośnie razem z wysokością: przy samej
   wysokości logotyp z napisem („serwis24") uderzyłby w limit szerokości
   i zostałby ścięty zamiast urosnąć. */
.logo-obraz{height:68px;width:auto;max-width:100%;object-fit:contain;flex:0 0 auto}
.logo-obraz.duze{height:88px;max-width:300px}
/* Gdy w pasku jest wgrany znak, tekst schodzi do własnego rzędu -
   inaczej jedno drugiemu zabiera miejsce i nie mieści się nic. */
.brandbar .logo-obraz + .brandtext{flex:1 1 100%}

/* Zdjecie pracownika w ustawieniach - okragly podglad dokladnie taki,
   jaki zobaczy klient w portalu, zeby nie bylo niespodzianki po
   wgraniu zdjecia w kadrze do pasa. */
.zdjecie-edycja{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap}
.zdjecie-podglad{width:72px;height:72px;border-radius:50%;object-fit:cover;
  border:2px solid var(--line);background:var(--surface-2);display:flex;
  align-items:center;justify-content:center;font-size:1.5rem;font-weight:680;
  color:var(--accent)}
.zdjecie-podglad.puste{background:var(--accent-soft);border-color:var(--accent-border)}

/* Logo klienta w naglowku jego karty - poznanie karty jednym
   spojrzeniem, zanim sie przeczyta nazwe. */
.kartahd .logo-klienta{height:36px;width:auto;max-width:140px;object-fit:contain;
  border-radius:var(--radius-sm)}

/* ---------------------------------------------------------------------
   PODPINANIE KALENDARZA GOOGLE.
   Trzy kroki wypisane po kolei, bo tyle ich naprawde jest - a przy
   OAuth najlatwiej zgubic sie w tym, ktory jest teraz.
   --------------------------------------------------------------------- */
.kroki-lista{margin:0 0 var(--s3);padding-left:22px;color:var(--ink-2);line-height:1.6}
.kroki-lista li{margin-bottom:6px}
.kroki-lista b{color:var(--ink)}
/* Adres powrotu przepisuje sie do Google recznie, wiec ma byc duzy,
   jednoznaczny i z przyciskiem do skopiowania. Jedna literka roznicy
   to blad, ktorego nikt nie znajdzie golym okiem. */
.adres-powrotu{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding:12px 14px;border:1px dashed var(--line);border-radius:var(--radius);
  background:var(--surface-2)}
.adres-powrotu code{font-family:var(--mono);font-size:var(--fs-base);color:var(--ink);
  word-break:break-all}

/* Podtytul w naglowku panelu: mowi, czego dotyczy to, na co patrzysz -
   przy kalendarzu jest to dzisiejsza data. */
.widget > .hd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.hd-podtytul{color:var(--ink-3);font-size:var(--fs-sm)}
/* "cały dzień" nie jest godzina, wiec nie stoi w kolumnie liczb - inaczej
   udawaloby jedna z nich. */
.lista-widget .kiedy.slowo{font-size:var(--fs-sm);color:var(--ink-3);font-style:italic}

/* Numer zlecenia NAD opisem, w tej samej komorce. W panelu na pol
   ekranu osobna kolumna na numer zjadala tyle miejsca, ze z opisu
   zostawaly trzy slowa i wielokropek. */
.lista-widget .opis .numer-w-opisie{font-size:var(--fs-sm);color:var(--ink-3);
  letter-spacing:.01em}

/* ---------------------------------------------------------------------
   KOLUMNY WIDGETOW - wyrownanie.
   Lukasz, 03.09.2026: "kolumny ze statusami tez nie sa wycentrowane".
   `stan` trzyma sie prawej krawedzi (tam konczy sie wiersz i tam oko
   szuka wyniku), `stan-lewo` - lewej, bo numer stanowiska i nazwisko
   technika czyta sie od poczatku, a nie od konca.
   --------------------------------------------------------------------- */
/* Plakietka stanu stoi POD swoim naglowkiem, a nie przy prawej
   krawedzi. Lukasz, 03.09.2026: "rob tak, zeby pod opisami kolumn
   rzeczy byly zawsze dobrze ulozone" - a naglowki sa wyrownane do
   lewej, wiec tresc tez musi byc. Do prawej wyrownana zostaje tylko
   kolumna czasu, bo tam liczby maja sie konczyc rowno. */
.lista-widget .stan{align-items:flex-start;justify-content:center;gap:4px}
.lista-widget .stan-lewo{align-items:flex-start;justify-content:center;gap:2px;min-width:0}
.lista-widget .stan .muted,.lista-widget .stan-lewo .muted{font-size:var(--fs-sm)}
.lista-widget .technik{font-size:var(--fs-sm);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;max-width:100%}
/* Numer stanowiska: czcionka maszynowa, bo to kod z naklejki na
   obudowie - i przycisk, bo prowadzi do karty tego komputera. */
.kod-stanowiska{font-size:var(--fs-sm);color:var(--ink-2);white-space:nowrap}
button.kod-stanowiska{border:0;background:none;padding:0;cursor:pointer;
  color:var(--accent);text-decoration:underline;text-underline-offset:2px}
button.kod-stanowiska:hover{color:var(--accent-hover)}
button.kod-stanowiska:focus-visible{outline:none;box-shadow:var(--focus);border-radius:3px}
/* Data i godzina pod soba w kolumnie "Data". */
.lista-widget .kiedy > span{display:block}

/* =====================================================================
   PASKI PRZEWIJANIA.
   Lukasz, 03.09.2026: "damy rade, zeby te paski do przewijania okien
   gralY kolorystycznie?".
   Damy rade i warto: w ciemnym motywie systemowy pasek jest jasny
   i swieci przez pol ekranu jak zapomniana lampka. Kolory bierzemy
   z tokenow, wiec zmieniaja sie razem z motywem.
   `scrollbar-color` obsluguje Firefox, `::-webkit-scrollbar` - reszta.
   ===================================================================== */
*{scrollbar-color:var(--g4) transparent;scrollbar-width:thin}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--g4);border-radius:999px;
  /* Ramka w kolorze tla robi z suwaka waski pasek z odstepem od
     krawedzi - bez niej dotyka scianek i wyglada jak element okna,
     a nie jak uchwyt. */
  border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--g5);background-clip:content-box;
  border:3px solid transparent}
::-webkit-scrollbar-corner{background:transparent}

/* Wewnatrz paneli suwak ma byc jeszcze dyskretniejszy - to element
   listy, a nie okna. */
.widget ::-webkit-scrollbar,.lista-widget::-webkit-scrollbar{width:9px;height:9px}

/* Ciasne kolumny w panelach: mniejszy oddech po bokach, zeby piec
   kolumn zmiescilo sie na polowie ekranu bez przewijania w bok. */
.widget .lista-widget .wrs > *,.widget .lista-widget .nagl > span{padding-left:10px;padding-right:10px}
/* Plakietka nie moze wyjsc poza swoja kolumne - nazwa kalendarza albo
   dlugi status urywalby sie o krawedz panelu. `display:block` jest tu
   konieczne: `text-overflow` nie dziala na elemencie inline. */
.widget .lista-widget .stan .pill{display:block;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

/* Kiedy monitoring ostatni raz cos powiedzial. */
.monitoring-pasek{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  margin-bottom:var(--s4);padding:9px 14px;border-radius:var(--radius);
  border:1px solid var(--line);background:var(--surface-2);
  color:var(--ink-2);font-size:var(--fs-sm)}
.monitoring-pasek strong{color:var(--ink)}
.monitoring-pasek.stary{border-color:var(--warn-border);background:var(--warn-bg);color:var(--warn)}
.monitoring-uwaga{margin-left:auto;text-align:right}

/* Trzy liczby o dostepnosci na ekranie monitoringu. */
.stan-liczba{display:flex;flex-direction:column;gap:2px;padding:12px 14px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.stan-liczba .w{font-size:var(--fs-2xl);font-weight:660;font-variant-numeric:tabular-nums}
.stan-liczba .o{color:var(--ink-2);font-size:var(--fs-sm)}


/* --------------------------------------------------------------------
   Tabelka prob polaczenia z API AnyDeska.
   Wyglada technicznie, bo taka jest - to jest miejsce, w ktorym program
   pokazuje surowa odpowiedz serwera zamiast udawac, ze wie lepiej.
   -------------------------------------------------------------------- */
.proby-api{width:100%;margin-top:var(--s3);border-collapse:collapse;
  font-size:var(--fs-xs)}
.proby-api th{text-align:left;padding:4px 8px;color:var(--ink-3);font-weight:600;
  border-bottom:1px solid var(--line)}
.proby-api td{padding:4px 8px;border-bottom:1px solid var(--line-soft);
  vertical-align:top}
.proby-api tr:last-child td{border-bottom:0}
.proby-api .probka{margin-top:2px;color:var(--ink-3);word-break:break-all;
  max-width:46ch;white-space:pre-wrap}
details > summary{cursor:pointer;color:var(--ink-2)}


/* --------------------------------------------------------------------
   ZRODLA DOSTEPNOSCI - dwie karty obok siebie.

   Lukasz, 03.09.2026: "nie damy rady upchac tego w widgetach obok
   siebie? Eset i Anydesk? (...) w sumie sa 4 okienka do wypelnienia".
   Mial racje: kazde zrodlo mialo wlasna sekcje na cala szerokosc
   i wlasny akapit o tym samym. Cztery pola zajmowaly dwa ekrany.
   -------------------------------------------------------------------- */
.zrodla{display:grid;gap:var(--s4);margin-top:var(--s4);
  grid-template-columns:repeat(auto-fit,minmax(360px,1fr));align-items:start}

.zrodlo{display:flex;flex-direction:column;gap:var(--s3);
  padding:var(--s4);border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);box-shadow:var(--shadow-1);min-width:0}
.zrodlo > header{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding-bottom:var(--s3);border-bottom:1px solid var(--line-soft)}
.zrodlo .nazwa{font-weight:660;font-size:var(--fs-base)}
/* Rola zrodla jednym slowem - jedyna rzecz, ktorej nie widac z ekranu. */
.zrodlo .rola{margin-left:auto;color:var(--ink-3);font-size:var(--fs-sm)}
/* Kropka mowi, czy zrodlo pyta samo. Zielona = chodzi, szara = spi. */
.zrodlo .kropka{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
.zrodlo .kropka.zywa{background:var(--ok-solid)}
.zrodlo .kropka.spi{background:var(--ink-3);opacity:.45}

.zrodlo .pola.ciasne{grid-template-columns:1fr}
.zrodlo .formrow{gap:var(--s2);flex-wrap:wrap;margin:0}

/* Ptaszek i liczba minut w jednej linii - to jedno ustawienie,
   a nie dwa osobne pytania. */
.zrodlo-auto{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.zrodlo-auto .input.w-min{width:64px;height:32px;text-align:center}
.zrodlo-auto label{margin:0}

.zrodlo-stopka{color:var(--ink-3);font-size:var(--fs-sm);line-height:1.5}
.zrodlo .note{margin:0}
.zrodlo .proby-api{font-size:var(--fs-xs)}
.zrodlo .proby-api td{padding:3px 6px}

/* „z ręki" przy kolumnie KTO SIEDZI - mala, szara adnotacja, ze to
   wpisany tekst, a nie przypisana osoba. Ma odrozniac, a nie krzyczec. */
.recznie{font-size:var(--fs-xs);opacity:.75}

/* --------------------------------------------------------------------
   RAPORTY. Szablony jako kafle z opisem, bo o wyborze raportu decyduje
   zdanie "po co on jest", a nie sama nazwa. W rozwijanym polu tego
   zdania nie ma gdzie postawic.
   -------------------------------------------------------------------- */
.raporty-lista{display:grid;gap:var(--s3);margin-top:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
.raport-kafel{display:flex;flex-direction:column;gap:4px;text-align:left;
  padding:var(--s3) var(--s4);border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface);cursor:pointer;
  font:inherit;color:inherit;min-width:0}
.raport-kafel:hover{border-color:var(--ink-3)}
.raport-kafel.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);
  background:var(--accent-soft)}
.raport-kafel .nazwa{font-weight:650}
.raport-kafel .opis{color:var(--ink-2);font-size:var(--fs-sm);line-height:1.45}
/* Spis kolumn malym drukiem - mowi, co bedzie w pliku, zanim ktos go
   pobierze. Trzy sekundy tu oszczedzaja pobranie nie tego raportu. */
.raport-kafel .kolumny{color:var(--ink-3);font-size:var(--fs-xs);margin-top:2px}
a.btn.wylaczony{opacity:.45;pointer-events:none}

/* Surowa odpowiedz cudzego API. Wyglada technicznie, bo taka jest -
   i to jest jedyne miejsce, z ktorego dowiemy sie, czego ESET oczekuje. */
.odpowiedz-api{margin:6px 0 0;padding:8px 10px;border-radius:var(--radius-sm);
  background:var(--surface-2);border:1px solid var(--line);
  font-family:var(--mono);font-size:var(--fs-xs);line-height:1.45;
  white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}

/* Firma z oddzialami w liscie stanowisk.
   Nazwa firmy zostaje mocna, nazwa punktu idzie obok - mniejsza i szara,
   zeby czytalo sie jako dopisek, a nie jako druga firma. Gdy zabraknie
   miejsca, ucina sie punkt, nie firma. */
.firma-z-oddzialem{display:flex;align-items:baseline;gap:6px;min-width:0}
.firma-z-oddzialem>.tnij{flex:0 0 auto}
.oddzial{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-size:var(--fs-xs);color:var(--ink-3);font-weight:400}

/* Pasek akcji na wielu stanowiskach.
   Siedzi nad tabela i pojawia sie dopiero, gdy jest na czym dzialac -
   zaznaczenie albo zawezony filtr firmy. Wyglada jak czesc listy, a nie
   jak osobne narzedzie, bo to jest ten sam ruch: "te maszyny". */
.pasek-grupowy{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin:var(--s3) 0;padding:8px 10px;border-radius:8px;
  background:var(--surface-2,rgba(127,127,127,.08));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.pasek-grupowy .pg-info{margin-right:auto;min-width:0}
.pg-panel{flex:1 0 100%;margin-top:8px;padding-top:8px;
  border-top:1px solid var(--linia,rgba(127,127,127,.25))}
.kol-zazn{width:34px;text-align:center}
.kol-zazn input{cursor:pointer}
tr.zaznaczony{background:var(--surface-2,rgba(127,127,127,.10))}

/* Lista komputerow przy stanowisku. Nazwa maszyny i "rozdziel" w jednej
   linii - przycisk pojawia sie tylko tam, gdzie jest co rozdzielac. */
.kompy-wiersz{display:flex;align-items:baseline;gap:8px}
.kompy-wiersz .rowlink{cursor:pointer}
.kompy-wiersz .jak-link{font-size:var(--fs-xs)}

/* Trzy kropki przy czekaniu na wynik zadania.
   Nie pasek postepu - nikt nie wie, ile potrwa skan, a pasek udajacy
   te wiedze klamie. Kropki mowia tylko tyle, ze program nie stoi. */
.czekanie{display:flex;align-items:center;flex-wrap:wrap;gap:4px;margin-top:6px}
.kropki{display:inline-flex;gap:3px;margin-left:2px;vertical-align:baseline}
.kropki i{width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.3;
  animation:kropka 1.2s infinite ease-in-out}
.kropki i:nth-child(2){animation-delay:.2s}
.kropki i:nth-child(3){animation-delay:.4s}
@keyframes kropka{0%,60%,100%{opacity:.25;transform:translateY(0)}
                  30%{opacity:1;transform:translateY(-2px)}}
@media (prefers-reduced-motion:reduce){
  /* Ruch znika, kropki zostaja - animacja bywa problemem, informacja nie. */
  .kropki i{animation:none;opacity:.55}
}

/* Sekcje w skrzynce pod dzwonkiem. */
.dzwonek-naglowek{display:flex;align-items:center;gap:8px;padding:6px 10px;
  font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);border-bottom:1px solid var(--linia,rgba(127,127,127,.2))}
/* WPIS W DZWONKU CZYTA SIE Z GORY NA DOL, NIE W POPRZEK.
   `.podpowiedz` jest z natury wierszem (flex w poziomie) - w podpowiedzi
   szukajki to ma sens, bo tam jest jedna linijka. W dzwonku wpis ma
   dwie czesci: nagłowek z odznaka i data, a pod nim tresc. Ustawione
   w poziomie lądowały obok siebie i tresc scisnięta do 120 px lamala
   sie po dwa slowa. */
.dzwonek-lista .podpowiedz{flex-direction:column;align-items:stretch;gap:4px;
  padding:10px 12px}
.dzwonek-lista .podpowiedz > div{min-width:0;max-width:100%}
.dzwonek-lista .podpowiedz .muted{white-space:normal;line-height:1.45}
.dzwonek-naglowek{display:flex;align-items:center;gap:8px}

.powiad-glowa{display:flex;align-items:center;gap:6px;min-width:0;flex-wrap:nowrap}
/* Tytul ustepuje miejsca dacie, a nie odwrotnie - data ma stala
   szerokosc i musi sie zmiescic w calosci. */
.powiad-glowa strong{flex:1 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.powiad-glowa .pill{flex:0 0 auto}
.podpowiedz.przeczytane{opacity:.55}

/* Kreator zestawien: wybor kolumn w grupach.
   Trzydziesci ptaszkow w jednej kolumnie to sciana - podzial na grupy
   ("Stanowisko", "Sprzet", "System", "Siec") sprawia, ze szuka sie
   wzrokiem, a nie czytaniem od gory do dolu. */
.kolumny-wybor{display:grid;gap:var(--s4);margin-top:4px;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.kolumny-grupa{min-width:0}
.kolumny-tytul{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);margin-bottom:6px;padding-bottom:4px;
  border-bottom:1px solid var(--linia,rgba(127,127,127,.25))}
.ptaszek-linia{display:flex;align-items:center;gap:7px;padding:3px 0;
  cursor:pointer;font-size:var(--fs-sm);min-width:0}
.ptaszek-linia input{cursor:pointer;flex:0 0 auto}
.ptaszek-linia span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Karta urzadzenia infrastruktury - rozwija sie POD wierszem listy,
   zeby technik porownujacy dwa switche w tej samej szafie nie tracil
   listy z oczu. */
.rozwiniecie{background:var(--surface-2,rgba(127,127,127,.06));padding:var(--s4)}
.karta-infra .pola{margin-top:4px}

/* =====================================================================
   MAPA SIECI
   Rysunek ma byc czytelny z odleglosci metra - stad grube ksztalty,
   nazwa pod ikonka i adres pod nazwa. Kolory ida z motywu, wiec mapa
   dziala tak samo w jasnym i ciemnym.
   ===================================================================== */
.mapa-pasek{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin:var(--s3) 0;padding:8px 10px;border-radius:8px;
  background:var(--surface-2,rgba(127,127,127,.08));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.mapa-uklad{display:flex;gap:var(--s4);align-items:flex-start;min-width:0}
.mapa-szuflada{flex:0 0 210px;max-height:640px;overflow:auto;padding-right:4px}
.mapa-pozycja{display:flex;flex-direction:column;gap:1px;width:100%;text-align:left;
  padding:6px 8px;margin-bottom:4px;border-radius:6px;cursor:pointer;
  background:var(--surface,transparent);color:inherit;font:inherit;
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.mapa-pozycja:hover{border-color:var(--accent)}
.mapa-pozycja strong{font-size:var(--fs-sm)}
.mapa-pozycja span{font-size:var(--fs-xs)}
.mapa-plotno{flex:1 1 auto;min-width:0;overflow:hidden;
  /* Wysokosc liczona od okna, nie na sztywno - plansza ma sie miescic
     na ekranie w calosci, bo mapa przewijana razem ze strona traci
     sens: dolna czesc rysunku jest wtedy zawsze poza kadrem. */
  height:clamp(340px,calc(100vh - 340px),780px);
  border:1px solid var(--linia,rgba(127,127,127,.25));border-radius:8px;
  background:var(--surface,transparent);cursor:grab;touch-action:none;
  /* Delikatna kratka - daje oko punkt odniesienia przy przesuwaniu,
     inaczej przy przeciaganiu pustego tla nie widac, ze cos sie dzieje. */
  background-image:radial-gradient(var(--linia,rgba(127,127,127,.22)) 1px,transparent 1px);
  background-size:26px 26px}
.mapa-plotno:active{cursor:grabbing}
.mapa-plotno.edycja{border-color:var(--accent)}
.mapa-boczek{flex:0 0 220px;padding:10px;border-radius:8px;
  background:var(--surface-2,rgba(127,127,127,.08));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.mapa-svg{display:block;touch-action:none}

/* Wezel: prostokat z ksztaltem, nazwa i adresem. */
.mapa-wezel.edytowalny{cursor:grab}
.mapa-wezel.edytowalny:active{cursor:grabbing}
.mapa-wezel.otwieralny{cursor:pointer}
/* Element czysto rysunkowy ("Internet") nie ma kartoteki do otwarcia. */
.mapa-wezel.otwieralny.rysunkowy{cursor:default}
.mapa-wezel.otwieralny:not(.rysunkowy):hover .tlo{stroke:var(--accent);stroke-width:2.5}
.mapa-wezel .tlo{fill:var(--surface-2,rgba(127,127,127,.10));
  stroke:var(--linia,rgba(127,127,127,.4));stroke-width:1.5}
.mapa-wezel:hover .tlo{stroke:var(--accent)}
.mapa-wezel.wybrany .tlo{stroke:var(--accent);stroke-width:2.5}
.mapa-wezel.laczony .tlo{stroke:var(--accent);stroke-width:2.5;stroke-dasharray:5 4}
.mapa-wezel .ksztalt{fill:none;stroke:var(--ink-2);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.mapa-nazwa{text-anchor:middle;font-size:11px;font-weight:600;fill:var(--ink-1,currentColor)}
/* ADRES: najwiekszy tekst po nazwie - to sie z mapy przepisuje. */
.mapa-adres{text-anchor:middle;font-size:13px;font-weight:700;fill:var(--ink-1,currentColor);
  font-family:ui-monospace,Consolas,monospace;letter-spacing:.2px}

/* NUMER STANOWISKA - jak numer na drzwiach, w rogu kafelka. */
.mapa-stanowisko rect{fill:var(--accent);opacity:.92}
.mapa-stanowisko text{text-anchor:middle;font-size:12px;font-weight:800;
  fill:var(--na-akcencie,#fff);letter-spacing:.3px}

/* DOSTEPNOSC: kropka pulsuje, krzyzyk nie. Ksztalt niesie to samo,
   co kolor - wydruk jest czarno-bialy, a czesc ludzi nie odroznia
   zieleni od czerwieni. */
.mapa-dostepnosc.jest circle{fill:var(--ok-solid,#22a06b);
  animation:mapa-puls 2.4s ease-in-out infinite}
.mapa-dostepnosc.nie-ma line{stroke:var(--bad-solid,#d64545);stroke-width:2.2;
  stroke-linecap:round}
@keyframes mapa-puls{
  0%,100%{opacity:1;r:5}
  50%{opacity:.55;r:6.5}}
@media (prefers-reduced-motion:reduce){
  .mapa-dostepnosc.jest circle{animation:none}}

/* PREDKOSC I UWAGA NA KABLU. Predkosc czytelnie, uwaga ciszej -
   to podpowiedz ("kabel pod nogami"), nie parametr lacza. */
.mapa-kabel-opis rect{fill:var(--surface,#fff);stroke:var(--linia,rgba(127,127,127,.3));
  stroke-width:1;opacity:.94}
.mapa-kabel-opis.klikalny{cursor:pointer}
.mapa-kabel-opis.klikalny:hover rect{stroke:var(--accent)}
.mapa-predkosc{text-anchor:middle;font-size:10.5px;font-weight:700;
  fill:var(--ink-2,currentColor);font-family:ui-monospace,Consolas,monospace}
.mapa-uwaga{text-anchor:middle;font-size:9px;font-style:italic;fill:var(--ink-3)}
.mapa-port{text-anchor:middle;font-size:9.5px;fill:var(--ink-3);
  font-family:ui-monospace,Consolas,monospace}
.mapa-kabel{cursor:pointer}
.mapa-kabel:hover line:last-of-type{stroke-width:3.5}

/* Osobny rysunek na papier - na ekranie schowany. */
.mapa-druk,.mapa-stopka-druku{display:none}

@media print{
  /* Na papier idzie sam rysunek - menu, pasek narzedzi i szuflada nie
     sa dokumentacja, tylko sposobem jej robienia. */
  @page{size:A4 landscape;margin:8mm}
  .side,.topbar,.mapa-pasek,.mapa-szuflada,.mapa-boczek,.wyjasnienie,.hd,
  .note,.mapa-plotno{display:none!important}
  .card{box-shadow:none;border:0;padding:0;margin:0;background:#fff}
  .content,.main,body{background:#fff}
  /* Siatka programu to dwie kolumny: menu i tresc. Po schowaniu menu
     tresc ladowala w kolumnie po nim - 244 px - i cala mapa drukowala
     sie wielkosci znaczka. Na papierze nie ma dwoch kolumn. */
  .shell{display:block!important}
  .main,.content{width:auto!important;max-width:none!important}

  /* CALY rysunek, przyciety do tego, co narysowane, przeskalowany do
     kartki - a nie ten kawalek, ktory akurat byl widoczny na ekranie. */
  .mapa-druk{display:block;width:100%!important;max-width:100%;height:auto;
    max-height:175mm;margin:0 auto;align-self:stretch}
  .mapa-stopka-druku{display:block;margin-top:4mm;font-size:9pt;color:#444;
    text-align:center}

  /* Na bialym papierze ciemny motyw sie nie drukuje - wymuszamy
     czern na bieli, zeby kartka byla czytelna i nie zzerala tonera. */
  .mapa-druk .mapa-wezel .tlo{fill:#fff;stroke:#444;stroke-width:1.2}
  .mapa-druk .ksztalt{stroke:#222}
  .mapa-druk .mapa-nazwa,.mapa-druk .mapa-adres{fill:#000}
  .mapa-druk .mapa-port,.mapa-druk .mapa-predkosc{fill:#333}
  .mapa-druk .mapa-uwaga{fill:#555}
  .mapa-druk .mapa-opis-portu rect,.mapa-druk .mapa-kabel-opis rect{fill:#fff;stroke:#bbb}
  .mapa-druk .mapa-stanowisko rect{fill:#111}
  .mapa-druk .mapa-stanowisko text{fill:#fff}
  .mapa-druk .mapa-dostepnosc.jest circle{fill:#fff;stroke:#111;stroke-width:1.6;animation:none}
  .mapa-druk .mapa-dostepnosc.nie-ma line{stroke:#111}
}

/* Opis portu leży na wierzchu kabla i ikonek - z podkladem, zeby dalo
   sie go przeczytac takze tam, gdzie przecina inna linie. */
.mapa-opis-portu{cursor:pointer}
.mapa-opis-portu rect{fill:var(--surface,#fff);stroke:var(--linia,rgba(127,127,127,.3));
  stroke-width:1}
.mapa-opis-portu:hover rect{stroke:var(--accent)}

/* =====================================================================
   WYKRESY NA PANELU
   Kolory ida z tokenow programu (--ok-solid, --bad-solid, --accent),
   wiec motyw ciemny dziala bez osobnej palety. Slupki sa jednokolorowe:
   dlugosc niesie znaczenie, kolor nie.
   ===================================================================== */
/* W waskim widgecie (jedna kolumna siatki) pierscien staje NAD legenda,
   a nie obok - obok zostawaloby mu 40 pikseli i nic by z niego nie bylo
   widac. Przy szerszym wraca uklad poziomy. */
.wykres-kolo{display:flex;align-items:center;justify-content:center;
  gap:var(--s3);flex-wrap:wrap;padding:var(--s2) 0}
/* Lukasz, 04.09.2026: "w dostepnosci stanowisk to kolko powieksz
   smialo o jakies 100%". Pierscien jest tu glownym elementem widgetu,
   a nie ikonka obok liczb - wiec ma tak wygladac. */
/* Kadr jest teraz szerszy niż wysoki (250×176), bo podpisy stoją po
   bokach pierścienia. Szerokość prowadzi, wysokość wynika z proporcji. */
.kolo-svg{width:100%;max-width:420px;height:auto;flex:0 0 auto}
/* W wąskim widgecie pierścień staje NAD legendą. `nowrap` jest tu
   konieczne: przy kolumnie i ograniczonej wysokości panelu zawijanie
   przerzuca legendę w DRUGĄ KOLUMNĘ obok koła - czyli robi dokładnie
   to, czego chcieliśmy uniknąć, i ucina jej podpisy. */
.panel>.w1 .wykres-kolo{flex-direction:column;flex-wrap:nowrap;gap:var(--s2)}
.panel>.w1 .kolo-legenda{width:100%;flex:0 0 auto}
/* KÓŁKO DOPASOWUJE SIĘ DO MIEJSCA, KTÓRE ZOSTAŁO.
   Lukasz, 04.09.2026: "chce zeby bylo idealnie tak, zeby nie rozciagal
   sie widget w dol (zeby nie musiec przewijac) (...) na mniejszych
   monitorach te widgety tak sie dostosowuja".
   Zamiast stałego rozmiaru w pikselach pierścień dostaje resztę
   wysokości panelu (`flex:1 1 0` + `min-height:0`), a SVG z `viewBox`
   sam skaluje się do tego pudełka. Na małym monitorze zrobi się
   mniejszy zamiast wypychać legendę poza kadr. */
.wykres-kolo{height:100%;min-height:0;overflow:hidden;padding:var(--s2) 0}
.panel .kolo-svg{flex:1 1 auto;min-height:0;width:100%;height:100%;max-width:none}
.kolo-kawalek{transition:stroke-width .12s}
.kolo-kawalek.klik{cursor:pointer}
.kolo-kawalek.klik:hover{stroke-width:22}
.kolo-liczba{text-anchor:middle;dominant-baseline:middle;font-size:26px;font-weight:700;
  fill:var(--ink);font-variant-numeric:tabular-nums}
.kolo-podpis{text-anchor:middle;font-size:10px;fill:var(--ink-3);
  text-transform:uppercase;letter-spacing:.08em}
.kolo-legenda{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
.legenda-wiersz{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  padding:5px 8px;border:0;border-radius:var(--radius-sm);background:none;
  color:inherit;font:inherit;font-size:var(--fs-sm);cursor:pointer}
.legenda-wiersz:disabled{cursor:default}
.legenda-wiersz:not(:disabled):hover{background:var(--surface-2)}
.legenda-nazwa{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;color:var(--ink-2)}
.legenda-wiersz strong{font-variant-numeric:tabular-nums}
/* Znak w legendzie niesie ksztalt, nie tylko kolor - kolo pelne,
   kolo w kreski, kolo puste. Bez tego czerwony i zielony sa dla czesci
   ludzi tym samym. */
.legenda-znak{width:11px;height:11px;border-radius:50%;flex:0 0 auto}
.legenda-znak.ton-ok{background:var(--ok-solid)}
.legenda-znak.ton-zle{background:repeating-linear-gradient(45deg,
  var(--bad-solid) 0 2px, var(--surface) 2px 4px);border:1px solid var(--bad-solid)}
.legenda-znak.ton-uwaga{background:var(--warn)}
.legenda-znak.ton-nic{background:transparent;border:1.5px solid var(--ink-3)}
/* Środek pierścienia bywa teraz ułamkiem („16/19"), a nie procentem.
   Dłuższy napis musi zmieścić się w otworze, więc stopień pisma
   zależy od długości - inaczej „16/19" dotyka krawędzi pierścienia. */
.kolo-liczba{font-size:26px}
.kolo-svg text.kolo-liczba[data-dlugi="1"]{font-size:21px}

.wykres-slupki{display:flex;flex-direction:column;gap:2px;padding:var(--s2) 0;
  overflow:auto}
.slupek-wiersz{display:grid;grid-template-columns:minmax(80px,1fr) 1.4fr auto;
  align-items:center;gap:10px;width:100%;text-align:left;padding:7px 8px;
  border:0;border-radius:var(--radius-sm);background:none;color:inherit;font:inherit;
  font-size:var(--fs-sm);cursor:pointer}
.slupek-wiersz:disabled{cursor:default}
.slupek-wiersz:not(:disabled):hover{background:var(--surface-2)}
.slupek-nazwa{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
/* Lukasz, 04.09.2026: "te slupki - da rade, zeby byly wyzsze? Fajniej
   by to wizualnie wygladalo." Racja: cienka kreska czyta sie jak linia
   pomocnicza, a nie jak wielkosc. */
.slupek-tor{height:15px;border-radius:4px;background:var(--surface-2);overflow:hidden}
.slupek-wypelnienie{display:block;height:100%;border-radius:4px;
  background:var(--accent);min-width:4px}
.slupek-wiersz:not(:disabled):hover .slupek-wypelnienie{background:var(--accent-hover)}
.slupek-liczba{font-variant-numeric:tabular-nums}
.slupek-uwaga{grid-column:2 / -1;font-size:var(--fs-xs);color:var(--warn);
  margin-top:-2px}

/* Dokumenty: lista po lewej, dokument po prawej - jak skrzynka pocztowa.
   Pisze sie je seriami, wiec przeskok miedzy nimi ma byc jednym klikiem. */
.dok-uklad{display:flex;gap:var(--s4);align-items:flex-start;min-width:0;
  margin-top:var(--s3)}
.dok-lista{flex:0 0 280px;max-height:70vh;overflow:auto;display:flex;
  flex-direction:column;gap:3px}
.dok-pozycja{display:flex;flex-direction:column;gap:1px;text-align:left;width:100%;
  padding:8px 10px;border-radius:var(--radius-sm);cursor:pointer;color:inherit;font:inherit;
  background:none;border:1px solid transparent}
.dok-pozycja:hover{background:var(--surface-2)}
.dok-pozycja.on{background:var(--surface-2);border-color:var(--accent)}
.dok-numer{font-size:var(--fs-xs);color:var(--ink-3)}
.dok-tytul{font-weight:600;font-size:var(--fs-sm);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.dok-meta{font-size:var(--fs-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dok-tresc{flex:1 1 auto;min-width:0}
.dok-podsumowanie{margin:var(--s3) 0 0 auto;max-width:320px;display:flex;
  flex-direction:column;gap:3px}
.dok-podsumowanie div{display:flex;justify-content:space-between;gap:16px;
  font-size:var(--fs-sm)}
.dok-podsumowanie strong{font-variant-numeric:tabular-nums}
.dok-podsumowanie .razem{border-top:1px solid var(--ink);margin-top:5px;padding-top:6px;
  font-size:var(--fs-md);font-weight:700}
.wybor-sprzetu{max-height:320px;overflow:auto;margin-top:8px;
  border-top:1px solid var(--line);padding-top:6px}

/* Tryb układania panelu. Przeciąganie włączone na stałe kończy się tym,
   że ktoś przesuwa panel, chcąc kliknąć w zgłoszenie - stąd osobny tryb
   i wyraźne obramowanie, żeby było widać, że ekran zachowuje się
   inaczej niż zwykle. */
.widget.ukladany{cursor:grab;outline:1.5px dashed var(--accent);outline-offset:-2px}
.widget.ukladany:active{cursor:grabbing}
.widget.ukladany .hd h3{pointer-events:none}
.rozmiar-widgetu{display:flex;align-items:center;gap:4px;font-size:var(--fs-xs)}
.rozmiar-widgetu .btn{padding:0 6px;min-width:22px;line-height:1.6}
.rozmiar-widgetu strong{min-width:12px;text-align:center;font-variant-numeric:tabular-nums}

/* Słupki w wąskim widgecie: nazwa i liczba w jednej linii, pasek pod
   spodem na całą szerokość. W układzie trzykolumnowym na ćwiartce ekranu
   nazwa "Sprzęt 5 lat i starszy" ucinała się do "Sprzęt 5 lat i sta…",
   a to jest akurat ta część, która niesie znaczenie - pasek bez nazwy
   nie mówi nic. */
.panel>.w1 .slupek-wiersz{grid-template-columns:1fr auto;gap:2px 8px;padding:6px 8px}
.panel>.w1 .slupek-nazwa{white-space:normal;overflow:visible;grid-area:1 / 1}
/* Miejsca w siatce wskazane WPROST. Bez tego liczba ladowala pod
   paskiem zamiast obok nazwy - automatyczne ukladanie stawia elementy
   w kolejnosci z HTML-a, a pasek rozpiety na dwie kolumny przesuwa
   wszystko, co po nim. */
.panel>.w1 .slupek-liczba{grid-area:1 / 2}
.panel>.w1 .slupek-tor{grid-area:2 / 1 / 3 / 3;height:12px}
.panel>.w1 .slupek-uwaga{grid-area:3 / 1 / 4 / 3;margin-top:0}

/* Miejsce na upuszczenie panelu na koniec - widoczne tylko w trybie
   ukladania. Bez niego nie da sie przesunac panelu ZA ostatni. */
.panel-koniec{grid-column:1 / -1;min-height:64px;border-radius:var(--radius);
  border:1.5px dashed var(--line);display:flex;align-items:center;
  justify-content:center;color:var(--ink-3);font-size:var(--fs-sm)}
.panel-koniec.nad{border-color:var(--accent);background:var(--accent-soft)}

/* Wiersz wykrycia, ktorym ktos sie juz zajal.
   Przygaszony, a nie ukryty: historia obslugi jest tu tak samo wazna
   jak sama lista - to po niej widac, ze ktos przy tej maszynie byl. */
/* wykrycie odhaczone */
tr.zrobione td{opacity:.62}
tr.zrobione:hover td{opacity:1}

/* Ślad po obsłudze wykrycia: kto, co napisał, czy poszło do konsoli.
   Jedna linia pod opisem - dzięki temu wiersze tabeli mają równą
   wysokość i kolumny stoją w linii także wtedy, gdy komentarz jest
   długi. Za długi tekst ucinamy wielokropkiem, całość jest w title. */
.wykrycie-slad{font-size:var(--fs-xs);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:52ch}
.wykrycie-slad .cytat{font-style:italic}

/* Oś czasu stanowiska: znak rodzaju, czas, treść - trzy stałe kolumny,
   żeby dziesięć wpisów czytało się jak jedna lista, a nie jak dziesięć
   akapitów. Kolumna czasu ma stałą szerokość i cyfry o równej szerokości
   (tabular-nums), więc daty kończą się w tym samym miejscu. */
.os-czasu{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:18px 128px minmax(0,1fr);gap:2px var(--s2);align-items:baseline}
.os-czasu li{display:contents}
.os-czasu li>*{padding:3px 0;border-bottom:1px solid var(--line-2,var(--line))}
.os-znak{text-align:center;color:var(--ink-3)}
.os-kiedy{font-size:var(--fs-xs);font-variant-numeric:tabular-nums;white-space:nowrap}
.os-tresc{min-width:0;overflow:hidden;text-overflow:ellipsis}
.os-czasu li.os-wykrycie .os-znak{color:var(--warn,var(--ink-2))}
.os-czasu li.os-zdalne .os-znak{color:var(--accent)}

/* „×47" przy nazwie wykrycia: ile razy ESET zapisał to samo zdarzenie.
   Mała, spokojna plakietka - to jest liczność, a nie alarm. */
.mnoznik{display:inline-block;margin-left:6px;padding:0 6px;border-radius:999px;
  background:var(--surface-2);border:1px solid var(--line);
  font-size:var(--fs-xs);font-variant-numeric:tabular-nums;color:var(--ink-2)}

/* Stawki w grupach po kilka pól, a nie dziewięć w jednym rzędzie.
   Na szerokim ekranie `auto-fill` upychał wszystko w jedną linię,
   a podpowiedzi o różnej długości robiły z tego drabinkę. Grupa ma
   własny nagłówek i własną, krótszą siatkę - i zawija się przewidywalnie. */
.grupa-stawek{margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line)}
.grupa-stawek:first-of-type{border-top:0;padding-top:0}
.grupa-stawek > .pola.ciasne{max-width:1080px;
  grid-template-columns:repeat(auto-fill,minmax(230px,1fr));align-items:start}

/* Rozbicie robocizny na rodzaje pracy: co, ile, po ile, razem.
   Wąska tabelka w ramce podpowiedzi - liczby wyrównane do prawej
   i o równej szerokości cyfr, żeby kolumna kwot czytała się pionowo. */
.robocizna-rozbicie{margin:6px 0;border-collapse:collapse;font-size:var(--fs-sm)}
.robocizna-rozbicie td{padding:2px 10px 2px 0;border:0}
.robocizna-rozbicie .num{text-align:right;font-variant-numeric:tabular-nums}

/* Odpowiedź modelu językowego. Wyróżniona ramką i podpisana, ZAWSZE:
   tekst z modelu ma wyglądać inaczej niż dane z programu, bo to jest
   podpowiedź, a nie fakt z bazy. Bez tej różnicy po tygodniu nikt już
   nie pamięta, które zdanie skąd pochodzi. */
.ai-wyjasnienie{margin-top:6px;padding:8px 10px;border-radius:var(--radius);
  border:1px dashed var(--line);background:var(--surface-2);
  font-size:var(--fs-sm);white-space:pre-wrap;max-width:70ch}
.ai-znak{font-size:var(--fs-xs);color:var(--ink-3);margin-bottom:4px;
  text-transform:uppercase;letter-spacing:.03em}

/* Wyjaśnienie z modelu stoi w OKIENKU, nie w wierszu listy: pięć
   akapitów wepchniętych w komórkę tabeli rozpycha całą tabelę.
   Okienko znika po kliknięciu gdziekolwiek - to rzecz do przeczytania
   raz, a nie panel do obsługi. */
.ai-okno{width:min(520px,94vw);border-top:3px solid var(--accent);cursor:default}
.ai-czesci{margin:0;display:flex;flex-direction:column;gap:2px}
.ai-czesci dt{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-3);margin-top:var(--s3)}
.ai-czesci dt:first-child{margin-top:0}
.ai-czesci dd{margin:0;font-size:var(--fs-base);line-height:1.5;color:var(--ink)}
.ai-okno .pasek-akcji{margin-top:var(--s4);align-items:center;gap:var(--s3)}

/* Podpowiedzi z cennika pod polem nazwy pozycji. Lista wisi NAD resztą
   formularza (position:absolute), żeby jej pojawienie się nie przesuwało
   pól pod spodem - przesuwający się formularz to kliknięcie w nie to,
   co się chciało. */
.podpowiedzi-pole{position:relative}
.podpowiedzi-lista{position:absolute;z-index:40;left:0;right:0;top:calc(100% + 2px);
  max-height:280px;overflow:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--cien-2,0 8px 24px rgba(0,0,0,.18))}
.podpowiedz-cennik{display:flex;flex-direction:column;gap:1px;width:100%;text-align:left;
  padding:7px 10px;border:0;background:none;cursor:pointer;color:inherit;font:inherit}
.podpowiedz-cennik:hover,.podpowiedz-cennik:focus-visible{background:var(--surface-2)}
.podpowiedz-cennik .glowny{font-weight:600}
.podpowiedz-cennik .muted{font-size:var(--fs-xs)}

/* =====================================================================
   MAGAZYN
   Rozbicie stanu na miejsca musi się mieścić w jednej komórce tabeli
   i nie może rozpychać wiersza - stąd zawijane pigułki zamiast listy.
   ===================================================================== */
.mag-gdzie{display:flex;flex-wrap:wrap;gap:4px}
.mag-miejsce{display:inline-block;padding:1px 7px;border-radius:var(--radius-pill);
  background:var(--surface-2);border:1px solid var(--line-soft);
  font-size:var(--fs-xs);color:var(--ink-2);white-space:nowrap}
.mag-miejsce.auto{background:var(--accent-soft);border-color:var(--accent-border);color:var(--accent)}
.mag-miejsce.klient{background:var(--warn-bg);border-color:var(--warn-border);color:var(--warn)}

.mag-karta-gora{display:flex;flex-wrap:wrap;gap:var(--s5);
  padding:var(--s3) 0 var(--s4);border-bottom:1px solid var(--line-soft);margin-bottom:var(--s4)}
.mag-karta-gora > div{display:flex;flex-direction:column;gap:2px}
.mag-karta-gora .muted{font-size:var(--fs-xs)}
.mag-karta-gora strong{font-size:var(--fs-md)}

.mag-ruchy{display:flex;flex-direction:column;gap:var(--s4)}
.mag-ruch h4{margin:0 0 var(--s2);font-size:var(--fs-sm);text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-3)}
.mag-ruch .formrow{flex-wrap:wrap;gap:var(--s2)}
.mag-dodaj{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  padding:var(--s3);background:var(--surface-2);border-radius:var(--radius);
  margin-bottom:var(--s4);position:relative}
.mag-dodaj .podpowiedzi{display:flex;flex-wrap:wrap;gap:4px}
.mag-dodaj .podpowiedz{padding:3px 9px;border:1px solid var(--line);border-radius:var(--radius-pill);
  background:var(--surface);font-size:var(--fs-sm);cursor:pointer}
.mag-dodaj .podpowiedz:hover{border-color:var(--accent);color:var(--accent)}

/* Ile tego mam PRZY SOBIE - najważniejsza informacja w podpowiedzi
   przy zleceniu, więc kolorem, a nie drobnym drukiem. */
.mag-stan{font-size:var(--fs-xs);padding:1px 6px;border-radius:var(--radius-pill);
  border:1px solid var(--line-soft);background:var(--surface-2);color:var(--ink-2);
  font-weight:400;white-space:nowrap}
.mag-stan.ma{background:var(--ok-bg);border-color:var(--ok-border);color:var(--ok)}
.mag-stan.gdzies{background:var(--warn-bg);border-color:var(--warn-border);color:var(--warn)}

td.plus{color:var(--ok);font-variant-numeric:tabular-nums}
td.minus{color:var(--ink-2);font-variant-numeric:tabular-nums}
.nowrap{white-space:nowrap}
tr.wybrany td{background:var(--accent-soft)}

/* Pola w ruchach magazynowych nie mogą się rozciągać na całą szerokość -
   "1" w polu szerokim na pół ekranu wygląda jak pomyłka układu. */
.mag-ruch .formrow{align-items:center}
.mag-ruch .input.w-ilosc{width:84px;flex:0 0 84px;text-align:right}
.mag-ruch select.input{flex:0 1 auto;width:auto;min-width:180px;max-width:280px}
.mag-ruch .input:not(.w-ilosc):not(select){flex:1 1 200px;min-width:160px}
.mag-dodaj .input.w-ilosc{width:84px;flex:0 0 84px;text-align:right}
/* Pasek nad tabelą magazynu: pole szukania stałe, licznik nie zawija. */
.card > .hd .rozpychacz{white-space:nowrap}

/* Jednozdaniowe streszczenie wykrycia w wierszu listy.
   Powstaje samo przy pobraniu; kliknięcie otwiera pełne wyjaśnienie.
   Musi się MIEŚCIĆ - jedna linia, wielokropek na końcu - bo inaczej
   rozpycha wiersz i wraca problem, dla którego to powstało. */
.ai-skrot{display:block;max-width:52ch;margin-top:2px;padding:0;border:0;background:none;
  text-align:left;font:inherit;font-size:var(--fs-sm);color:var(--ink-2);
  cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ai-skrot:hover{color:var(--accent);text-decoration:underline}
.ai-skrot:disabled{cursor:default;opacity:.6}
.ai-iskra{color:var(--accent);margin-right:5px;font-size:var(--fs-xs)}

/* =====================================================================
   ASYSTENT AI - ustawienia
   Łukasz, 04.09.2026: „panel ustawiania AI też wygląda jak gówno -
   weź popraw bo tam wszystko na siebie najeżdża". Trzy przyczyny:
   długi adres w <span class="mono"> nie zawijał się i rozpychał całą
   stronę w poziomie; pola formularza nie miały minimalnej szerokości,
   więc przy węższym oknie nachodziły na siebie; a cztery zastosowania
   bez ramek zlewały się w ścianę tekstu.
   ===================================================================== */
.ai-uwaga{overflow-wrap:anywhere}
.ai-uwaga .mono{white-space:nowrap;font-size:.94em}

/* Wiersz modelu to KARTA, a nie notatka na marginesie. Wcześniej stała
   tu klasa `.recznie` (mniejsze pismo, 75% krycia) — użyta nie tam,
   gdzie trzeba: cały blok ustawień modelu wyglądał przez nią na
   przygaszony i ciasny, choć jest głównym elementem tego ekranu. */
.ai-model{margin-bottom:var(--s3);padding:var(--s3) var(--s4);
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.ai-model > .formrow{gap:var(--s3);flex-wrap:wrap;align-items:center}
.ai-model .pola.ciasne{margin-top:var(--s3)}
.ai-model .ptaszek{white-space:nowrap}

.ai-nowy{margin-top:var(--s4);padding:var(--s4);border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface-2)}
.ai-nowy-tytul{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-3);margin-bottom:var(--s3)}
.ai-nowy .pasek-akcji{margin-top:var(--s3);align-items:center;gap:var(--s3);flex-wrap:wrap}
.ai-nowy .pasek-akcji .muted{font-size:var(--fs-sm)}

/* Pola nie mogą się ściskać poniżej czytelnej szerokości - poniżej
   tego progu zawijają się do kolejnego wiersza zamiast nachodzić. */
.pola.ciasne > *{min-width:190px}

.ai-uzycie{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--s3);
  padding:var(--s3) 0;border-top:1px solid var(--line-soft)}
.ai-uzycia > .ai-uzycie:first-child{border-top:0}
.ai-uzycie-opis{flex:1 1 300px;min-width:0}
.ai-uzycie-opis .muted{font-size:var(--fs-sm);margin-top:2px;max-width:62ch}
.ai-uzycie.nieczynne strong{color:var(--ink-2)}
.ai-uzycie-sterowanie{flex:0 0 auto;display:flex;align-items:center;gap:var(--s2);
  flex-wrap:wrap;margin-left:auto}
.ai-uzycie-sterowanie select{flex:0 0 210px;width:210px}

/* Lista w widgecie monitoringu. Bez punktorów i bez zawijania w drugi
   wiersz - widget ma się dać przeczytać jednym spojrzeniem, a nie
   rozrosnąć na pół panelu. */
.widget-lista{list-style:none;margin:0;padding:var(--s2) 0 0;
  display:flex;flex-direction:column;gap:6px}
.widget-lista li{display:flex;align-items:center;gap:6px;min-width:0;
  font-size:var(--fs-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.widget-lista li .clip{overflow:hidden;text-overflow:ellipsis;min-width:0}

.ptaszek.nieczynny{opacity:.55;cursor:default}

/* =====================================================================
   WIDGETY MONITORINGU
   Łukasz, 04.09.2026: „bym zrobił widget na główny ekran w jakimś
   fajnym stylu graficznym". Zasada: kolor i długość słupka mają nieść
   informację, której nie da się przeczytać szybciej niż zobaczyć -
   a nie być ozdobą. Stąd tylko dwa progi (75% i 90%) i tylko jedna
   pozycja na maszynę.
   ===================================================================== */
.widget-pusto{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s4) var(--pad-card);
  color:var(--ink-3);font-size:var(--fs-sm)}
.widget-pusto .ikona{display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;border-radius:50%;background:var(--ok-bg);color:var(--ok);
  font-size:var(--fs-sm);flex:0 0 auto}

/* ---------------------------------------------------------------------
   WSPÓLNY SZKIELET WIERSZA W TRZECH WIDGETACH MONITORINGU

   Łukasz, 05.09.2026: „te kafle dyski ile zostało czasu, najmocniej
   obciążone, monitoring — hosty z problemami zdecydowanie wizualnie
   odbiegają od reszty (...) są rozciągnięte na całe kafle na szerokość,
   a nie tak jak reszta ładnie mają marginesy".

   Ma rację i był to mój błąd: te listy dostały `padding: … 0`, więc
   słupki i nazwy dotykały krawędzi kafla, podczas gdy każda inna lista
   na panelu (.lista-widget) trzyma się `var(--pad-card)` — tego samego
   marginesu, co tytuł widgetu nad nią. Wiersz, którego tekst nie stoi
   w jednej linii pionowej z tytułem, czyta się jak wklejony z innego
   programu.

   Trzy zasady, te same dla wszystkich trzech list:
   1. wiersz sięga od krawędzi do krawędzi (żeby podświetlenie i pasek
      wagi obejmowały CAŁY wiersz), ale jego TREŚĆ ma margines
      `var(--pad-card)` — dokładnie pod tytułem widgetu;
   2. wiersze rozdziela linia, a nie odstęp — tak jak w .lista-widget;
   3. kolorowy pasek wagi po lewej stoi PRZY krawędzi, bo tam jest
      widoczny kątem oka, a nie w środku tekstu.
   --------------------------------------------------------------------- */
.hosty-problemy,.obciazenie,.dyski{
  list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column}

.host-wiersz,.obc-wiersz,.dysk-wiersz{
  position:relative;min-width:0;
  padding:10px var(--pad-card) 11px;
  border-bottom:1px solid var(--line-soft);
  border-left:3px solid transparent;
  /* Margines treści jest po prawej stronie paska wagi, więc pasek nie
     zabiera tekstowi miejsca i wszystkie wiersze - z paskiem i bez -
     zaczynają się w tym samym pionie. */
  padding-left:calc(var(--pad-card) - 3px)}
.host-wiersz:last-child,.obc-wiersz:last-child,.dysk-wiersz:last-child{
  border-bottom:0}
.host-wiersz:hover,.obc-wiersz:hover,.dysk-wiersz:hover{
  background:var(--surface-2)}

/* Ton wiersza = pasek po lewej. Jeden zestaw klas dla trzech list. */
.w-disaster,.w-high,.ton-zle{border-left-color:var(--bad)}
.w-average,.w-warning,.ton-uwaga{border-left-color:var(--warn)}
.ton-ok{border-left-color:var(--ok)}
.w-information,.w-not_classified{border-left-color:var(--line)}

/* --- hosty z problemami --- */
.host-wiersz{display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:2px var(--s3);align-items:center}
.host-nazwa{grid-column:1;font-size:var(--fs-sm);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.host-co{grid-column:1;grid-row:2;font-size:var(--fs-xs);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.host-liczby{grid-column:2;grid-row:1 / span 2;display:flex;align-items:center;
  gap:var(--s2);font-size:var(--fs-xs);white-space:nowrap}
.host-ile{display:inline-flex;align-items:center;justify-content:center;
  min-width:22px;height:20px;padding:0 6px;border-radius:var(--radius-pill);
  font-weight:600;font-size:var(--fs-xs);
  background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line-soft)}
.host-ile.disaster,.host-ile.high{background:var(--bad-bg);color:var(--bad);
  border-color:var(--bad-border)}
.host-ile.average,.host-ile.warning{background:var(--warn-bg);color:var(--warn);
  border-color:var(--warn-border)}

/* --- najmocniej obciążone i dyski: ta sama budowa wiersza --- */
.obc-wiersz,.dysk-wiersz{display:flex;flex-direction:column;gap:5px}
.obc-gora{display:flex;align-items:center;gap:var(--s2);min-width:0;
  font-size:var(--fs-sm)}
.obc-gora .mono,.obc-gora .jak-link{overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;min-width:0;font-weight:600}
/* Znacznik zasobu (CPU / RAM / DYSK E:) jest ETYKIETĄ, nie tekstem -
   dlatego wersaliki, mniejszy stopień i własne tło. Bez tła zlewał się
   z nazwą maszyny i trzeba było czytać, żeby je rozdzielić. */
.obc-znak{font-size:var(--fs-xs);letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink-3);background:var(--surface-2);
  border:1px solid var(--line-soft);border-radius:var(--radius-sm);
  padding:1px 6px;white-space:nowrap;flex:0 0 auto;line-height:1.4}
.obc-procent{margin-left:auto;font-weight:700;font-variant-numeric:tabular-nums;
  flex:0 0 auto;font-size:var(--fs-base)}
.obc-procent.zle{color:var(--bad)}
.obc-procent.uwaga{color:var(--warn)}
.obc-procent.ok{color:var(--ink-2)}

/* Słupek: wyższy niż był (7 px ginęło przy nazwie w tym samym wierszu)
   i bez własnej ramki - ramka wokół 7-pikselowego paska to same krawędzie
   i żadnego wypełnienia. Tor jest po prostu ciemniejszym tłem. */
.obc-pasek{height:9px;border-radius:var(--radius-pill);
  background:var(--line-soft);overflow:hidden}
.obc-pasek .wypelnienie{display:block;height:100%;border-radius:var(--radius-pill);
  transition:width .3s ease;min-width:3px}
.obc-pasek .wypelnienie.zle{background:var(--bad)}
.obc-pasek .wypelnienie.uwaga{background:var(--warn)}
.obc-pasek .wypelnienie.ok{background:var(--ok)}

/* Podpis pod słupkiem: firma przy obciążeniu, termin przy dyskach. */
.obc-firma{font-size:var(--fs-xs);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

@media (prefers-reduced-motion:reduce){
  .obc-pasek .wypelnienie{transition:none}
}

/* Dyski: TERMIN jest tu najważniejszy - Łukasz, 04.09.2026: „dysk
   zapełni się za 6 dni jest warte więcej niż zajęte w 91%". Dlatego
   termin dostaje własną plakietkę w kolorze pilności, a nie jest
   kolejnym zdaniem drobnym drukiem pod słupkiem. */
.dysk-termin{display:flex;align-items:center;gap:var(--s2);
  font-size:var(--fs-xs);min-width:0}
.dysk-termin .termin{display:inline-flex;align-items:center;flex:0 0 auto;
  padding:1px 8px;border-radius:var(--radius-pill);font-weight:700;
  border:1px solid var(--line-soft);background:var(--surface-2);color:var(--ink-2)}
.dysk-termin .termin.zle{background:var(--bad-bg);color:var(--bad);
  border-color:var(--bad-border)}
.dysk-termin .termin.uwaga{background:var(--warn-bg);color:var(--warn);
  border-color:var(--warn-border)}
.dysk-termin .reszta{min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.obc-znak.disk{font-family:var(--mono, ui-monospace, monospace);
  text-transform:none;letter-spacing:0}

/* =====================================================================
   TYTUŁY WIDGETÓW NA PANELU IT
   Łukasz, 04.09.2026: „te tytuły widgetów na panelu IT bym dał
   drukowanymi literami". Wersaliki robią z paska nagłówka etykietę
   panelu, a nie zdanie - i tego właśnie oczekuje się od centrum
   dowodzenia. Litery rozstrzelamy odrobinę, bo wersaliki bez odstępu
   czyta się gorzej niż tekst zwykły.
   ===================================================================== */
.widget > .hd h3{text-transform:uppercase;letter-spacing:.06em;
  font-size:var(--fs-sm);font-weight:700}
.widget > .hd .hd-podtytul{text-transform:uppercase;letter-spacing:.05em;
  font-size:var(--fs-xs);color:var(--ink-3)}

/* =====================================================================
   ZAKŁADKI PANELU IT
   Łukasz, 05.09.2026: „Panel IT ma tak jakby zakładki które są różnymi
   widokami - przełączamy się między tymi zakładkami na górze, jak
   w przeglądarkach internetowych".
   ===================================================================== */
.panel-zakladki{margin:0 0 var(--s4);flex-wrap:wrap;align-items:center}
.panel-zakladki .ikona{font-size:1.05em}
.panel-zakladki .dodaj{font-size:var(--fs-xs);text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-3);border-bottom-color:transparent}
.panel-zakladki .dodaj:hover{color:var(--accent)}
.panel-zakladki .dodaj.groznie:hover{color:var(--bad)}

/* =====================================================================
   EKRAN KOPII ZAPASOWYCH

   Łukasz, 05.09.2026: „chodzi o to, żeby z grubsza wizualnie widać
   było, czy wszystko jest OK".

   Cały układ jest podporządkowany jednej rzeczy: pierwsza linijka ma
   być widoczna z drugiego końca pokoju. Dlatego werdykt ma własne tło
   w kolorze stanu i znak po lewej — a nie jest kolejnym akapitem.

   Wszystkie kolory idą z tokenów (--ok / --warn / --bad wraz z ich
   tłami i obwódkami), więc ekran działa też w motywie ciemnym. Wpisany
   na sztywno zielony wygląda dobrze dokładnie do momentu, w którym ktoś
   przełączy motyw na wieczór.
   ===================================================================== */
.kopie-ekran{display:flex;flex-direction:column;gap:var(--s4)}

.kopie-werdykt{display:flex;align-items:center;gap:var(--s4);
  padding:var(--s4) var(--s5);border-radius:var(--radius-lg);
  background:var(--ok-bg);border:1px solid var(--ok-border)}
.kopie-werdykt .znak{flex:0 0 auto;width:34px;height:34px;border-radius:999px;
  display:grid;place-items:center;font-size:19px;font-weight:700;
  background:var(--ok-solid);color:var(--ok-solid-ink)}
.kopie-werdykt .tresc{flex:1 1 auto;min-width:0}
.kopie-werdykt .zdanie{font-size:var(--fs-lg);font-weight:650;line-height:1.3}
.kopie-werdykt .drobne{font-size:var(--fs-sm);margin-top:2px;
  overflow-wrap:anywhere}
.kopie-werdykt .zly{color:var(--bad)}
.kopie-werdykt.uwaga{background:var(--warn-bg);border-color:var(--warn-border)}
.kopie-werdykt.uwaga .znak{background:var(--warn);color:var(--surface)}
.kopie-werdykt.zle{background:var(--bad-bg);border-color:var(--bad-border)}
.kopie-werdykt.zle .znak{background:var(--bad-solid);color:var(--bad-solid-ink)}

/* Kafle liczb ZAWIJAJĄ SIĘ, a nie ściskają: przy wąskim oknie osiem
   pozycji ma wejść w dwa rzędy, a nie zrobić się nieczytelne. */
.kopie-liczby{display:grid;gap:var(--s3);
  /* Cztery kolumny, a nie „ile wejdzie": kafli jest osiem, więc przy
     czterech w rzędzie oba rzędy są PEŁNE. Przy „ile wejdzie" ostatni
     kafel zostawał sam i rozciągał się na całą szerokość — wyglądało
     to jak błąd, bo jest błędem. */
  grid-template-columns:repeat(4,minmax(0,1fr))}
.kopie-kafel{padding:var(--s3) var(--s4);
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.kopie-kafel .duza{font-size:var(--fs-xl);font-weight:680;line-height:1.15;
  font-variant-numeric:tabular-nums}
.kopie-kafel .opis{font-size:var(--fs-sm);color:var(--ink-3);margin-top:2px}
.kopie-kafel.uwaga{border-color:var(--warn-border);background:var(--warn-bg)}
.kopie-kafel.uwaga .duza{color:var(--warn)}
.kopie-kafel.zle{border-color:var(--bad-border);background:var(--bad-bg)}
.kopie-kafel.zle .duza{color:var(--bad)}

/* Maszyny: pasek stanu po lewej, żeby lista czytała się kolorem, zanim
   ktokolwiek przeczyta nazwę. */
.kopie-serwery{list-style:none;margin:0;padding:0}
.kopie-serwer{display:flex;align-items:center;gap:var(--s4);
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-soft);
  border-left:3px solid transparent}
.kopie-serwer:last-child{border-bottom:0}
.kopie-serwer.ton-dobrze{border-left-color:var(--ok)}
.kopie-serwer.ton-uwaga{border-left-color:var(--warn);background:var(--warn-bg)}
.kopie-serwer.ton-zle{border-left-color:var(--bad);background:var(--bad-bg)}
.kopie-serwer .kto{flex:1 1 auto;min-width:0}
.kopie-serwer .nazwa{font-weight:620}
.kopie-serwer .pod{font-size:var(--fs-sm);margin-top:1px}
.kopie-serwer .kiedy{flex:0 0 auto;text-align:right}
.kopie-serwer .kiedy .wiek{font-weight:600;font-variant-numeric:tabular-nums}
.kopie-serwer .kiedy .drobne{font-size:var(--fs-sm)}
.kopie-serwer .stan{flex:0 0 auto;display:flex;align-items:center;gap:var(--s2);
  min-width:130px;justify-content:flex-end}

.kopie-ciche{list-style:none;margin:0;padding:0}
.kopie-ciche li{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s4);padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-soft)}
.kopie-ciche li:last-child{border-bottom:0}
.kopie-ciche li.krytyczny{background:var(--bad-bg)}
.kopie-ciche .nazwa{font-weight:600}
.kopie-ciche .pill{margin-left:var(--s2)}

.kopie-ekran .card > .hd .rozpychacz{margin-left:auto}

.kopie-dziennik td .drobne{font-size:var(--fs-sm)}
.kopie-dziennik .kol-stan{white-space:nowrap;line-height:1.3}
.kopie-dziennik .kol-stan .drobne{margin-top:2px}
.kopie-dziennik .clip{max-width:340px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}

@media (max-width:1080px){ .kopie-liczby{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:760px){
  .kopie-serwer{flex-wrap:wrap}
  .kopie-serwer .kiedy{text-align:left}
  .kopie-serwer .stan{min-width:0;justify-content:flex-start}
}

/* =====================================================================
   KONDYCJA FIRMY — zakładka ze zbiorczymi liczbami

   Łukasz, 05.09.2026: „chcę móc wejść w konkretną firmę i tam wyświetlić
   ZBIORCZE INFORMACJE (...) i pokaże konkrety w liczbach".

   Układ jest jednoznaczny: karta = jedna dziedzina, w karcie jedna DUŻA
   liczba i pod nią rozbicie drobnym drukiem. Duża liczba jest po to,
   żeby dało się ją przeczytać, nie zatrzymując się przy karcie.

   Cztery tony (dobrze / uwaga / źle / nieznany) niosą pasek u góry karty.
   „Nieznany" jest szary i to jest decyzja: brak monitoringu ma wyglądać
   jak brak wiedzy, a nie jak awaria.
   ===================================================================== */
.kondycja{display:flex;flex-direction:column;gap:var(--s4);
  padding:var(--s4) var(--pad-card) var(--s5)}

.kond-grupy{display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.kond-rzedy{display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}

.kond-karta,.kond-blok{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);padding:var(--s4);
  border-top:3px solid var(--line);display:flex;flex-direction:column;gap:var(--s2)}
.kond-karta.ton-dobrze,.kond-blok.ton-dobrze{border-top-color:var(--ok)}
.kond-karta.ton-uwaga,.kond-blok.ton-uwaga{border-top-color:var(--warn)}
.kond-karta.ton-zle,.kond-blok.ton-zle{border-top-color:var(--bad)}
.kond-karta.ton-nieznany,.kond-blok.ton-nieznany{border-top-color:var(--line)}

.kond-karta > header,.kond-blok > header{display:flex;align-items:baseline;
  gap:var(--s2);flex-wrap:wrap}
.kond-karta h4,.kond-blok h4{margin:0;font-size:var(--fs-sm);font-weight:700;
  text-transform:uppercase;letter-spacing:.05em}
.kond-karta > header .muted,.kond-blok > header .muted{font-size:var(--fs-xs)}
.kond-blok > header .rozpychacz{margin-left:auto;font-size:var(--fs-sm)}

/* Duża liczba: cyfra i to, czego dotyczy, w jednej linii bazowej. */
.kond-liczba{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.kond-liczba strong{font-size:var(--fs-2xl);font-weight:700;line-height:1.05;
  font-variant-numeric:tabular-nums}
.kond-liczba .z{font-size:var(--fs-lg);color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.kond-liczba .podpis{font-size:var(--fs-sm);color:var(--ink-3);margin-left:2px}
.ton-zle .kond-liczba strong{color:var(--bad)}
.ton-uwaga .kond-liczba strong{color:var(--warn)}

.kond-typy,.kond-lista,.kond-terminy{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column}
.kond-typy li,.kond-lista li{display:flex;align-items:baseline;gap:var(--s2);
  padding:5px 0;border-top:1px solid var(--line-soft);font-size:var(--fs-sm);
  min-width:0}
.kond-typy li:first-child,.kond-lista li:first-child{border-top:0;padding-top:var(--s1)}
.kond-typy .nazwa,.kond-lista .nazwa{flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kond-typy .ile,.kond-lista .stan{flex:0 0 auto;white-space:nowrap;
  font-variant-numeric:tabular-nums}
/* Trzy kolumny w wierszu typu: nazwa (kurczy się), ile sztuk, ile
   odpowiada. Kolumny liczbowe mają stałą szerokość i wyrównanie do
   prawej, żeby cyfry stały w pionie między wierszami - inaczej „11"
   i „4 z 6" zaczynają się w innym miejscu i lista wygląda na krzywą. */
.kond-typy .szt{flex:0 0 auto;min-width:52px;text-align:right;
  font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.kond-typy .ile{min-width:56px;text-align:right}
.kond-doliczenia{font-size:var(--fs-xs);margin-top:-2px}

/* Wiersz problemu z monitoringu: maszyna i waga w pierwszej linii,
   opis w drugiej. W jednej linii opis dostawał resztkę miejsca. */
.kond-lista li.dwuwiersz{flex-direction:column;align-items:stretch;gap:2px}
.kond-lista li.dwuwiersz .gora{display:flex;align-items:center;gap:var(--s2);
  min-width:0}
.kond-lista li.dwuwiersz .gora .mono,
.kond-lista li.dwuwiersz .gora .jak-link{flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}
.kond-lista li.dwuwiersz .gora .stan{display:flex;align-items:center;gap:6px}
.kond-lista li.dwuwiersz .dol{font-size:var(--fs-xs);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kond-typy .ile.zle,.kond-lista .stan.zle{color:var(--bad);font-weight:600}
.kond-lista.drobne li{font-size:var(--fs-sm)}
.kond-lista .pill{flex:0 0 auto}
.kond-blok .pusto{margin:0;font-size:var(--fs-sm)}

.kond-terminy li{display:flex;align-items:baseline;gap:var(--s2);
  padding:5px 0;border-top:1px solid var(--line-soft);font-size:var(--fs-sm)}
.kond-terminy li:first-child{border-top:0}
.kond-terminy .nazwa{font-weight:600}
.kond-terminy .kiedy{margin-left:auto;white-space:nowrap;color:var(--ink-3)}
.kond-terminy li.pilne .kiedy{color:var(--bad);font-weight:700}

/* ---------------------------------------------------------------------
   MASZYNY Z DUPLISTATUSA JAKO KAFLE

   Łukasz, 05.09.2026: „ta lista w dół ciągnąca się stanowisk — bardzo
   niewygodna. Nie możemy tego zrobić w formie kafli? Lepiej będzie
   wyglądać 20 kafelków koło siebie niż ta lista ciągnąca się w dół".

   To nie jest tylko kwestia gustu. Pytanie brzmi „czy któraś maszyna
   milczy" i odpowiada się na nie JEDNYM SPOJRZENIEM po siatce kolorów.
   Lista dziewiętnastu wierszy zajmuje dwa ekrany i zmusza do przewijania
   — czyli do zapamiętywania tego, co się już przewinęło.

   Kafel jest w całości klikalny, kiedy prowadzi do stanowiska; kiedy nie
   prowadzi, mówi o tym wprost („wskaż stanowisko") zamiast nie robić nic.
   --------------------------------------------------------------------- */
.kopie-kafle{display:grid;gap:var(--s3);padding:var(--s4) var(--pad-card);
  grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
.kopie-maszyna{border:1px solid var(--line);border-radius:var(--radius);
  border-left:3px solid var(--line);background:var(--surface);
  padding:var(--s3) var(--s4);display:flex;flex-direction:column;gap:3px;
  min-width:0}
.kopie-maszyna.ton-dobrze{border-left-color:var(--ok)}
.kopie-maszyna.ton-uwaga{border-left-color:var(--warn);background:var(--warn-bg)}
.kopie-maszyna.ton-zle{border-left-color:var(--bad);background:var(--bad-bg)}
.kopie-maszyna.klik{cursor:pointer}
.kopie-maszyna.klik:hover{border-color:var(--accent-border);
  box-shadow:var(--shadow-1)}
.kopie-maszyna.klik:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.kopie-maszyna .gora{display:flex;align-items:center;gap:var(--s2);min-width:0}
.kopie-maszyna .nazwa{flex:1 1 auto;min-width:0;font-weight:650;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kopie-maszyna .gora .pill{flex:0 0 auto}
.kopie-maszyna .wiek{font-size:var(--fs-sm);font-weight:600;
  font-variant-numeric:tabular-nums}
.kopie-maszyna .pod,.kopie-maszyna .stopka{font-size:var(--fs-xs);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Stopka odsuwa się od reszty, żeby kafle o różnej treści miały
   tę samą wysokość i siatka nie wyglądała na poszarpaną. */
.kopie-maszyna .stopka{margin-top:auto;padding-top:4px}

/* Wybór stanowiska dla maszyny bez dopasowania. */
.wybor-stanowiska{display:flex;flex-direction:column;margin-top:var(--s3);
  max-height:46vh;overflow-y:auto;border:1px solid var(--line-soft);
  border-radius:var(--radius)}
.wybor-stanowiska .pozycja{display:flex;align-items:baseline;gap:var(--s3);
  padding:9px var(--s3);border:0;border-bottom:1px solid var(--line-soft);
  background:none;text-align:left;font:inherit;cursor:pointer;color:inherit}
.wybor-stanowiska .pozycja:last-child{border-bottom:0}
.wybor-stanowiska .pozycja:hover{background:var(--surface-2)}
.wybor-stanowiska .pozycja .mono{flex:0 0 auto;font-weight:600}
.wybor-stanowiska .pozycja .muted{min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.wybor-stanowiska .pozycja .drobne{margin-left:auto;font-size:var(--fs-xs)}
.wybor-stanowiska .pusty-wybor{padding:var(--s4);font-size:var(--fs-sm);line-height:1.5}

/* ---------------------------------------------------------------------
   WYBÓR WIDGETU DO DOŁOŻENIA NA ZAKŁADKĘ

   Łukasz, 05.09.2026: „robię nowy widok, jest pusty i jak dodać tam
   widget? (...) przydałoby się móc kliknąć dodaj widget i wybrać z listy
   szablonów dostępnych".

   Kafel, a nie wiersz listy: wybiera się TREŚĆ, a treść ma tu opis
   w dwóch linijkach. W wierszu opis musiałby się zmieścić obok nazwy
   albo zniknąć - a bez niego „Gdzie się dzieje" nie mówi nic.
   --------------------------------------------------------------------- */
.wybor-widgetow{display:grid;gap:var(--s3);margin-top:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
  max-height:56vh;overflow-y:auto;padding-right:2px}
.kafel-widgetu{display:flex;flex-direction:column;gap:3px;text-align:left;
  padding:var(--s3) var(--s4);border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface);font:inherit;
  color:inherit;cursor:pointer;min-width:0}
.kafel-widgetu:hover:not(:disabled){border-color:var(--accent-border);
  background:var(--accent-soft)}
.kafel-widgetu:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.kafel-widgetu .tytul{font-weight:650}
.kafel-widgetu .opis{font-size:var(--fs-sm);line-height:1.35}
.kafel-widgetu .stopka{font-size:var(--fs-xs);margin-top:auto;padding-top:6px}
.kafel-widgetu.juz{opacity:.55;cursor:default}

/* Kafel „Dodaj widget" stoi W SIATCE, na miejscu następnego panelu -
   tam, gdzie ten panel się pojawi. Przycisk schowany w nagłówku kazałby
   go szukać, a pusta zakładka nie ma czego pokazać poza nim. */
.panel-dodaj{grid-column:span 1;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:6px;min-height:140px;
  border:2px dashed var(--line);border-radius:var(--radius);
  background:none;color:var(--ink-3);font:inherit;font-weight:600;
  cursor:pointer}
.panel-dodaj:hover{border-color:var(--accent);color:var(--accent);
  background:var(--accent-soft)}
.panel-dodaj:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.panel-dodaj .plus{font-size:26px;line-height:1}

/* Sekcja ustawień dla mniejszości przypadków: tytuł i opis widoczne
   zawsze, pola po kliknięciu. Ukrycie całości kazałoby się zastanawiać,
   czy funkcja w ogóle istnieje. */
.sekcja.skladana > h3{display:flex;align-items:baseline;gap:var(--s3);
  flex-wrap:wrap}
.sekcja.skladana > h3 .rozwin{font-size:var(--fs-sm);font-weight:500}

/* „Wróciło" — wykrycie ESET-a, które było już zamknięte i zgłosiło się
   znowu. Bez tego znacznika lista wygląda tak, jakby oznaczenie się nie
   zapisało; z nim mówi, że problem nawraca. Kolor ostrzeżenia, nie
   błędu: to nie jest awaria programu. */
.wrocilo{display:inline-flex;align-items:center;margin-left:6px;
  padding:0 6px;border-radius:var(--radius-pill);font-size:var(--fs-xs);
  font-weight:700;text-transform:lowercase;letter-spacing:.02em;
  background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn-border);
  cursor:help}

/* Pusty widok panelu: komunikat i JEDEN przycisk, który z niego
   wyprowadza. Ekran bez wyjścia jest gorszy niż brak ekranu. */
.panel-pusty{display:flex;flex-direction:column;align-items:center;
  gap:var(--s3);padding:var(--s6) var(--pad-card);
  border:2px dashed var(--line);border-radius:var(--radius-lg)}
.panel-pusty .srodek{display:flex;justify-content:center}

/* ---------------------------------------------------------------------
   PODPISY PRZY WYCINKACH PIERŚCIENIA

   Łukasz, 05.09.2026: „nie uważasz, że te podpisy pod spodem są słabe?
   Może dajmy te opisy/liczby przy tym kółku, przy odpowiednich polach?".

   Legenda pod wykresem każe czytać w trzech ruchach: kolor przy słowie
   → z powrotem do koła → szukanie tego koloru → z powrotem po liczbę.
   Podpis stojący przy swoim wycinku znosi całe to tam i z powrotem.

   Rozmiary są w jednostkach viewBoxa (kadr 250×176), więc skalują się
   razem z kołem - na wąskim widgecie napis nie zostaje wielki przy
   małym pierścieniu ani odwrotnie.
   --------------------------------------------------------------------- */
.kolo-kreska{fill:none;stroke:var(--line);stroke-width:1.2}
.kolo-ile{font-size:13px;font-weight:700;fill:var(--ink);
  font-variant-numeric:tabular-nums}
.kolo-slowo{font-size:9.5px;fill:var(--ink-3)}
.kolo-podpis-grupa.klik{cursor:pointer}
.kolo-podpis-grupa.klik:hover .kolo-ile,
.kolo-podpis-grupa.klik:hover .kolo-slowo{fill:var(--accent)}
.kolo-podpis-grupa.klik:hover .kolo-kreska{stroke:var(--accent)}

/* ---------------------------------------------------------------------
   ALARMY I PROGI

   Łukasz, 05.09.2026: „w ustawieniach sobie ustalimy jakieś ustawienia
   alarmów (...) reguły które będą określały jak panel nas informuje".

   Reguła jest KARTKĄ, nie wierszem tabeli: ma nazwę, zdanie wyjaśniające,
   trzy pola i przełącznik. W tabeli to zdanie nie miałoby gdzie stanąć,
   a bez niego „dysk_termin 7" nie znaczy nic.
   --------------------------------------------------------------------- */
.alarm-grupa{margin-top:var(--s4)}
.alarm-grupa > h4{margin:0 0 var(--s2);font-size:var(--fs-sm);font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}
.alarm-regula{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);padding:var(--s3) var(--s4);margin-bottom:var(--s2)}
.alarm-regula.wylaczona{opacity:.62;background:var(--surface-2)}
.alarm-regula .glowa{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.alarm-regula .alarm-licznik{margin-left:auto;display:flex;align-items:center;
  gap:6px;font-size:var(--fs-sm);white-space:nowrap}
.alarm-regula .alarm-licznik .cicho{color:var(--ink-3)}
.alarm-regula .opis{font-size:var(--fs-sm);margin:2px 0 var(--s2);line-height:1.4}
/* Pola zawijają się i mają stałą minimalną szerokość - inaczej przy
   wąskim oknie „przypominaj co" ścisnęłoby się do trzech znaków. */
.pola-alarmu{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s4);align-items:flex-end}
.pola-alarmu > label{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm)}
.pola-alarmu input.input{width:86px;text-align:right;
  font-variant-numeric:tabular-nums}
.pola-alarmu select.input{min-width:130px}
.pola-alarmu .jednostka{font-size:var(--fs-xs)}
.pola-alarmu .ptaszek{margin-left:auto}

/* Przykładowa treść webhooka - do przeczytania i skopiowania, nie do
   edycji. Przewija się w poziomie zamiast rozpychać ekran. */
.kod-blok{margin:var(--s3) 0 0;padding:var(--s3) var(--s4);border-radius:var(--radius);
  background:var(--surface-2);border:1px solid var(--line-soft);
  font-family:var(--mono);font-size:var(--fs-sm);line-height:1.5;
  overflow-x:auto;white-space:pre;max-height:340px;overflow-y:auto}

/* Obciążenie na karcie stanowiska: te same paski co na panelu, ale bez
   marginesu listy widgetu - tu siedzą wewnątrz karty, która ma już swój. */
.obciazenie.stanowisko{gap:var(--s3);margin-bottom:var(--s4)}
.obciazenie.stanowisko .obc-wiersz{padding:8px 0 9px;border-left:0;
  border-bottom:1px solid var(--line-soft)}
.obciazenie.stanowisko .obc-wiersz:last-child{border-bottom:0}
.obciazenie.stanowisko .obc-firma{font-size:var(--fs-sm)}
.obciazenie.stanowisko .obc-firma .zly{color:var(--bad)}

/* --- Drobiazgi w ustawieniach ekranu na telewizor --------------------- */
/* Wiersz wylaczony: widoczny, ale przygaszony. Ukrywanie go byloby
   gorsze - ktos szukalby ekranu, ktory sam wczoraj wylaczyl. */
tr.przygaszone > td{opacity:.55}
.mini{font-size:var(--fs-xs);line-height:1.3}
.lista-krokow{margin:0 0 var(--s3);padding-left:22px;color:var(--ink-2)}
.lista-krokow li{margin-bottom:var(--s2)}

/* --- KOLO W WYSOKIM KAFLU --------------------------------------------
   Kadr z podpisami po bokach jest szerszy niz wyzszy, wiec w kaflu
   1x3 zostawialby pod spodem pustke. Tu kolo bierze gore kafla,
   a podpisy stoja pod nim jako lista - i jedno, i drugie klika sie
   tak samo jak wycinek. */
.wykres-kolo.pionowo{flex-direction:column;flex-wrap:nowrap;gap:var(--s2);
  align-items:stretch;justify-content:flex-start}
/* KOŁO MA MIEĆ MINIMALNY ROZMIAR.
   06.09.2026: po dodaniu do legendy drugiego wiersza przy każdej pozycji
   („3 po terminie") legenda urosła dwukrotnie, a `flex:1 1 auto` oddał
   jej całą wysokość — pierścień skurczył się do znaczka wielkości
   ikony i przestał cokolwiek pokazywać.
   `min-height` znaczy: legenda może rosnąć, ale nie kosztem wykresu.
   Gdy zabraknie miejsca, kafel się przewinie — a to jest lepsze niż
   wykres, którego nie da się odczytać. */
/* 06.09.2026, drugie podejscie. Lukasz: „te pozostale dwa widgety,
   wydaje mi sie, ze damy rade je powiekszyc". Zmierzone w kaflu 315x360:
   kolo dostawalo 132 px (czyli dokladnie swoje minimum), a legenda 149 -
   bo kazda pozycja miala DWA wiersze („CARFREE" + „3 po terminie").
   Dopisek stoi teraz obok nazwy, legenda zeszla do polowy wysokosci,
   a roznica poszla na wykres. `min-height` rosnie razem z tym: kolo ma
   miec pierwszenstwo do wolnego miejsca, nie legenda. */
.wykres-kolo.pionowo .kolo-svg{flex:1 1 auto;min-height:150px;width:100%;height:100%}
/* Legenda przewija się we własnym pudełku, zamiast wypychać koło poza
   kafel. `flex:0 0 auto` (a nie `0 1 auto`) jest tu istotne: przy
   `shrink:1` koło zabierało cały wolny zapas i rosło do 173 px, podczas
   gdy legenda ściskała się do czterech widocznych wierszy z sześciu.
   Teraz legenda bierze najpierw tyle, ile naprawdę potrzebuje — nie
   więcej niż 46% wysokości kafla — a koło dostaje resztę i i tak wychodzi
   większe niż było, bo pozycje są jednowierszowe. */
.wykres-kolo.pionowo .kolo-legenda{max-height:46%;overflow-y:auto;flex:0 0 auto}
.kolo-legenda{flex:0 0 auto;display:flex;flex-direction:column;gap:2px;
  list-style:none;margin:0;padding:0}
.kolo-legenda li{display:flex;align-items:baseline;gap:8px;padding:3px 2px;
  border-radius:var(--radius-sm);font-size:var(--fs-sm);color:var(--ink-2)}
.kolo-legenda li.klik{cursor:pointer}
.kolo-legenda li.klik:hover{background:var(--surface-2);color:var(--ink)}
.kolo-legenda .kropka{width:10px;height:10px;border-radius:3px;flex:0 0 auto;
  align-self:center}
.kolo-legenda strong{font-variant-numeric:tabular-nums;min-width:2.2em;text-align:right}
.kolo-legenda .slowo{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Kropka legendy przy „zle" powtarza kreskowanie z wycinka - inaczej
   dwa rozne wycinki maja w legendzie identyczna kropke. */
.kolo-legenda li .kropka.zle{background-image:repeating-linear-gradient(45deg,
  transparent 0 2px, var(--surface) 2px 3.4px)}

/* Pasek nad kaflami z liczbami - widoczny TYLKO w trybie układania.
   Stoi przy kaflach, a nie w ustawieniach, bo to ustawienie zakładki,
   a zakładkę widać wyłącznie stąd. */
.kafle-pasek{display:flex;align-items:center;gap:var(--s3);
  margin:0 0 var(--s2);font-size:var(--fs-sm)}

/* Kolumna „w górę / w dół / zdejmij". Jeden rząd i bez zawijania —
   rozbita na dwie linie czyta się jak ozdoba przy krawędzi tabeli,
   a nie jak przyciski, którymi się przestawia kolejność. */
td.kolumna-kolejnosci{width:1%;white-space:nowrap;text-align:right}
td.kolumna-kolejnosci .strzalki{display:inline-flex;gap:2px;margin-right:var(--s3)}
td.kolumna-kolejnosci .strzalki .btn{border-radius:0}
td.kolumna-kolejnosci .strzalki .btn:first-child{
  border-radius:var(--radius-sm) 0 0 var(--radius-sm)}
td.kolumna-kolejnosci .strzalki .btn:last-child{
  border-radius:0 var(--radius-sm) var(--radius-sm) 0}

/* Przycisk „Centrum" w górnym pasku. Ikona zostaje zawsze, napis znika
   na wąskim ekranie — telewizor i tak wiesza się z komputera. */
.przycisk-centrum{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto}
@media (max-width:1100px){ .przycisk-centrum .etykieta{display:none} }

/* --- MENU Z PODMENU ---------------------------------------------------
   Łukasz, 05.09.2026: „wchodzac w nia to POD NIA bedzie sie rozwijac jej
   podmenu z funkcjami". Podmenu rozwija się po WEJŚCIU w pozycję, nie po
   najechaniu — menu, które podskakuje pod kursorem, trafia się w nie
   przypadkiem. Pionowa kreska po lewej mówi, że to nadal ta sama gałąź. */
.side button.nav.ma-podmenu .strzalka{margin-left:auto;color:var(--ink-3);
  transition:transform .14s;display:inline-block}
.side button.nav.ma-podmenu .strzalka.otwarta{transform:rotate(90deg)}
.side .podmenu{margin:2px 0 6px 0;padding-left:14px;
  border-left:2px solid var(--line-soft)}
.side button.nav.pod{padding:6px 10px 6px 12px;font-size:var(--fs-sm);
  color:var(--ink-2);border-left-color:transparent}
.side button.nav.pod.on{background:var(--accent-soft);color:var(--accent);font-weight:640}

/* LICZBA PRZY POZYCJI PODMENU.
   Łukasz, 07.09.2026: „daj liczbę jaśniejszą czcionką" — liczba ma
   dopowiadać, a nie konkurować z nazwą ekranu. Stąd lżejsza grubość,
   przygaszony kolor i cyfry o stałej szerokości: 5 i 11 mają wtedy ten
   sam odstęp od krawędzi i kolumna liczb stoi równo.
   `margin-left:auto` odsuwa je do prawej — pozycja jest flexem, tak
   samo jak strzałka przy pozycji nadrzędnej. */
.side button.nav.pod .nav-liczba{margin-left:auto;color:var(--ink-3);
  font-size:var(--fs-xs);font-weight:450;font-variant-numeric:tabular-nums;
  letter-spacing:.02em}
/* Na pozycji otwartej liczba idzie za kolorem napisu, ale zostaje
   lżejsza — inaczej wyglądałaby jak druga etykieta. */
.side button.nav.pod.on .nav-liczba{color:var(--accent);opacity:.7}

/* Wiersz, którego nikt jeszcze nie otworzył. Delikatnie — to nie alarm,
   tylko informacja, że lista rośnie, a nikt do niej nie zagląda. */
tr.nieprzeczytane > td:first-child{box-shadow:inset 3px 0 0 var(--accent)}
tr.nieprzeczytane strong{font-weight:750}

/* =====================================================================
   EKRAN ROUTERÓW (moduł operatora)
   =====================================================================
   Łukasz, 05.09.2026: „ściśnięte wszystko na sobie że hej jest".
   Miał rację: zakładki, kafelki producentów, wyszukiwarka, dwie ramki
   z tekstem i nagłówek tabeli szły jedno po drugim bez ani jednej
   przerwy — sześć pasm informacji sklejonych w jeden blok.

   Zamiast dokładać marginesy po kawałku: pasek narzędziowy zostaje
   ZŁOŻONY W JEDNO PUDEŁKO (bo to jedna rzecz — sterowanie listą),
   a wszystko na tym ekranie dostaje jeden rytm odstępu.
   ===================================================================== */
.ekran-routery > * + *{margin-top:var(--s5)}

.ekran-routery .narzedzia{display:flex;flex-direction:column;gap:var(--s3);
  padding:var(--s4);background:var(--g1);border:1px solid var(--line);
  border-radius:var(--radius)}

/* Producenci to filtr, a nie akcje — mają wyglądać jak znaczniki do
   klikania, nie jak rząd przycisków równorzędnych z „Szukaj". */
.ekran-routery .producenci{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.ekran-routery .producenci .etykieta{color:var(--ink-3);font-size:var(--fs-sm);
  margin-right:var(--s1)}
.ekran-routery .producenci button{padding:3px 10px;border:1px solid var(--line);
  background:transparent;color:var(--ink-2);border-radius:999px;
  font:inherit;font-size:var(--fs-sm);cursor:pointer;white-space:nowrap}
.ekran-routery .producenci button:hover{border-color:var(--accent);color:var(--ink)}
.ekran-routery .producenci button.on{background:var(--accent);border-color:var(--accent);
  color:#fff}

/* Wiersz tabeli niesie tu trzy–cztery linijki (wartość, wiek odczytu,
   szczegół), więc domyślna wysokość wiersza sklejała je z sąsiadami. */
.ekran-routery table td{padding-top:10px;padding-bottom:10px;vertical-align:top}
.ekran-routery table td > * + *{margin-top:3px}

/* =====================================================================
   POWIADOMIENIA W DZWONKU — WIĘCEJ TREŚCI, MNIEJ MIEJSCA
   =====================================================================
   Łukasz, 06.09.2026: „widac, ale nie do konca (...) moze po prostu
   zmniejszyc ciut czcionke? Lub po najechaniu zeby pokazal sie dymek".
   Robimy jedno i drugie: tytuł łamie się na DWA wiersze mniejszą
   czcionką, a pełna treść siedzi w dymku pod kursorem.

   Dwa wiersze, a nie dowolna liczba: lista ma dalej dawać się przelecieć
   wzrokiem. Powiadomienie, które rozlewa się na sześć linijek, przestaje
   być listą, a staje się tekstem do czytania.
   ===================================================================== */
.powiadomienie .powiad-glowa strong.powiad-tytul{
  /* Przebijamy regułę `.powiad-glowa strong` wyżej, która wymusza
     jedną linijkę z wielokropkiem — właśnie ona ucinała tytuł
     w połowie słowa. */
  white-space:normal;text-overflow:clip;
  font-size:var(--fs-sm);line-height:1.3;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;min-width:0;flex:1 1 auto;
  /* Łamanie w środku długich identyfikatorów typu SERWER-WAPRO —
     bez tego przeglądarka woli zostawić pustą linijkę niż przeciąć. */
  overflow-wrap:anywhere}
.powiadomienie .powiad-glowa{align-items:flex-start}
/* Nazwa firmy pod spodem schodzi do jednej linijki i mniejszego stopnia —
   jest kontekstem, a nie treścią zdarzenia. */
.powiadomienie .mini{line-height:1.25}

/* =====================================================================
   OBCIĄŻENIE STANOWISKA — KOŁA OBOK SIEBIE
   ===================================================================== */
.obc-kola{display:flex;flex-wrap:wrap;gap:var(--s4);align-items:flex-start}
.obc-kolo{width:112px;text-align:center}
.obc-kolo .kolko{width:72px;height:72px;display:block;margin:0 auto}
.obc-kolo .kolko .tlo{fill:none;stroke:var(--g3);stroke-width:7}
.obc-kolo .kolko .luk{fill:none;stroke-width:7;stroke-linecap:round}
.obc-kolo .kolko .luk.ok{stroke:var(--ok)}
.obc-kolo .kolko .luk.uwaga{stroke:var(--warn)}
.obc-kolo .kolko .luk.zle{stroke:var(--bad)}
.obc-kolo .kolko .srodek{fill:var(--ink);font-size:15px;font-weight:700;
  text-anchor:middle;dominant-baseline:central}
.obc-kolo .obc-nazwa{margin-top:4px;font-size:var(--fs-sm);font-weight:600;
  overflow-wrap:anywhere}
.obc-kolo .obc-pod{font-size:var(--fs-sm);line-height:1.35}
.obc-kolo .obc-pod .zly{color:var(--bad)}

/* Zdarzenia z monitoringu na karcie maszyny. */
.zdarzenia-hosta td{padding:6px 10px 6px 0;vertical-align:top}
.zdarzenia-hosta tr.zamkniete{opacity:.6}

/* Trzy adresy DNS jeden pod drugim, ciasno — to jest dopisek do werdyktu,
   a nie osobna kolumna. Adres spoza listy na czerwono, żeby przy trzech
   pozycjach nie trzeba było ich porównywać wzrokiem z ustawieniami. */
.ekran-routery .dns-lista{line-height:1.3;margin-top:2px}
.ekran-routery .dns-lista .zly{color:var(--bad);font-weight:600}

/* „Pobieram dane…" — trzy kropki, które faktycznie się ruszają.
   Statyczny napis przy pustym ekranie i tak wygląda na zawieszony. */
.wczytywanie .kropki{display:inline-flex;gap:4px;margin-left:8px;vertical-align:middle}
.wczytywanie .kropki i{width:6px;height:6px;border-radius:50%;background:var(--accent);
  animation:kropka 1s ease-in-out infinite}
.wczytywanie .kropki i:nth-child(2){animation-delay:.15s}
.wczytywanie .kropki i:nth-child(3){animation-delay:.3s}
@keyframes kropka{0%,80%,100%{opacity:.25;transform:translateY(0)}
                  40%{opacity:1;transform:translateY(-3px)}}
@media (prefers-reduced-motion:reduce){.wczytywanie .kropki i{animation:none;opacity:.6}}

/* Odnośnik stylowany na przycisk łamał się na dwie linijki i rozpadał na
   dwa prostokąty — `.btn` zakłada element blokowy, a `<a>` nim nie jest. */
.ekran-routery a.btn{display:inline-flex;align-items:center;white-space:nowrap;
  text-decoration:none}
/* „D-LINK DIR-878" łamane po myślniku wyglądało na dwa różne modele. */
.ekran-routery td.kol-router{white-space:nowrap}
.ekran-routery td.kol-router .mini{white-space:normal}

/* =====================================================================
   WYRÓWNANIE KOLUMN NA LIŚCIE ROUTERÓW
   =====================================================================
   Łukasz, 06.09.2026: „może wycentrujemy informacje pod opisami kolumn?".
   Problem był realny: pod nagłówkiem „URZĄDZENIA ZA ROUTEREM" stała
   samotna „4" dosunięta do lewej krawędzi szerokiej kolumny — czyli
   kilkanaście pikseli od słowa, którego dotyczy.

   Ale NIE centrujemy wszystkiego. Wyśrodkowany akapit czyta się gorzej
   niż wyrównany do lewej, a w kolumnach DNS, WAN czy SSID stoi po kilka
   linii tekstu. Środek dostają tylko te kolumny, w których treścią jest
   POJEDYNCZY ZNACZNIK: plakietka stanu, liczba, przycisk. Tam nie ma
   czego czytać linia po linii, a jest co zgrać z nagłówkiem.
   ===================================================================== */
.ekran-routery th.srodek,
.ekran-routery td.srodek{text-align:center}
.ekran-routery td.srodek > *{margin-left:auto;margin-right:auto}

/* Wybór treści tablicy — ptaszki pod wierszem ekranu, w jednym rzędzie
   z zawijaniem. Osobna tabela byłaby drugą listą tego samego. */
.bloki-tablicy{padding-top:0;padding-bottom:var(--s3)}
.lista-blokow{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);margin-top:6px}
.lista-blokow > *{flex:0 1 260px}

/* =====================================================================
   SESJE I LIMIT — DWA PIERŚCIENIE
   Lukasz, 06.09.2026: „czy informacje o sesjach i limitach mozemy zrobic
   w formie dwoch malych wykresikow kolowych obok siebie z widoczna
   informacja kolorystyczna i liczbowa?"

   Dwa, bo to sa dwa rozne pytania: ILE MIEJSC zajmuje (decyduje, czy sie
   zaloguje) i ILE Z NICH ZYJE (decyduje, czy ma teraz internet). Kolor
   niesie werdykt, liczba w srodku - wartosc.
   ===================================================================== */
/* SZEROKOSC KAFELKA = SZEROKOSC PIERSCIENIA, PODPIS POZA UKLADEM.
   Lukasz, 06.09.2026: „uciekaja te kolka w prawo, nie sa ladnie pod
   opisem kolumny".

   Historia tego kawalka w trzech krokach, bo kazdy naprawial cos innego:

   1. Kafelek miал szerokosc podpisu -> „bez limitu" rozpychal wiersz
      i pierscienie skakaly w bok miedzy wierszami.
   2. Kafelek dostal stale 62 px -> wiersze przestaly skakac, ale 34 px
      pierscienia wysrodkowane w 62 px daje 14 px pustego z lewej,
      czyli cala kolumna odjechala od naglowka.
   3. Teraz kafelek ma DOKLADNIE szerokosc pierscienia (34 px), a podpis
      jest wyjety z ukladu (`position:absolute`) i wysrodkowany pod nim.
      Lewa krawedz pierscienia = lewa krawedz komorki = poczatek napisu
      w naglowku. Podpis moze byc szerszy od pierscienia i nikomu nie
      przeszkadza, bo nie zajmuje juz miejsca.

   Odstep 30 px nie jest dobrany na oko: najszerszy podpis („bez limitu")
   ma okolo 48 px, czyli wystaje 7 px poza kafelek z kazdej strony.
   30 px zostawia miedzy podpisami ~16 px swiatla. */
.zajetosc-kola{display:flex;gap:30px;align-items:flex-start}
.pierscien{position:relative;width:34px;flex:0 0 34px;
           padding-bottom:13px;cursor:help;line-height:1}
.pierscien svg{display:block}
.pierscien .tor{stroke:var(--line-soft)}
.pierscien .srodek{font-size:13px;font-weight:700;fill:var(--ink);
                   font-variant-numeric:tabular-nums}
.pierscien .podpis{position:absolute;bottom:0;left:50%;transform:translateX(-50%);
                   font-size:10px;color:var(--ink-3);white-space:nowrap;
                   letter-spacing:.02em;text-align:center}
.pierscien.ok      .luk{stroke:var(--ok)}
.pierscien.warn    .luk{stroke:var(--warn)}
.pierscien.bad     .luk{stroke:var(--bad)}
.pierscien.neutral .luk{stroke:var(--accent)}
/* Werdykt „ten czlowiek sie nie zaloguje" musi byc widoczny takze
   w samej liczbie, nie tylko w luku - przy 34 px sam kolor obwodki
   ginie w skanowaniu kolumny w dol. */
.pierscien.bad .srodek{fill:var(--bad)}
.pierscien.ok  .srodek{fill:var(--ok)}
@media (prefers-reduced-motion:no-preference){
  .pierscien .luk{transition:stroke-dasharray .3s ease-out}
}

/* ODSTĘP MIĘDZY PASKIEM SZUKANIA A TABELĄ.
   Lukasz, 06.09.2026: „tam gdzie szukaj przycisk, trzeba zrobic odstep,
   bo wchodzi na kolumny". Selektor sasiedztwa, a nie globalny margines
   na `table` - inaczej rozjechalyby sie tabele osadzone w blokach,
   ktore maja wlasny padding. */
.formrow + table, .formrow + .tabela-przewijana,
.pasek-akcji + table{margin-top:var(--s4)}

/* =====================================================================
   PASEK LICZB — nagłówek ekranu, który da się objąć wzrokiem
   =====================================================================
   Zastępuje sześć akapitów wyjaśnień. Liczby zostają na wierzchu, bo to
   one są treścią; tłumaczenie chowa się pod „co to znaczy?" i wraca na
   żądanie. Zrzut ekranu dla kogoś z zewnątrz wygląda wtedy jak raport,
   a nie jak instrukcja obsługi.
   ===================================================================== */
.pasek-liczb{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s3) var(--s5);
  padding:var(--s3) var(--s4);background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);margin-bottom:var(--s4)}
.pasek-liczb .liczba{color:var(--ink-2);font-size:var(--fs-sm);white-space:nowrap}
.pasek-liczb .liczba b{color:var(--ink);font-size:var(--fs-md);font-weight:750;
  font-variant-numeric:tabular-nums;margin-right:4px}
.co-to-znaczy{white-space:nowrap}
.wyjasnienie-zwiniete{flex:1 1 100%;margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--line-soft);color:var(--ink-2);font-size:var(--fs-sm)}
.wyjasnienie-zwiniete p{margin:0 0 var(--s2)}
.wyjasnienie-zwiniete p:last-child{margin-bottom:0}

/* =====================================================================
   ZASADY W JEDNEJ LINII — zwiezle opisy z powodem w dymku
   Lukasz, 06.09.2026: „chce pokazac uninetowi kilka screenow - mozemy
   pozbyc sie tych po czesci opisow (...) albo co lepiej - mozna dac
   dymki wyjasniajace po najechaniu".

   Zamiana akapitu na linie nie moze skonczyc sie tym, ze czlowiek nie
   wie, gdzie jest reszta. Stad dwie rzeczy: kropkowane podkreslenie pod
   haslem (uniwersalny znak „tu jest wiecej") i `cursor:help`.
   ===================================================================== */
.zasady{list-style:none;margin:0 0 var(--s4);padding:0;
        display:flex;flex-direction:column;gap:2px}
.zasady li{position:relative;padding:9px 14px 9px 26px;
           font-size:var(--fs-base);line-height:1.45;color:var(--ink-2);
           border-radius:var(--radius-sm);cursor:help}
.zasady li:nth-child(even){background:var(--pas)}
.zasady li:hover{background:var(--surface-2)}
/* Znacznik pozycji. Kropka, nie „•" z listy - chcemy ja miec w kolorze
   akcentu i na stalej wysokosci, niezaleznie od dlugosci wiersza. */
.zasady li::before{content:'';position:absolute;left:11px;top:17px;
                   width:5px;height:5px;border-radius:50%;background:var(--accent);
                   opacity:.55}
.zasady li b{color:var(--ink);font-weight:660;
             border-bottom:1px dotted var(--line);padding-bottom:1px}
.zasady li code{font-family:var(--mono);font-size:var(--fs-sm);
                background:var(--surface-2);border:1px solid var(--line-soft);
                border-radius:4px;padding:1px 5px}

/* Skrocony akapit, ktory ma dymek z pelna trescia — ten sam sygnal. */
.wyjasnienie.zwiezle{cursor:help}
.wyjasnienie.zwiezle::after{content:' ⓘ';color:var(--ink-3);font-size:var(--fs-sm)}

/* Kazdy element z dymkiem, ktory NIE jest przyciskiem ani polem, ma
   pokazac kursorem, ze da sie z niego cos wyciagnac. Bez tego dymek
   istnieje, ale nikt na niego nie najedzie. */
[data-dymek]:not(button):not(input):not(select):not(a):not(.btn){cursor:help}

/* =====================================================================
   BAZA WIEDZY — moduł Operatora
   Lukasz, 06.09.2026: „zebysmy tez sie uczyli i wiedzieli co i jak?
   Przyda sie i mnie i Kubie i Kacprowi do nauki i zrozumienia."

   To jest ekran DO CZYTANIA, nie do klikania - i tak jest zbudowany:
   szerokosc tekstu ograniczona do ~72 znakow (dluzsze linie gubia oko
   przy powrocie do lewej krawedzi), spis tresci przyklejony z boku,
   zeby nie trzeba bylo skrolowac w gore po kazdym rozdziale.
   ===================================================================== */
.ekran-wiedza{display:grid;grid-template-columns:290px minmax(0,1fr);
              gap:var(--s6);align-items:start}

/* --- spis tresci --- */
.wiedza-spis{position:sticky;top:var(--s4);display:flex;flex-direction:column;gap:2px;
             background:var(--surface);border:1px solid var(--line);
             border-radius:var(--radius);padding:var(--s3);box-shadow:var(--shadow-1)}
.wiedza-spis-hd{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.06em;
                color:var(--ink-3);font-weight:700;padding:2px 8px 8px}
.wiedza-poz{display:flex;flex-direction:column;gap:2px;text-align:left;
            background:none;border:0;cursor:pointer;font:inherit;
            padding:9px 10px;border-radius:var(--radius-sm);
            border-left:3px solid transparent}
.wiedza-poz .t{font-weight:620;color:var(--ink);font-size:var(--fs-sm);line-height:1.3}
.wiedza-poz .p{color:var(--ink-3);font-size:var(--fs-xs);line-height:1.35}
.wiedza-poz:hover{background:var(--surface-2)}
.wiedza-poz.wybrany{background:var(--accent-soft);border-left-color:var(--accent)}
.wiedza-poz.wybrany .t{color:var(--accent)}

/* --- tresc --- */
.wiedza-tresc{background:var(--surface);border:1px solid var(--line);
              border-radius:var(--radius);padding:var(--s6) var(--s7);
              box-shadow:var(--shadow-1);max-width:none}
/* Miara wiersza. Wszystko, co jest zwyklym tekstem, siedzi w ~72 znakach.
   Tabele i bloki kodu celowo NIE - one maja swoja szerokosc. */
.wiedza-tresc > p, .wiedza-tresc > ol, .wiedza-tresc > ul,
.wiedza-tresc > dl, .wiedza-tresc > .uwaga, .wiedza-tresc > .wiedza-sedno{
  max-width:72ch}
.wiedza-tresc h2{margin:0 0 var(--s2);font-size:var(--fs-2xl);line-height:1.2;
                 text-wrap:balance}
.wiedza-tresc h3{margin:var(--s6) 0 var(--s2);font-size:var(--fs-lg);
                 line-height:1.3;text-wrap:balance;
                 padding-bottom:6px;border-bottom:1px solid var(--line-soft)}
.wiedza-tresc p{margin:0 0 var(--s3);line-height:1.62;color:var(--ink-2)}
.wiedza-tresc p b, .wiedza-tresc p strong, .wiedza-tresc li b{color:var(--ink)}
.wiedza-lead{font-size:var(--fs-md);color:var(--ink)!important;
             padding-bottom:var(--s3);border-bottom:1px solid var(--line-soft)}
.wiedza-tresc code{font-family:var(--mono);font-size:.88em;
                   background:var(--surface-2);border:1px solid var(--line-soft);
                   border-radius:4px;padding:1px 5px;white-space:nowrap}
.wiedza-tresc table{margin:var(--s3) 0 var(--s4);
                    border:1px solid var(--line);border-radius:var(--radius-sm);
                    overflow:hidden}
.wiedza-tresc .input{max-width:320px;margin-bottom:var(--s4)}
.analogia{padding-left:var(--s4);border-left:3px solid var(--line);
          font-style:italic}

/* --- SEDNO: jedno zdanie, ktore ma zostac w glowie po rozdziale --- */
.wiedza-sedno{background:var(--accent-soft);border:1px solid var(--accent-border);
              border-left:4px solid var(--accent);border-radius:var(--radius-sm);
              padding:var(--s4) var(--s5);margin:var(--s4) 0;
              line-height:1.6;color:var(--ink)}
.wiedza-sedno.mocny{font-size:var(--fs-md)}
.wiedza-sedno pre{margin:var(--s2) 0}
.wiedza-sedno ul{margin:var(--s2) 0 0;padding-left:var(--s5)}
.wiedza-sedno .drobne{margin-top:var(--s2);font-size:var(--fs-sm);color:var(--ink-2)}

/* --- UWAGA: pulapka, blad, rzecz ktora myli --- */
.wiedza-tresc .uwaga{background:var(--warn-bg);border:1px solid var(--warn-border);
                     border-left:4px solid var(--warn);border-radius:var(--radius-sm);
                     padding:var(--s3) var(--s4);margin:var(--s3) 0;
                     font-size:var(--fs-sm);line-height:1.55;color:var(--ink-2)}

/* --- KROKI: ponumerowany lancuch, bo tu kolejnosc NIESIE TRESC --- */
.kroki{margin:var(--s4) 0;padding:0;list-style:none;counter-reset:krok;
       display:flex;flex-direction:column;gap:var(--s3)}
.kroki li{counter-increment:krok;position:relative;padding-left:44px;
          line-height:1.6;color:var(--ink-2)}
.kroki li::before{content:counter(krok);position:absolute;left:0;top:0;
                  width:28px;height:28px;border-radius:50%;
                  display:flex;align-items:center;justify-content:center;
                  background:var(--accent);color:var(--accent-ink);
                  font-size:var(--fs-sm);font-weight:700}
/* Kreska laczaca kroki - to jest lancuch, nie luzna lista punktow. */
.kroki li:not(:last-child)::after{content:'';position:absolute;left:13px;top:32px;
                                  bottom:calc(-1 * var(--s3) - 4px);
                                  width:2px;background:var(--line-soft)}
.kroki .uwaga{margin-top:var(--s2)}

/* --- ETYKIETY WIARYGODNOSCI ---------------------------------------
   Fakt, wniosek i niewiedza maja rozny ciezar i MUSZA sie roznic
   wizualnie. Czlowiek, ktory sie uczy, nauczy sie inaczej naszych
   hipotez niz pomiarow - pod warunkiem, ze widzi ktore jest ktore. */
.etykieta{display:inline-flex;align-items:center;gap:4px;
          font-size:var(--fs-xs);font-weight:700;letter-spacing:.03em;
          text-transform:uppercase;padding:1px 7px;border-radius:var(--radius-pill);
          border:1px solid transparent;vertical-align:1px;white-space:nowrap;
          cursor:help}
.etykieta.fakt{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-border)}
.etykieta.wniosek{background:var(--warn-bg);color:var(--warn);border-color:var(--warn-border)}
.etykieta.nie-wiemy{background:var(--surface-2);color:var(--ink-3);border-color:var(--line)}

/* --- listy opisowe: stany, slowniczek --- */
.stany-opis{display:grid;grid-template-columns:auto 1fr;gap:var(--s3) var(--s4);
            margin:var(--s3) 0 var(--s4);align-items:start;max-width:72ch}
.stany-opis dt{padding-top:2px}
.stany-opis dt code{white-space:nowrap}
.stany-opis dd{margin:0;line-height:1.6;color:var(--ink-2)}

.slownik{display:grid;grid-template-columns:minmax(140px,220px) 1fr;
         gap:0;margin:0;border:1px solid var(--line);border-radius:var(--radius-sm);
         overflow:hidden}
.slownik dt{padding:11px var(--s4);font-weight:700;color:var(--ink);
            display:flex;flex-direction:column;gap:2px;
            border-top:1px solid var(--line-soft)}
.slownik dt .rozw{font-weight:400;font-size:var(--fs-xs);color:var(--ink-3);
                  text-transform:none;letter-spacing:0;line-height:1.3}
.slownik dd{margin:0;padding:11px var(--s4);line-height:1.55;color:var(--ink-2);
            border-top:1px solid var(--line-soft)}
.slownik dt:first-of-type, .slownik dd:first-of-type{border-top:0}
/* Paskowanie par - bez niego dwukolumnowa lista rozjezdza sie przy
   dluzszych opisach i nie widac, ktory opis nalezy do ktorego hasla. */
.slownik dt:nth-of-type(even), .slownik dd:nth-of-type(even){background:var(--pas)}

@media (max-width:1100px){
  .ekran-wiedza{grid-template-columns:1fr}
  .wiedza-spis{position:static}
  .wiedza-tresc{padding:var(--s5)}
  .slownik{grid-template-columns:1fr}
  .slownik dd{padding-top:0;border-top:0}
}

/* Zakup i gwarancja — blok wpisywany RĘCZNIE na karcie sprzętu.
   Wydzielony ramką, bo to jedyne miejsce na tej karcie, gdzie dane
   pochodzą od człowieka, a nie z ESET-a, AnyDeska czy Zabbiksa.
   Ta różnica jest ważna przy czytaniu karty: reszta może się zmienić
   sama, to nie. */
.blok-zakup{margin-top:var(--s4);padding:var(--s4);
            background:var(--surface-2);border:1px solid var(--line);
            border-radius:var(--radius)}
.blok-zakup .kolumny-tytul{margin-bottom:var(--s3)}
.blok-zakup .pasek-akcji{margin-top:var(--s3)}

/* =====================================================================
   TELEFON: ŻADNA TABELA NIE MA PRAWA ROZPYCHAĆ STRONY
   06.09.2026, przed wydaniem wersji dla techników.

   OBJAW: na karcie stanowiska otwartej na telefonie tekst uciekał poza
   prawą krawędź, nagłówek był przycięty, a cała strona wyglądała na
   pomniejszoną.

   PRZYCZYNA (zmierzona, nie zgadnięta): tabela „Sieć" w szufladzie ma
   506 px przy szufladzie szerokiej na 389. Tabela bez własnego
   przewijania nie zwęża się poniżej swojej zawartości - rozpycha
   rodzica, rodzic rozpycha dokument, a przeglądarka na telefonie
   reaguje na dokument szerszy od ekranu ODDALENIEM CAŁEJ STRONY.
   Stąd `window.innerWidth` = 482 zamiast 390 i stąd wrażenie, że
   „wszystko jest za małe" - bo faktycznie było, tylko winna była
   jedna tabela, a nie rozmiary czcionek.

   ROZWIĄZANIE: `display:block` robi z tabeli zwykły blok, który da się
   przewijać w poziomie. Wiersze i komórki układają się dalej po
   tabelarycznemu (anonimowe pudełka tabeli), więc kolumny, paskowanie
   i obramowania zostają - zmienia się tylko to, że nadmiar SIĘ PRZEWIJA
   zamiast rozpychać ekran.

   Dlaczego nie `overflow-x:hidden` na `body`: to ukrywa treść zamiast
   dać do niej dojść. Technik w terenie ma zobaczyć adres MAC, a nie
   dowiedzieć się, że gdzieś jest, tylko nie da się go pokazać.
   ===================================================================== */
@media (max-width:900px){
  .drawer table, .content table, .karta-infra table{
    display:block; overflow-x:auto; -webkit-overflow-scrolling:touch;
    max-width:100%;
  }
  /* Cień na prawej krawędzi mówi „to się przewija". Bez tego nikt nie
     próbuje przesunąć palcem, bo tabela wygląda na całą. */
  .drawer table, .content table{
    background-image:linear-gradient(to left, rgba(0,0,0,.06), rgba(0,0,0,0) 24px);
    background-attachment:local, scroll;
  }
  /* Szuflada MA zakrywać ekran w całości. Przy dokumencie szerszym niż
     ekran `100vw` liczyło się od rozdmuchanego dokumentu i szuflada
     przestawała pokrywać lewą krawędź - widać było spod niej listę. */
  .drawer{width:100% !important;inset:0 !important;border-left:0}
}

/* =====================================================================
   TELEFON: PRAWA STRONA PASKA MA SIĘ ZAWIJAĆ, A NIE WYSTAWAĆ
   06.09.2026.

   Zmierzone: `.top-ja` (awatar, klucz, tarcza, wyjście) kończył się na
   482 px przy ekranie 390 px. Efekt był podstępny, bo NIE wyglądał na
   uciętą ikonę - przeglądarka na telefonie widzi dokument szerszy od
   ekranu i ODDALA CAŁĄ STRONĘ, żeby się zmieścił. Cały interfejs robił
   się mniejszy, a winne było 92 px w rogu paska.

   Dlatego dwie rzeczy naraz: pozwalamy grupie zawinąć się do drugiego
   rzędu ORAZ zabraniamy jej wypychać pasek (`min-width:0`). Samo
   zawijanie nie wystarczy, jeśli któreś dziecko ma własną szerokość
   minimalną - wtedy grupa dalej rozpycha rodzica.
   ===================================================================== */
@media (max-width:640px){
  .topbar{flex-wrap:wrap;row-gap:var(--s2)}
  .top-prawo{flex-wrap:wrap;min-width:0;flex:1 1 100%;
             justify-content:flex-start;gap:var(--s2)}
  .top-ja{min-width:0;flex-wrap:wrap}
  /* Imię i nazwisko przy awatarze to na telefonie strata połowy rzędu.
     Kto jest zalogowany, widać po samym awatarze - a jak nie widać,
     to jest to w menu pod ≡. */
  .top-ja .ja-opis{display:none}
  .top-lewo{flex:1 1 100%;min-width:0}
}

/* =====================================================================
   NAGŁÓWEK SZUFLADY
   Styl przeniesiony z atrybutu `style` do arkusza, bo na telefonie ten
   układ musi wyglądać inaczej — a stylu wpisanego w JSX nie obejmie
   żadne zapytanie medialne.
   ===================================================================== */
.drawer-hd{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
           margin-bottom:var(--s4)}
.drawer-hd .zamknij{margin-left:auto}

@media (max-width:640px){
  /* NA TELEFONIE „zamknij" IDZIE DO ROGU, NIE NA WŁASNY WIERSZ.
     Przy zawijaniu długa nazwa firmy („Centrum Ogrodnicze Zielona Aleja
     · Siedziba · Biuro 1") zajmowała całą szerokość i wypychała przycisk
     do osobnego rzędu — 90 px ekranu na jeden przycisk, zanim technik
     zobaczył cokolwiek o maszynie.

     Siatka zamiast zawijania: tytuł w pierwszej kolumnie, przycisk
     w drugiej, opis pod spodem przez całą szerokość. */
  .drawer-hd{display:grid;grid-template-columns:1fr auto;
             align-items:start;gap:6px 10px;margin-bottom:var(--s3)}
  .drawer-hd > h2{grid-column:1;margin:0;font-size:var(--fs-xl);line-height:1.2}
  .drawer-hd .zamknij{grid-column:2;grid-row:1;margin-left:0;align-self:start}
  /* Wszystko inne (dostępność, nazwa firmy) ląduje pod spodem,
     w pełnej szerokości i w kolejności, w jakiej stoi w kodzie. */
  .drawer-hd > *:not(h2):not(.zamknij){grid-column:1 / -1}
}

/* =====================================================================
   FILTRY ZWIJANE — tylko na telefonie
   Na monitorze filtry stoją w jednym rzędzie i nic nie kosztują.
   Na ekranie 390 px zajmowały 209 px, a pierwsze zgłoszenie zaczynało
   się na 554 px — czyli po wejściu na listę technik widział pięć list
   rozwijanych i ani jednego zgłoszenia.
   ===================================================================== */
.filtry-przelacz{display:none}

@media (max-width:640px){
  .filtry-przelacz{
    display:inline-flex;align-items:center;gap:8px;
    background:var(--surface);border:1px solid var(--line);
    border-radius:var(--radius-sm);padding:9px 14px;
    font:inherit;font-weight:620;color:var(--ink);cursor:pointer;
    min-height:40px}
  .filtry-przelacz:hover{background:var(--surface-2)}
  /* Liczba włączonych filtrów NA PRZYCISKU. Bez niej zwinięty pasek
     wygląda tak samo przy filtrach włączonych i wyłączonych — a to
     jest dokładnie ta pomyłka, po której ktoś dzwoni, że „zgłoszenia
     zniknęły". */
  .filtry-przelacz .ile{
    display:inline-flex;align-items:center;justify-content:center;
    min-width:20px;height:20px;padding:0 6px;border-radius:var(--radius-pill);
    background:var(--accent);color:var(--accent-ink);
    font-size:var(--fs-xs);font-weight:700}
  /* Zwinięte jest sterowanie, NIE plakietki włączonych filtrów —
     te zostają widoczne zawsze. */
  .filters:not(.rozwiniete) > .sterowanie{display:none}
  .filters{padding:var(--s3)}
  .filters .row{gap:8px}
  .filters select.input{flex:1 1 100%;max-width:none !important}
}

/* =====================================================================
   CELE DOTYKOWE — telefon w terenie, nie mysz przy biurku
   06.09.2026, przed wydaniem wersji dla techników.

   Zmierzone na ekranie 390 px: każdy `.btn.sm` miał 34 px wysokości.
   Przy myszy to jest w porządku - kursor trafia w piksel. Palcem nie:
   przyjęte minimum to 44 px (Apple) / 48 px (Google), i nie jest to
   widzimisię projektanta, tylko średnia powierzchnia opuszki.
   34 px znaczy chybione dotknięcia, a chybione dotknięcie na tym ekranie
   to przypadkowo otwarte cudze zgłoszenie albo zatrzymany zegar.

   Podnosimy WYSOKOŚĆ, nie czcionkę - napisy zostają tam, gdzie były,
   rośnie tylko pole, w które można trafić. Dzięki temu układ nie
   przeskakuje, a przyciski nie zaczynają wyglądać jak dla dzieci.
   ===================================================================== */
@media (max-width:640px){
  .btn, .btn.sm, button.jak-link.btn{min-height:44px}
  /* Kwadratowe przyciski z samą ikoną potrzebują też szerokości —
     44 px wysokości przy 35 px szerokości dalej się nie trafia. */
  .btn.sm{padding-left:14px;padding-right:14px}
  .btn.ikona, .zamknij{min-width:44px}
  /* Pola formularzy: 36 px to za mało, żeby trafić w nie kciukiem
     przy wpisywaniu minut na kolanie w aucie. */
  .input, select.input, textarea.input{min-height:44px}
  /* Ptaszki i przełączniki mają większy obszar klikalny niż sam kwadracik. */
  .ptaszek, .przelacznik{min-height:44px}
  /* Odstęp między sąsiadującymi przyciskami — dwa cele po 44 px stykające
     się krawędziami to nadal jeden cel dla palca. */
  .pasek-akcji, .formrow{gap:10px}
}

/* Podpis źródła przy wartości uzupełnionej z monitoringu. Ma być
   czytelny, ale nie ma konkurować z samą wartością — to przypis,
   nie treść. */
.zrodlo-faktu{font-size:var(--fs-sm);cursor:help}

/* Wersja programu w stopce menu. Przygaszona — to jest informacja
   na żądanie, nie element, na który ma się patrzeć przy pracy. */
.sidefoot .wersja{margin-left:6px;padding:1px 6px;border-radius:var(--radius-pill);
  background:var(--surface-2);border:1px solid var(--line-soft);
  color:var(--ink-3);font-variant-numeric:tabular-nums;cursor:help}

/* Wyjaśnienie pod rzędem ustawienia automatu — nie w środku zdania.
   Wcięcie równa się szerokości ptaszka plus odstęp, żeby tekst zaczynał
   się pod etykietą, a nie pod kwadracikiem. */
.zrodlo-auto-opis{margin:2px 0 var(--s3) 26px;
  color:var(--ink-3);font-size:var(--fs-sm);line-height:1.45;max-width:62ch}

/* =====================================================================
   KRĄŻKI — po jednym kółku na pozycję, każde z własnym mianownikiem
   Lukasz, 06.09.2026: chcial trzy widgety kolowe. Dwa dostaly pierscien,
   ten - osobne kolka, bo jego kategorie NACHODZA NA SIEBIE i jeden
   pierscien twierdzilby, ze to rozlaczne czesci calosci. Szczegoly
   w komentarzu przy komponencie `Krazki`.
   ===================================================================== */
/* WYSRODKOWANE I WIEKSZE.
   Lukasz, 06.09.2026: „te 3 kolka wycentruj i ciut powieksz, bo jest
   miejsce". Miejsce faktycznie bylo: trzy wiersze stały przy gornej
   krawedzi kafla, a pod nimi zostawala pusta polowa.

   Pionowo srodkuje `justify-content`, poziomo - `max-width` na wierszu
   plus `align-items:center`. Poziome srodkowanie MUSI isc przez stala
   szerokosc wiersza, a nie przez `width:auto`: przy szerokosci z tresci
   kazdy wiersz mialby inna i kolka rozjechalyby sie w pionie - dokladnie
   to, co poprawialismy przy pierscieniach w UNINET.
   `overflow:auto` zostaje na wypadek niskiego kafla; przy scisku
   `justify-content:center` w kontenerze przewijanym potrafi uciac
   pierwszy wiersz, wiec zamiast niego stoi `margin:auto` na grupie. */
/* SIATKA, NIE TRZY OSOBNE WIERSZE.
   Łukasz, 06.09.2026: „chyba są krzywo (szczególnie te 3 pod sobą)".
   Miał rację i powód był w poprzedniej poprawce. Wiersze były pudełkami
   o wspólnej szerokości, a para „kółko + opis" środkowała się w środku
   każdego z nich. Kółka stały równo, ale opis jest krótszy niż jego
   pudełko, więc CAŁA grupa wyglądała na przesuniętą w lewo — puste
   miejsce zostawało po prawej.

   Siatka z dwiema kolumnami `max-content` rozwiązuje jedno i drugie
   naraz: szerokość kolumny bierze się z najszerszego wiersza, więc
   kółka stoją w jednej linii, a `justify-content:center` środkuje
   całość — bez pustego pasa, bo siatka ma dokładnie szerokość treści.
   `align-content` robi to samo w pionie.

   `safe` znaczy: środkuj, ale gdy zabraknie miejsca — wróć do góry.
   Bez tego wyśrodkowana treść w pudełku przewijanym ucina PIERWSZY
   wiersz i nie da się do niego doscrollować. Starsze przeglądarki nie
   znają słowa `safe` i zostają przy linijce wyżej — dlatego stoją obie. */
.krazki{display:grid;grid-template-columns:max-content minmax(0, max-content);
        gap:var(--s2) var(--s4);
        height:100%;min-height:0;overflow:auto;
        justify-content:center;align-content:center;
        justify-content:safe center;align-content:safe center}
.krazek{display:grid;grid-column:1 / -1;grid-template-columns:subgrid;
        align-items:center;
        background:none;border:0;padding:6px 0;border-radius:var(--radius);
        font:inherit;text-align:left;color:inherit}
.krazek.klik{cursor:pointer}
.krazek.klik:hover{background:var(--surface-2)}
.krazek:disabled{cursor:default}
.krazek svg{flex:0 0 auto;display:block}
.krazek .tor{stroke:var(--line-soft)}
/* Kolor niesie WAGE, nie tozsamosc: udzial we flocie decyduje o tym,
   czy to drobiazg, czy robota na jutro. */
.krazek.ok    .luk{stroke:var(--ok-solid)}
.krazek.uwaga .luk{stroke:var(--warn)}
.krazek.zle   .luk{stroke:var(--bad-solid)}
.krazek-proc{font-size:15px;font-weight:700;fill:var(--ink);
             font-variant-numeric:tabular-nums}
/* Szerokość opisu ustala teraz SIATKA (druga kolumna `max-content`),
   a nie stała podstawa — patrz komentarz przy `.krazki`. Tutaj zostaje
   tylko `min-width:0`, żeby długa nazwa przycięła się wielokropkiem
   zamiast rozpychać kafel. */
.krazek-opis{display:flex;flex-direction:column;gap:1px;min-width:0}
.krazek-opis strong{font-size:var(--fs-lg);line-height:1.1;
                    font-variant-numeric:tabular-nums}
.krazek-nazwa{font-size:var(--fs-sm);color:var(--ink-2);line-height:1.25;
              overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.krazek-z{font-size:var(--fs-xs);color:var(--ink-3)}

/* Wyjątek przy pozycji legendy („3 po terminie", „bez wsparcia").
   Słowem, nie barwą — inaczej trzeba by zgadywać, co znaczy inny
   odcień, a przy sześciu barwach kategorycznych nie ma już wolnego.

   Do prawej krawędzi i BEZ kurczenia: nazwa firmy może się skrócić
   wielokropkiem, ta liczba nie może zniknąć — to dla niej ktoś patrzy
   na ten widget. */
.kolo-legenda .legenda-uwaga{font-style:normal;flex:0 0 auto;margin-left:auto;
  padding-left:8px;font-size:var(--fs-xs);color:var(--warn);line-height:1.25;
  white-space:nowrap}

/* =====================================================================
   ANALIZA OD NORY — warstwa wewnętrzna na karcie zgłoszenia.

   Łukasz, 06.09.2026: „`nora` jest warstwą wewnętrzną. Widoczna na
   karcie zgłoszenia i dla technika. Nigdy w mailu do klienta i nigdy
   w rozmowie ze zgłaszającym."

   Wygląd niesie tę granicę: inne tło, kreska z boku i podpis „NORA".
   Ocena modelu i słowa klienta muszą różnić się na pierwszy rzut oka,
   bo mają zupełnie inną wiarygodność — a złożone tym samym krojem
   wyglądają identycznie.
   ===================================================================== */
.od-nory{margin-top:var(--s3);padding:var(--s3);border-radius:var(--radius);
  background:var(--surface-2);border-left:3px solid var(--ink-3)}
.od-nory-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-size:var(--fs-xs);margin-bottom:6px}
.od-nory-hd .znak{font-weight:700;letter-spacing:.08em;color:var(--ink-2)}
.od-nory-hd .pewnosc{margin-left:auto;font-variant-numeric:tabular-nums;
  color:var(--ink-2);white-space:nowrap}
.od-nory-hd .pewnosc.slaba{color:var(--warn)}
.od-nory-tresc{margin:0;font-size:var(--fs-sm);line-height:1.45;color:var(--ink)}
.od-nory-etykiety{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
.od-nory-etykiety .nora-tag{display:inline-block;font-size:var(--fs-xs);
  padding:2px 8px;border-radius:var(--radius-pill);border:1px solid var(--line);
  color:var(--ink-2);background:var(--surface);
  /* Bez wersalików — w środku jest wolny tekst od modelu, nie nazwa
     stanu ze słownika. Patrz komentarz przy komponencie `OdNory`. */
  text-transform:none;letter-spacing:0}

/* =====================================================================
   KOMUNIKATY DO ABONENTÓW — wiersze wyboru w kreatorze
   =====================================================================
   Radio i checkbox z opisem obok. Cały wiersz jest etykietą, więc
   klikalne jest zdanie, a nie sam kwadracik o boku dwunastu pikseli. */
.wybor-wiersz {
  display: flex; align-items: flex-start; gap: 9px; cursor: pointer;
  padding: 7px 8px; margin: 0 -8px; border-radius: 7px; line-height: 1.45;
}
.wybor-wiersz:hover { background: var(--tlo-2, rgba(127,127,127,.07)); }
.wybor-wiersz input { margin: 3px 0 0; flex: 0 0 auto; width: 16px; height: 16px;
                      cursor: pointer; }
.wybor-wiersz input:disabled { cursor: not-allowed; }
.wybor-wiersz input:disabled + span { opacity: .55; }

/* =====================================================================
   HASŁO JEDNORAZOWE — pudełko, którego nie da się przeoczyć
   =====================================================================
   Pokazujemy je RAZ, więc przeoczenie kosztuje drugi reset i drugie
   wylogowanie człowieka. Ekran podjeżdża do niego sam (patrz
   settings.tsx), a tutaj dokładamy to, co widać: krótki błysk obwódki
   przy pojawieniu i hasło w rozmiarze, który da się przeczytać
   z drugiego końca biurka, gdy dyktuje się je przez telefon. */
.note.haslo{outline:none;animation:haslo-uwaga .9s ease-out 1}
.note.haslo:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
@keyframes haslo-uwaga{
  0%{box-shadow:0 0 0 0 var(--accent)}
  40%{box-shadow:0 0 0 6px color-mix(in srgb,var(--accent) 30%,transparent)}
  100%{box-shadow:0 0 0 0 transparent}
}
@media (prefers-reduced-motion:reduce){ .note.haslo{animation:none} }
.haslo-wiersz{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin:6px 0}
.note.haslo .mono.duze{font-size:1.6rem;font-weight:700;letter-spacing:.06em;
  user-select:all}

/* =====================================================================
   KARTA ABONENTA (moduł operatora)
   =====================================================================
   Dwie kolumny o różnej roli, a nie siatka równych kafelków: po lewej
   „kim jest" (kartoteka, adresacja, sesje, router), po prawej „co się
   z nim działo i co mogę zrobić". Pierwsza wersja korzystała z gotowego
   `.karta-kolumny` i rozłożyła wszystkie kafle w jeden rząd — bo tamten
   układ jest zbudowany pod DWA kafle, a nie pod dwie kolumny kafli.
   ===================================================================== */
.karta-abonenta{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
                gap:var(--s5);align-items:start}
.karta-abonenta > .kolumna{display:flex;flex-direction:column;gap:var(--s4);min-width:0}
.karta-abonenta .kafel{margin:0}
.karta-abonenta table{width:100%}
@media (max-width:1100px){ .karta-abonenta{grid-template-columns:1fr} }

/* ---------------------------------------------------------------------
   JEDNA SKALA NA CAŁEJ KARCIE
   ---------------------------------------------------------------------
   Łukasz, 07.09.2026: „wyrównaj czcionki — bo są dziwne, raz mniejsza,
   raz większa, wygląda to słabo".

   Miał rację i przyczyna była mechaniczna: klasa `.mono` zmienia nie
   tylko krój, ale i ROZMIAR (`--fs-sm`). Na karcie, gdzie w jednej
   kolumnie stoją obok siebie nazwisko (zwykłą czcionką) i konto
   (monospace), dawało to dwa różne rozmiary w sąsiednich wierszach tej
   samej listy — a `.kafel-fakty` dokładało trzeci.

   Tutaj monospace ma znaczyć „to jest identyfikator do przepisania",
   a nie „to jest mniej ważne". Więc krój zostaje, rozmiar się wyrównuje.
   --------------------------------------------------------------------- */
.karta-abonenta dl.kv dt,
.karta-abonenta dl.kafel-fakty dt{font-size:var(--fs-sm);line-height:var(--lh)}
.karta-abonenta dl.kv dd,
.karta-abonenta dl.kafel-fakty dd{font-size:var(--fs-base);line-height:var(--lh)}
.karta-abonenta .mono,
.karta-abonenta dl.kv dd.mono{font-size:var(--fs-base)}
/* Wiersz drugiego rzędu (gmina, powiat, „skąd wiemy") zostaje mniejszy —
   to jest dopisek pod wartością, a nie druga wartość. */
.karta-abonenta dd .mini,
.karta-abonenta dd .muted.mini{font-size:var(--fs-sm)}
.karta-abonenta table th{font-size:var(--fs-sm)}
.karta-abonenta table td{font-size:var(--fs-base)}
.karta-abonenta table td .mono{font-size:var(--fs-base)}
.karta-abonenta table td .mini{font-size:var(--fs-sm)}
.karta-abonenta dl.kv{grid-template-columns:150px minmax(0,1fr);margin-bottom:0}
.karta-abonenta .kafel-fakty{grid-template-columns:auto minmax(0,1fr)}

/* Panel zgłoszenia siedzi w tej samej rodzinie ekranów, więc dziedziczy
   tę samą skalę — inaczej po kliknięciu w numer zmieniałaby się typografia. */
.drawer.waski dl.kv dt{font-size:var(--fs-sm)}
.drawer.waski dl.kv dd,
.drawer.waski dl.kv dd.mono{font-size:var(--fs-base)}
.drawer.waski dl.kv{grid-template-columns:132px minmax(0,1fr)}
.karta-abonenta td.nowrap{white-space:nowrap}
/* Kolumna „czego dotyczy" bierze resztę szerokości, żeby numer, status
   i data nie łamały się na kilka linii przy wąskiej szufladzie. */
.karta-abonenta table td:nth-child(2){width:99%}

/* Kolumna „stan łącza": plakietka i podpis w jednej osi.
   Wcześniej podpis wisiał wyrównany do lewej pod wyśrodkowaną
   plakietką i wyglądało to na przypadek, a nie na układ. */
.stan-lacza{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center}
.stan-lacza .mini{line-height:1.35}
.uwaga-nexera{color:var(--warn)}

/* Historia zgłoszeń: suma po lewej, trzy pierścienie po prawej.
   Pierścienie są TYM SAMYM komponentem, co przy sesjach w Radiusie —
   ta sama rzecz ma w programie wyglądać tak samo. */
.historia-zgl{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;
              padding:4px 0 2px}
.historia-suma{display:flex;flex-direction:column;line-height:1.1;min-width:0}
.historia-n{font-size:var(--fs-2xl);font-weight:700;font-variant-numeric:tabular-nums}
.historia-e{font-size:var(--fs-sm);color:var(--ink-3);margin-top:2px}
.historia-od{font-size:var(--fs-xs);color:var(--ink-3);margin-top:6px}
/* PIERŚCIENIE DUŻE I NA ŚRODKU WOLNEGO MIEJSCA.
   Łukasz, 07.09.2026: „ikonki super, ale są wyrzucone w prawo, takie
   samotne — śmiało mogłyby być dużo większe i wycentrowane w ramach
   wolnego miejsca". 34 px to rozmiar dobrany do GĘSTEJ LISTY sesji,
   gdzie pierścień stoi w komórce tabeli. Tutaj jest sam w kaflu i ten
   sam rozmiar czyta się jak zapomniana ozdoba, a nie jak treść.
   `flex:1` zamiast `margin-left:auto` — grupa zajmuje całą resztę
   szerokości i środkuje się w niej, zamiast przywierać do krawędzi. */
.historia-zgl .zajetosc-kola{flex:1 1 auto;justify-content:center;
  align-items:flex-start;gap:44px;margin-left:0}
.historia-zgl .pierscien{width:64px;flex:0 0 64px;padding-bottom:20px}
.historia-zgl .pierscien svg{width:64px;height:64px}
.historia-zgl .pierscien .podpis{font-size:12px}
@media (max-width:900px){
  .historia-zgl .zajetosc-kola{gap:28px}
  .historia-zgl .pierscien{width:52px;flex-basis:52px}
  .historia-zgl .pierscien svg{width:52px;height:52px}
}

/* =====================================================================
   RAPORT DIAGNOZY ABONENTA
   =====================================================================
   Łukasz, 07.09.2026: „zlituj się, nie może tak to wyglądać. Pełne
   informacje (…) i ten wynik pomiaru ma być w formie przystępnej".
   Miał rację — surowy JSON na ekranie jest wygodny dla programisty
   i bezużyteczny dla technika, który za chwilę dzwoni do abonenta.
   Liczby dostają więc własną typografię: duża wartość, mała jednostka,
   etykieta wersalikami i jedno zdanie kontekstu pod spodem.
   ===================================================================== */
.raport-diag{width:min(920px,95vw);max-height:88vh;overflow:auto}
.kartahd-nr{font-weight:500;font-size:var(--fs-sm);color:var(--ink-3);margin-left:6px}

.diag-glowa{display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap;
  padding:12px 14px;margin-bottom:var(--s4);border-radius:var(--radius-sm);
  background:var(--surface,rgba(127,127,127,.06));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.diag-kto{flex:1 1 260px;min-width:0}
.diag-stan{flex:0 0 auto;text-align:right}
.diag-uwagi{white-space:pre-line}

/* Listwa pomiarów — równe kolumny, cyfry tablicowe. */
.miary{display:grid;gap:10px;margin:0 0 var(--s4);
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.miara{padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--surface,rgba(127,127,127,.06));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.miara-e{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.08em;
  font-weight:700;color:var(--ink-3)}
.miara-v{margin-top:4px;font-size:var(--fs-xl,22px);font-weight:700;
  letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.miara-v .jedn{font-size:var(--fs-sm);font-weight:600;color:var(--ink-3)}
.miara-p{margin-top:3px;font-size:var(--fs-xs);color:var(--ink-3);line-height:1.35}
.miara.warn{border-color:rgba(200,140,20,.5)}
.miara.bad{border-color:rgba(190,50,45,.5)}

.diag-werdykt{padding:12px 14px;margin-bottom:var(--s4);
  border-radius:var(--radius-sm);border:1px solid var(--linia,rgba(127,127,127,.25))}
.diag-tytul{margin-top:8px;font-weight:700;font-size:var(--fs-lg,17px)}
.diag-werdykt p{margin-top:4px}

/* Powody — kropka sygnału po lewej, tak jak w portalu abonenta. */
.lista-powodow{list-style:none;margin:6px 0 var(--s4);padding:0;display:grid;gap:6px}
.lista-powodow li{position:relative;padding-left:18px;font-size:var(--fs-sm);
  line-height:1.5}
.lista-powodow li::before{content:'';position:absolute;left:0;top:.55em;
  width:7px;height:7px;border-radius:50%;background:var(--ink-3)}
.lista-powodow li.s-ok::before{background:#1c9c62}
.lista-powodow li.s-uwaga::before{background:#c88c14}
.lista-powodow li.s-zle::before{background:#c0332e}
.lista-powodow li.s-info::before{background:transparent;
  box-shadow:inset 0 0 0 1.5px var(--ink-3)}

/* Kropka „to nie z ewidencji, to z monitoringu" — mała, bez krzyku.
   Liczba bez podpisu źródła za miesiąc jest liczbą, o której nikt nie
   wie, skąd się wzięła, a przy sporze z klientem o konfigurację
   sprzętu to jest pytanie, które pada. */
.zrodlo-kropka{display:inline-block;width:5px;height:5px;border-radius:50%;
  margin-left:5px;vertical-align:.35em;background:currentColor;opacity:.45}

/* =====================================================================
   LISTA ZGŁOSZEŃ — CZYTELNA Z DRUGIEGO KOŃCA BIURKA
   =====================================================================
   Łukasz, 08.09.2026: „powiększ czcionki na ile się da, bo nr iPot jest
   malutki, imię nazwisko malutkie, ulica malutka. Wiersze możesz dać
   delikatnie wyższe, zachowaj rozsądek i estetykę".
   Ten ekran jest czytany przez cały dzień i z dystansu, więc dostaje
   własną skalę: drugi wiersz w komórce (nazwisko, gmina, godzina,
   podpis pod plakietką) przestaje być „mini" i schodzi tylko o pół
   stopnia niżej od głównego tekstu. Wiersze rosną o tyle, żeby to
   pomieściło się bez ścisku — nie więcej. */
.tab-zgloszen tbody td{padding:15px 14px;line-height:1.45}
.tab-zgloszen tbody td .mini,
.tab-zgloszen tbody td .muted.mini{font-size:var(--fs-sm);line-height:1.4}
.tab-zgloszen tbody td.mono,
.tab-zgloszen tbody td .mono{font-size:var(--fs-base);letter-spacing:.01em}
.tab-zgloszen thead th{font-size:var(--fs-sm);padding:12px 14px}
/* Odstęp między pierwszą a drugą linią w komórce — bez niego
   nazwisko klei się do numeru, a godzina do daty. */
.tab-zgloszen tbody td > .mini,
.tab-zgloszen tbody td > .muted.mini{margin-top:3px}

/* PLAKIETKA, KTÓRA MUSI SIĘ ZAWINĄĆ — W TABELI ZGŁOSZEŃ.
   Łukasz, 08.09.2026: „w awariach zgłoszonych do Nexery popsuł się
   tekst w kategorii, wypadł z obramówki". Globalna plakietka ma stałą
   wysokość 26 px i `nowrap` — dobrze przy „Online", źle przy „awaria,
   zgłoszone do nexera", które w wąskiej kolumnie musi zejść do drugiej
   linii. Tutaj (i tylko tutaj) plakietka rośnie z tekstem: wysokość
   z zawartości, zawijanie dozwolone, tekst wyśrodkowany. */
.tab-zgloszen .pill{height:auto;min-height:26px;white-space:normal;
  padding:3px 10px;line-height:1.3;text-align:center;display:inline-block}

/* W ZAMKNIĘTYCH JEST O JEDNĄ KOLUMNĘ WIĘCEJ — ciaśniej, ale równo.
   Łukasz: „lista na zamkniętych się rozjeżdża, możesz ścieśnić kolumny,
   bo tam jest więcej opisów". Zwężamy odstępy w komórkach i minimalnie
   tekst pomocniczy; główna treść zostaje w tym samym rozmiarze, bo to
   ją się czyta. */
.tab-zgloszen.zamkniete tbody td{padding:13px 9px}
.tab-zgloszen.zamkniete thead th{padding:11px 9px}
.tab-zgloszen.zamkniete tbody td .mini,
.tab-zgloszen.zamkniete tbody td .muted.mini{font-size:var(--fs-xs);line-height:1.35}
.tab-zgloszen.zamkniete .pill{font-size:var(--fs-xs);padding:3px 8px}

/* Lista zgłoszeń od abonentów — kolumny trzymają szerokość, treść się
   do nich dostosowuje, a nie odwrotnie. */
.tab-zgloszen{table-layout:fixed;width:100%}
.tab-zgloszen td{vertical-align:top}
.tab-zgloszen .kol-temat{white-space:normal;overflow-wrap:anywhere;line-height:1.4}
/* Kolumna stanu łącza: plakietka i podpis pod nią, nigdy obok siebie —
   „Bez sesji" z długim wyjaśnieniem rozpychało wiersz na dwie linie
   w losowych miejscach. */
.tab-zgloszen td .brak-stanu,
.tab-zgloszen td .muted.mini{white-space:normal;line-height:1.35}
/* Nagłówki mogą się ZAWIJAĆ, a nie znikać w wielokropku.
   „NR ZGŁOSZ…" nie mówi nic; „Nr zgłoszenia iPot" w dwóch linijkach
   mówi wszystko i nie kosztuje ani piksela szerokości kolumny. */
.tab-zgloszen th{white-space:normal;line-height:1.25;overflow:hidden}

/* Kolumna stanu łącza wyrównana DO LEWEJ, jak reszta tabeli.
   Wcześniej treść była wyśrodkowana w kolumnie, a nagłówek — jak
   w każdej innej kolumnie — przy lewej krawędzi. Efekt: „STAN ŁĄCZA"
   stało nad pustym miejscem, a plakietki wisiały obok, i wiersz
   wyglądał na rozjechany, choć kolumny miały właściwe szerokości. */
/* KOLUMNA STANU ŁĄCZA JEST WYŚRODKOWANA W CAŁOŚCI — razem z nagłówkiem.
   Trzy podejścia i dopiero to trzecie wygląda jak trzeba. Wyrównanie
   do lewej rozjeżdżało plakietkę z szerszym od niej opisem; blok
   kurczący się do treści siadał wprawdzie pod nagłówkiem, ale nagłówek
   ma inne wcięcie niż komórka, więc oś i tak się nie zgadzała.
   Skoro to kolumna stanu, a nie tekstu — środkujemy oba końce i cała
   kolumna ma jedną oś. */
/* WYŚRODKOWANIE LICZONE OD KOŃCA, NIE OD POCZĄTKU.
   Łukasz, 08.09.2026: „na bieżących plakietki Online są ładnie
   wyśrodkowane, a w zamkniętych uciekają w lewo". Bo reguła wskazywała
   SZÓSTĄ kolumnę — a w zamkniętych doszła kolumna „Zamknięte" i szósta
   przestała być kolumną Radiusa. Liczone od prawej te dwie kolumny
   stoją w tym samym miejscu w obu widokach: Radius przedostatnia,
   kategoria ostatnia. */
.tab-zgloszen th:nth-last-child(2),
.tab-zgloszen td:nth-last-child(2),
.tab-zgloszen th:last-child,
.tab-zgloszen td:last-child{text-align:center}
.tab-zgloszen .stan-lacza{display:flex;align-items:center;text-align:center}

/* Wiersz listy zgłoszeń jest wejściem do zgłoszenia — i ma to po sobie
   pokazywać, zanim ktoś w niego kliknie. */
.wiersz-klik{cursor:pointer}
.wiersz-klik:hover{background:rgba(127,127,127,.07)}
.wiersz-klik:focus-visible{outline:2px solid var(--akcent,#2f6fed);outline-offset:-2px}

/* Pasek abonenta na karcie zgłoszenia: kto po lewej, stan łącza po
   prawej — to są dwie pierwsze rzeczy, których technik szuka. */
.zgl-abonent{display:flex;flex-direction:column;gap:8px;
  padding:10px 12px;margin-bottom:var(--s3);border-radius:var(--radius-sm);
  background:var(--surface,rgba(127,127,127,.06));
  border:1px solid var(--linia,rgba(127,127,127,.25))}
.zgl-abonent-kto{min-width:0}
/* Stan, konto i IP w jednej linii — trzy fakty o tym samym połączeniu. */
.zgl-abonent-stan{display:flex;align-items:center;gap:8px;flex-wrap:wrap}

/* ZGŁOSZENIE JUŻ PRZEKAZANE DO NEXERY — wiersz ma to mówić z odległości
   metra, tak jak w iPocie, z którego korzysta biuro klienta. Delikatny
   pasek przy krawędzi i lekkie tło: to znaczy „ktoś już się tym zajął",
   a nie „alarm". */
.tab-zgloszen tr.wiersz-nexera td:first-child{box-shadow:inset 3px 0 0 var(--bad)}
.tab-zgloszen tr.wiersz-nexera{background:rgba(190,50,45,.055)}
.tab-zgloszen tr.wiersz-nexera:hover{background:rgba(190,50,45,.10)}
/* Kolumna kategorii łamie się normalnie — nazwy bywają długie
   („awaria, zgłoszone do nexera") i nie ma powodu ich uciekać.
   Tekst w plakietce WYŚRODKOWANY, bo cała kolumna jest wyśrodkowana:
   dwie linie wyrównane do lewej wewnątrz wyśrodkowanej plakietki
   wyglądały jak przesunięte. */
.tab-zgloszen td:last-child .pill{white-space:normal;text-align:center}
.notatki-znak{margin-top:4px;cursor:help}

/* =====================================================================
   PASEK KAFLI NAD LISTAMI MODUŁU OPERATORA
   =====================================================================
   Łukasz, 07.09.2026: „ma to wyglądać jak centrum dowodzenia".
   Kafle są RÓWNE i dzielą szerokość — nierówne wyglądają jak lista
   przypadkowych ciekawostek, a nie jak pulpit. Liczba jest duża,
   etykieta mała, a podpis pod nią mówi, skąd ta liczba i co znaczy. */
/* JEDEN RZĄD, CAŁA SZEROKOŚĆ.
   Łukasz, 07.09.2026: „czemu nie w jednej linii?". Bo to była siatka
   `repeat(auto-fit, minmax(150px,1fr))` — na szerokim ekranie robiła
   dziewięć torów po 150 px, cztery kafle zajmowały cztery z nich
   i siedziały ściśnięte przy lewej krawędzi, a reszta rzędu stała
   pusta. `auto-fit` zwija PUSTE tory, ale nie zwija tych, które
   rozpycha kafel `szeroki` przez `grid-column: 1 / -1`.
   Flex nie ma torów: każdy kafel bierze równą część wolnego miejsca,
   ile by ich nie było — cztery na sesjach, pięć na zgłoszeniach. */
.pasek-kafli{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:var(--s4)}
.pasek-kafli > .kafel-liczby{flex:1 1 150px;min-width:0}
/* WSZYSTKIE KAFLE MAJĄ TREŚĆ W PIONOWEJ OSI KAFLA.
   Kafel z pierścieniami jest wyższy od kafla z samą liczbą i to on
   ustala wysokość rzędu — bez wyśrodkowania liczby wisiały u góry,
   a kółka w połowie, i pasek wyglądał na rozjechany. */
.kafel-liczby{display:flex;flex-direction:column;justify-content:center;
  padding:12px 14px;border-radius:var(--radius-sm);text-align:left;
  background:var(--surface,rgba(127,127,127,.06));
  border:1px solid var(--linia,rgba(127,127,127,.25));font:inherit;color:inherit}
.kafel-liczby.klik{cursor:pointer}
.kafel-liczby.klik:hover{border-color:var(--accent);background:rgba(127,127,127,.10)}
.kafel-liczby .kl-n{font-size:var(--fs-2xl,26px);font-weight:700;line-height:1.05;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.kafel-liczby .kl-e{margin-top:3px;font-size:var(--fs-xs);text-transform:uppercase;
  letter-spacing:.07em;font-weight:700;color:var(--ink-3)}
.kafel-liczby .kl-p{margin-top:4px;font-size:var(--fs-xs);color:var(--ink-3);
  line-height:1.35}
.kafel-liczby.ok   .kl-n{color:var(--ok)}
.kafel-liczby.warn .kl-n{color:var(--warn)}
.kafel-liczby.bad  .kl-n{color:var(--bad)}
/* Pierścienie w pasku kafli: ten sam rozmiar co w historii zgłoszeń,
   żeby dwa sąsiadujące ekrany nie miały kółek dwóch wielkości. */
.pasek-kafli .zajetosc-kola{gap:26px;justify-content:center;align-items:flex-start;
  padding:6px 0 2px}
/* 68 px, a nie 56: przy czterech znakach w środku („49%") mniejszy
   pierścień dociskał cyfry do obwodki. */
.pasek-kafli .pierscien{width:68px;flex:0 0 68px;padding-bottom:18px}
.pasek-kafli .pierscien svg{width:68px;height:68px}
.pasek-kafli .pierscien .podpis{font-size:11px}
/* ODCIENIE SERII przy rozkładzie pakietów. Cztery pierścienie w jednym
   kolorze czyta się jak cztery pomiary tej samej rzeczy — a to są
   cztery różne pakiety. Kolory z jednej rodziny (chłodne, o rosnącej
   jasności), żeby nie zaczęły udawać sygnału „dobrze/źle": tu nie ma
   lepszych i gorszych pakietów, jest po prostu rozkład. */
.pasek-kafli .pierscien.seria-0 .luk{stroke:var(--accent)}
.pasek-kafli .pierscien.seria-1 .luk{stroke:#7aa2f7}
.pasek-kafli .pierscien.seria-2 .luk{stroke:#54c7c2}
.pasek-kafli .pierscien.seria-3 .luk{stroke:#a58bf0}
.pasek-kafli .pierscien.seria-4 .luk{stroke:#5bb98c}
.pasek-kafli .pierscien.seria-5 .luk{stroke:#e0a84a}
/* ROZKŁAD PAKIETÓW DOSTAJE WŁASNY WIERSZ, na całą szerokość.
   Łukasz, 07.09.2026: „chyba więcej jest pakietów, brakuje 800, 1000?".
   Miał rację — mieściły się cztery, bo kafel walczył o miejsce
   z liczbami w tym samym rzędzie. Osobny wiersz mieści osiem i przy
   okazji kończy spór o wysokości: liczby są w jednym rzędzie, kółka
   w drugim. */
.pasek-kafli > .kafel-liczby.szeroki{flex:1 0 100%}
.kafel-liczby.szeroki .zajetosc-kola{flex-wrap:wrap;row-gap:14px}

/* Pasek narzędzi nad listą (Odśwież, numer klienta, Otwórz kartę)
   przywierał do kafli pod spodem: `formrow` nie ma własnego marginesu
   dolnego, a kafle miały tylko dolny odstęp od tabeli. Jedna reguła na
   sąsiedztwo, a nie margines dosypany do samego paska — dzięki temu
   nie rozpycha się tam, gdzie po nim nic nie stoi. */
.formrow + .pasek-kafli{margin-top:var(--s4)}

/* Nagłówek sekcji w podmenu — mniejszy i lżejszy niż nagłówek grupy
   głównej („OPERATOR"), żeby hierarchia była widoczna od razu: grupa
   modułów, moduł, sekcja w module. Pierwszy nie dostaje górnego
   odstępu, bo przywierałby do nazwy modułu nad nim. */
.podmenu .podgrp{margin:12px 0 4px 18px;font-size:10px;font-weight:800;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);opacity:.75}
.podmenu .podgrp:first-child{margin-top:6px}


/* Tabelka identyfikatorów w kontroli zgłoszenia iPota — dwie kolumny,
   nazwa pola i wartość. Nie jest to „tabela danych", tylko dowód
   rzeczowy, więc bez nagłówków i bez ozdób. */
.mini-tab{border-collapse:collapse;width:auto}
.mini-tab td{padding:2px 12px 2px 0;vertical-align:top;border:0}
.mini-tab code{font-size:12px}


/* NUMER KLIENTA I LOGIN W NAGŁÓWKU KARTY ZGŁOSZENIA.
   Łukasz, 07.09.2026: „brakuje mi tam jak ciul numeru klienta, loginu".

   To są DWIE RÓŻNE liczby, które łatwo pomylić: numer klienta podaje
   człowiek przez telefon, a login siedzi w Radiusie i przy koncie
   czterocyfrowym ma jedynkę z przodu (5004 → 15004). Gołe cyfry obok
   siebie zachęcałyby do wpisania jednej w miejsce drugiej, więc każda
   dostaje podpis — mały, ale zawsze widoczny. */
.zgl-ident { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 6px; }
.zgl-ident span { display: flex; flex-direction: column; line-height: 1.25; }
.zgl-ident i { font-style: normal; font-size: 10px; text-transform: uppercase;
               letter-spacing: .08em; font-weight: 700; color: var(--ink-3); }
.zgl-ident b { font-size: 15px; font-variant-numeric: tabular-nums;
               letter-spacing: .01em; }

/* =====================================================================
   TELEFON — PORZĄDKI PO TESTACH TERENOWYCH (09.09.2026)
   =====================================================================
   Łukasz, z iPhone 14 Pro Max (430 px):
     „niektóre długie statusy zlecenia wyjeżdżają poza stronę",
     „strona robi się czasami szersza niż ekran i nie mogę jej zmniejszyć,
      żeby się wyśrodkowała",
     „w miejscach niektórych, szczególnie na górze zlecenia, gdzie
      przydziela się serwisanta, trochę się rozjeżdżają przyciski".

   Wszystkie trzy mają wspólną przyczynę i wspólne lekarstwo, więc stoją
   w jednym miejscu, a nie rozsypane po arkuszu.

   PRZYCZYNA. Dziecko siatki albo flexa ma domyślnie `min-width:auto` —
   czyli NIE DA SIĘ go zwęzić poniżej jego treści. Jedno zdanie
   „ostatnio 17 dni temu · umówione co 26 godz." z `white-space:nowrap`
   rozpycha więc całą kolumnę, kolumna rozpycha siatkę, a siatka
   dokument. Zmierzone: ekran kopii zapasowych był o 34 px szerszy od
   telefonu.

   Dlaczego to boli AŻ TAK: przeglądarka na telefonie nie tnie takiego
   dokumentu — ona ODDALA CAŁĄ STRONĘ, żeby się zmieścił. Interfejs
   robi się mniejszy, a winne jest jedno zdanie w rogu. I dokładnie
   dlatego nie da się tego „zmniejszyć, żeby się wyśrodkowało" —
   przeglądarka już to zrobiła.

   LEKARSTWO. Pozwalamy się zwężać (`min-width:0`) i pozwalamy zawijać.
   Nigdzie nie ucinamy treści `overflow:hidden` — technik w terenie ma
   przeczytać adres MAC, a nie dowiedzieć się, że gdzieś jest.
   ===================================================================== */
@media (max-width:760px){
  /* --- 1. Dzieci siatek i pasków mogą się zwężać ------------------- */
  .lista-widget .wrs > *,
  .lista-widget .nagl > *,
  .kafel-fakty > *,
  .pasek-zlecenia .rzad > *{min-width:0}

  /* --- 2. Drugoplanowy tekst zawija się zamiast rozpychać ----------
     `nowrap` przy dacie na monitorze ma sens: „17 dni temu" złamane
     na dwie linie wygląda jak usterka. Na telefonie sensu nie ma —
     bo alternatywą jest rozjechany cały ekran. */
  .muted.nowrap,
  .lista-widget .muted,
  li > .muted.nowrap{white-space:normal}

  /* Długie słowa bez spacji (adresy, nazwy plików, identyfikatory)
     łamiemy dopiero wtedy, gdy naprawdę się nie mieszczą. */
  .lista-widget .wrs > *,
  .kafel-fakty dd,
  .card .bd{overflow-wrap:anywhere}
}

/* =====================================================================
   DŁUGIE STATUSY NA TELEFONIE
   „Oczekuje na decyzję klienta" to 27 znaków. Plakietka miała stałą
   wysokość 26 px i `white-space:nowrap`, czyli ~200 px w jednej linii —
   przy 430 px ekranu to jedna trzecia szerokości na sam status.
   Na telefonie plakietka ma się zawinąć i urosnąć w dół.
   ===================================================================== */
@media (max-width:760px){
  .pill{height:auto;min-height:26px;padding-top:3px;padding-bottom:3px;
        white-space:normal;text-align:center;max-width:100%;
        line-height:1.25}
  /* Stała szerokość kolumny statusu trzymała równą krawędź tabeli na
     monitorze. Na telefonie ta sama liczba jest już tylko balastem. */
  td.kol-status .pill{min-width:0}
}

/* =====================================================================
   PASEK PRACY NA GÓRZE ZLECENIA
   Łukasz: „gdzie przydziela się serwisanta, trochę się rozjeżdżają
   przyciski w różne strony".

   Rozjeżdżał je `margin-left:auto` przy „Zamknij zlecenie" — na
   monitorze odsuwa on zamknięcie od reszty (i słusznie, bo to inna
   waga sprawy), ale po zawinięciu na telefonie zostawiał guzik samotnie
   przy prawej krawędzi, pod nierówno poszarpanym rzędem.

   Na telefonie: działania pierwszoplanowe (zielone i zamknięcie) na
   całą szerokość, drugoplanowe parami. Równa siatka zamiast zawijania
   „jak wyjdzie".
   ===================================================================== */
@media (max-width:640px){
  .pasek-zlecenia .rzad{gap:8px}
  .pasek-zlecenia .etykieta-rzedu{flex:1 1 100%}
  .pasek-zlecenia .btn.zamknij-zlecenie{margin-left:0}
  .pasek-zlecenia .rzad > .btn{flex:1 1 calc(50% - 4px);justify-content:center}
  .pasek-zlecenia .rzad > .btn.zielony,
  .pasek-zlecenia .rzad > .btn.czerwony,
  .pasek-zlecenia .rzad > .btn.zamknij-zlecenie,
  .pasek-zlecenia .rzad > .stan-przydzialu{flex:1 1 100%}
}

/* Zakładki (Magazyn, panel) wystawały o dwa piksele — dość, żeby
   dokument stał się szerszy od ekranu ze wszystkimi tego skutkami. */
@media (max-width:760px){
  .zakladki{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .zakladki::-webkit-scrollbar{height:0}
}

/* Przełącznik pełnego menu na telefonie — stoi pod ostatnią grupą,
   więc musi wyglądać jak część menu, a nie jak zabłąkany przycisk. */
.nav.pelne-menu{width:100%;text-align:left;margin-top:var(--s3);
  border-top:1px solid var(--line);border-radius:0;
  font-size:var(--fs-sm);color:var(--ink-3)}
.nav.pelne-menu:hover{color:var(--ink)}
/* Zakładka oznaczona jako widok na telefon. */
.panel-zakladki .dodaj.on{background:var(--accent-soft);color:var(--accent);
  border-color:var(--accent)}
/* „telefon" przy zakładce panelu — dopisek, nie druga nazwa. */
.panel-zakladki .zakladka-telefon{margin-left:6px;font-size:10px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--accent);
  background:var(--accent-soft);border-radius:var(--radius-pill);padding:2px 7px;
  vertical-align:middle}

/* =====================================================================
   PASEK GÓRNY — 2 PIKSELE, KTÓRE ROZPYCHAŁY CAŁY DOKUMENT
   =====================================================================
   Zmierzone 09.09.2026 na 932 px (iPhone 14 Pro Max trzymany bokiem):
   dokument 934 px przy ekranie 932. Winna była grupa `.top-ja` — miała
   `min-width:auto`, czyli nie dawała się zwęzić, i ostatnia ikona
   wystawała o 2 px.

   Dwa piksele, a skutek jak przy dwustu: przeglądarka na telefonie
   ODDALA CAŁĄ STRONĘ, żeby zmieścić dokument. Łukasz: „strona robi się
   czasami szersza niż ekran i nie mogę jej zmniejszyć, żeby się
   wyśrodkowała". Nie mógł, bo przeglądarka już to zrobiła.

   Zabezpieczenie było, ale dopiero od 640 px w dół — a telefon bokiem
   ma 932. Dlatego teraz obowiązuje ZAWSZE: na szerokim ekranie i tak
   jest miejsce, więc nic się nie zawija, a na wąskim grupa woli zawinąć
   się do drugiego rzędu, niż rozpychać dokument.
   ===================================================================== */
.top-prawo{flex-wrap:wrap}
.top-ja{min-width:0;flex-wrap:wrap}
.top-ja > *{min-width:0}

/* Sam `min-width:0` nie wystarczył, bo rozpychała się SIATKA paska,
   a nie grupa w niej: `grid-template-columns: 1fr auto 1fr` ze środkową
   kolumną `auto` (zegar) zostawiał bocznym kolumnom mniej, niż wynosiła
   ich zawartość, i cała siatka wychodziła poza ekran.

   Poniżej 1100 px zegar nie jest wart własnej kolumny. Pasek staje się
   zwykłym rzędem, który się zawija — a wtedy nie ma czego rozepchnąć. */
@media (max-width:1100px){
  .topbar{display:flex;flex-wrap:wrap;align-items:center;row-gap:var(--s2)}
  .top-lewo{flex:1 1 260px}
  .top-srodek{flex:0 0 auto}
  .top-prawo{flex:1 1 auto;justify-content:flex-end}
  .top-prawo > *{min-width:0}
}

/* =====================================================================
   PEŁNE MENU NA TELEFONIE
   =====================================================================
   Łukasz, 09.09.2026: „a gdzie na mobilce w ogóle jest menu ze
   wszystkimi pozycjami?".

   Nigdzie — i to był błąd. Menu na telefonie jest poziomym paskiem,
   a przełącznik do reszty ekranów wylądował na jego KOŃCU, czyli poza
   ekranem, za pięcioma przesunięciami palca. Teraz „Menu" stoi na
   początku paska, przyklejone do lewej krawędzi, i nie odjeżdża przy
   przewijaniu — a otwiera pełną listę w pionie.
   ===================================================================== */
.nav.menu-telefon{position:sticky;left:0;z-index:2;flex:0 0 auto;
  font-weight:650;background:var(--surface);border:1px solid var(--line);
  box-shadow:6px 0 8px -6px rgba(16,24,40,.25)}

.menu-arkusz{position:fixed;inset:0 0 0 0;background:var(--surface);
  display:flex;flex-direction:column;overscroll-behavior:contain}
.menu-arkusz-hd{display:flex;align-items:center;gap:12px;
  padding:14px var(--s4);border-bottom:1px solid var(--line);flex:none}
.menu-arkusz-hd .zamknij{margin-left:auto}
.menu-arkusz-tresc{flex:1 1 auto;overflow-y:auto;padding:var(--s3) var(--s3) var(--s6)}
.menu-arkusz-grupa{margin-bottom:var(--s4)}
/* Nagłówki grup w pasku są schowane (`display:none !important`), więc
   tutaj trzeba je z powrotem pokazać — i to samo dotyczy szerokości
   pozycji, którą pasek zeruje na potrzeby układu poziomego. */
.menu-arkusz .grp{display:block !important;font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.07em;color:var(--ink-3);
  padding:6px 12px 4px}
/* Lista, nie stos kafelków. Osiemnaście wypełnionych prostokątów jeden
   pod drugim czyta się jak ściana — pozycje mają się różnić tekstem,
   a nie każda krzyczeć własnym tłem. Wyróżniona zostaje ta, na której
   człowiek właśnie jest. */
.menu-arkusz .nav{display:flex;align-items:center;gap:9px;
  width:100%;text-align:left;white-space:normal;
  min-height:44px;padding:11px 12px;background:transparent;border-radius:0;
  border:0;border-bottom:1px solid var(--line-soft);
  color:var(--ink);font:inherit;font-weight:520;cursor:pointer}
.menu-arkusz .nav:last-child{border-bottom:0}
.menu-arkusz .nav.on{background:var(--accent-soft);color:var(--accent);
  font-weight:650;border-radius:var(--radius)}
.menu-arkusz .podmenu{padding-left:10px;margin:2px 0 6px;
  border-left:2px solid var(--line)}
.menu-arkusz .podgrp{font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.07em;color:var(--ink-3);padding:8px 12px 2px}

/* =====================================================================
   LISTA ABONENTÓW
   =====================================================================
   Kolumny mają stałe szerokości (colgroup w komponencie), więc tabela
   nie rozpycha się nazwiskiem firmy ani nie wypycha MAC-a poza ekran.
   Reszta to czytelność: nazwisko wyżej od reszty, adres i miejscowość
   jedno pod drugim, liczby jednakowej szerokości.
   ===================================================================== */
.tab-abonentow{table-layout:fixed;width:100%}
.tab-abonentow th,
.tab-abonentow td{vertical-align:top;padding:12px 10px;font-size:15px;line-height:1.35}
.tab-abonentow td:first-child strong{font-size:15px}
.tab-abonentow .mini{font-size:13px}
/* IP i MAC: cyfry tej samej szerokości i mniejszy stopień — to są dane
   do przepisania, nie do czytania zdaniami. */
.tab-abonentow td.mono{font-size:13px;font-variant-numeric:tabular-nums;
  overflow-wrap:anywhere}
/* Plakietka stanu bywa długa („Bez klienta w iPocie") — ma się zawinąć
   w swojej kolumnie, a nie wyjść poza obramowanie. */
.tab-abonentow .pill{height:auto;white-space:normal;text-align:center;
  padding-top:3px;padding-bottom:3px;line-height:1.25}
/* Cały wiersz prowadzi do karty, więc ma wyglądać na klikalny. */
.tab-abonentow tbody tr{cursor:pointer}

@media (max-width:900px){
  /* Na telefonie tabela o dziewięciu kolumnach nie ma sensu — zostaje
     to, po czym się rozpoznaje człowieka i czy ma internet. Reszta
     jest na karcie, o jedno dotknięcie dalej. */
  .tab-abonentow{table-layout:auto}
  .tab-abonentow colgroup{display:none}
  .tab-abonentow th:nth-child(n+4),
  .tab-abonentow td:nth-child(n+4){display:none}
}
/* Nagłówki tej tabeli zawijają się jak wszystkie inne — „OSTATNI
   KONTAKT" w jednej linii wchodziłby na sąsiednią kolumnę. */
.tab-abonentow th{white-space:normal}
/* Pierścienie zajętości w wąskiej kolumnie stoją ciasno obok siebie. */
.tab-abonentow .zajetosc-kola{gap:6px}
/* Trzy kolumny nie potrzebują 720 px. Globalne `.tblwrap table{min-width:720px}`
   trzyma szerokie tabele w ryzach, ale ta na telefonie ma już tylko
   abonenta, lokalizację i stan — i ma się mieścić bez przewijania w bok. */
@media (max-width:900px){
  .tblwrap .tab-abonentow{min-width:0}
}

/* =====================================================================
   OTWARCIE MENU NA TELEFONIE
   ===================================================================== */
.otworz-menu{flex:none;width:40px;height:40px;display:grid;place-items:center;padding:0}
.otworz-menu .kreski{display:grid;gap:4px;width:18px}
.otworz-menu .kreski i{display:block;height:2px;border-radius:2px;background:currentColor}

/* Przełącznik pełnego menu — ostatnia pozycja w szufladzie, oddzielona
   kreską, żeby czytało się jak „i jeszcze to", a nie jak kolejny ekran. */
.side button.nav.pelne-menu{width:100%;text-align:left;margin-top:var(--s3);padding:12px 12px;
  border:0;border-left:0;border-top:1px solid var(--line);border-radius:0;background:none;
  font:inherit;font-size:var(--fs-sm);color:var(--ink-3);cursor:pointer;min-height:44px}
.nav.pelne-menu:hover{color:var(--ink)}

@media (max-width:900px){
  /* Nagłówki grup i stopka wracają — w pionie jest na nie miejsce, a to
     one dzielą kilkanaście pozycji na cztery zrozumiałe kawałki. */
  .side .grp{display:block}
  .side .sidefoot{display:block}
  .side .brandtext{display:block}
  .brandbar{padding:4px 6px var(--s4)}
  /* Treść zajmuje całą szerokość — szuflada jej nie zwęża, bo leży NAD
     nią, a nie obok. */
  .shell{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  .side{transition:none}
}

/* =====================================================================
   GÓRNY PASEK NA TELEFONIE — JEDEN RZĄD ZAMIAST TRZECH
   =====================================================================
   Zmierzone 09.09.2026 na 430 px: pasek zajmował trzy rzędy i mieścił
   dziewięć celów po 32 px, stykających się krawędziami. 32 px to
   poniżej progu, w który trafia kciuk (44 px), a dwa takie cele bez
   odstępu to dla palca JEDEN cel — czyli loteria między „zmień motyw"
   a „wyloguj".

   Ikony schodzą pod awatar (patrz `MenuUzytkownika`). Zostaje to,
   czego technik używa naprawdę: menu, nazwa ekranu, czat i „ja".
   ===================================================================== */
@media (max-width:900px){
  .tylko-szeroko{display:none !important}
  /* Cele wielkości kciuka i z odstępem — dotyczy też ikon, które
     zostają (czat, awatar). */
  .topbar .ikona{width:44px;height:44px}
  .topbar .ikony{gap:6px}
  .top-prawo{gap:10px}
  /* Awatar jest przyciskiem: ma wyglądać na klikalny i mieć zapas na
     palec, ale nie udawać przycisku z ramką. */
  .top-ja.klikalne{cursor:pointer;padding:4px 6px;border-radius:var(--radius);
    min-height:44px}
  .top-ja.klikalne:active{background:var(--surface-2)}
  .top-ja.klikalne:focus-visible{outline:none;box-shadow:var(--focus)}
}

/* =====================================================================
   MENU POD AWATAREM
   ===================================================================== */
.menu-ja{position:fixed;left:0;right:0;bottom:0;background:var(--surface);
  border-top-left-radius:16px;border-top-right-radius:16px;
  box-shadow:0 -8px 32px rgba(16,24,40,.22);
  padding:var(--s3) var(--s3) var(--s5);
  max-height:82vh;overflow-y:auto;overscroll-behavior:contain}
.menu-ja-hd{display:flex;align-items:center;gap:12px;
  padding:8px 12px var(--s3);border-bottom:1px solid var(--line);margin-bottom:6px}
.menu-ja-poz{display:flex;flex-direction:column;align-items:flex-start;gap:2px;
  width:100%;min-height:48px;padding:12px;border:0;border-radius:var(--radius);
  background:none;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.menu-ja-poz:active{background:var(--surface-2)}
.menu-ja-poz.groznie{color:var(--bad);font-weight:600}
.menu-ja-kreska{height:1px;background:var(--line);margin:6px 12px}

/* =====================================================================
   ZAKŁADKI — ODSTĘP MIĘDZY CELAMI NA TELEFONIE
   =====================================================================
   Zmierzone na siedmiu ekranach (Sesje, Routery, Magazyn, Monitoring,
   Do zrobienia i innych): sąsiednie zakładki stykały się krawędziami.
   Dwa cele bez odstępu to dla palca jeden cel — a tu koszt pomyłki
   to przeskoczenie na inną listę w połowie roboty.
   ===================================================================== */
@media (max-width:900px){
  .zakladki{gap:10px;overflow-x:auto;flex-wrap:nowrap}
  .zakladki button{min-height:44px;white-space:nowrap;padding:var(--s2) var(--s3)}
  /* Przyciski akcji obok siebie w wierszu listy — ta sama zasada. */
  .pasek-akcji, .formrow, .wiersz-akcje{gap:10px}
}

@media (max-width:900px){
  /* JEDEN RZĄD. Zawijanie zostawiało 117 px paska na 900 px ekranu —
     czyli jedną ósmą wysokości na rzeczy, które mieszczą się w linii.
     Nazwa ekranu oddaje miejsce jako pierwsza: jest podpisem tego, co
     widać pod spodem, a nie treścią. */
  .topbar{flex-wrap:nowrap;padding:10px var(--s4);gap:10px}
  .top-lewo{flex:1 1 auto;min-width:0;gap:10px}
  .top-tytul{min-width:0}
  .top-tytul h1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .top-prawo{flex:0 0 auto}
  /* Plakietka czatu też jest celem dla kciuka. */
  .topbar .czatnik{min-height:44px}
}

/* =====================================================================
   CELE DO DOTKNIĘCIA W TREŚCI — RESZTA AUDYTU (09.09.2026)
   =====================================================================
   Po naprawie górnego paska zostały trzy rodzaje celów za małych dla
   kciuka. Każdy wymaga innego lekarstwa, bo to trzy różne rzeczy.
   ===================================================================== */
@media (max-width:900px){

  /* 1. ODNOŚNIKI W TREŚCI (nazwa firmy w wierszu, numer konta, „wskaż
        stanowisko →"). Mają ~22 px wysokości, bo to TEKST, a nie
        przycisk — i tekstem mają zostać, inaczej rozepchną każdą tabelę
        w programie.

        Powiększamy sam OBSZAR DOTYKU: `padding` w pionie daje palcowi
        zapas, ujemny `margin` odbiera go z powrotem układowi. Wiersz
        wygląda tak samo, a trafia się w niego dwa razy łatwiej. */
  .jak-link, .klikalny{padding-top:10px;padding-bottom:10px;
    margin-top:-10px;margin-bottom:-10px}

  /* 2. PRZYCISKI AKCJI W WIERSZU TABELI („biorę", „→ zlecenie",
        „nie robimy"). Stały krawędź w krawędź, oddzielone samą spacją
        z kodu — dla palca to jeden cel z trzema wynikami, a jeden z nich
        odrzuca zgłoszenie. Rozdzielamy je i dajemy im wysokość. */
  td .btn.sm{margin:3px 6px 3px 0;min-height:40px}

  /* 3. MENU SEKCJI W USTAWIENIACH — 39 px, czyli tuż pod progiem.
        Pięć pikseli, ale to jest lista, po której się nawiguje. */
  .ust-poz{min-height:44px;display:flex;align-items:center}
}

@media (max-width:900px){
  /* 4. PTASZKI. Przeglądarka rysuje `input[type=checkbox]` w 13 px —
        to jest rozmiar dla myszy, nie dla palca. Zaznaczanie wierszy na
        liście stanowisk było na telefonie loterią.
        `accent-color` trzyma je w kolorze firmy mimo powiększenia. */
  input[type=checkbox], input[type=radio]{width:26px;height:26px;
    accent-color:var(--accent)}
  /* Etykieta z ptaszkiem to jeden cel razem z napisem — palec ma trafiać
     w słowo, nie w kwadracik. */
  .ptaszek-linia{min-height:44px;display:inline-flex;align-items:center;gap:10px}
  /* Ptaszek w nagłówku tabeli („zaznacz wszystkie") stoi sam, więc musi
     mieć własny zapas. */
  /* Ptaszek w tabeli stoi sam, bez napisu do trafienia — margines
     robi mu wolne pole dookoła, żeby sąsiedni wiersz nie łapał
     dotknięcia przeznaczonego dla tego. */
  th input[type=checkbox], td input[type=checkbox]{margin:9px}

  /* 5. PLAKIETKI-FILTRY z krzyżykiem („z ustaleniami ✕"). Klikalne, więc
        obowiązuje je ta sama zasada co przyciski — tyle że jako chipy
        mogą być trochę niższe niż pełny przycisk. */
  .pill[title*="filtr"], button.pill{min-height:40px;padding-left:14px;padding-right:14px}

  /* Odnośnik w komórce tabeli miał 39 px — pięć poniżej progu. */
  td .jak-link{padding-top:12px;padding-bottom:12px;margin-top:-12px;margin-bottom:-12px}
}

/* =====================================================================
   KARTA ABONENTA — TABELE, KTÓRE NIE UCIEKAJĄ W BOK
   ---------------------------------------------------------------------
   Łukasz, 10.09.2026: „w karcie abonenta rozjeżdża się sesja w
   Radiusie, ucieka w bok mocno".

   Miał rację i przyczyna była prosta: kafel „Sesje w Radiusie" stoi
   w lewej kolumnie karty (ok. 400 px), a tabela ma w środku cztery
   kolumny, z czego dwie to identyfikatory monospace (konto, IP), a
   jedna to data z godziną. `table` domyślnie NIE zwęża się poniżej
   swojej zawartości — rozpycha rodzica i wystaje poza zaokrąglony
   brzeg kafla.

   Dwie rzeczy naraz:
   1. `.kafel-tabela` — kontener z własnym poziomym suwakiem. Nawet
      przy najgorszych danych tabela przewinie się W SOBIE, zamiast
      rozpychać kartę. To jest bezpiecznik, nie rozwiązanie.
   2. Rozwiązaniem jest to, że tabela wolno się zwęża: `table-layout`
      zostaje automatyczny, ale identyfikatory dostają `min-width:0`
      i mogą się złamać, a data ma `nowrap`, bo złamana data czyta się
      fatalnie („2026-09-" / „09").
   ===================================================================== */
.kafel-tabela{overflow-x:auto;-webkit-overflow-scrolling:touch;
  margin:0 calc(var(--s1) * -1);padding:0 var(--s1)}
.kafel-tabela > table{width:100%;min-width:0}
.kafel-tabela th,.kafel-tabela td{padding-left:6px;padding-right:6px}
.kafel-tabela th:first-child,.kafel-tabela td:first-child{padding-left:0}
.kafel-tabela th:last-child,.kafel-tabela td:last-child{padding-right:0}
/* Data zawsze w jednej linii — złamana data jest nieczytelna. */
.kafel-tabela td.nowrap,.kafel-tabela th.nowrap{white-space:nowrap}
/* Identyfikatory wolno łamać, byle nie rozpychały kolumny. */
.kafel-tabela td.mono{word-break:break-all;min-width:0}

/* ---------------------------------------------------------------------
   OPIS USTERKI: JEDNA LINIA, RESZTA PO KLIKNIĘCIU
   ---------------------------------------------------------------------
   Łukasz, 10.09.2026: „skróć opis usterki maksymalnie i zrób tak, żeby
   można było na niego kliknąć i wtedy pojawi się w okienku. Bo teraz
   ten opis usterki niepotrzebnie nam wiersz niesamowicie ciągnie w dół".

   Opisy z iPota bywają na trzy zdania. W tabeli o czterech kolumnach
   taki opis zawijał się na pięć linii i JEDEN wiersz zjadał tyle
   miejsca, co całe pozostałe cztery. Karta ma być do pracy, więc opis
   dostaje dokładnie jedną linię z wielokropkiem, a pełna treść otwiera
   się w okienku — tam, gdzie jest na nią miejsce.

   `max-width:1px` z `width:100%` to nie pomyłka: w tabeli o
   automatycznym układzie to jedyny sposób, żeby komórka NIE liczyła
   swojej szerokości z treści. Bez tego `text-overflow` nigdy nie
   zadziała, bo komórka zawsze będzie dość szeroka.
   --------------------------------------------------------------------- */
td.usterka{max-width:1px;width:100%}
button.skrot{display:block;width:100%;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  text-align:left;padding:10px 0;margin:-10px 0}

/* Hasło PPPoE na karcie abonenta: wartość i dwa linki obok siebie,
   z zawijaniem — na telefonie „kopiuj/ukryj" schodzą pod hasło
   zamiast rozpychać kolumnę. */
.haslo-pppoe{display:inline-flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.haslo-pppoe .jak-link{font-size:var(--fs-sm)}
