/* 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);font-weight:var(--font-waga,400);
     -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);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. */
/* 20.09.2026: 256 px — znak ANANAS24 z plakietką „Serwis” się nie mieścił. */
.shell{display:grid;grid-template-columns:256px 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-text);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-text)}

/* 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-text)}
.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}

/* TEKST NA ŚRODKU PRZYCISKU, NIE PRZY GÓRNEJ KRAWĘDZI.
   Łukasz, 10.09.2026: „tekst w środku jest przytulony do górnej
   krawędzi”. Zmierzone na jego zrzucie: przycisk 34 px, napis od 83 do
   95 — siedem pikseli nad tekstem, czternaście pod. Siedem pikseli
   różnicy na trzydziestu czterech widać gołym okiem.
   Przyczyna: przycisk miał ustaloną WYSOKOŚĆ i odstępy tylko po bokach,
   a nic nie mówiło, gdzie w tej wysokości ma stanąć linia tekstu.
   Domyślnie ląduje u góry. Dotyczyło to każdego przycisku w programie —
   po prostu najbardziej widać to na wypełnionym kolorem, bo tam
   krawędzie są wyraźne.
   `inline-flex` z wyśrodkowaniem w obu osiach ustawia tekst na środku
   niezależnie od wysokości, kroju pisma i tego, czy przycisk jest
   znacznikiem <button>, odnośnikiem <a>, czy etykietą <label> (te
   ostatnie nie centrują treści same z siebie). */
.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;
     display:inline-flex;align-items:center;justify-content:center;gap:6px;
     line-height:1.2;text-align:center}
.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-text)}

/* [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-xs);text-transform:uppercase;
         letter-spacing:.06em;color:var(--ink-2);font-weight:750;padding:12px 13px;
         background:var(--naglowek);
         border-bottom:1px solid var(--line);cursor:pointer;user-select:none;
         /* NAGŁÓWEK MOŻE SIĘ ZAWINĄĆ (19.09.2026). Przy `nowrap` długi
            nagłówek („Ostatnie zgłoszenie") ustalał szerokość kolumny,
            w której stoi krótka data — i tabela wyjeżdżała poza ekran.
            Tabela zawija go tylko wtedy, gdy brakuje miejsca; wyrównanie
            `balance` dzieli go na dwie równe linie, a nie „słowo + reszta". */
         white-space:normal;text-wrap:balance;vertical-align:bottom}
tbody td{padding:var(--pad-cell);border-bottom:1px solid var(--wiersz-linia);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. */
/* 20.09.2026 — BEZ ZEBRY. Łukasz pokazał makietę z samymi poziomymi
   liniami i wyższymi wierszami: „wygląda dużo przejrzyściej niż nasza".
   Zebra zabierała też jedyny kanał, którym wiersz może powiedzieć
   „zajmij się mną" — tło (patrz WIERSZE, KTÓRE CZEKAJĄ NA RUCH niżej). */
tbody tr:hover{background:var(--wiersz-hover)}
.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:260px}

/* 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)}
/* =====================================================================
   STOPKA LISTY (STRONICOWANIE) — TA SAMA NA KAŻDYM EKRANIE
   =====================================================================
   Łukasz, 10.09.2026: „poprawić dół listy, bo widzisz, że się
   rozjechało — sprawdź to wszędzie, gdzie są listy i strony".
   Rząd nie miał `flex-wrap`, więc przy zwężaniu nic się nie przenosiło
   do następnej linii — wszystko ściskało się w miejscu. Napis
   „1–25 z 891" schodził do czterech linii po jednym słowie, a strzałka
   odrywała się od słowa „następna". Wyglądało to na awarię i nią było.
   Ta stopka jest wspólna dla WSZYSTKICH list w programie, więc jedna
   poprawka tutaj naprawia każdy ekran naraz. */
.pager{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
       padding:var(--s3) var(--pad-card);
       border-top:1px solid var(--line-soft);color:var(--ink-3);font-size:var(--fs-sm)}
.pager .btn{white-space:nowrap}
.pager > span{white-space:nowrap}

/* Na wąskim ekranie zamiast rzędu — trzy równe piętra: ile z ilu,
   dwa przyciski po połowie, wybór liczby wierszy. Wszystko na środku,
   bo stopka nie ma treści, która wyznaczałaby lewą krawędź. */
@media (max-width:640px){
  .pager{display:grid;grid-template-columns:1fr 1fr;gap:8px 10px;
    justify-items:stretch;text-align:center}
  .pager > span{order:1;grid-column:1 / -1;text-align:center}
  .pager .btn{order:2;width:100%;min-width:0}
  .pager .na-stronie{order:3;grid-column:1 / -1;margin-left:0;
    justify-content:center}
}
.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)}

/* --- okienko z tabelą -------------------------------------------------
   Łukasz, 17.09.2026: „rozszerz to okno, bo się nie mieści wszystko" —
   w historii sesji ucinało ostatnią kolumnę, czyli POWÓD ROZŁĄCZENIA,
   po który to okno się otwiera.

   Sześć kolumn z datami i liczbami nie zmieści się na 760 px; `szerokie`
   jest dobre do formularza, nie do tabeli. Dlatego osobna szerokość, a nie
   podbicie tamtej: formularze mają zostać wąskie, bo tak się je czyta.
   Poziomy pasek przewijania zostaje jako zapas na małym ekranie — lepszy
   niż kolumna schowana poza krawędzią, o której nikt nie wie. */
.okienko.tabelka{width:min(1180px,96vw)}
.okienko.tabelka .tblwrap{overflow-x:auto}
.okienko.tabelka table{width:100%}
.okienko.tabelka th,.okienko.tabelka td{white-space:nowrap}
/* Jedyna kolumna, której wolno się łamać — zdanie o powodzie bywa
   dłuższe niż reszta wiersza razem wzięta. */
.okienko.tabelka td.zawijaj{white-space:normal;min-width:14ch}

/* Dwa przyciski w kolumnie akcji jeden pod drugim, o wspólnej krawędzi.
   Obok siebie nie zmieszczą się przy wąskim oknie, a rozjechane w pionie
   wyglądają jak dwa przypadki, nie jak para. */
/* KOLUMNY SŁUCHAJĄ `colgroup`, A NIE ZAWARTOŚCI.
   Bez `fixed` przeglądarka i tak przelicza szerokości od tego, co
   w komórkach — i ten sam ekran przy innym zestawie wierszy układa się
   inaczej. Z `fixed` odstępy są takie, jakie zapisaliśmy. Długi napis
   ma się wtedy złamać albo uciąć, a nie rozpychać tabelę. */
.tab-sesje{table-layout:fixed}
/* KOLUMNA MA STAŁĄ SZEROKOŚĆ, WIĘC TREŚĆ MUSI SIĘ W NIEJ ZMIEŚCIĆ.
   Ogólna reguła tabel trzyma komórki w jednej linii (`nowrap`) — to jest
   dobre, gdy kolumna rozszerza się do treści. Tu jest odwrotnie: przy
   `table-layout:fixed` szerokość jest z góry, więc nagłówek „Sesje /
   limit" i adres MAC po prostu WYCHODZIŁY poza swoją kolumnę i wchodziły
   na sąsiednią — stąd „SESJE / LIMITOD KIEDY" i MAC pod przyciskami.
   Zawijanie jest jedynym wyjściem, które niczego nie ukrywa. */
.tab-sesje thead th{white-space:normal;overflow-wrap:break-word;hyphens:none}
.tab-sesje td{white-space:normal;overflow-wrap:anywhere}
/* `td.mono{white-space:nowrap}` z reguły ogólnej jest tu szkodliwe:
   przy stałej szerokości kolumny adres nie ma dokąd się rozepchnąć,
   więc zamiast się złamać, wchodził na sąsiada. */
.tab-sesje td.mono{white-space:normal}
/* KOMÓRKA TABELI NIE MOŻE BYĆ `display:flex`.
   Łukasz, 18.09.2026: „w sesjach abonentów rozjechały się style przy
   guzikach". Stało tu `display:flex` na `<td>` — a to WYPISUJE KOMÓRKĘ
   Z TABELI: przeglądarka przestaje ją liczyć do siatki kolumn, więc
   `table-layout:fixed` i `colgroup` przestają jej dotyczyć, przyciski
   wychodzą poza krawędź, a sąsiednie kolumny dostają jej szerokość.
   Wyglądało to jak błąd w przyciskach, a było błędem w komórce.
   Dwa przyciski jeden pod drugim robimy więc blokami z marginesem —
   `gap` i tak nie ma tu czego rozstawiać. */
.tab-sesje .kol-akcja{white-space:nowrap}
.tab-sesje .kol-akcja .btn{display:flex;width:100%;justify-content:center}
/* `td > .btn + .btn{margin-left:12px}` (niżej w pliku) rozstawia akcje
   stojące OBOK siebie w komórce. Tutaj stoją jedna POD drugą, więc ten
   margines tylko przesuwał dolny przycisk o 12 px w prawo — to właśnie
   ten uskok widać było na zrzucie. Zerujemy go wprost. */
.tab-sesje .kol-akcja .btn + .btn{margin-left:0;margin-top:6px}

.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}
/* TABELA STATUSÓW ROŚNIE O KOLUMNĘ CO KILKA MIESIĘCY.
   Każdy nowy ptaszek („powiadamia klienta", „po zgodzie na wycenę",
   „gotowe do odbioru") zabiera szerokość pierwszej kolumnie, aż nazwa
   statusu zwęża się do „Przyję". Pole, w którym nie widać, co się
   wpisuje, jest gorsze niż tabela, którą trzeba przewinąć — więc nazwa
   dostaje swoje minimum, a tabela przewija się w bok. */
.grupa-stawek .tblwrap table{min-width:1040px}
.grupa-stawek .tblwrap th:first-child,
.grupa-stawek .tblwrap td:first-child{min-width:180px}
.grupa-stawek .tblwrap td:first-child .input{width:100%}
/* Kolumna koloru miała ten sam problem: wybierak pokazywał „nie" zamiast
   „niebieski". Wybór koloru, w którym nie widać nazwy koloru, wymaga
   zgadywania po pierwszych trzech literach. */
.grupa-stawek .tblwrap th:nth-child(2),
.grupa-stawek .tblwrap td:nth-child(2){min-width:130px}
.grupa-stawek .tblwrap td:nth-child(2) .input{width:100%}

/* 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)}
/* Belka „coś jest w drodze": ani błąd, ani potwierdzenie — stan
   przejściowy, o którym ktoś ma pamiętać. Stąd kolor ostrzeżenia
   i normalny kolor tekstu, żeby dało się czytać treść, a nie tylko
   zauważyć pasek. */
.note.ostrzega{border-left-color:var(--warn);background:var(--warn-bg)}
.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)}
/* PDF w powiększeniu: ramka z czytnikiem przeglądarki. Musi dostać
   konkretny rozmiar - <iframe> bez wysokości zwija się do 150 px
   i wygląda dokładnie jak „nic się nie wyświetla". */
.lightbox-pdf{width:min(1000px,94vw);align-self:stretch;justify-self:center;
  min-height:320px;border:0;border-radius:var(--radius);background:#fff;cursor:default}
.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%}
}

/* =====================================================================
   DZIAŁANIA W KOMÓRCE TABELI — TEŻ POTRZEBUJĄ ODDECHU
   =====================================================================
   Łukasz, 14.09.2026: „popraw usuń obok siebie bardzo - proszę popraw
   to". Dwa odnośniki stały w jednej komórce bez żadnego odstępu, więc
   czytało się to jako jedno słowo „poprawusuń" — i łatwo było trafić
   w „usuń", celując w „popraw".
   Reguła jest ogólna, a nie dla jednej tabeli: dwa działania obok
   siebie w komórce nigdy nie mają prawa się stykać, niezależnie od
   tego, w którym ekranie ktoś je kiedyś postawi. Odstęp taki sam jak
   w `.formrow`, żeby program wyglądał wszędzie tak samo. */
td > .jak-link + .jak-link,
td > .jak-link + .btn,
td > .btn + .jak-link,
td > .btn + .btn{margin-left:12px}
/* Komórka z działaniami nie zawija ich do drugiej linii - „popraw"
   i „usuń" mają stać w jednym rzędzie albo nie stać wcale. */
.akcje-wiersza{white-space:nowrap;text-align:right}

/* 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-text);
  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)}
/* „12. raz" przy powiadomieniu, które wraca. Ma być widoczne, ale nie
   krzyczeć głośniej niż plakietka wagi obok — to dopowiedzenie, nie
   drugi alarm. */
.powiad-licznik{flex:0 0 auto;padding:1px 6px;border-radius:9px;
  border:1px solid var(--line);color:var(--ink-2);
  font-size:var(--fs-xs);font-weight:600;white-space:nowrap}

.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}
/* Ptaszek z podpisem w wierszu z przyciskiem (23.09.2026, zgłoszenie
   Kuby): po odhaczeniu „Płatne" podpis zmieniał się na dłuższy, wiersz
   ma `nowrap`, więc tekst wypychał „Dopisz" poza ekran telefonu. Ptaszek
   może się zwężać, a jego podpis — zawijać; przycisk zostaje na miejscu. */
.formrow label.ptaszek{white-space:normal}
.pola.ciasne .pole .formrow .ptaszek{flex:1 1 auto;min-width:0;white-space:normal}
.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}
.pola.ciasne .input.w-jednostka{width:96px}
.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-text)}

/* =====================================================================
   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}
/* =====================================================================
   NAGŁÓWEK KARTY NA WĄSKIM EKRANIE — NA ŚRODKU
   =====================================================================
   Łukasz, 10.09.2026: „wyśrodkować całość”.
   Na monitorze ten nagłówek jest rzędem: numer po lewej, plakietki
   obok, „zamknij” dosunięte do prawej krawędzi — i tak ma zostać, bo
   krawędzie są wtedy dwie i obie coś znaczą. Na wąskim ekranie rząd
   zawija się na trzy–cztery linie, każda innej długości, a „zamknij”
   traci prawą krawędź, do której było dosunięte. Zostaje poszarpana
   lewa kolumna. Wtedy środek jest jedyną osią, którą wszystkie linie
   mogą dzielić.
   Podtytuł (firma · lokalizacja · stanowisko) idzie za nagłówkiem,
   inaczej byłby jedyną linią przy lewej krawędzi. */
@media (max-width:640px){
  .kartahd{justify-content:center;text-align:center}
  .kartahd .zamknij{margin-left:0}
  .karta-podtytul{justify-content:center;text-align:center}
}

/* 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}

/* DWA PRZYCISKI, KTÓRE MAJĄ CZYTAĆ SIĘ JAKO PARA.
   Równe kolumny, więc oba dostają szerokość szerszego napisu i mają
   wspólną lewą oraz prawą krawędź. Na wąskim ekranie schodzą jeden pod
   drugi — nadal równe. */
.para-przyciskow{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:10px;flex:0 0 auto}
.para-przyciskow > .btn{width:100%;display:inline-flex;align-items:center;
  justify-content:center;text-align:center}
@media (max-width:520px){
  /* `flex:1 1 100%` zamiast `width:100%` — szerokość liczona od
     zawartości rzędu, a nie od jego pełnej szerokości razem
     z odstępami; inaczej para wystaje poza ekran o wielkość przerwy
     i cała strona przewija się w bok. */
  .para-przyciskow{grid-auto-flow:row;flex:1 1 100%;min-width:0}
}

@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}
  /* Karta ma szerokość ekranu — `min-width:720px` z widoku tabeli
     wypychał ją poza prawą krawędź i obcinał opis (20.09.2026). */
  .tblwrap table.karty{min-width:0}
  .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}
  /* JEDNA KRAWĘDŹ NA CAŁEJ KARCIE.
     Reguły niżej pochodziły z czasów, gdy kolumny stały w innej
     kolejności: „Wpłynęło" dostawało odstęp z lewej, bo doklejało się
     do „Technika" w tej samej linii. Po przestawieniu kolumn
     (02.09.2026: status, wpłynęło, numer, firma…) ten odstęp został,
     ale doklejać się już nie było do czego — więc jedna linia karty
     zaczynała się dziesięć pikseli dalej niż wszystkie pozostałe.
     Widać to od razu i wygląda na przypadek, bo nim było.

     Zamiast łatać odstęp, układamy kartę jawnie: wiersz staje się
     kolumną bloków o wspólnej krawędzi, a stan i data dzielą pierwszą
     linię — jak nagłówek. Reszta idzie pod spodem, jedno pod drugim. */
  .tblwrap table.karty tr{display:flex;flex-wrap:wrap;align-items:baseline;
    gap:0 8px}
  /* `min-width:0` jest tu konieczne: bez niego pole nie zwęża się
     poniżej swojej treści (domyślne `min-width:auto` w układzie flex),
     a data ma `nowrap` — przez co wychodziła na 492 px w karcie
     szerokiej na 400 i po prostu znikała za krawędzią. */
  .tblwrap table.karty td{flex:1 1 100%;min-width:0}
  /* Na karcie pole ma całą szerokość — limit kolumny z tabeli (260 px)
     pozwalał opisowi wskoczyć obok nazwy firmy. */
  .tblwrap table.karty td.clip{max-width:none}
  .tblwrap table.karty td[data-label="Technik"]{font-size:var(--fs-sm)}
  .tblwrap table.karty td[data-label="Status"]{flex:0 0 auto;margin:0 0 4px}
  /* Data trzyma swoją szerokość i idzie do prawej krawędzi. Gdy razem
     ze stanem nie mieści się w jednej linii, schodzi do następnej —
     nadal przy prawej krawędzi, więc karta ma dwie równe kolumny,
     a nie jedną rozjechaną. */
  .tblwrap table.karty td[data-label="Wpłynęło"]{flex:0 0 auto;margin:0 0 4px auto;
    text-align:right;font-size:var(--fs-sm)}
  /* 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;
  /* Zawsze jedna linijka: Krazki rezerwują pod pasek stałe miejsce,
     a zawinięty napis zjadałby ostatni wiersz. */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  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-text);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(475px,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 > .sekcja-hd > 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-hd > 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-text);border-bottom-color:var(--accent)}
/* Licznik przy zakładce — mówi, że tam coś wisi, zanim ktoś tam wejdzie.
   Bez liczby zakładka „Do zamówienia" wygląda tak samo pusta jak pełna. */
.zakladki button .licznik{display:inline-block;margin-left:6px;padding:0 6px;
  min-width:18px;border-radius:9px;background:var(--accent);color:#fff;
  font-size:var(--fs-xs);font-weight:700;line-height:18px;text-align:center}
.zakladki button.on .licznik{background:var(--accent)}
/* Drugi poziom zakładek w środku ekranu — lżejszy, bez własnej kreski,
   żeby nie konkurował z głównym paskiem nad sobą. */
.zakladki.drugie{border-bottom:0;margin-bottom:0;gap:2px}
.zakladki.drugie button{padding:var(--s2) var(--s3);font-weight:500}
/* Wiersz, który woła o uwagę — część po terminie. Nie czerwone tło na
   całej szerokości, tylko pasek z boku: widać, nie krzyczy. */
tr.uwaga > td:first-child{box-shadow:inset 3px 0 0 var(--bad,#c0392b)}

/* 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. */
/* KRESKA IDZIE PRZEZ CAŁĄ KARTĘ, TEKST KOŃCZY SIĘ NA 80 ZNAKACH.
   Wcześniej `max-width` ścinało cały blok, więc linia oddzielająca
   urywała się w połowie karty — wyglądało to na niedokończone
   obramowanie, a nie na zamierzony koniec akapitu. Dopełnienie z prawej
   robi to samo dla tekstu, nie ruszając ramki. */
.wyjasnienie{margin:0;color:var(--ink-2);font-size:var(--fs-sm);
  padding:var(--s3) var(--pad-card);
  padding-right:max(var(--pad-card), 100% - 80ch - var(--pad-card));
  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-text)}
.przebieg .pz-podpis .pz-znak,.przebieg .pz-protokol .pz-znak{color:var(--ok-solid)}
/* Zdarzenia z historii kontaktu — te same znaki co reszta osi, tylko
   w kolorach, które niosą znaczenie: pieniądze na zielono (wpłynęło),
   wycena w akcencie (czeka na decyzję klienta).
   Kreska z lewej przy wpisie OD KLIENTA: przy sporze „nie zgadzałem się
   na to" pierwsze pytanie brzmi, która strona co zrobiła. */
.przebieg .pz-pieniadze .pz-znak{color:var(--ok-solid)}
.przebieg .pz-wycena .pz-znak{color:var(--accent-text)}
.przebieg .pz-od-klienta{position:relative}
.przebieg .pz-od-klienta::before{content:'';position:absolute;left:0;top:2px;bottom:2px;
  width:2px;border-radius:2px;background:var(--accent)}
@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-text)}
.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);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)}
/* =====================================================================
   PULPIT NAPRAW
   =====================================================================
   Dwa rzędy kafli, bo to dwa różne pytania: gdzie stoi robota i gdzie
   leżą pieniądze. Patrzy na nie kto inny i o innej porze — serwisant
   rano, właściciel wieczorem.

   Kafel jest PRZYCISKIEM, nie kafelkiem z liczbą: każdy zawęża listę
   napraw tym samym warunkiem, którym się policzył. Stąd kursor, stąd
   obramówka reagująca na najechanie. Kafel, który wygląda jak przycisk
   i nic nie robi, uczy ludzi, że w ten program nie warto klikać. */
/* `auto-fill`, nie `auto-fit`: przy dwóch kaflach w rzędzie „Pieniądze"
   auto-fit rozciągnąłby je na całą szerokość i dwa kafle wyglądałyby
   jak inny rodzaj elementu niż sześć kafli nad nimi. Puste tory trzymają
   szerokość wspólną dla obu rzędów. */
.kafle-napraw{display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(178px,1fr))}
.kafle-napraw .kafel-napraw{display:flex;flex-direction:column;gap:2px;
  text-align:left;padding:12px 14px;border-radius:var(--radius);
  border:1px solid var(--line);background:var(--surface);color:inherit;
  font:inherit;cursor:pointer}
.kafle-napraw .kafel-napraw:hover{border-color:var(--accent)}
.kafle-napraw .kafel-napraw:focus-visible{outline:none;box-shadow:var(--focus)}
.kafle-napraw .etykieta{font-size:var(--fs-xs);font-weight:650;
  letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2)}
.kafle-napraw .liczba{font-size:28px;font-weight:700;line-height:1.1;
  font-variant-numeric:tabular-nums}
.kafle-napraw .kwota{font-size:var(--fs-sm);font-weight:650;color:var(--ink-2);
  font-variant-numeric:tabular-nums}
.kafle-napraw .hint{font-size:var(--fs-xs);color:var(--ink-3)}
/* KOLOR MA ZNACZYĆ, a nie zdobić: czerwone = robota, która czeka za
   długo; zielone = dobra wiadomość. Reszta zostaje neutralna, bo liczba,
   która sama z siebie nic nie mówi, nie ma prawa krzyczeć. */
.kafle-napraw .kafel-napraw.zle .liczba{color:var(--bad)}
.kafle-napraw .kafel-napraw.ok .liczba{color:var(--ok)}
/* Zero to brak roboty — i ma tak wyglądać. Czerwone zero przy „po
   terminie" byłoby alarmem o tym, że wszystko jest w porządku. */
.kafle-napraw .kafel-napraw.pusty .liczba{color:var(--ink-3)}
.kafle-napraw .kafel-napraw.pusty{opacity:.75}

.pulpit-moduly{display:grid;gap:var(--s4);margin-top:var(--s5);
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.pulpit-modul{border:1px solid var(--line);border-radius:var(--radius);
  padding:12px 14px;background:var(--surface)}
.pulpit-wiersz{display:flex;align-items:center;gap:var(--s3);
  padding:5px 0;border-top:1px solid var(--line);font-size:var(--fs-sm)}
.pulpit-wiersz:first-of-type{border-top:0}
.pulpit-wiersz .clip{flex:1 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
.pulpit-notatka{padding:6px 0;border-top:1px solid var(--line);
  font-size:var(--fs-sm)}
.pulpit-notatka:first-of-type{border-top:0}
/* Notatka bywa akapitem. Dwie linijki wystarczą, żeby wiedzieć, czy
   warto kliknąć — a pulpit ma się dać ogarnąć wzrokiem. */
.pulpit-notatka .clip2{display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;color:var(--ink-2)}

/* „bez punktu" w szufladzie mapy.
   Sprzet, ktory wjechal z Zabbiksa albo ESET-a, nie ma przypisanego
   biura - widac go wiec na mapie KAZDEGO punktu firmy. Bez tego
   dopisku wygladalby jak reszta, a po wyciagnieciu na plansze punkt
   dopisalby mu sie bez slowa wyjasnienia.
   Maly, spokojny znacznik - to dopowiedzenie, nie ostrzezenie. */
.mapa-pozycja .mapa-bez-punktu{align-self:flex-start;margin-top:2px;
  padding:0 6px;border-radius:var(--radius-pill);font-weight:650;
  font-size:var(--fs-xs);line-height:16px;
  background:var(--surface-2);color:var(--ink-3);
  border:1px solid var(--line,rgba(127,127,127,.25))}
.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(--s5);align-items:flex-start;min-width:0}
.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}
/* DOKUMENT MA SWOJĄ SZEROKOŚĆ, NIE SZEROKOŚĆ MONITORA.
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „cała ta tabela z wyceną może być zdecydowanie
   węższa, nie musi być tak rozciągnięta, mamy sporo miejsca (…) teraz
   ciągnie cały ekran w prawo".

   Główka dokumentu miała granicę (1180 px), a tabela pod nią nie —
   więc na monitorze 2000 px formularz kończył się w połowie ekranu,
   a pozycje szły do samej krawędzi. Dwie różne prawe krawędzie na
   jednym dokumencie czyta się jak usterka.

   Granica jest tu, na kolumnie treści, żeby WSZYSTKO pod nią — główka,
   pozycje, podsumowanie i wysyłka — kończyło się w tym samym miejscu. */
.dok-tresc{flex:1 1 auto;min-width:0;max-width:1180px}
.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-text)}

/* „×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:var(--radius-pill,6px);
  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-text)}
.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-text)}

/* 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);text-decoration:underline}
.ai-skrot:disabled{cursor:default;opacity:.6}
.ai-iskra{color:var(--accent-text);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-text)}
.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-text);
  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,.sekcja.skladana > .sekcja-hd > h3{display:flex;align-items:baseline;gap:var(--s3);
  flex-wrap:wrap}
.sekcja.skladana > h3 .rozwin,.sekcja.skladana > .sekcja-hd > 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-text);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-text);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}

/* =====================================================================
   EKRAN ROUTERÓW NA WĄSKIM EKRANIE
   =====================================================================
   Łukasz, 10.09.2026: „routery abonentów — ładniej ułożyć i te przyciski
   od filtrowania i od szukajki".
   Wszystko tu stało w rzędach, które zawijają się „jak wyjdzie": liczby
   po trzy w linii, znaczniki producentów schodkiem, a pole szukania,
   dwa przyciski, lista rozwijana i „Odśwież tę stronę" w jednym rzędzie
   rozdzielonym rozpychaczem. Na szerokim monitorze to działa. Poniżej
   900 px każdy z tych rzędów łamie się w innym miejscu i ekran wygląda,
   jakby elementy spadły tam przypadkiem.
   Poniżej układamy to jawnie: równe siatki, wspólne krawędzie, etykieta
   filtra w swojej własnej linii. */
@media (max-width:900px){
  /* Etykieta „Producent" w osobnej linii — inaczej pierwszy znacznik
     jest przesunięty względem wszystkich pozostałych. */
  .ekran-routery .producenci .etykieta{flex:1 1 100%;margin:0 0 2px}

  /* Pole szukania na całą szerokość, oba przyciski pod nim po połowie. */
  .ekran-routery .szukajka{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .ekran-routery .szukajka .input{grid-column:1 / -1;width:100%;flex:none;min-width:0}
  .ekran-routery .szukajka .btn{width:100%;flex:none}

  /* Wybór parametru i odświeżanie: jedno pod drugim, na pełną szerokość.
     „Odśwież tę stronę (25)" nie mieści się obok listy rozwijanej,
     a skracanie tego napisu odebrałoby mu jedyną konkretną informację
     — ile routerów ruszy. */
  .ekran-routery .odswiezanie{display:grid;grid-template-columns:1fr;gap:10px}
  .ekran-routery .odswiezanie .input,
  .ekran-routery .odswiezanie .btn{width:100%;flex:none;min-width:0}
}

/* 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}
/* 20.09.2026, Łukasz: „wycentrujmy informacje w powiadomieniach" — plakietka,
   licznik i godzina stoją na środku wysokości tytułu, także dwuwierszowego
   (wcześniej przyklejone do górnej linii). */
.powiadomienie .powiad-glowa{align-items:center}
/* 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}

/* Trzy skaczące kropki mieszkały tutaj do 18.09.2026. Zastąpił je
   wspólny kołowrotek `<Wczytywanie />` (koniec pliku) — bo kropki
   trzeba było wklejać ręcznie na każdym ekranie i większość ekranów
   ich nie miała. */

/* 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}

/* LICZBY W SIATCE, GDY RZĄD PRZESTAJE MIEĆ SENS.
   Pięć par „liczba + opis" w jednym rzędzie zawija się na wąskim
   ekranie tak, że w pierwszej linii stoi jedna para, w drugiej dwie,
   w trzeciej znowu jedna — bez żadnej wspólnej krawędzi. Siatka
   o równych polach ustawia je w kolumny, a liczba idzie NAD opis,
   więc oko czyta najpierw same liczby, a dopiero potem podpisy. */
@media (max-width:900px){
  .pasek-liczb{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));
    gap:var(--s3) var(--s4);align-items:start}
  .pasek-liczb .liczba{display:flex;flex-direction:column;white-space:normal;
    line-height:1.25}
  .pasek-liczb .liczba b{font-size:var(--fs-xl);margin-right:0}
  .pasek-liczb .rozpychacz{display:none}
  /* Odnośnik i rozwinięte wyjaśnienie zajmują całą szerokość siatki —
     `flex:1 1 100%` z układu rzędowego w siatce nic nie znaczy. */
  .pasek-liczb .co-to-znaczy,
  .pasek-liczb .wyjasnienie-zwiniete{grid-column:1 / -1;white-space:normal}
}
.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-text)}

/* --- 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}
.krazki.od-gory{align-content:start}
/* Wiersz ma wysokość ustawioną przez Krazki (równa część kafla), więc
   wysciółka nie może jej powiększać, a treść stoi w środku wiersza. */
.krazki .krazek[style]{box-sizing:border-box;padding-top:0;padding-bottom:0}
.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){
  /* NA WĄSKIM EKRANIE WSZYSTKO NA ŚRODKU.
     Łukasz, 10.09.2026: „w karcie abonenta można historię zgłoszeń
     ładniej ułożyć, może wyśrodkować wszystko?".
     Miał rację i widać dlaczego: przy szerokim kaflu suma stoi po
     lewej, a pierścienie środkują się w reszcie miejsca — i to jest
     poprawne, bo są to dwie rzeczy obok siebie. Gdy kafel się zwęża,
     rząd zawija się na dwie linie i wtedy te same reguły dają liczbę
     przyklejoną do lewej krawędzi i pierścienie wyśrodkowane pod nią.
     Dwie różne osie w jednym kaflu wyglądają na niedokończone.
     Poniżej 900 px układamy to więc jawnie w kolumnę i środkujemy
     całość — jedna oś, jeden porządek. */
  .historia-zgl{flex-direction:column;align-items:center;text-align:center;
    gap:var(--s4)}
  .historia-suma{align-items:center;text-align:center}
  .historia-zgl .zajetosc-kola{flex:0 0 auto;width:100%;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}

/* --- kolumny z plakietką i podpisem pod nią ---------------------------
   Łukasz, 17.09.2026: „Router w ACS rozjeżdża się, plakietka »jest«
   w lewo leci, zamiast być centralnie na środku modelu routera. Daj też
   jakiś delikatny margines, bo prawie dotykają się".

   Przyczyna: plakietka siedzi w przycisku, a przycisk jest z natury
   elementem liniowym zwężonym do swojej treści — więc stawał przy lewej
   krawędzi komórki, podczas gdy podpis pod nim (model routera, numer
   konta) szedł już zwykłym tokiem i wyrównywał się do środka. Dwa różne
   wyrównania w jednej kolumnie, w dodatku różne w zależności od tego,
   czy wiersz ma przycisk, czy sam napis „nie ma".

   Naprawa jest jedna dla obu kolumn: przycisk staje się blokiem na całą
   szerokość komórki, więc jego zawartość układa się po tej samej osi,
   co wszystko inne pod spodem. Dotyczy to zarówno listy bieżących, jak
   i zamkniętych oraz widoku Nexery — to jedna tabela w trzech widokach. */
.tab-zgloszen .kol-sesja,
.tab-zgloszen .kol-acs{text-align:center;padding-inline:18px}
/* `button.jak-link`, a nie każdy przycisk: „napraw →" w tej samej
   kolumnie to zwykły przycisk akcji i ma zostać wąski. */
.tab-zgloszen .kol-sesja > button.jak-link,
.tab-zgloszen .kol-acs > button.jak-link{display:block;width:100%;text-align:center}
/* Odstęp między plakietką a podpisem — bez niego napis dokleja się do
   krawędzi plakietki i czyta się jak jej część. */
.tab-zgloszen .kol-sesja > button.jak-link > .pill,
.tab-zgloszen .kol-acs > button.jak-link > .pill{margin-bottom:4px}
/* Sąsiednia kolumna też potrzebuje powietrza: „TP-Link EC230-G1"
   i plakietka kategorii stały ramię w ramię. */
.tab-zgloszen .kol-kategoria{padding-left:18px}
.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-xs);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}

/* =====================================================================
   PRZYCISKI W ZGŁOSZENIU — RÓWNO, NIE „JAK WYJDZIE”
   =====================================================================
   Łukasz, 10.09.2026: „poukładałbym ładniej przyciski, może bardziej
   wyśrodkował/wycentrował wszystko? Wyrównać”.
   Stały tu w zwykłym rzędzie (`formrow`), więc każdy miał szerokość
   swojego napisu i zawijały się poszarpanym schodkiem: „Karta abonenta”
   długa, „NEXERA” krótka, a druga linia zaczynała się w losowym
   miejscu. Oko szuka wtedy krawędzi, której nie ma.
   Siatka o równych polach daje wszystkim przyciskom tę samą szerokość
   i wspólne krawędzie z lewej i z prawej. `auto-fit` sam dobiera liczbę
   kolumn: dwie na telefonie, trzy albo cztery na monitorze — bez
   żadnego progu wpisanego na sztywno. */
.zgl-akcje,.siatka-akcji{display:grid;gap:10px;margin-bottom:var(--s3);
  grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.zgl-akcje > .btn,.siatka-akcji > .btn{width:100%;display:inline-flex;
  align-items:center;justify-content:center;text-align:center;line-height:1.2}
/* Napis dłuższy niż przycisk schodzi do drugiej linii zamiast wystawać
   poza obramowanie — „Zapisz, co zrobiliśmy” przy dwóch kolumnach. */
.zgl-akcje > .btn.sm,.siatka-akcji > .btn.sm{height:auto;min-height:34px;
  padding-top:6px;padding-bottom:6px;white-space:normal}
/* `.siatka-akcji` to ta sama siatka, użyta przy zadaniach ESET-a na
   karcie stanowiska. Łukasz, 10.09.2026: „panel stanowiska —
   wyśrodkować te przyciski". Siedem przycisków o różnej długości
   napisu układało się schodkiem: dwa, dwa, dwa, jeden — każdy rząd
   innej długości, żadnej wspólnej krawędzi. */

/* =====================================================================
   LISTA ZGŁOSZEŃ NA TELEFONIE
   =====================================================================
   Łukasz, 10.09.2026: „w panelu operatora zgłoszenia bym zrobił kolumny
   OD KIEDY, ABONENT, LOKALIZACJA, SESJA RADIUS. Usterkę sobie
   przeczytamy, jak wejdziemy".
   Siedem kolumn na ekranie szerokim na 360 px nie mieści się w żaden
   sposób — a przy `table-layout:fixed` opis usterki dostawał ~90 px
   i rozpychał wiersz na dziesięć linii, przez co na ekran wchodziły
   dwa zgłoszenia zamiast dwudziestu.
   Zostaje to, po czym rozpoznaje się sprawę w kolejce: kiedy wpłynęła,
   czyja jest, gdzie i czy łącze żyje. Reszta jest w zgłoszeniu,
   o jedno dotknięcie dalej.
   W widoku zamkniętych chowamy dodatkowo „Od kiedy” — ta lista układa
   się po dacie ZAMKNIĘCIA i to ona ma zostać na wąskim ekranie. */
@media (max-width:900px){
  .tab-zgloszen{table-layout:auto}
  .tab-zgloszen colgroup{display:none}
  .tblwrap .tab-zgloszen{min-width:0}
  .tab-zgloszen .kol-numer,
  .tab-zgloszen .kol-temat,
  /* ACS schodzi na telefonie razem z kategorią — to informacja do
     pracy przy biurku, nie do rozpoznania sprawy w kolejce. */
  .tab-zgloszen .kol-acs,
  .tab-zgloszen .kol-kategoria{display:none}
  .tab-zgloszen.zamkniete .kol-odkiedy{display:none}
  /* Cztery kolumny zamiast siedmiu znaczy, że każda dostaje więcej
     miejsca — ale marginesy z ekranu 27-calowego są tu marnotrawstwem. */
  .tab-zgloszen tbody td{padding:11px 8px}
  .tab-zgloszen thead th{padding:9px 8px}
  /* Adres i nazwisko mają się zawijać, a nie wypychać tabeli w bok.
     `break-word`, NIE `anywhere`: `anywhere` łamie w środku wyrazu przy
     pierwszej okazji i na ekranie robi się „Suchedni / ów”, „Kwaśniew /
     ski”. Nazwisko przecięte w połowie czyta się gorzej niż wąska
     kolumna. `break-word` przenosi całe słowo, a dzieli dopiero takie,
     które samo nie mieści się w kolumnie. */
  .tab-zgloszen .kol-lokalizacja,
  .tab-zgloszen .kol-abonent{white-space:normal;overflow-wrap:break-word}

  /* LISTA RAPORTÓW Z DIAGNOSTYKI — to samo, o jedną kolumnę mniej.
     Łukasz, 10.09.2026: „tutaj wystarczy tylko kolumna KIEDY ABONENT
     SESJA RADIUS".
     Werdykt i objaw czyta się w raporcie, a raport i tak trzeba
     otworzyć, żeby cokolwiek z nim zrobić. Przycisk „Otwórz" znika
     razem z nimi, bo od 10.09.2026 cały wiersz prowadzi do raportu —
     inaczej na telefonie nie byłoby jak wejść. */
  .tab-diagnoz{table-layout:auto}
  .tblwrap .tab-diagnoz{min-width:0}
  .tab-diagnoz .kol-werdykt,
  .tab-diagnoz .kol-objaw,
  .tab-diagnoz .kol-otworz{display:none}
  .tab-diagnoz td{padding:11px 8px}
  .tab-diagnoz th{padding:9px 8px}
  .tab-diagnoz .kol-abonent{white-space:normal;overflow-wrap:break-word}
  /* Nagłówki też — „LOKALIZACJA” pociętej w środku nikt nie oczekuje. */
  .tab-zgloszen thead th{overflow-wrap:break-word;hyphens:none}
}

/* =====================================================================
   SESJE ABONENTÓW NA WĄSKIM EKRANIE
   =====================================================================
   Dziesięć kolumn (taryfa, limit, czasy, IP, MAC) opisuje sesję
   dokładnie — i żadnej z nich nie da się przeczytać na 390 px.
   Zostaje to, po czym rozpoznaje się wiersz, plus jedyna akcja tego
   ekranu. */
/* DZIESIĘĆ KOLUMN POTRZEBUJE 1100 px — PONIŻEJ TABELA SIĘ PRZEWIJA,
   A NIE ŚCISKA. Przy 1020 px na kolumnę „Taryfa" zostawały 54 px, więc
   łamał się sam jej NAGŁÓWEK: „TARYF / A". Ściśnięta tabela nie jest
   kompromisem — jest nieczytelna, a przewinięcie w bok kosztuje jeden
   ruch myszy i niczego nie ukrywa. Pudełko `.tblwrap` przewija się samo.
   Na telefonie jest inaczej (blok niżej): tam kolumn zostaje mniej. */
.tblwrap .tab-sesje{min-width:1100px}

/* DŁUGI NAPIS NA PRZYCISKU ZALEŻY OD SZEROKOŚCI TABELI, NIE OKNA.
   „Połącz od nowa" potrzebuje ~130 px, czyli kolumny akcji z tabeli
   szerokiej na 1150 px. Okno bywa szersze od tabeli (menu boczne,
   marginesy karty), więc pytanie o szerokość OKNA odpowiadałoby na
   niewłaściwe pytanie — pytamy o POJEMNIK TABELI.
   Domyślny jest napis KRÓTKI: gdyby przeglądarka nie znała zapytań
   o pojemnik, zostaje wariant, który mieści się zawsze. */
.tblwrap:has(> .tab-sesje){container:tabela-sesji / inline-size}
.tab-sesje .btn .szeroko{display:none}
.tab-sesje .btn .wasko{display:inline}
@container tabela-sesji (min-width:1150px){
  .tab-sesje .btn .szeroko{display:inline}
  .tab-sesje .btn .wasko{display:none}
}
@media (max-width:900px){
  .tab-sesje{table-layout:auto}
  .tblwrap .tab-sesje{min-width:0}
  .tab-sesje th:nth-child(n+4):not(.kol-akcja),
  .tab-sesje td:nth-child(n+4):not(.kol-akcja){display:none}
  .tab-sesje td,.tab-sesje th{padding-left:8px;padding-right:8px}
  /* Nazwisko i konto muszą dać się złamać, inaczej „Nexera-UNI=2314294”
     wyznacza szerokość kolumny i wypycha stan poza ekran. */
  .tab-sesje td:nth-child(1),
  .tab-sesje td:nth-child(2){white-space:normal;overflow-wrap:anywhere}
  .tab-sesje .pill{font-size:var(--fs-xs);padding-left:7px;padding-right:7px;
    overflow-wrap:normal}
  .tab-sesje .btn .szeroko{display:none}
  .tab-sesje .btn .wasko{display:inline}
  .tab-sesje .kol-akcja{white-space:nowrap}
}

/* Raporty z diagnostyki: cały wiersz prowadzi do raportu, więc ma
   wyglądać na klikalny — tak samo jak wiersz na liście zgłoszeń. */
.tab-diagnoz tbody tr{cursor:pointer}
.tab-diagnoz td{vertical-align:top}

/* 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-text);
  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-text);
  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-text);
  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}
  /* TRZY KOLUMNY, KTÓRE MUSZĄ SIĘ ZMIEŚCIĆ.
     Łukasz, 10.09.2026: „abonenci kolumna ABONENT LOKALIZACJA STAN” —
     kolumny były już schowane, ale STAN i tak uciekał za krawędź.
     Powód: nazwy firm bywają jednym długim wyrazem („LICENCJONOWANE”,
     „Mroczków-Kamionka”) i taki wyraz wyznacza NAJMNIEJSZĄ możliwą
     szerokość kolumny. Przy 390 px sama tabela wychodziła na 428 px
     i plakietka stanu była ucięta.
     `anywhere` (a nie `break-word`) jest tu konieczne: tylko ono
     pozwala złamać wyraz i realnie zwęzić kolumnę. Nazwa firmy
     przeniesiona w połowie czyta się gorzej niż w całości — ale
     niewidoczny stan łącza jest gorszy od obu. */
  .tab-abonentow td:nth-child(1),
  .tab-abonentow td:nth-child(2),
  .tab-abonentow th:nth-child(1),
  .tab-abonentow th:nth-child(2){white-space:normal;overflow-wrap:anywhere}
  .tab-abonentow td,.tab-abonentow th{padding-left:8px;padding-right:8px}
  /* Plakietka stanu ma zostać w jednym kawałku — „Zablokowany” złamane
     na „Zabloko / wany” nie mówi nic szybciej niż całe słowo. */
  .tab-abonentow td:nth-child(3){white-space:normal}
  .tab-abonentow .pill{overflow-wrap:normal;font-size:var(--fs-xs);padding-left:7px;padding-right:7px}
}
/* 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}
.kafel-tabela > table{width:100%;min-width:0}
.kafel-tabela th,.kafel-tabela td{padding-left:8px;padding-right:8px}
/* Ramka tabeli w kafelku — tabela jest wtedy wyraźnym blokiem, a nie
   pasem wchodzącym w krawędzie kafla. */
.kafel-tabela > table{border:1px solid var(--line);border-radius:0}
/* Skrajne komórki z marginesem we WSZYSTKICH motywach: nagłówek ma tło,
   więc tekst przyklejony do jego krawędzi wyglądał na ucięty. */
.kafel-tabela th:first-child,.kafel-tabela td:first-child{padding-left:10px}
.kafel-tabela th:last-child,.kafel-tabela td:last-child{padding-right:10px}
/* Tabela w kafelku jest MNIEJSZA niż lista na cały ekran (19.09.2026,
   karta abonenta: „sesje w Radiusie się rozjeżdżają, trzeba zwęzić
   i dać marginesy"). Drobniejsze pismo i niższe wiersze — to jest
   podgląd obok innych kafli, a nie główna tabela ekranu. */
.kafel-tabela > table{font-size:var(--fs-sm)}
.kafel-tabela thead th{font-size:var(--fs-xs);letter-spacing:.03em;padding-top:8px;padding-bottom:8px}
.kafel-tabela tbody td{height:auto;padding-top:8px;padding-bottom:8px}
/* Gdy nagłówek ma tło albo tabela ramkę (motyw ANANAS), skrajne
   komórki nie mogą dotykać krawędzi. */

/* 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)}

/* =====================================================================
   PASEK CZASU NA LIŚCIE NAPRAW
   =====================================================================
   W NPS pasek pod numerem powtarzał status, który stał obok — i przez to
   nie niósł żadnej informacji. Ten rysuje, ile z terminu już minęło.

   Kolor jest DRUGIM nośnikiem, nie jedynym: obok paska stoi zdanie
   „zostało 5 dni" albo „3 dni po terminie". Pasek ma przyciągnąć wzrok
   przy przewijaniu listy, a nie być jedynym źródłem prawdy — jedna
   trzecia mężczyzn myli czerwień z zielenią.
   ===================================================================== */
.pasek-czasu {
  height: 4px; border-radius: 2px; margin-top: 4px;
  background: var(--linia); overflow: hidden;
}
.pasek-czasu > span {
  display: block; height: 100%; border-radius: 2px;
  background: var(--ok, #1f7a4d);
  transition: width .2s ease;
}
.pasek-czasu > span.blisko { background: var(--uwaga, #8a6116); }
.pasek-czasu > span.po     { background: var(--zle, #a5322c); }

/* Pasek jest ozdobą informacji, nie samą informacją — przy wyłączonej
   animacji nie ma nic do animowania. */
@media (prefers-reduced-motion: reduce) {
  .pasek-czasu > span { transition: none; }
}

/* =====================================================================
   SEKCJE W SZUFLADZIE PRZYJĘCIA
   =====================================================================
   Formularz przyjęcia to cztery bloki jeden pod drugim, a nie jedna
   ściana pól. Tytuł sekcji ma odstęp NAD sobą, nie pod — inaczej
   „Stan sprzętu przy przyjęciu" przykleja się do pola powyżej i czyta
   jak jego podpis, a nie jak nowy temat.
   ===================================================================== */
.sekcja-tytul{margin:0 0 var(--s3);font-size:var(--fs-lg);line-height:1.3}
.sekcja-tytul.dalszy{margin-top:var(--s6)}

/* Pole po polu potrzebuje powietrza. Domyślny `.pola` jest ustawiony
   pod gęste tabelki na karcie zlecenia; tutaj czyta się to raz, przy
   kliencie, i liczy się czytelność, nie ile się zmieści. */
.drawer .pola.ciasne{row-gap:var(--s4);column-gap:var(--s4)}
.drawer .card{margin-bottom:var(--s4)}
.drawer .card:last-of-type{margin-bottom:0}

/* Podpowiedź pod polem ma należeć do TEGO pola, nie wisieć między
   dwoma. Bez tego „Po nim najczęściej szuka się klienta" rozpycha
   wiersz i wygląda, jakby opisywało sąsiedni e-mail. */
.drawer .pola .podpowiedz-pola{margin-top:4px;line-height:1.4}

/* Tekstowe pola opisowe: wyraźnie wyższe niż jednoliniowe inputy,
   bo do nich naprawdę się pisze. */
.drawer textarea.input{min-height:5.5rem;line-height:1.5}

/* =====================================================================
   WZÓR BLOKADY EKRANU (przyjęcie sprzętu)
   =====================================================================
   Siatka 3×3 rysowana palcem, jak na telefonie. Dwa okręgi na punkt:
   duży NIEWIDOCZNY to strefa trafienia (palec nie jest myszą i nie
   trafia w kropkę o promieniu 7 px), mały widoczny to sama kropka.

   `touch-action:none` jest tu warunkiem działania, nie kosmetyką: bez
   niego przeciągnięcie palcem po tablecie przewija stronę zamiast
   rysować wzór. */
.wzor-blokady{width:240px;max-width:100%;aspect-ratio:1;touch-action:none;
  border:1px solid var(--line);border-radius:14px;background:var(--surface-2);
  cursor:crosshair;user-select:none}
.wzor-strefa{fill:transparent}
.wzor-punkt{fill:var(--ink-3);transition:fill .12s,r .12s}
.wzor-punkt.uzyty{fill:var(--accent)}
.wzor-linia{fill:none;stroke:var(--accent);stroke-width:4;
  stroke-linecap:round;stroke-linejoin:round;opacity:.65}
.wzor-numer{fill:var(--accent-ink);font-size:11px;font-weight:700;
  pointer-events:none}

/* =====================================================================
   PRZYJĘCIE SPRZĘTU — ETAPY, POLA, PASEK KROKÓW
   =====================================================================
   Łukasz, 12.09.2026: „niektóre pola są absurdalnie za duże — po co?",
   „cyfra z krokiem i opisem tytułu są takie... nijakie".

   Trzy rzeczy do naprawienia naraz i jedna zasada, która je łączy:
   FORMA MA COŚ ZNACZYĆ. Szerokość pola mówi, ile się w nim spodziewamy;
   wielkość napisu mówi, na którym piętrze się jest; kolor mówi, czy coś
   jest już zrobione. Wcześniej wszystko było mniej więcej tej samej
   wielkości i tego samego koloru, więc nie mówiło nic — stąd „nijakie".
   ===================================================================== */

/* --- 1. POLA O SZEROKOŚCI DOBRANEJ DO TREŚCI ----------------------- */
/* Siatka `auto-fill` rozciągała każde pole do szerokości kolumny: kod
   pocztowy dostawał tyle miejsca co adres. Tutaj układ jest zwyczajnym
   zawijanym rzędem, a każde pole ma szerokość swojej zawartości —
   dzięki temu w jednym rzędzie mieści się ich więcej i formularz jest
   niższy. */
.pola.wymiarowe{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s4);
  align-items:flex-start}
.pola.wymiarowe > .pole{flex:0 0 auto;min-width:0;gap:3px}
.pola.wymiarowe > .pole.mikro{width:104px}
.pola.wymiarowe > .pole.waskie{width:148px}
.pola.wymiarowe > .pole.srednie{width:206px}
.pola.wymiarowe > .pole.szerokie{width:290px}
.pola.wymiarowe > .pole.rosnie{flex:1 1 260px;min-width:220px}
.pola.wymiarowe > .pole > .input{width:100%}
.pola.wymiarowe .input{height:34px}
.pola.wymiarowe .input.mono{font-variant-numeric:tabular-nums}
@media (max-width:560px){
  .pola.wymiarowe > .pole{width:auto;flex:1 1 100%}
}

/* Etykieta mniejsza i spokojniejsza niż treść pola. Do 12.09 miała ten
   sam rozmiar co wpisywany tekst i walczyła z nim o uwagę. */
.etap .pole-etykieta{font-size:12px;font-weight:640;color:var(--ink-2);
  letter-spacing:.01em}
.etap .pole-podpowiedz{font-size:12px;color:var(--ink-3);line-height:1.35}
.etap .pole-blad{font-size:12px}
/* Zdania wyjaśniające w kaflu były większe od etykiet pól, więc czytały
   się jak treść, a nie jak przypis. */
.etap .wyjasnienie{font-size:12px;color:var(--ink-3);line-height:1.45}

/* --- 2. PODSEKCJA: mały wersalik, nie drugi nagłówek --------------- */
/* „Odblokowanie ekranu" i „Co się dzieje" były `h3` tej samej wielkości
   co tytuł etapu — dwa piętra hierarchii wyglądające identycznie. */
.podsekcja{margin:var(--s5) 0 var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--line-soft);
  font-size:11px;font-weight:800;text-transform:uppercase;
  letter-spacing:.09em;color:var(--ink-3)}
.etap .bd > .podsekcja:first-child{margin-top:0;padding-top:0;border-top:0}

/* --- 3. KAFEL ETAPU ------------------------------------------------ */
/* Kafle w jednym rzędzie mają RÓWNĄ WYSOKOŚĆ. Pierwsza wersja miała
   `align-items:start` i krótszy kafel zostawiał pod sobą dziurę —
   Łukasz: „robią się przerwy". Dziura między kaflami czyta się jak błąd
   układu; kilka pustych pikseli w środku kafla nie czyta się wcale, bo
   kafel ma ramkę i widać, że po prostu się skończył. */
.etapy{display:grid;grid-template-columns:repeat(auto-fit,minmax(440px,1fr));
  gap:var(--s4);align-items:stretch;margin-top:var(--s4)}

.etap{margin:0;height:100%;display:flex;flex-direction:column;
  overflow:hidden;position:relative;
  transition:box-shadow .18s, border-color .18s}

/* Kreska nad kaflem zapala się na kolor marki, gdy etap jest zrobiony.
   To jedyne miejsce, w którym kafel zmienia się sam — reszta stoi
   spokojnie, żeby formularz nie migotał przy pisaniu. */
.etap::before{content:'';position:absolute;inset:0 0 auto;height:3px;
  background:var(--line);transition:background .2s}
.etap.zrobiony::before{background:var(--accent)}

/* KAFEL, W KTÓRYM SIĘ WŁAŚNIE PISZE, WYCHODZI DO PRZODU.
   Przy czterech kaflach naraz to jest jedyna podpowiedź, gdzie stoi
   kursor — na ekranie dotykowym nie ma go widać wcale. */
.etap:focus-within{box-shadow:var(--shadow-2);border-color:var(--accent-border)}

/* NAGŁÓWEK KAFLA — TA SAMA ROBOTA CO W PORTALU ABONENTA.
   Tam karta stanu niesie werdykt samym tłem: delikatny gradient w kolorze
   stanu, listwa u góry i znak w kółku z poświatą. Ten sam chwyt działa
   tutaj, bo pytanie jest tego samego rodzaju — „czy to już jest zrobione".
   Gradient schodzi do zera w połowie nagłówka, więc pod spodem formularz
   zostaje biały i czytelny. */
.etap > .hd{display:flex;align-items:flex-start;gap:12px;
  padding:var(--s4) var(--pad-card);
  background:linear-gradient(178deg, var(--surface-2) 0%, var(--surface) 92%);
  border-bottom:1px solid var(--line-soft)}
.etap.zrobiony > .hd{background:linear-gradient(178deg,
  hsl(var(--accent-h) var(--accent-s) 48% / .09) 0%, var(--surface) 92%)}
.etap.zly > .hd{background:linear-gradient(178deg, var(--bad-bg) 0%, var(--surface) 92%)}
.etap > .bd{flex:1 1 auto}

.etap-tytul{margin:0;font-size:var(--fs-lg);font-weight:700;
  letter-spacing:-.02em;line-height:1.15}
.etap-opis{margin:5px 0 0;color:var(--ink-2);font-size:12px;
  line-height:1.4;max-width:46ch}

/* Numer kroku: cyfra w kółku, z rezerwą na dwie cyfry (`tabular-nums`),
   żeby „10" nie rozjechało kółka, gdyby etapów kiedyś przybyło. */
.etap-nr{flex:0 0 auto;width:30px;height:30px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--fs-sm);font-weight:800;font-variant-numeric:tabular-nums;
  background:var(--surface);color:var(--ink-3);
  border:1.5px solid var(--line);
  transition:background .2s,color .2s,border-color .2s}
.etap.zrobiony .etap-nr{background:var(--accent);color:var(--accent-ink);
  border-color:var(--accent);
  box-shadow:0 0 0 4px var(--surface),
             0 0 0 6px hsl(var(--accent-h) var(--accent-s) 48% / .16)}

.etap-stan{flex:0 0 auto;margin-top:3px;
  font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;
  color:var(--ink-3);white-space:nowrap}
.etap-stan.ok{color:var(--accent-text)}

/* --- 4. PASEK KROKÓW NAD FORMULARZEM ------------------------------- */
/* Cztery kafle mieszczą się obok siebie dopiero na szerokim monitorze.
   Pasek pokazuje całą drogę w jednym rzędzie — i przewija do kafla,
   więc nie jest samą ozdobą.

   Nazwa klasy jest długa NIE PRZEZ PRZYPADEK: `.kroki` już istnieje
   w tym arkuszu (numerowana lista kroków w instrukcji) i ma
   `flex-direction:column`. Moja wersja stała niżej, więc wygrywała
   wszystkim poza tym jednym, odziedziczonym ustawieniem — i cztery
   kroki ustawiły się w pionie wewnątrz poziomej pigułki. */
.kroki-przyjecia{position:relative;display:flex;justify-content:center;
  margin-top:var(--s4);padding:7px 16px;
  border:1px solid var(--line);border-radius:var(--radius-pill);
  background:var(--surface-2)}

/* Kroki WYŚRODKOWANE, licznik wyjęty z rzędu i przyklejony do prawej —
   inaczej jego szerokość przesuwałaby środek zależnie od tego, czy pisze
   się „0 z 4" czy „4 z 4". */
.kroki-srodek{display:flex;align-items:center;gap:2px;flex-wrap:wrap;
  justify-content:center}

.kroki-przyjecia .krok{display:inline-flex;align-items:center;gap:8px;
  height:34px;padding:0 14px 0 6px;border:0;border-radius:var(--radius-pill);
  background:transparent;color:var(--ink-2);cursor:pointer;
  font:inherit;font-size:var(--fs-sm);font-weight:600;white-space:nowrap;
  transition:background .15s,color .15s}
.kroki-przyjecia .krok:hover{background:var(--surface);color:var(--ink)}
.kroki-przyjecia .krok:focus-visible{outline:none;box-shadow:var(--focus)}

/* Kreska między krokami. Zapalona znaczy „ten przed nią jest zrobiony",
   więc pasek rysuje przebytą drogę, a nie cztery osobne kółka. */
.krok-kreska{flex:0 0 auto;width:22px;height:2px;border-radius:2px;
  background:var(--line);transition:background .35s ease}
.krok-kreska.przebyta{background:var(--accent)}

.kroki-przyjecia .krok-nr{flex:0 0 auto;width:22px;height:22px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:800;font-variant-numeric:tabular-nums;
  background:var(--surface);color:var(--ink-3);
  border:1px solid var(--line);
  transition:background .2s,color .2s,border-color .2s}

/* Krok jeszcze pusty. Przerywane kółko zamiast pełnego — widać różnicę
   przez pół sekundy, bez czytania napisu. */
.kroki-przyjecia .krok.pusty .krok-nr{border-style:dashed}

.kroki-przyjecia .krok.zrobiony{color:var(--ink);background:var(--accent-soft)}
.kroki-przyjecia .krok.zrobiony .krok-nr{background:var(--accent);
  color:var(--accent-ink);border-color:var(--accent);
  /* Jednorazowy błysk w chwili, gdy krok się domyka. Bez pętli:
     animacja odpala się raz, przy dołożeniu klasy. */
  animation:krok-zapala .42s cubic-bezier(.2,.9,.3,1.4)}

@keyframes krok-zapala{
  0%   {transform:scale(.7);box-shadow:0 0 0 0 hsl(var(--accent-h) var(--accent-s) 48% / .5)}
  60%  {transform:scale(1.16)}
  100% {transform:scale(1);box-shadow:0 0 0 9px hsl(var(--accent-h) var(--accent-s) 48% / 0)}
}

/* KROK, W KTÓRYM STOI KURSOR — TEN JEDEN TĘTNI.
   Ten sam chwyt co kropka stanu w portalu abonenta. Tętni WYŁĄCZNIE
   bieżący krok: cztery pulsujące kółka naraz to nie jest wskazówka,
   tylko migotanie, od którego po godzinie przy ladzie bolą oczy. */
.kroki-przyjecia .krok.teraz{background:var(--surface);color:var(--ink);
  box-shadow:var(--shadow-1)}
.kroki-przyjecia .krok.teraz .krok-nr{border-color:var(--accent);
  color:var(--accent-text);
  animation:krok-tetno 2.4s ease-out infinite}
.kroki-przyjecia .krok.teraz.zrobiony .krok-nr{color:var(--accent-ink)}

@keyframes krok-tetno{
  0%   {box-shadow:0 0 0 0 hsl(var(--accent-h) var(--accent-s) 48% / .45)}
  70%  {box-shadow:0 0 0 7px hsl(var(--accent-h) var(--accent-s) 48% / 0)}
  100% {box-shadow:0 0 0 0 hsl(var(--accent-h) var(--accent-s) 48% / 0)}
}

.kroki-przyjecia .krok.zly{color:var(--bad);background:var(--bad-bg)}
.kroki-przyjecia .krok.zly .krok-nr{background:var(--bad);color:#fff;
  border-color:var(--bad);animation:none}

.kroki-licznik{position:absolute;right:18px;top:50%;transform:translateY(-50%);
  font-size:12px;font-weight:700;color:var(--ink-3);
  font-variant-numeric:tabular-nums;white-space:nowrap;pointer-events:none}

/* Kto prosił system o mniej ruchu, dostaje mniej ruchu. Informacja
   zostaje ta sama — niesie ją kolor i kształt, animacja tylko ją
   podkreślała. */
@media (prefers-reduced-motion:reduce){
  .kroki-przyjecia .krok-nr,
  .kroki-przyjecia .krok.teraz .krok-nr{animation:none}
  .krok-kreska{transition:none}
}
:root[data-ruch="mniej"] .kroki-przyjecia .krok-nr{animation:none}

@media (max-width:760px){
  .kroki-przyjecia .krok-tytul{display:none}
  .kroki-przyjecia .krok{padding:0 6px}
  .krok-kreska{width:12px}
  .kroki-licznik{display:none}
}

/* Podpowiedź pod WĄSKIM polem nie może być wąska razem z nim — zdanie
   złamane na cztery wiersze pod kratką na datę rozpychało kafel bardziej
   niż samo pole. Podpowiedź ma prawo być szersza od swojego pola; sąsiad
   jej nie dotyka, bo rząd i tak zawija się poniżej. */
.pola.wymiarowe > .pole.mikro .pole-podpowiedz,
.pola.wymiarowe > .pole.waskie .pole-podpowiedz{width:max-content;max-width:230px}

/* --- 5. PRZYCISK ROZWIJAJĄCY SEKCJĘ -------------------------------- */
/* Zastępuje `<details><summary>` udające odnośnik. Odnośnik w formularzu
   obiecuje, że coś się otworzy GDZIE INDZIEJ; ten przełącznik dokłada
   pola w tym samym miejscu, więc ma wyglądać jak przycisk. */
.btn.rozwin{gap:8px}
.rozwin-strzalka{display:inline-block;transition:transform .15s;
  font-weight:700;line-height:1}
.btn.rozwin.otwarte{border-color:var(--accent-border);color:var(--accent-text)}
.btn.rozwin.otwarte .rozwin-strzalka{transform:rotate(90deg)}

/* --- 6. WZÓR BLOKADY ----------------------------------------------- */
/* Siatka 3×3 rysowana palcem, jak na telefonie. Dwa okręgi na punkt:
   duży NIEWIDOCZNY to strefa trafienia (palec nie jest myszą i nie
   trafia w kropkę o promieniu 7 px), mały widoczny to sama kropka.

   `touch-action:none` jest tu warunkiem działania, nie kosmetyką: bez
   niego przeciągnięcie palcem po tablecie przewija stronę zamiast
   rysować wzór. */
.wzor-blokady{width:240px;max-width:100%;aspect-ratio:1;touch-action:none;
  border:1px solid var(--line);border-radius:14px;background:var(--surface-2);
  cursor:crosshair;user-select:none}
.wzor-strefa{fill:transparent}
.wzor-punkt{fill:var(--ink-3);transition:fill .12s,r .12s}
.wzor-punkt.uzyty{fill:var(--accent)}
.wzor-linia{fill:none;stroke:var(--accent);stroke-width:4;
  stroke-linecap:round;stroke-linejoin:round;opacity:.65}
.wzor-numer{fill:var(--accent-ink);font-size:11px;font-weight:700;
  pointer-events:none}

.wzor-blokady.podglad{width:76px;flex:0 0 auto;cursor:default;
  background:var(--surface);border-radius:10px}
.wzor-blokady.podglad .wzor-linia{stroke-width:6}

.wzor-zapisany{display:flex;gap:var(--s3);align-items:center;
  margin-top:var(--s3);padding:var(--s3);
  border:1px solid var(--accent-border);border-radius:var(--radius);
  background:var(--accent-soft)}

.wzor-srodek{display:flex;justify-content:center;margin-top:var(--s3)}

/* Podpis pod siatką: DWA WIERSZE ZAREZERWOWANE NA STAŁE, żeby okienko
   nie zmieniało wysokości w trakcie rysowania. Okienko jest wyśrodkowane,
   więc każdy dołożony wiersz podnosiłby siatkę pod palcem klienta
   i ucinał wzór w połowie. */
.wzor-podpis{min-height:2.8em;margin:var(--s3) 0 0;
  color:var(--ink-2);font-size:var(--fs-sm);text-align:center}
.wzor-podpis.uwaga{color:var(--warn)}

/* Okienko wzoru stoi NAD szufladą przyjęcia (ta ma z-index 40), a jego
   przesłona tuż pod nim — bez tego klik obok okienka trafiałby w pola
   formularza pod spodem. */
.scrim.nad-szuflada{z-index:59}
.okienko.nad-szuflada{z-index:60}

/* --- 7. SZUFLADA I PASEK ZAPISU ------------------------------------ */
/* Szuflada przyjęcia jest szersza od zwykłej, bo ma zmieścić dwa kafle
   obok siebie. Zwykła szuflada zostaje bez zmian. */
.drawer.przyjecie{width:min(96vw,1320px)}

.pasek-przyjecia{position:sticky;bottom:calc(-1 * var(--s5));
  display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
  margin:var(--s4) calc(-1 * var(--s6)) calc(-1 * var(--s5));
  padding:var(--s3) var(--s6);
  background:var(--surface);border-top:1px solid var(--line);
  box-shadow:0 -6px 18px rgba(20,18,14,.06);z-index:1}

@media (max-width:720px){
  .etapy{grid-template-columns:1fr}
  .pasek-przyjecia{margin-left:calc(-1 * var(--s4));margin-right:calc(-1 * var(--s4));
    padding-left:var(--s4);padding-right:var(--s4)}
}

/* --- ETAP, KTÓRY BLOKUJE ZAPIS ------------------------------------- */
/* Kolor błędu jest tu użyty JEDEN RAZ i zawsze znaczy to samo: ten etap
   nie pozwoli przyjąć sprzętu. Kafel z czerwonym komunikatem pod polem
   świecił wcześniej na pasku jako „uzupełnione". */
.etap.zly::before{background:var(--bad)}
.etap.zly .etap-nr{background:var(--bad-bg);color:var(--bad);
  border-color:var(--bad-border);box-shadow:none}
.etap-stan.zly{color:var(--bad)}
.kroki-przyjecia .krok.zly{color:var(--bad);background:var(--bad-bg)}
.kroki-przyjecia .krok.zly .krok-nr{background:var(--bad);color:#fff;
  border-color:var(--bad)}
.pasek-brak{color:var(--bad);font-weight:640;font-size:var(--fs-sm)}

/* Pytanie tak/nie przy przyjęciu — pigułka do klikania, nie goła kratka.
   Przy ladzie klika się w to palcem na tablecie, a pole 13×13 px trafia
   się co drugi raz. */
.odpowiedz-tak-nie{display:inline-flex;align-items:center;gap:8px;
  padding:7px 14px 7px 10px;border:1px solid var(--line);
  border-radius:var(--radius-pill);background:var(--surface);
  font-size:var(--fs-sm);color:var(--ink-2);cursor:pointer;
  transition:border-color .15s,background .15s,color .15s}
.odpowiedz-tak-nie:hover{border-color:var(--g5)}
.odpowiedz-tak-nie:has(input:checked){border-color:var(--accent);
  background:var(--accent-soft);color:var(--accent-text);font-weight:640}
.odpowiedz-tak-nie input{margin:0;accent-color:var(--accent)}

/* =====================================================================
   PO PRZYJĘCIU — ZDJĘCIA, POTEM WYDRUK
   =====================================================================
   Ten ekran ma jedno zadanie: doprowadzić do zdjęć, ZANIM klient
   dostanie kartkę i wyjdzie. Dlatego kroki są ponumerowane tak samo jak
   w formularzu, a kod zajmuje pół szerokości — ma być pierwszą rzeczą,
   na którą pada wzrok. */
.drawer.przyjete{width:min(94vw,860px)}

.numer-zlecenia{font-size:2.4rem;font-weight:700;letter-spacing:.01em;
  line-height:1.1;margin-bottom:var(--s2)}

.po-krok{margin-top:var(--s6);padding-top:var(--s4);
  border-top:1px solid var(--line-soft)}
.po-krok-hd{display:flex;align-items:center;gap:10px;margin-bottom:var(--s2)}
.po-krok-tytul{margin:0;font-size:var(--fs-md);font-weight:680;
  letter-spacing:-.01em}
.po-krok-nr{flex:0 0 auto;width:26px;height:26px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--fs-sm);font-weight:800;font-variant-numeric:tabular-nums;
  background:var(--surface-2);color:var(--ink-3);border:1.5px solid var(--line);
  transition:background .2s,color .2s,border-color .2s}
.po-krok.zrobiony .po-krok-nr{background:var(--accent);color:var(--accent-ink);
  border-color:var(--accent)}
.po-krok-stan{margin-left:auto;font-size:11px;font-weight:800;
  text-transform:uppercase;letter-spacing:.07em;color:var(--ink-3)}
.po-krok-stan.ok{color:var(--accent-text)}
.po-krok-opis{margin:0 0 var(--s3);color:var(--ink-2);font-size:var(--fs-sm);
  line-height:1.5;max-width:62ch}
.po-krok-opis.ostrzega{color:var(--warn)}

.po-kod{display:flex;gap:var(--s5);align-items:flex-start;flex-wrap:wrap}
.po-kod-obraz{width:190px;height:190px;flex:0 0 auto;border-radius:12px;
  border:1px solid var(--line);background:#fff;padding:8px}
.po-kod-obok{flex:1 1 260px;min-width:0}

.po-miniatury{display:flex;gap:8px;flex-wrap:wrap;margin-top:var(--s3)}
/* Miniatura wjeżdża sama, gdy zdjęcie doleci z telefonu — to jedyne
   potwierdzenie, jakie serwisant dostaje, że wysyłka się udała. */
.po-miniatura{width:62px;height:62px;border-radius:10px;object-fit:cover;
  border:1px solid var(--line);background:var(--surface-2);
  animation:miniatura-wchodzi .3s ease}
@keyframes miniatura-wchodzi{
  from{opacity:0;transform:scale(.86)}
  to{opacity:1;transform:scale(1)}
}
@media (prefers-reduced-motion:reduce){ .po-miniatura{animation:none} }

@media (max-width:560px){
  .po-kod-obraz{width:160px;height:160px}
}

/* Stan dwóch rzeczy do zrobienia telefonem. Jedna linijka na każdą,
   bo to jest lista kontrolna przy kliencie, a nie raport. */
.po-stan-lista{display:grid;gap:6px}
.po-stan{display:flex;align-items:baseline;gap:10px;
  padding:7px 12px;border-radius:var(--radius);
  border:1px solid var(--line);background:var(--surface-2);
  font-size:var(--fs-sm)}
.po-stan b{font-weight:660;min-width:110px}
.po-stan span{color:var(--ink-3)}
.po-stan.ok{border-color:var(--accent-border);background:var(--accent-soft)}
.po-stan.ok span{color:var(--accent-text);font-weight:600}

/* =====================================================================
   KARTA NAPRAWY
   =====================================================================
   Trzy kolumny, każda o czymś innym: lewa to FAKTY (sprzęt, dowody),
   środek to PRZEBIEG (oś czasu, czas pracy), prawa to DECYZJE (status,
   serwisant, wydruki). Patrzy się od lewej do prawej — i tak samo
   schodzą pod siebie na wąskim ekranie. */
.karta-naprawy{max-width:1680px}

.kn-hd{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  margin-bottom:var(--s4);padding-bottom:var(--s3);
  border-bottom:1px solid var(--line)}
.kn-numer{margin:0;font-size:var(--fs-2xl);font-weight:700;letter-spacing:.01em}
.kn-kto{text-align:right;line-height:1.3}
.kn-klient{font-weight:660}

.kn-kolumny{display:grid;gap:var(--s4);
  grid-template-columns:minmax(300px,1fr) minmax(380px,1.45fr) minmax(260px,.85fr);
  align-items:start}
.kn-kolumna{display:flex;flex-direction:column;gap:var(--s4);min-width:0}
.kn-kolumna > .card{margin:0}

@media (max-width:1280px){
  .kn-kolumny{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  /* Decyzje wracają na górę: przy dwóch kolumnach status jest pierwszą
     rzeczą, po którą sięga ręka. */
  .kn-kolumna:last-child{grid-column:1 / -1;
    flex-direction:row;flex-wrap:wrap;order:-1}
  .kn-kolumna:last-child > .card{flex:1 1 240px}
}
@media (max-width:760px){
  .kn-kolumny{grid-template-columns:1fr}
  .kn-kolumna:last-child{flex-direction:column}
}

.kn-wartosc{font-weight:640;font-size:var(--fs-base);min-height:22px}
.kn-opis{margin:0 0 var(--s3);line-height:1.55;white-space:pre-wrap}

/* --- zdjęcia --- */
.kn-etap-zdjec + .kn-etap-zdjec{margin-top:var(--s4)}
/* Pierwszy nagłówek etapu siedzi tuż pod belką karty — bez linii
   i odstępu, które rozdzielają dopiero kolejne etapy. */
.kn-etap-zdjec:first-child > .podsekcja{margin-top:0;padding-top:0;border-top:0}
.kn-galeria{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));
  gap:8px}
.kn-galeria img{width:100%;aspect-ratio:1;object-fit:cover;display:block;
  border-radius:10px;border:1px solid var(--line);background:var(--surface-2)}
.kn-galeria a:hover img{border-color:var(--accent)}

/* --- oś czasu --- */
.kn-filtr{display:flex;gap:4px}
.kn-dopisz{margin-bottom:var(--s4);padding-bottom:var(--s4);
  border-bottom:1px solid var(--line-soft)}
.kn-dopisz .formrow{margin-top:var(--s2)}

.kn-os{list-style:none;margin:0;padding:0;position:relative}
/* Pionowa nitka spinająca wpisy w jeden ciąg — bez niej to jest lista
   akapitów, a nie historia. */
.kn-os::before{content:'';position:absolute;left:5px;top:6px;bottom:6px;
  width:1px;background:var(--line)}
.kn-wpis{position:relative;padding:0 0 var(--s4) 22px}
.kn-wpis::before{content:'';position:absolute;left:0;top:6px;
  width:11px;height:11px;border-radius:50%;
  background:var(--surface);border:2px solid var(--line)}
.kn-wpis.notatka::before{border-color:var(--accent)}
.kn-wpis.status::before{background:var(--ink-3);border-color:var(--ink-3)}

.kn-wpis-hd{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  font-size:var(--fs-sm)}
.kn-wpis-kto{font-weight:660}
.kn-wpis-czas{color:var(--ink-3);font-size:12px}
.kn-znacznik{font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.06em;padding:2px 7px;border-radius:var(--radius-pill,6px);
  background:var(--surface-2);color:var(--ink-3);border:1px solid var(--line)}
.kn-wpis-tresc{margin-top:3px;line-height:1.5;white-space:pre-wrap}
.kn-wpis.status .kn-wpis-tresc{color:var(--ink-2);font-size:var(--fs-sm)}
.kn-wpis-komentarz{margin-top:3px;color:var(--ink-2);font-size:var(--fs-sm);
  padding-left:10px;border-left:2px solid var(--line)}

/* --- czas pracy --- */
.kn-czasy{list-style:none;margin:var(--s3) 0 0;padding:0;
  display:grid;gap:5px;font-size:var(--fs-sm)}
.kn-czasy li{display:flex;gap:10px;align-items:baseline;
  padding:5px 10px;border-radius:var(--radius-sm);background:var(--surface-2)}
.kn-czasy b{min-width:64px;font-variant-numeric:tabular-nums}

.kn-kod{width:100%;max-width:190px;border-radius:12px;
  border:1px solid var(--line);background:#fff;padding:8px;display:block;
  margin-bottom:var(--s3)}

.formrow.pion{flex-direction:column;align-items:stretch}

/* =====================================================================
   SKĄD JEST TA CENA — przy podpowiedzi z cennika.
   Cena dopasowana do modelu i cena ogólna wyglądają identycznie, dopóki
   się ich nie rozróżni; a to jest różnica między „bierz i zapisuj"
   a „popraw, zanim zapiszesz".
   ===================================================================== */
.cena-skad{margin-left:var(--s2);font-size:var(--fs-xs);font-weight:500;
  padding:1px var(--s2);border-radius:var(--radius-pill,6px);white-space:nowrap;
  background:var(--surface-2);color:var(--ink-3);border:1px solid var(--line)}
.cena-skad.dopasowana{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-border)}

/* =====================================================================
   POZYCJE NA KARCIE NAPRAWY
   Trzy kolumny liczb i przycisk: nazwa rośnie, liczby trzymają prawą
   krawędź w tej samej pionowej linii (tabular-nums), żeby dało się je
   porównać wzrokiem bez czytania każdej osobno.
   ===================================================================== */
.kn-pozycje{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.kn-pozycje td{padding:var(--s2) 0;border-bottom:1px solid var(--line);vertical-align:top}
.kn-pozycje tbody tr:last-child td{border-bottom:0}
.kn-pozycje .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.kn-pozycje .kn-poz-ile{padding-left:var(--s3);width:1%}
.kn-pozycje .kn-poz-suma{padding-left:var(--s4);width:1%}
.kn-pozycje .kn-poz-usun{padding-left:var(--s3);width:1%;text-align:right}
.kn-poz-nazwa{font-weight:600}
.kn-pozycje tfoot td{padding-top:var(--s3);border-top:1px solid var(--line);border-bottom:0}
.kn-dopisz-pozycje{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line)}

/* Na telefonie wiersz przestaje być wierszem tabeli i staje się kafelkiem
   2×2: nazwa i ilość po lewej, kwota i „Usuń" po prawej. Samo rozbicie
   komórek na `display:block` nie wystarcza — szerokości `width:1%`
   z wersji szerokiej zostają i ściskają przycisk do jednej litery
   na linię. Dlatego siatka, z jawnie wskazanym miejscem każdej komórki. */
@media (max-width:560px){
  .kn-pozycje,.kn-pozycje tbody,.kn-pozycje tfoot{display:block;width:100%}
  /* `auto` w drugiej kolumnie potrafi zejść poniżej treści, gdy pierwsza
     bierze `1fr` — kwota traci wtedy ostatni znak. `max-content` mówi
     wprost: kolumna z kwotami ma tyle, ile trzeba, reszta dla nazwy. */
  .kn-pozycje tr{display:grid;grid-template-columns:minmax(0,1fr) max-content;
    gap:2px var(--s3);align-items:start;
    padding:var(--s3) 0;border-bottom:1px solid var(--line)}
  .kn-pozycje tbody tr:last-child{border-bottom:0}
  .kn-pozycje td{display:block;width:auto;padding:0;border:0;text-align:left}
  /* Te trzy mają w wersji szerokiej `width:1%` i wyższą wagę selektora
     niż `.kn-pozycje td` — bez powtórzenia z tą samą wagą przycisk „Usuń"
     dostaje 12 px i wychodzi poza komórkę. */
  .kn-pozycje .kn-poz-ile,
  .kn-pozycje .kn-poz-suma,
  .kn-pozycje .kn-poz-usun{width:auto;padding-left:0}
  /* Ilość stoi pod nazwą, w lewej kolumnie — dosunięta do prawej
     wyglądałaby jak druga kwota. */
  .kn-pozycje .kn-poz-ile{text-align:left}
  .kn-pozycje tr > td:nth-child(1){grid-area:1/1}
  .kn-pozycje tr > td:nth-child(2){grid-area:2/1}
  .kn-pozycje tr > td:nth-child(3){grid-area:1/2;text-align:right}
  .kn-pozycje tr > td:nth-child(4){grid-area:2/2;text-align:right;
    justify-self:end;margin-top:var(--s2)}
  .kn-pozycje tfoot tr{border-bottom:0;border-top:1px solid var(--line);
    padding-top:var(--s3)}
  /* W stopce brutto ma stać przy słowie „Razem" — to ta kwota, o którą
     pyta klient. Netto schodzi linijkę niżej. */
  .kn-pozycje tfoot tr > td:nth-child(2){grid-area:2/2;text-align:right}
  .kn-pozycje tfoot tr > td:nth-child(3){grid-area:1/2;text-align:right}
  /* Czwarta komórka stopki jest pusta — na siatce zostawiłaby dziurę. */
  .kn-pozycje tfoot tr > td:nth-child(4){display:none}
}

/* Podpowiedzi puste — informacja, gdzie dopisać pozycję na stałe. */
.podpowiedz-pusto{padding:var(--s3);font-size:var(--fs-sm);line-height:1.5}

/* =====================================================================
   KARTA NAPRAWY — dopięcia do układu przejętego z karty zgłoszenia IT.
   Wszystko, co da się wziąć stamtąd (kartahd, pasek-zlecenia,
   karta-kolumny, kafel, blok), jest brane stamtąd; tu zostają tylko
   rzeczy, których karta IT nie ma.
   ===================================================================== */

/* Ostrzeżenie o nietypowym przejściu statusu stoi w pasku, obok
   przycisku, który je wywoła — nie w osobnym pudełku pod spodem. */
.ostrzezenie-przejscia{flex:1 1 100%;font-size:var(--fs-sm);color:var(--warn,var(--bad))}

/* Kod QR na telefon: pokazuje się po kliknięciu i znika po schowaniu,
   zamiast zajmować kolumnę przez cały czas. */
.kn-kod-kafel{display:flex;gap:var(--s4);align-items:center;margin-bottom:var(--s4)}
.kn-kod-kafel .kn-kod{width:132px;height:132px;flex:none}

/* Historia klienta — lista, nie tabela: cztery pola w rzędzie. */
.kn-historia-lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s2)}
.kn-historia-lista li{display:grid;grid-template-columns:auto auto 1fr auto;
  gap:var(--s3);align-items:baseline;font-size:var(--fs-sm)}
.kn-historia-lista .tnij{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
@media (max-width:560px){
  .kn-historia-lista li{grid-template-columns:auto 1fr}
  .kn-historia-lista li > :nth-child(3){grid-column:1/-1}
}

/* Kod odblokowania odsłonięty na ekranie — duży i jednoznaczny.
   Serwisant przepisuje go na telefon, patrząc raz. */
.kod-jawny{font-family:var(--font-mono,ui-monospace,monospace);font-size:var(--fs-lg);
  letter-spacing:.12em;padding:2px var(--s2);border-radius:var(--radius-sm,4px);
  background:var(--surface-2);border:1px solid var(--line)}

/* Odpowiedzi z przyjęcia: te same dwie kolumny co w kaflu z faktami,
   tylko na całą szerokość bloku. */
.kn-pytania{margin:0}

/* Na karcie naprawy obie kolumny niosą tyle samo faktów — sprzęt po
   lewej, klient i pieniądze po prawej. Wąska prawa kolumna z karty IT
   (tam jest w niej stanowisko, czyli trzy linijki) łamała tu „923,04 zł
   z 1123,04 zł po zaliczce" na trzy wiersze, a lewa stała pusta. */
.karta-naprawy .karta-kolumny > .lewa,
.karta-naprawy .karta-kolumny > .prawa{flex:1 1 420px;min-width:0}

/* Notatki na karcie naprawy — ta sama forma co wpisy w przebiegu. */
.kn-notatki{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s3)}
.kn-notatki li{padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
.kn-notatki li:last-child{padding-bottom:0;border-bottom:0}
/* Opis przy wpisie czasu: to on odpowiada na pytanie „za co ta godzina". */
.kn-czas-opis{margin-left:var(--s3)}

/* Okienko NA karcie, która sama jest szufladą — musi być nad nią,
   nie pod. Szuflada ma z-index 50, więc te idą wyżej. */
.scrim-2{z-index:70}
.okienko-2{z-index:71;width:min(720px,92vw)}
.kn-okno-kod{display:flex;justify-content:center;padding:var(--s5) 0}
.okienko .kn-historia-lista li{padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.okienko .kn-historia-lista li:last-child{border-bottom:0}

/* Pliki przy zleceniu — lista do czytania, nie galeria miniatur. */
.kn-pliki{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s2)}
.kn-pliki li{display:grid;grid-template-columns:1fr auto auto;gap:var(--s3);
  align-items:baseline;font-size:var(--fs-sm);padding-bottom:var(--s2);
  border-bottom:1px solid var(--line)}
.kn-pliki li:last-child{border-bottom:0;padding-bottom:0}
.kn-plik-nazwa{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:560px){
  .kn-pliki li{grid-template-columns:1fr auto}
  .kn-pliki li > :last-child{grid-column:1/-1}
}

/* Wgrywanie przez <label class="btn"> — input jest schowany, więc etykieta
   musi zachowywać się jak przycisk, łącznie z kursorem. */
label.btn{cursor:pointer}
label.btn.zajety{opacity:.6;pointer-events:none}
.kn-zdjecia-akcje{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line)}

/* Poprawianie pozycji rozpycha wiersz na całą szerokość tabeli. */
.kn-popraw-pozycje{padding:var(--s3) 0}

/* Punkt (oddział) z przyciskiem przeniesienia w jednej linii. */
.kn-punkt{display:flex;gap:var(--s3);align-items:baseline;flex-wrap:wrap}

/* Numer i status w jednej kolumnie: numer u góry, status mniejszy pod
   spodem. Plakietka dostaje własny wiersz, żeby numery zostały w jednej
   pionowej linii i dały się porównać wzrokiem. */
.kol-numer{white-space:nowrap}
.kol-numer .numer-stanowiska{font-weight:650;margin-bottom:3px}
.kol-numer .pill{font-size:var(--fs-xs)}

/* Wpłaty przy zleceniu — kwota, forma, kto, i guzik do pomyłek. */
.kn-wplaty{list-style:none;margin:var(--s3) 0 0;padding:0;
  display:flex;flex-direction:column;gap:var(--s2)}
.kn-wplaty li{display:grid;grid-template-columns:auto auto 1fr auto;gap:var(--s3);
  align-items:baseline;font-size:var(--fs-sm);
  padding-bottom:var(--s2);border-bottom:1px solid var(--line)}
.kn-wplaty li:last-child{border-bottom:0;padding-bottom:0}
.ok-tekst{color:var(--ok)}
@media (max-width:560px){
  .kn-wplaty li{grid-template-columns:1fr auto}
  .kn-wplaty li > :nth-child(3){grid-column:1/-1}
}

/* =====================================================================
   KASA
   =====================================================================
   Baner „na ten moment w kasie powinno być" to jedyna rzecz, dla której
   ktoś otwiera ten ekran w środku dnia — więc jest największą liczbą na
   ekranie i nie dzieli miejsca z niczym innym.
   ===================================================================== */
.kasa-punkt{margin-bottom:var(--s4)}
.kasa-baner{background:var(--surface-2);border:1px solid var(--line);
  border-left:4px solid var(--accent);border-radius:var(--radius-lg);
  padding:var(--s4) var(--s5);margin-bottom:var(--s4)}
.kasa-baner.zamkniety{border-left-color:var(--g5)}
.kasa-baner-l{font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-3)}
.kasa-baner-v{font-size:calc(var(--fs-2xl) * 1.5);font-weight:680;letter-spacing:-.03em;
  line-height:1.1;margin-top:2px;font-variant-numeric:tabular-nums}
.kasa-baner-d{font-size:var(--fs-sm);color:var(--ink-3);margin-top:6px}
.kasa-baner-roznica{margin-top:var(--s3);font-size:var(--fs-sm);font-weight:600;
  color:var(--bad)}
.kasa-kpi{margin-bottom:var(--s4)}
/* KASA — układ z wykresem (27.09.2026). Baner z rachunkiem szuflady po
   lewej, utarg z 30 dni po prawej; niżej cztery kafle z trendem. */
.kasa-gora{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s3);
  margin-bottom:var(--s3);align-items:stretch}
.kasa-gora .kasa-baner{margin-bottom:0;display:flex;flex-direction:column}
.kasa-rachunek{margin:auto 0 0;padding-top:var(--s4);display:flex;flex-direction:column;gap:6px}
.kasa-rachunek > div{display:flex;align-items:baseline;gap:8px;font-size:var(--fs-sm)}
.kasa-rachunek > div::after{content:"";order:1;flex:1;border-bottom:1px dotted var(--line-2, var(--line));transform:translateY(-4px)}
.kasa-rachunek dt{order:0;color:var(--ink-2);margin:0;white-space:nowrap}
.kasa-rachunek dd{order:2;margin:0;font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap}
.kasa-rachunek dd.ton-ok{color:var(--ok)} .kasa-rachunek dd.ton-zle{color:var(--bad)}
.kasa-rachunek .op{display:inline-block;width:12px;color:var(--ink-3);font-weight:600}
.kasa-rachunek .wynik{border-top:1px solid var(--line);padding-top:8px;margin-top:2px}
.kasa-rachunek .wynik dt{color:var(--ink);font-weight:650}
.kasa-rachunek .wynik dd{font-weight:750;font-size:var(--fs-md, 15px)}
.kasa-rachunek .obok{color:var(--ink-3)} .kasa-rachunek .obok dt,.kasa-rachunek .obok dd{color:var(--ink-3);font-weight:500}
.kasa-baner{padding-bottom:var(--s4)}

.kasa-utarg{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:var(--s4) var(--s4) var(--s3);display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.kasa-utarg-hd{display:flex;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;align-items:flex-start}
.kasa-utarg-hd h4{margin:0;font-size:var(--fs-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--ink-2)}
.kasa-utarg-pod{font-size:var(--fs-sm);color:var(--ink-3);margin-top:4px}
.kasa-utarg-pod strong{color:var(--ink);font-variant-numeric:tabular-nums}
.kasa-legenda{display:flex;gap:var(--s3);font-size:var(--fs-xs);color:var(--ink-2);flex-wrap:wrap}
.kasa-legenda span,.kasa-dymek span{display:inline-flex;align-items:center;gap:6px}
.kasa-legenda i,.kasa-dymek i{display:inline-block;width:10px;height:10px;border-radius:3px}
i.got{background:var(--seria-2)} i.bez{background:var(--seria-1)}

.kasa-wykres{display:grid;grid-template-columns:auto 1fr;grid-template-rows:170px auto;column-gap:8px}
.kasa-wykres-os{display:flex;flex-direction:column;justify-content:space-between;align-items:flex-end;
  font-size:var(--fs-xs);color:var(--ink-3);font-variant-numeric:tabular-nums;
  margin:-7px 0;white-space:nowrap}
.kasa-wykres-pole{position:relative;min-width:0}
.kasa-wykres-siatka{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:space-between;pointer-events:none}
.kasa-wykres-siatka i{display:block;border-top:1px solid var(--line);opacity:.7}
.kasa-wykres-siatka i:last-child{opacity:1;border-top-color:var(--line-2, var(--line))}
.kasa-wykres-srednia{position:absolute;left:0;right:0;border-top:1.5px dashed var(--ink-3);pointer-events:none;z-index:1}
.kasa-wykres-srednia span{position:absolute;left:4px;bottom:3px;font-size:var(--fs-xs);color:var(--ink-2);
  background:var(--surface);padding:0 4px;border-radius:3px}
.kasa-wykres-slupki{position:absolute;inset:0;display:flex;align-items:stretch;gap:3px}
.kasa-slupek{flex:1 1 0;min-width:0;display:flex;align-items:flex-end;cursor:default;outline:none;border-radius:4px}
.kasa-slupek:focus-visible{box-shadow:0 0 0 2px var(--accent)}
.kasa-slupek-stos{width:100%;height:100%;display:flex;flex-direction:column-reverse;gap:2px}
.kasa-slupek .seg{width:100%;min-height:2px;opacity:.55;transition:opacity .12s}
.kasa-slupek .seg.got{background:var(--seria-2)} .kasa-slupek .seg.bez{background:var(--seria-1)}
.kasa-slupek .seg:last-child{border-radius:4px 4px 0 0}
.kasa-slupek.wybrany .seg,.kasa-slupek.nad .seg{opacity:1}
.kasa-slupek.wybrany{background:color-mix(in srgb, var(--accent) 10%, transparent)}
.kasa-wykres-daty{grid-column:2;position:relative;height:18px;font-size:var(--fs-xs);color:var(--ink-3);margin-top:4px}
.kasa-wykres-daty span{position:absolute;transform:translateX(-50%);white-space:nowrap}
.kasa-dymek{position:absolute;top:0;transform:translateX(-50%);z-index:3;pointer-events:none;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 6px 20px rgba(0,0,0,.14);padding:8px 10px;display:flex;flex-direction:column;gap:3px;
  font-size:var(--fs-xs);white-space:nowrap;color:var(--ink-2)}
.kasa-dymek b{color:var(--ink);font-variant-numeric:tabular-nums;margin-left:4px}
.kasa-dymek strong{color:var(--ink);font-size:var(--fs-sm)}

.kasa-skad{border-top:1px solid var(--line);padding-top:var(--s3);display:flex;flex-direction:column;gap:6px}
.kasa-skad-t{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.04em;color:var(--ink-3)}
.kasa-skad-w{display:grid;grid-template-columns:minmax(120px,170px) 1fr auto auto;gap:10px;align-items:center;font-size:var(--fs-sm)}
.kasa-skad-w .pasek{height:8px;border-radius:4px;background:var(--surface-2);overflow:hidden}
.kasa-skad-w .pasek i{display:block;height:100%;border-radius:4px}
.kasa-skad-w .v{font-weight:620;text-align:right}
.kasa-skad-w .o{color:var(--ink-3);font-size:var(--fs-xs);min-width:72px;text-align:right}

.kasa-kpi{grid-template-columns:repeat(4,minmax(0,1fr))}
.kasa-kafel{display:flex;flex-direction:column}
.kasa-kafel-opis{font-size:var(--fs-xs);color:var(--ink-3);margin-top:2px}
.kasa-kafel .kpi-trend{margin-top:auto;padding-top:10px;height:36px}
.kasa-kafel .v.ton-ok ~ .kpi-trend{color:var(--seria-2)}
.kasa-zmiana{font-weight:650;color:var(--ink-2);font-variant-numeric:tabular-nums}
@media (max-width:1100px){
  .kasa-gora{grid-template-columns:1fr}
  .kasa-kpi{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:560px){
  .kasa-kpi{grid-template-columns:1fr}
  .kasa-skad-w{grid-template-columns:1fr auto}
  .kasa-skad-w .pasek,.kasa-skad-w .o{display:none}
}

/* Porównanie „powinno być / przeliczono" w okienku zamknięcia. */
.kasa-porownanie{display:flex;gap:var(--s4);flex-wrap:wrap;
  background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius);padding:var(--s3) var(--s4);margin-bottom:var(--s4)}
.kasa-porownanie > div{display:flex;flex-direction:column;gap:2px;flex:1 1 120px;min-width:0}
.kasa-porownanie .l{font-size:var(--fs-sm);color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.04em}
.kasa-porownanie .v{font-size:var(--fs-lg);font-weight:640;
  font-variant-numeric:tabular-nums}

.kasa-tab td.num,.kasa-tab th.num{text-align:right;font-variant-numeric:tabular-nums}
.kasa-tab td.akcje,.kasa-tab th.akcje{width:1%;white-space:nowrap;text-align:right}
.kasa-tab tr.wygaszony td{opacity:.55;text-decoration:line-through}
.kasa-tab tr.wygaszony td.akcje{text-decoration:none}
.kasa-tab .ton-ok{color:var(--ok)}
.kasa-tab .ton-zle{color:var(--bad)}

@media (max-width:760px){
  .kasa-baner-v{font-size:var(--fs-2xl)}
  /* Na telefonie „Usuń"/„Storno" nie może zostać zgnieciona do 12 px —
     szerokość 1% z wersji biurkowej wygrywała specyficznością. */
  .kasa-tab td.akcje,.kasa-tab th.akcje{width:auto}
}

/* =====================================================================
   WYCENA DO AKCEPTACJI (karta naprawy)
   =====================================================================
   Pasek stoi NAD listą pozycji, bo to on mówi, czy tę listę wolno
   jeszcze ruszać. Kolor lewej krawędzi niesie stan: czekamy / zgoda /
   odmowa — żeby dało się to odczytać, zanim ktokolwiek przeczyta napis.
   ===================================================================== */
.kn-wycena{border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:var(--radius);padding:var(--s3) var(--s4);margin:0 0 var(--s3);
  background:var(--surface-2)}
.kn-wycena.zaakceptowana{border-left-color:var(--ok)}
.kn-wycena.odrzucona{border-left-color:var(--bad)}
.kn-wycena-hd{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap}
.kn-wycena-hd .mono{margin-left:auto;font-size:var(--fs-lg);font-weight:660;
  font-variant-numeric:tabular-nums}
.kn-wycena-uwaga{margin-top:var(--s2);padding-left:var(--s3);
  border-left:2px solid var(--line);color:var(--ink-2)}
.kn-wycena .pasek-akcji{margin-top:var(--s3)}
.kn-wycena-start{margin:0 0 var(--s3)}

/* ROZJAZD KWOTY — dotyczy wyceny ręcznej (migracja 187). Klient zgodził
   się na kwotę, pozycje mają się do niej zsumować. Czerwień jest tu na
   miejscu: zamknięcie zlecenia na inną kwotę niż uzgodniona to spór przy
   ladzie. Wariant „czeka" jest spokojny, bo brak pozycji to jeszcze nie
   pomyłka, tylko praca przed sobą. */
.kn-wycena-rozjazd{margin-top:var(--s2);padding:var(--s2) var(--s3);
  border-radius:var(--radius-sm);background:var(--bad-bg);color:var(--bad);
  border:1px solid var(--bad-border);font-size:var(--fs-sm);line-height:1.5}
.kn-wycena-rozjazd.czeka{background:var(--g0);color:var(--ink-2)}

/* WYBÓR TRYBU WYCENY — „z pozycji" kontra „kwotą z palca". Stoi na górze
   okienka, bo zmienia wszystko, co pod nim. */
.kn-tryb-wyceny{display:flex;gap:var(--s2);margin:0 0 var(--s3);flex-wrap:wrap}
.kn-tryb-wyceny .btn.wybrany{background:var(--accent-soft);
  border-color:var(--accent-border);color:var(--accent-text);font-weight:600}

/* =====================================================================
   WYCENA W DYMKU ROZMOWY
   =====================================================================
   Łukasz, 13.09.2026: „dać większą czcionką pełną kwotę za usługę /
   grubszą żeby się wyróżniało i rozbić na pozycje niżej".
   Kwota jest jedyną liczbą, o którą ktokolwiek tu pyta — dostaje własny
   wiersz i własny stopień w skali. Pozycje pod spodem są jej
   uzasadnieniem, nie konkurencją, więc idą drobniej i ciszej. */
.wiad-wycena{border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:var(--radius);padding:var(--s3) var(--s4);margin:0 0 var(--s2);
  background:var(--surface)}
.wiad-wycena.zaakceptowana{border-left-color:var(--ok)}
.wiad-wycena.odrzucona,.wiad-wycena.wycofana{border-left-color:var(--bad)}
.wiad-wycena-hd{font-size:var(--fs-xs);text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-3);font-weight:600}
.wiad-wycena-hd .ok{color:var(--ok)}
.wiad-wycena-hd .zle{color:var(--bad)}
.wiad-wycena-hd .czeka{color:var(--ink-3);font-weight:500}
.wiad-wycena-kwota{font-size:calc(var(--fs-lg) * 1.45);font-weight:750;
  letter-spacing:-.02em;line-height:1.15;margin:2px 0 0;
  font-variant-numeric:tabular-nums}
.wiad-wycena-za{color:var(--ink-2);margin-top:2px}
.wiad-wycena-poz{list-style:none;margin:var(--s2) 0 0;padding:0;
  display:flex;flex-direction:column;gap:2px;font-size:var(--fs-sm)}
.wiad-wycena-poz li{display:flex;gap:var(--s3);align-items:baseline}
.wiad-wycena-poz li span:first-child{flex:1;min-width:0;color:var(--ink-2)}
.wiad-wycena-poz li .mono{font-variant-numeric:tabular-nums;white-space:nowrap}
.wiad-wycena-stopka{margin-top:var(--s2);font-size:var(--fs-xs);color:var(--ink-3)}

/* Rząd „Pieniądze" w pasku zlecenia — odpowiedź na pytanie, które przy
   ladzie pada pierwsze: brać pieniądze czy wydawać sprzęt. */
.rzad-pieniadze .kn-do-zaplaty{display:inline-flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.rzad-pieniadze .kn-do-zaplaty b{font-size:var(--fs-lg);font-variant-numeric:tabular-nums}
.rzad-pieniadze.oplacone .stan-przydzialu.zamkniete .kropka{background:var(--ok)}

/* Link do panelu klienta — ma być czytelny do przepisania z ekranu,
   bo przy ladzie często właśnie tak trafia do klienta. */
.kn-link-panelu{background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius);padding:var(--s3) var(--s4);margin:var(--s3) 0;
  word-break:break-all;font-size:var(--fs-sm);line-height:1.6;user-select:all}

/* Skąd przyszły pieniądze — rozbicie przychodu dnia na kanały.
   Gotówkowy kanał ma mocniejszą krawędź, bo tylko on rusza szufladę. */
.kasa-kanaly{display:flex;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s4)}
.kasa-kanal{flex:1 1 180px;background:var(--surface-2);border:1px solid var(--line);
  border-left:3px solid var(--g5);border-radius:var(--radius);padding:var(--s3) var(--s4)}
.kasa-kanal.gotowka{border-left-color:var(--accent)}
.kasa-kanal .l{display:block;font-size:var(--fs-sm);text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-3)}
.kasa-kanal .v{display:block;font-size:var(--fs-lg);font-weight:660;
  font-variant-numeric:tabular-nums;margin-top:2px}
.kasa-kanal .d{display:block;font-size:var(--fs-sm);color:var(--ink-3);margin-top:2px}

/* Karta klienta: kontakt na wierzchu i uwaga, która ma być widoczna. */
.klient-kontakt{margin-bottom:var(--s4)}
.klient-kontakt .kafel-fakty{grid-template-columns:110px 1fr}
.klient-kontakt a{color:var(--accent-text);text-decoration:none}
.klient-kontakt a:hover{text-decoration:underline}
.klient-notatka{margin-bottom:var(--s4);border-left-color:var(--warn,#b8860b)}

/* =====================================================================
   NAPRAWY, PRZY KTÓRYCH PIŁKA JEST PO NASZEJ STRONIE
   =====================================================================
   Łukasz, 13.09.2026: „Naprawa na liście napraw z zaakceptowaną wyceną /
   opłaconą naprawą powinna być zdecydowanie wyróżniająca się."

   Pasek przy lewej krawędzi wiersza, nie kolor tła. Tło kolidowałoby
   z zaznaczeniem i z wierszem po terminie, a lista, w której co drugi
   wiersz jest pokolorowany, przestaje cokolwiek wyróżniać. Pasek widać
   kątem oka przy przewijaniu i nie zabiera niczego innego.

   Opłacone wygrywa z zaakceptowanym, gdy zachodzą oba: przy wydaniu
   liczy się pytanie o pieniądze. */
.karty tbody tr.wiersz-zgoda > td:first-child,
.karty tbody tr.wiersz-oplacone > td:first-child{position:relative}
.karty tbody tr.wiersz-zgoda > td:first-child::before,
.karty tbody tr.wiersz-oplacone > td:first-child::before{
  content:'';position:absolute;left:0;top:4px;bottom:4px;width:4px;
  border-radius:0 3px 3px 0}
.karty tbody tr.wiersz-zgoda > td:first-child::before{background:var(--accent)}
.karty tbody tr.wiersz-oplacone > td:first-child::before{background:var(--ok)}
.karty tbody tr.wiersz-oplacone.wiersz-zgoda > td:first-child::before{background:var(--ok)}

/* Plakietki pod statusem — jedna pod drugą, żeby numer i status zostały
   tam, gdzie ludzie już przywykli ich szukać. */
.kol-numer .pill{margin-top:3px}
.kol-numer .pill + .pill{display:block;width:fit-content}

/* =====================================================================
   OKIENKO, KTÓRE MA NIE UMKNĄĆ
   =====================================================================
   Wyskakuje serwisantowi w środku pracy, więc musi być rozpoznawalne
   w ułamku sekundy jako „coś stoi", a nie jako kolejne potwierdzenie.
   Kolorowa krawędź u góry niesie wagę — przy trzecim przypomnieniu
   o tej samej naprawie jest już czerwona. */
.okienko-pilne{border-top:4px solid var(--accent)}
.okienko-pilne.uwaga{border-top-color:var(--warn)}
.okienko-pilne.blad{border-top-color:var(--bad)}
.okienko-pilne .kartahd h3{font-size:var(--fs-lg);line-height:1.3}
.okienko-pilne .muted.mini{margin-top:var(--s2)}

/* Znacznik wydania obok numeru wersji — cicho, ale czytelnie. Ma być
   do odczytania, gdy ktoś go szuka, i niewidoczny, gdy nie szuka. */
.sidefoot .wersja .build{opacity:.75;font-variant-numeric:tabular-nums}

/* =====================================================================
   HISTORIA KONTAKTU Z KLIENTEM
   =====================================================================
   Osobny blok od „Przebiegu", bo odpowiada na inne pytanie: tamten mówi,
   co robiliśmy ze sprzętem, ten — co ustaliliśmy z człowiekiem.

   Kolor krawędzi niesie STRONĘ, nie wagę: czy to był ruch klienta, czy
   nasz. Przy „nie zgadzałem się na to" i „nikt mnie nie powiadomił" to
   jest pierwsza rzecz, której się szuka na tej liście. */
.kn-kontakt{list-style:none;margin:0;padding:0;display:flex;
  flex-direction:column;gap:2px}
.kn-kontakt-wpis{padding:var(--s2) var(--s3);border-left:3px solid var(--line);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;background:var(--surface-2)}
.kn-kontakt-wpis.od-klienta{border-left-color:var(--accent)}
.kn-kontakt-wpis.od-nas{border-left-color:var(--line)}
/* Pieniądze i wycena to zdarzenia, o które ktoś kiedyś zapyta —
   dostają mocniejszy kolor niż zwykła wiadomość. */
.kn-kontakt-wpis.pieniadze{border-left-color:var(--ok)}
.kn-kontakt-wpis.wycena.od-klienta{border-left-color:var(--ok)}
.kn-kontakt-hd{display:flex;align-items:baseline;gap:var(--s3)}
.kn-kontakt-hd strong{font-weight:600;min-width:0}
.kn-kontakt-czas{margin-left:auto;white-space:nowrap;color:var(--ink-3);
  font-size:var(--fs-sm);font-variant-numeric:tabular-nums}
.kn-kontakt-wpis .cichy{font-size:var(--fs-sm);margin-top:1px;overflow-wrap:anywhere}

/* Słowa klienta o sprzęcie — cytat, nie nasza klasyfikacja. Kursywa
   i cudzysłów mówią to bez dopisywania „klient napisał". */
.kn-slowa-klienta{font-style:italic;color:var(--ink-2)}
.kn-slowa-klienta::before{content:'„'}
.kn-slowa-klienta::after{content:'"'}

/* =====================================================================
   ZAPROSZENIE KLIENTÓW DO PANELU
   =====================================================================
   Okienko szersze od zwykłego, bo musi pomieścić listę z nazwiskiem
   i adresem — to po nich widać, że ktoś tu nie powinien być, a po
   wysyłce jest już za późno. */
.okienko-zaproszenia{max-width:820px;width:min(820px,94vw)}
.okienko-zaproszenia .tblwrap{overflow:auto}

/* Kafle w okienku: trzy w rzędzie i mniejsza liczba. W wersji na cały
   ekran mają przyciągać wzrok, tutaj są tylko trzema liczbami przed
   decyzją — i nie mogą zepchnąć listy poza ekran. */
.kpi-rzad.ciasny{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);
  margin-bottom:var(--s3)}
.kpi-rzad.ciasny .kpi{padding:var(--s2) var(--s3)}
.kpi-rzad.ciasny .kpi .v{font-size:var(--fs-xl)}
.kpi-rzad.ciasny .kpi .d{font-size:var(--fs-xs)}
@media (max-width:700px){ .kpi-rzad.ciasny{grid-template-columns:1fr} }

/* =====================================================================
   PACZKI PRZY ZLECENIU
   =====================================================================
   Przy naprawie wysyłkowej to jest pierwsze pytanie po „czy zapłacone":
   gdzie w tej chwili jest ten sprzęt. Kolor lewej krawędzi niesie stan,
   żeby dało się to odczytać przed przeczytaniem napisu. */
.kn-paczka{border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:var(--radius);padding:var(--s3) var(--s4);margin:0 0 var(--s2);
  background:var(--surface-2)}
.kn-paczka.zamowiona,.kn-paczka.nadana,.kn-paczka.w_drodze{border-left-color:var(--accent)}
.kn-paczka.doreczona{border-left-color:var(--ok)}
.kn-paczka.blad{border-left-color:var(--bad)}
.kn-paczka.anulowana{opacity:.6}
.kn-paczka-hd{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap}
/* Paczka w drodze na górze karty naprawy (26.09.2026) */
.kn-paczki-gora{margin:0 0 var(--s4)}
.kn-paczki-gora>.blok{margin:0}
.kn-paczki-starsze{margin:var(--s2) 0 0}
.kn-paczka-numer{font-size:var(--fs-lg);letter-spacing:.02em;user-select:all;
  margin-top:2px}
.kn-paczka .pasek-akcji{margin-top:var(--s2)}
.kn-paczka .note{margin-top:var(--s2)}

/* Ślad przewoźnika: najnowsze na górze, bo pytanie brzmi „gdzie jest
   teraz", a nie „od czego się zaczęło". */
.kn-paczka-slad{list-style:none;margin:var(--s2) 0 0;padding:0;
  display:flex;flex-direction:column;gap:2px;font-size:var(--fs-sm);
  max-height:190px;overflow:auto}
.kn-paczka-slad li{padding:2px 0;border-bottom:1px solid var(--line)}
.kn-paczka-slad li:last-child{border-bottom:none}

/* Adresy w okienku zamawiania — do sprawdzenia wzrokiem przed kliknięciem. */
.kn-paczka-adresy{margin:0 0 var(--s3)}

/* PROPOZYCJA DOPISANIA PRACOWNIKA Z PORTALU (migracja 197).
   Belka, nie okienko: to jest propozycja obok faktów o zgłoszeniu,
   a nie decyzja, która ma zatrzymać pracę. Kto nie chce się nią
   zajmować, po prostu czyta dalej. */
.propozycja-osoby{border:1px dashed var(--line);border-radius:var(--radius);
  padding:10px 12px;background:var(--surface-2);display:flex;flex-direction:column;gap:8px}
.po-tresc{line-height:1.45}
.po-akcje{display:flex;gap:8px;flex-wrap:wrap}
.po-pola{display:flex;gap:8px;flex-wrap:wrap}
.po-pola>.input{flex:1 1 180px;min-width:0}

/* LISTA OSÓB Z PORTALU DO DOPISANIA (migracja 197).
   Zwinięta belka nad listą stanowisk — nie znika z oczu, ale też nie
   zajmuje ekranu komuś, kto przyszedł tu po co innego. */
.z-portalu{border:1px dashed var(--line);border-radius:var(--radius);
  background:var(--surface-2);padding:10px 12px;margin-bottom:var(--s3)}
.z-portalu-hd{display:flex;align-items:baseline;gap:10px;width:100%;
  background:none;border:0;padding:0;font:inherit;color:var(--ink);
  cursor:pointer;text-align:left;flex-wrap:wrap}
.z-portalu .tabela{margin-top:var(--s3)}

/* SZYBKI SERWIS (migracja 201).
   Przycisk w górnym pasku i okno startu — dwa pola, nic więcej. */
.szybki-firmy{display:flex;flex-direction:column;gap:4px;margin-top:6px;
  max-height:220px;overflow-y:auto;overscroll-behavior:contain;
  border:1px solid var(--line-soft);border-radius:var(--radius);padding:4px;
  background:var(--surface-2)}
.szybki-firma{display:block;width:100%;text-align:left;padding:9px 12px;flex:0 0 auto;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  color:var(--ink);font:inherit;cursor:pointer}
.szybki-firma:hover{border-color:var(--accent)}
.szybki-rodzaje{display:flex;gap:8px;flex-wrap:wrap}
.szybki-rodzaje .btn{flex:1 1 120px}

/* Zegar w pasku: kropka pulsuje, żeby chodzący czas było widać kątem oka
   — zapomniany stoper to godziny doliczone klientowi po nocy. */
.szybki-leci{display:inline-flex;align-items:center;gap:7px;
  border-color:var(--ok-border,#b9e0c6);background:var(--ok-bg,#e8f5ec);
  color:var(--ok-ink,#1f7a3f);font-variant-numeric:tabular-nums}
.kropka-leci{width:8px;height:8px;border-radius:50%;background:currentColor;
  animation:kropka-puls 2s ease-in-out infinite}
@keyframes kropka-puls{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.kropka-leci{animation:none}}

/* =====================================================================
   SKUP I SPRZEDAŻ — umowa kupna-sprzedaży
   ===================================================================== */
/* Pasek po wystawieniu umowy. Nie jest to zwykły komunikat „zapisano",
   tylko miejsce, z którego robi się trzy następne rzeczy: wydruk,
   pieniądze, magazyn. Dlatego stoi na górze ekranu i zostaje, dopóki
   ktoś go nie zamknie. */
.pasek-po-umowie{display:flex;flex-direction:column;gap:8px}
.pasek-po-umowie .pasek-akcji{margin-top:2px}

/* Sumy pod filtrami liczą DOKŁADNIE to, co widać na liście. */
.umowy-sumy{gap:var(--s5);color:var(--ink-2);font-size:var(--fs-sm);
  padding:var(--s3) 0;border-bottom:1px solid var(--line-soft)}
.umowy-sumy b{color:var(--ink);font-variant-numeric:tabular-nums}

/* Podpowiedzi klientów w formularzu umowy: pionowa lista przycisków,
   a nie rząd — nazwiska bywają długie i rozjeżdżałyby okno. */
.umowy-podpowiedzi{display:flex;flex-direction:column;gap:4px;margin:4px 0 var(--s3)}
.umowy-podpowiedzi .btn{justify-content:flex-start;text-align:left}
.umowy-wybrany{display:flex;align-items:center;gap:var(--s3)}
.umowy-szukajka{flex:1 1 320px;max-width:420px}
/* Wybieraki w pasku akcji nie rozpychają się na całą szerokość:
   „Tylko skup" i „gdzie położyć" to krótkie listy, a rozciągnięte
   wyglądają jak pole do wpisywania. */
.umowy-waski{width:auto;flex:0 0 auto;max-width:280px}

/* =====================================================================
   PASEK NAD LISTĄ, KTÓRA SIEDZI JUŻ W PRZEGLĄDARCE
   =====================================================================
   Szukajka i licznik nad tabelą w karcie firmy. Stoi WEWNĄTRZ bloku,
   tuż nad nagłówkami — tam, gdzie człowiek patrzy, gdy lista okazuje
   się za długa, a nie w osobnym pasku nad całą kartą. */
.lista-pasek{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-soft)}
.lista-szukajka{flex:1 1 240px;max-width:340px}
.lista-pasek .muted{font-size:var(--fs-sm);white-space:nowrap}
/* Wiersz zaznaczony do czynności hurtowej — widać, co pójdzie. */
tr.zaznaczony > td{background:var(--accent-soft,rgba(37,99,235,.07))}
.ptaszek-kol{width:32px}
/* Szukajka w szufladzie mapy — pełna szerokość szuflady, bo szuflada
   jest wąska i pole węższe od niej wyglądałoby na pomyłkę. */
.mapa-szukajka{width:100%;margin:6px 0 8px}

/* Komentarz klienta pod decyzją o wycenie. Cytat, a nie kolejna linijka
   metadanych — bo to jedyne w tej tabeli zdanie napisane ręką klienta
   i to ono mówi, co zrobić dalej. */
.dok-uwaga-klienta{margin-top:5px;padding-left:9px;
  border-left:3px solid var(--accent-border);
  font-size:var(--fs-sm);font-style:italic;color:var(--ink-2);
  max-width:34ch}

/* =====================================================================
   KANDYDACI NA ABONENTA PRZY RĘCZNYM PRZYPISANIU ROUTERA
   =====================================================================
   Lista wyborów, nie lista informacji — więc cały wiersz jest celem
   kliknięcia, a nie sam znaczek. Technik robi to jedną ręką, często na
   laptopie na kolanie w aucie. */
.lista-kandydatow{display:flex;flex-direction:column;gap:6px;margin:6px 0 var(--s3)}
.kandydat{display:flex;align-items:flex-start;gap:10px;
  padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);cursor:pointer}
.kandydat:hover{background:var(--surface-2)}
.kandydat.on{border-color:var(--accent);background:var(--accent-soft)}
.kandydat input{margin-top:3px;flex:0 0 auto}
.kandydat>span{min-width:0}

/* =====================================================================
   „RUSZONE" I ZEGAR SLA NA LIŚCIE ZGŁOSZEŃ ABONENTÓW
   =====================================================================
   Łukasz, 16.09.2026: „bo to, że są notatki, to się zlewa. Chcę po
   prostu wiedzieć od razu patrząc na listę, że ktoś to dotknął".

   Stąd dwie decyzje: plakietka ma własny wiersz (nie dokleja się do
   szarego tekstu notatek z iPota), a „nietknięte" jest wyraźnie
   słabsze wizualnie od „ruszone" — bo brak akcji ma być ODCZYTANY,
   a nie krzyczeć z każdego drugiego wiersza. */
.znak-ruch{margin-top:4px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.znak-ruch .muted{font-size:var(--fs-xs)}
.nietkniete{font-style:italic;opacity:.75;
  border-bottom:1px dotted var(--line);cursor:help}

/* Zegar SLA. Kolor NIESIE TREŚĆ, więc obok koloru zawsze stoi słowo —
   „po terminie", „zostało" — żeby wiersz dało się przeczytać także
   wtedy, gdy ktoś nie odróżnia tych barw. */
.sla{margin-top:3px;font-weight:650;font-variant-numeric:tabular-nums}
.sla.zapas{color:var(--ink-3);font-weight:400}
.sla.blisko{color:var(--warn)}
.sla.po{color:var(--bad)}
.sla.spoznione{color:var(--bad);font-weight:400}
.sla.zdazone{color:var(--ok);font-weight:400}

/* Kafel, który WŁĄCZA filtr — widać, że jest wciśnięty. Bez tego lista
   pokazuje mniej niż zwykle i wygląda na urwaną. */
.kafel-liczby.wlaczony{border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent)}
.kafel-liczby.wlaczony .kl-e{color:var(--accent-text)}

/* =====================================================================
   KARTA ZGŁOSZENIA — SZEROKOŚĆ I UKŁAD (16.09.2026)
   =====================================================================
   Łukasz: „pracując dłużej na tym wszystkim uważam, że jest ciut ciut
   za wąska na komputerze, można ją dać o kilkanaście procent szerszą".

   420 → 490 px, czyli +17%. Własna klasa, nie poszerzony `waski`:
   tamten noszą jeszcze trzy inne szuflady i nie ma powodu ruszać ich
   przy okazji.

   Sama szerokość to połowa sprawy — druga to wykorzystanie jej. Przy
   420 px etykiety „Czego dotyczy" łamały się na dwie linie, a stan
   łącza musiał schodzić pod nazwisko. Poniżej jedno i drugie wraca
   na swoje miejsce. */
.drawer.zgloszenie{width:min(94vw,490px)}

/* Ta sama typografia i te same odstępy, co miał `waski` — poszerzenie
   panelu nie może zmienić skali pisma, bo to ta sama rodzina ekranów. */
.drawer.zgloszenie dl.kv dt{font-size:var(--fs-sm)}
.drawer.zgloszenie dl.kv dd,
.drawer.zgloszenie dl.kv dd.mono{font-size:var(--fs-base)}
/* Kolumna etykiet szersza o te same kilkanaście procent, co panel —
   inaczej cała nadwyżka poszłaby w kolumnę wartości, a to etykiety
   („Czego dotyczy", „Serwisant") łamały się na dwie linie. */
.drawer.zgloszenie dl.kv{grid-template-columns:150px minmax(0,1fr)}

/* =====================================================================
   PASEK ABONENTA — TRZY PIĘTRA NA PEŁNEJ SZEROKOŚCI
   =====================================================================
   Łukasz, 16.09.2026: „dane klienta są TURBO MAŁE. Musi to być bardziej
   widoczne".

   Numer klienta, login i telefon to liczby, które technik CZYTA NA GŁOS
   przez telefon i przepisuje do drugiego systemu. Stały pisane 15 px pod
   etykietą 10 px — czyli najdrobniejszym drukiem na całym ekranie było
   to, po co się na ten ekran wchodzi. Teraz 21 px, tabularnie.

   Układ w dwie kolumny (nazwisko | stan łącza), który wstawiłem godzinę
   wcześniej przy poszerzaniu panelu, zwężał lewą stronę na tyle, że trzy
   fakty przestawały mieścić się w rzędzie i rozjeżdżały po jednym na
   linię. Wycofany: plakietka stanu siada teraz przy nazwisku, a numery
   dostają całą szerokość. */
.drawer.zgloszenie .zgl-abonent{flex-direction:column;gap:12px;padding:14px 14px 12px}

/* Piętro 1: nazwisko i stan łącza w jednej linii. */
.drawer.zgloszenie .zgl-abonent-gora{display:flex;align-items:center;
  justify-content:space-between;gap:var(--s3)}
.drawer.zgloszenie .zgl-nazwa{font-size:19px;font-weight:700;letter-spacing:-.01em;
  line-height:1.25;min-width:0}
.drawer.zgloszenie .zgl-abonent-stan{flex:0 0 auto}

/* Piętro 2: numery. Etykieta czytelna, liczba duża. */
.drawer.zgloszenie .zgl-ident{gap:10px 22px;margin-top:0}
.drawer.zgloszenie .zgl-ident i{font-size:11px;letter-spacing:.06em;
  color:var(--ink-2)}
.drawer.zgloszenie .zgl-ident b{font-size:21px;font-weight:700;line-height:1.15;
  margin-top:1px}
/* TELEFON RÓWNIE DUŻY, CO NUMER KLIENTA.
   Był mniejszy i wyglądało to na pomyłkę, bo nią było: numer telefonu
   siedzi w `<a class="mono">`, a `.mono` ustawia rozmiar WPROST na tym
   odnośniku — więc 21 px z otaczającego `<b>` nigdy do niego nie
   docierało. `inherit` oddaje mu rozmiar rodzica.
   A to jest liczba, którą technik wybiera na klawiaturze telefonu. */
.drawer.zgloszenie .zgl-ident b a{font-size:inherit;text-decoration:none}
.drawer.zgloszenie .zgl-ident b a:hover{text-decoration:underline}

/* Piętro 3: adres, mail i dane sesji.
   Łukasz, 16.09.2026: „IP powiększamy, nexerę powiększamy, adres
   powiększamy". Wszystkie trzy to rzeczy, które się CZYTA I PRZEPISUJE —
   adres do nawigacji, konto i IP do drugiego okna. Pisane trzynastką
   szarością były na granicy czytelności na monitorze z daleka. */
.drawer.zgloszenie .zgl-abonent-dol{display:flex;flex-direction:column;gap:5px;
  font-size:var(--fs-base);color:var(--ink-2);line-height:1.4}
.drawer.zgloszenie .zgl-adres{font-size:var(--fs-md);color:var(--ink);
  font-weight:500}
/* Konto i adres IP: rozmiar jak reszta tego piętra, ale ciemniej niż
   dotąd — to są wartości do przepisania, nie podpis pod obrazkiem.
   `.mono` ustawia rozmiar wprost na elemencie, więc nadpisujemy go
   tutaj, a nie liczymy na dziedziczenie. */
.drawer.zgloszenie .zgl-sesja.mono{font-size:var(--fs-sm);color:var(--ink-2)}

/* Na wąskiej szufladzie (telefon) liczby schodzą o stopień, żeby trzy
   fakty nadal mieściły się w dwóch rzędach zamiast w trzech. */
@media (max-width:560px){
  .drawer.zgloszenie .zgl-ident b{font-size:18px}
  .drawer.zgloszenie .zgl-adres{font-size:var(--fs-base)}
  .drawer.zgloszenie .zgl-nazwa{font-size:17px}
  .drawer.zgloszenie dl.kv{grid-template-columns:1fr}
}

/* =====================================================================
   ZEGAR SLA — PLAKIETKA ZAMIAST SZAREGO DOPISKU
   =====================================================================
   Łukasz: „SLA można dać jakieś bardziej widoczne? (…) ma jednak dawać
   presję czasu. Innym kolorem, może zielonym? Potem na minusie dawać
   na czerwono".

   Kolory niesie `Pill` (ok / warn / bad), więc zgadzają się z resztą
   programu i działają w obu motywach. Tutaj zostaje tylko odstęp
   i wariant dla spraw zamkniętych. */
.sla-znak{margin-top:5px}
/* Plakietka NIE ŁAMIE SIĘ na dwie linie. „zostało 23 godz." rozbite na
   „zostało 23" / „godz." przestaje być jednym znakiem i zaczyna
   wyglądać na dwa. Kolumna jest i tak `nowrap`, więc rośnie o te
   kilkadziesiąt pikseli i nic przez to nie traci. */
.sla-znak .pill{white-space:nowrap}
/* Zamknięte: werdykt, nie alarm. Tam SLA jest już faktem i nie ma po co
   świecić obok spraw, które jeszcze da się zdążyć. */
.sla-znak.historia{opacity:.7}

/* --- sprzęt zabrany od klienta ---------------------------------------
   Wiersz, nie kafelek: tych rzeczy jest zwykle jedna albo dwie, a każda
   niesie kilka faktów (co, numer, po co, u kogo). Kafelek zmusiłby do
   ucięcia czegoś, co przy sporze o cudzą własność jest dowodem. */
.wiersz-sprzetu{display:flex;align-items:flex-start;gap:var(--s3);
  padding:var(--s3) 0;border-bottom:1px solid var(--line-soft)}
.wiersz-sprzetu:last-child{border-bottom:none}
.wiersz-sprzetu .drobne{font-size:var(--fs-sm)}

/* =====================================================================
   WCZYTYWANIE — kółko, które naprawdę się kręci
   =====================================================================
   Łukasz, 18.09.2026: „żeby było widać, że coś się dzieje".

   Podstawą jest natywny `<progress>` bez `value` — wskaźnik
   nieokreślony. Czytniki ekranu ogłaszają go same, więc nie dorabiamy
   ról ani atrybutów; my dokładamy tylko wygląd.
   ===================================================================== */
.wczytywanie{display:flex;align-items:center;gap:14px;
  padding:14px 16px;margin-bottom:var(--s4);
  border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:var(--radius);background:var(--surface-2);color:var(--ink-2)}
.wczytywanie.male{padding:8px 0;margin:0;border:0;background:none}
.wczytywanie-co{font-weight:650;color:var(--ink)}
.wczytywanie-tresc{min-width:0}
.wczytywanie-tresc > * + *{margin-top:6px}
/* Dłuższy komunikat (lista pytanych systemów) to już akapit, a nie
   etykieta - kołowrotek ma wtedy stać przy PIERWSZEJ linii, nie w
   połowie wysokości bloku. */
.wczytywanie:has(ul),.wczytywanie:has(p){align-items:flex-start}
.wczytywanie ul{margin:6px 0 0;padding-left:18px}
.wczytywanie li{margin:2px 0}

/* Natywny pasek postępu chowamy — zostaje samo pudełko do pomalowania. */
progress.kolowrotek::-webkit-progress-bar{display:none;background:none}
progress.kolowrotek::-webkit-progress-value{display:none;background:none}
progress.kolowrotek::-moz-progress-bar{display:none;background:none}

/* Kąty w zarejestrowanych właściwościach — bez tego przeglądarka nie
   umie ANIMOWAĆ gradientu i zostaje samo obracanie. */
@property --luk-od{syntax:"<angle>";inherits:false;initial-value:0deg}
@property --luk-do{syntax:"<angle>";inherits:false;initial-value:0deg}

progress.kolowrotek{
  --rozmiar:22px;--grubosc:2.5px;--czas:1.1s;
  flex:0 0 auto;width:var(--rozmiar);height:var(--rozmiar);
  border-radius:50%;appearance:none;border:0;
  background:conic-gradient(from calc(90deg + var(--luk-od)),
      var(--accent) calc(var(--luk-do) - var(--luk-od)), transparent 0)
    var(--line);
  /* Wydrążamy środek maską — `background-clip: border-area` nie jest
     jeszcze wszędzie, a maska działa w każdej przeglądarce, w której
     ten program ma chodzić. */
  mask-image:radial-gradient(farthest-side,
    transparent calc(100% - var(--grubosc)), #000 calc(100% - var(--grubosc)));
  animation:kolowrotek-obrot var(--czas) linear infinite,
            kolowrotek-luk 2.4s ease-in-out infinite;
}
@keyframes kolowrotek-obrot{to{rotate:1turn}}
@keyframes kolowrotek-luk{
  from{--luk-od:0deg;--luk-do:8deg}
  50%{--luk-od:100deg;--luk-do:340deg}
  to{--luk-od:360deg;--luk-do:368deg}
}

/* Kto wyłączył animacje w systemie, dostaje to samo kółko — tylko
   wolniejsze. ZATRZYMANE znaczyłoby „skończone", a to nieprawda. */
@media (prefers-reduced-motion:reduce){
  progress.kolowrotek{--czas:5s;animation:kolowrotek-obrot var(--czas) linear infinite}
}

/* =====================================================================
   RYTM PIONOWY W KARCIE — jeden odstęp zamiast dwudziestu przypadkowych
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „zrób marginesy między oknami, bo zobacz jak
   wszystko jest ściśnięte między sobą".
   Było tak, bo odstęp pochodził z `margin-bottom` doklejanego osobno do
   `.note`, `.kpis`, `.pasek-kafli`… a `.formrow`, `.tblwrap` i tabela
   nie miały go wcale. Efekt: raz 16 px, raz 12, raz zero — i sąsiedzi
   dotykali się bokami.
   Teraz odstęp daje POJEMNIK, nie element: każde kolejne dziecko karty
   dostaje ten sam margines od góry, a własne marginesy dolne dzieci są
   zerowane, żeby nie sumowały się do przypadkowej wartości. Dzięki temu
   nowy ekran jest rozstawiony poprawnie, zanim ktokolwiek napisze do
   niego jedną linijkę CSS.
   ===================================================================== */
.card > .bd > *{margin-bottom:0}
.card > .bd > * + *{margin-top:var(--s5)}
/* pasek akcji zamyka kartę - ma odetchnąć odrobinę mocniej niż reszta */
.card > .bd > .pasek-akcji{margin-top:var(--s6)}
/* zakładki są nagłówkiem treści, nie kolejnym pudełkiem: trzymają się
   tego, co pod nimi, i nie odpychają się od górnej krawędzi karty */
.card > .bd > .zakladki{margin-bottom:0}
.card > .bd > .zakladki + *{margin-top:var(--s4)}

/* to samo w środku bloku, tylko ciaśniej - blok jest mniejszym
   pojemnikiem i pełne 20 px rozbijałoby go na kawałki */
.blok > .blok-bd > *{margin-bottom:0}
.blok > .blok-bd > * + *{margin-top:var(--s4)}

/* Bloki stojące jeden na drugim: 16 px to za mało, żeby dwie ramki
   czytały się jak dwa osobne pudełka, a nie jak jedna gruba kreska. */
.blok{margin-bottom:var(--s5)}

/* Okienko modalne rządzi się tym samym prawem - nagłówek, wyjaśnienie,
   tabela i pasek akcji nie mogą się sklejać. */
.okienko > * + *{margin-top:var(--s4)}
.okienko > .kartahd + *{margin-top:var(--s3)}

/* =====================================================================
   TABELA POZYCJI DOKUMENTU — dwie wartości przy każdym wierszu
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „niech będą kolumny z wartościami netto/brutto,
   niezależnie co się wprowadzi". Brutto jest tym, co klient zapłaci,
   więc stoi na końcu i jest wytłuszczone — oko idzie do ostatniej
   kolumny i ma tam znaleźć liczbę, o której się rozmawia.
   ===================================================================== */
/* Dwie kolumny więcej znaczą mniej miejsca na nazwę — a nazwa to
   jedyna rzecz, po której rozpoznaje się pozycję. „Brother MFC-L2732DW"
   łamane na cztery linijki wygląda jak usterka. Tabela dostaje więc
   minimalną szerokość i przewija się w swoim pudełku, zamiast ściskać
   kolumnę, która nie ma się jak ścisnąć.

   Próg zszedł z 1080 na 880 px, bo z tabeli zniknęły dwie kolumny:
   jednostka wróciła do ilości („5 szt."), a rabat pokazuje się tylko
   wtedy, gdy któraś pozycja go ma. */
.tblwrap .tab-pozycji{min-width:880px}
.tab-pozycji td:nth-child(2){min-width:280px}
/* NAGŁÓWEK WOLNO ZŁAMAĆ NA DWIE LINIE. „Wartość netto" w jednej linii
   rezerwowało 158 px pod kwoty szerokie na 90 — a te 70 px brało się
   z kolumny z nazwą, czyli z jedynej, która ich naprawdę potrzebuje.
   Nagłówek łamie się raz, przy wczytaniu; nazwa łamie się przy każdej
   pozycji. */
.tab-pozycji thead th,.tab-pozycji thead th.num{white-space:normal}
.tab-pozycji td.num,.tab-pozycji th.num{white-space:nowrap}
/* Kwoty NIE ROZPYCHAJĄ SIĘ NA RESZTĘ SZEROKOŚCI. Bez tego „1%" na
   kolumnach liczbowych przeglądarka rozdzielała nadmiar po równo
   i między „NAZWA" a „ILOŚĆ" robiła się dziura na pół ekranu. */
.tab-pozycji th.num,.tab-pozycji .kol-akcje-poz{width:1%}
.tab-pozycji .kol-ilosc{white-space:nowrap}
/* „szt." i „netto" przy liczbie to przypis do niej, nie druga liczba —
   mniejsze pismo trzyma je w tej roli. */
.tab-pozycji .drobne{font-size:var(--fs-xs)}
.tab-pozycji .kol-akcje-poz{white-space:nowrap;text-align:right}
.tab-pozycji .kol-akcje-poz .jak-link + .jak-link{margin-left:12px}

/* =====================================================================
   PODGLĄD WŁASNEGO PODPISU
   ---------------------------------------------------------------------
   Podpis jest czarnym rysunkiem na przezroczystym tle — na ciemnym
   motywie zniknąłby zupełnie. Dlatego tło podglądu jest ZAWSZE białe,
   tak jak kartka, na której ten podpis wyjdzie z drukarki.
   ===================================================================== */
.podglad-podpisu{background:#fff;border:1px solid var(--line);
  border-radius:var(--radius);padding:10px 14px;display:flex;
  align-items:center;justify-content:center;min-height:90px}
.podglad-podpisu img{max-width:100%;max-height:120px;object-fit:contain}

/* Strzałki kolejności: para przycisków, która ma wyglądać jak JEDNA
   kontrolka, a nie jak dwa osobne odnośniki obok „popraw" i „usuń". */
.strzalki-kolejnosci{display:inline-flex;gap:2px;margin-right:12px;
  vertical-align:middle}
.strzalki-kolejnosci .jak-link{padding:0 5px;font-size:15px;line-height:1.1;
  color:var(--ink-2)}
.strzalki-kolejnosci .jak-link:disabled{opacity:.3;cursor:default}
.strzalki-kolejnosci .jak-link:not(:disabled):hover{color:var(--accent-text)}

/* =====================================================================
   GŁÓWKA DOKUMENTU — siatka zamiast jednego ciągnącego się rzędu
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „poukładajmy ładniej te pola (…) teraz jest
   w cały świat to".

   Wszystkie pola szły przez wspólny formularz układający je w JEDEN
   rząd. Przy czterech krótkich polach to działa; przy główce dokumentu
   na monitorze 2000 px daje formularz na całą szerokość ekranu, w którym
   „Data" stoi metr od „Tytułu".

   Dwanaście kolumn, bo dzieli się i na 2, i na 3, i na 4 — czyli na
   każdy układ, jaki tu wychodzi. Szerokość ma GRANICĘ: linia dłuższa
   niż ~90 znaków przestaje się czytać, a pole na datę szerokie na pół
   ekranu wygląda jak pomyłka.
   ===================================================================== */
.dok-naglowek{display:grid;grid-template-columns:repeat(12,1fr);
  gap:var(--s4) var(--s4);max-width:1180px;margin-bottom:var(--s5)}
.dok-naglowek .pole{min-width:0}
.dok-naglowek .input{width:100%}
.dok-naglowek-akcje{grid-column:1/-1;display:flex;align-items:center;gap:var(--s3);
  padding-top:var(--s2);border-top:1px solid var(--line-soft)}

/* Pole opisowe ROŚNIE Z TREŚCIĄ.
   `field-sizing` jest wsparciem, nie warunkiem: przeglądarka, która go
   nie zna, zostawia `rows={4}` i suwak — czyli dokładnie to, co było.
   Szerokość zostaje na 100%, bo pole zwężające się w poziomie przy
   pierwszej wpisanej literze (po zniknięciu podpowiedzi) szarpie
   całym formularzem. Górna granica jest po to, żeby akapit na pół
   strony nie zepchnął reszty formularza poza ekran. */
.input.rosnace{field-sizing:content;height:auto;width:100%;
  min-block-size:4lh;max-block-size:16lh;resize:vertical}

@media (max-width:1100px){
  /* Sześć kolumn: tytuł i pola opisowe na całą szerokość, daty po dwie
     w rzędzie. Poniżej tej szerokości trzy pola obok siebie robią się
     węższe niż ich własne etykiety. */
  .dok-naglowek{grid-template-columns:repeat(6,1fr)}
  .dok-naglowek > .pole{grid-column:span 3 !important}
  .dok-naglowek > .pole:has(textarea){grid-column:span 6 !important}
}
@media (max-width:640px){
  .dok-naglowek{grid-template-columns:1fr}
  .dok-naglowek > .pole{grid-column:span 1 !important}
  .dok-naglowek > .pole:has(textarea){grid-column:span 1 !important}
}


/* =====================================================================
   WYSYŁKA WYCENY — KOMU, WIDAĆ PRZED KLIKNIĘCIEM
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „na jakiego maila idzie oferta? Nie klikałem tego
   jeszcze, bo nie chciałem, żeby poszło z automatu".

   Panel był trzema polami w jednym rzędzie z klasą `.recznie` (mniejsze
   pismo, 75% krycia) — czyli wyglądał na przypis, a decyduje o tym,
   dokąd poleci oferta na kilkadziesiąt tysięcy. Teraz to jest normalny
   formularz: pola jedno pod drugim, adresaci z nazwiskami, a pod
   przyciskiem zdanie mówiące wprost, na ile adresów to pójdzie.
   ===================================================================== */
.dok-wysylka{display:flex;flex-direction:column;gap:var(--s4);
  padding:var(--s4);border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface-2);max-width:720px}
.dok-wysylka .input{width:100%}
.dok-wysylka-stopka{align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding-top:var(--s3);border-top:1px solid var(--line-soft)}
.dok-wysylka-stopka .muted{font-size:var(--fs-sm);flex:1 1 240px;
  overflow-wrap:anywhere}
.ostrzezenie-adresu{color:var(--warn)}

/* Lista adresów: ptaszek, adres, a obok — czyj to adres. Sam mail
   („biuro@") nie mówi, czy trafi do osoby decyzyjnej, czy na skrzynkę,
   której nikt nie czyta. */
.lista-adresow{display:flex;flex-direction:column;gap:2px;
  max-height:240px;overflow:auto;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface);padding:6px}
.adres-ptaszek{display:flex;align-items:baseline;gap:8px;padding:5px 7px;
  border-radius:var(--radius-sm);cursor:pointer;min-width:0}
.adres-ptaszek:hover{background:var(--surface-2)}
.adres-ptaszek input{flex:0 0 auto;align-self:center}
.adres-mail{overflow-wrap:anywhere}
.adres-kto{font-size:var(--fs-xs);margin-left:auto;white-space:nowrap;
  padding-left:10px}
@media (max-width:700px){
  .adres-ptaszek{flex-wrap:wrap}
  .adres-kto{margin-left:26px;white-space:normal;padding-left:0}
}


/* =====================================================================
   RYTM PIONOWY DOKUMENTU — ODSTĘPY DAJE POJEMNIK
   ---------------------------------------------------------------------
   Łukasz, 18.09.2026: „porobimy marginesy? Bo wszystko jest ściśnięte".

   Dół tego ekranu był płaską listą rodzeństwa, w której każdy element
   sam pilnował swojego odstępu: nagłówek miał `margin: var(--s5) 0 8px`,
   przycisk kasowania `margin-top: var(--s5)`, a tabela wysyłek i blok
   zdjęć — nic. Efekt jest zawsze ten sam: część odstępów się zlewa,
   część znika przy zawijaniu marginesów, a każdy nowy blok trzeba
   pamiętać, żeby dopisać mu margines ręcznie.

   Dwa poziomy zamiast tego. BLOKI (główka, pozycje, wysyłka, zdjęcia,
   kasowanie) dzieli --s6. WNĘTRZE bloku — nagłówek, pasek przycisków,
   tabela, podsumowanie — dzieli --s4, bo to jedna myśl, tylko rozpisana
   na kilka elementów.
   ===================================================================== */
.dok-tresc > * + *{margin-top:var(--s6)}
.dok-pasek-numeru{margin-bottom:0}

/* Sekcja to jedna myśl: `gap` zamiast marginesów na dzieciach, więc
   pusty blok (np. brak pozycji) nie zostawia po sobie dziury, a nowy
   element wstawiony w środek nie wymaga dopisywania mu marginesu. */
.dok-sekcja{display:flex;flex-direction:column;gap:var(--s4)}
.dok-sekcja > h3,.dok-sekcja > p{margin:0}
/* Zdanie wyjaśniające pod nagłówkiem sekcji: bez wcięcia karty, bo
   tu nie zaczyna się żaden nowy pojemnik. */
.dok-sekcja > .wyjasnienie{padding:0;max-width:80ch}
/* Suma NALEŻY do tabeli nad nią — `margin-left:auto` zostaje (to ono
   trzyma ją przy prawej krawędzi), znika tylko odstęp z góry, bo odstęp
   daje `gap` sekcji. */
.dok-sekcja > .dok-podsumowanie{margin-top:0}

/* Główka dokumentu ma już własny odstęp od siatki — a teraz dostaje go
   też z rytmu wyżej. Jeden wystarczy. */
.dok-tresc > .dok-naglowek{margin-bottom:0}

/* ===================================================================
   MAIL DO ABONENTA PRZY ZMIANIE STATUSU (19.09.2026)
   Jedna ramka z odstępem od reszty kafla — technik ma od razu widzieć,
   że TO pójdzie do abonenta, a nie do dziennika.
   =================================================================== */
.powiadomienie-statusu{margin-top:var(--s3);padding:var(--s3);
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--g0);
  display:flex;flex-direction:column;gap:var(--s2)}
.powiadomienie-statusu .podglad-komunikatu{display:flex;flex-direction:column;gap:2px;
  padding:var(--s2) var(--s3);border-left:3px solid var(--line);background:var(--bg)}

/* ===================================================================
   SZABLONY WIADOMOŚCI — grupy, lista, edytor obok (19.09.2026)
   Łukasz: „lista jest tak długa, że masakra + jak chcesz zmienić treść,
   to rozsuwa się na kolejny cały ekran". Lista po lewej się nie
   rozsuwa, edytor stoi zawsze w tym samym miejscu po prawej.
   =================================================================== */
.szablony{display:flex;flex-direction:column;gap:var(--s3)}
.szablony-grupy{display:flex;flex-wrap:wrap;gap:var(--s2)}
.szablony-grupy .licznik{margin-left:var(--s1);opacity:.7;font-variant-numeric:tabular-nums}
.szablony-opis{margin:0}
.szablony-uklad{display:grid;grid-template-columns:minmax(220px,300px) minmax(0,1fr);
  gap:var(--s4);align-items:start}
.szablony-lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s1);
  max-height:560px;overflow-y:auto}
.szablon-poz{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
  text-align:left;background:none;border:0;border-radius:var(--radius-sm);
  padding:var(--s2) var(--s3);cursor:pointer;color:inherit;font:inherit}
.szablon-poz:hover{background:var(--g1)}
.szablon-poz.wybrany{background:var(--g2);box-shadow:inset 3px 0 0 var(--accent, currentColor)}
.szablon-poz:focus-visible{outline:2px solid var(--accent, currentColor);outline-offset:1px}
.szablon-poz .nazwa{font-weight:600;line-height:1.3}
.szablon-poz .kod{font-size:var(--fs-xs);opacity:.65;overflow-wrap:anywhere}
.szablony-edytor{min-width:0;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:var(--s4);display:flex;flex-direction:column;gap:var(--s3)}
.szablony-edytor-hd{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.szablony-edytor-hd .przelacznik{display:inline-flex;gap:var(--s1)}
.szablony-edytor .podglad-tresc{max-height:360px}
.szablony-pusto{padding:var(--s6) 0;text-align:center}
@media (max-width: 900px){
  .szablony-uklad{grid-template-columns:1fr}
  .szablony-lista{max-height:260px}
}

/* Podgląd maila — jedno okienko dla całego programu (19.09.2026). */
.podglad-mail-ramka{display:block;width:100%;height:min(600px,62vh);border:0;background:#f3f4f6}
.okienko-podgladu-maila .podglad-mail{margin-top:var(--s3)}
.logo-operatora{height:36px;width:auto;max-width:200px;object-fit:contain;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius-sm);padding:4px 8px}

/* ===================================================================
   KOMÓRKI, KTÓRYCH NIE WOLNO ŁAMAĆ, I TAKIE, KTÓRE NIE MOGĄ SIĘ ŚCISNĄĆ
   (19.09.2026, przegląd tabel)
   Gdy tabela nie mieści się w ekranie, przeglądarka ściska każdą
   kolumnę do najdłuższego SŁOWA. Stąd „SSD / 1000 / GB" w trzech
   linijkach i system operacyjny słowo pod słowem, obok kolumn
   z zapasem. Dwie reguły to zatrzymują:
     .bez-lamania — wartość z jednostką zawsze w jednej linii,
     .tekst-min   — kolumna opisowa nie schodzi poniżej ~16 znaków;
                    zawija się najwyżej na dwie linie, zamiast w słupek.
   Co się dalej nie mieści, przewija się w bok w ramce tabeli.
   =================================================================== */
td.bez-lamania,.bez-lamania{white-space:nowrap}
td.tekst-min{min-width:16ch}

/* ===================================================================
   PANEL GŁÓWNY OPERATORA (19.09.2026)
   Trzy rzędy kafli z nagłówkami i dwie listy obok siebie pod spodem.
   =================================================================== */
.panel-operatora{display:flex;flex-direction:column;gap:var(--s5)}
.panel-operatora-hd{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  flex-wrap:wrap}
.panel-operatora-blok h3{margin:0 0 var(--s3);font-size:var(--fs-sm);text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-2)}
.panel-operatora-listy{display:grid;grid-template-columns:repeat(auto-fit,minmax(360px,1fr));
  gap:var(--s4);align-items:start}
.panel-lista{list-style:none;margin:0;padding:0}
.panel-lista li{padding:var(--s3) 0;border-bottom:1px solid var(--line-soft)}
.panel-lista li:last-child{border-bottom:0}
.panel-lista-gora{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.panel-lista-gora .nazwa{font-weight:600}
.panel-lista-dol{margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Wersja pokazowa — dane logowania nad formularzem */
.login .demo-logowanie { margin-bottom: var(--s4); line-height: 1.55; }
.login .demo-logowanie .btn { display: block; margin: var(--s3) auto 0; }

/* =====================================================================
   ZNAK ANANASA — test nowej marki (S24_MARKA=ananas)
   Krój Fredoka (SIL OFL 1.1), leży lokalnie w /fonts — bez Google Fonts.
   ===================================================================== */
@font-face { font-family: 'Fredoka'; font-weight: 700; font-style: normal; font-display: swap;
  src: url('/fonts/fredoka-latin-700-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2212; }
@font-face { font-family: 'Fredoka'; font-weight: 700; font-style: normal; font-display: swap;
  src: url('/fonts/fredoka-latin-ext-700-normal.woff2') format('woff2');
  unicode-range: U+0100-02AF, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
:root { --ananas-litera: #16a34a; --ananas-slowo: #0d1f3c; --ananas-it: #dcecfb; --ananas-it-ink: #0d3a66;
  --ananas-serwis: #fcf1c9; --ananas-serwis-ink: #5a4200; --ananas-isp: #d6f4df; --ananas-isp-ink: #0f4d26; }
[data-theme="dark"] { --ananas-litera: #3fd06c; --ananas-slowo: #f2f5fa; --ananas-it: #17314d; --ananas-it-ink: #b9dcfb;
  --ananas-serwis: #3d3212; --ananas-serwis-ink: #f6dc86; --ananas-isp: #173b25; --ananas-isp-ink: #a8e8bd; }
.znak-ananasa { display: flex; align-items: center; gap: 6px; min-width: 0; }
.znak-ananasa img { width: 44px; height: 44px; flex: 0 0 auto; object-fit: contain; }
.znak-ananasa .slowo { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 700; font-size: 22px;
  letter-spacing: .02em; line-height: 1; color: var(--ananas-slowo); }
.brandbar.ananas .znak-ananasa { gap: 5px; max-width: 100%; }
.brandbar.ananas .znak-ananasa img { width: 40px; height: 40px; }
.brandbar.ananas .znak-ananasa .slowo { font-size: 24px; }
.brandbar.ananas .znak-ananasa .plakietka { font-size: 12px; padding: 4px 6px; }
.brand-rozwiniecie .linia { display: block; white-space: nowrap; }
.znak-ananasa .plakietka { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 700; font-size: 13px;
  line-height: 1; padding: 4px 7px; border-radius: 6px; margin-left: 2px; white-space: nowrap; }
.znak-ananasa .plakietka.w-it { background: var(--ananas-it); color: var(--ananas-it-ink); }
.znak-ananasa .plakietka.w-serwis { background: var(--ananas-serwis); color: var(--ananas-serwis-ink); }
.znak-ananasa .plakietka.w-isp { background: var(--ananas-isp); color: var(--ananas-isp-ink); }
.znak-ananasa.duzy img { width: 88px; height: 88px; }
.znak-ananasa.duzy .slowo { font-size: 48px; }
.brandbar.ananas { flex-direction: column; align-items: flex-start; gap: 4px; }
.brandbar.ananas .brand-firma { font-size: var(--fs-sm); color: var(--ink-3); padding-left: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.login-marka { display: flex; flex-direction: column; align-items: center; gap: 6px; margin-bottom: var(--s5); }
.login-marka .login-firma { font-size: var(--fs-sm); color: var(--ink-3); }
.login-logo { display: flex; align-items: center; gap: 14px; }
.login-logo img { width: 104px; height: 104px; flex: 0 0 auto; object-fit: contain; }
.login-logo .slowo { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 700; font-size: 54px;
  line-height: .95; letter-spacing: .02em; color: var(--ananas-slowo); }
.login-rozwiniecie { margin-top: 6px; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 700;
  font-size: 13.5px; line-height: 1.3; color: var(--ananas-slowo); max-width: 250px; }
.login-rozwiniecie .litera { color: var(--ananas-litera); }

/* =====================================================================
   MOTYW ANANAS — śmiało (Łukasz, 19.09.2026: „śmiało leć z kolorystyką,
   ma być z jajem i ananasem"). Tu tylko to, czego nie da się zrobić
   samymi zmiennymi z tokens.css.
   ===================================================================== */
/* Tło strony: skórka ananasa — cienka kratka po skosie, ledwo widoczna.
   Karty zostają białe, więc wzór nie wchodzi pod dane. */
:root[data-theme="ananas"] body {
  background-color: var(--bg);
  background-image:
    linear-gradient(45deg, transparent 47%, rgba(232,140,0,.045) 47%, rgba(232,140,0,.045) 53%, transparent 53%),
    linear-gradient(-45deg, transparent 47%, rgba(232,140,0,.045) 47%, rgba(232,140,0,.045) 53%, transparent 53%);
  background-size: 34px 34px;
}
/* Górny pasek: biały z grubą żółtą krawędzią — jak etykieta na skrzynce. */
:root[data-theme="ananas"] .topbar { border-bottom: 4px solid var(--accent); }
:root[data-theme="ananas"] .top-tytul h1,
:root[data-theme="ananas"] .card > .hd h3,
:root[data-theme="ananas"] .card > .hd h2 { color: #0d1f3c; }
/* Nagłówek tabeli w granacie, napisy białe; strzałka sortowania żółta. */
/* 20.09.2026: nagłówek tabeli JASNY (kremowy), napisy granatowe, żółta
   kreska pod spodem. Granatowy pasek nad każdą tabelą ważył więcej niż
   dane pod nim — granat zostaje w menu. */
:root[data-theme="ananas"] thead th {
  color: #0d1f3c; border-bottom: 2px solid var(--accent);
}
:root[data-theme="ananas"] thead th:hover { background: #efede4; }
:root[data-theme="ananas"] thead th .strzalka,
:root[data-theme="ananas"] thead th [aria-hidden="true"] { color: #b98300; }
/* Karty i kafle: żółty pasek u góry — każdy blok wygląda jak plaster. */
:root[data-theme="ananas"] .card { border-color: var(--g4); border-top: 4px solid var(--accent); }
:root[data-theme="ananas"] .kpi { border-color: var(--g4); border-top: 4px solid #0d1f3c; }
:root[data-theme="ananas"] .kpi .v { color: #0d1f3c; }
:root[data-theme="ananas"] .kpi.alert { border-top-color: var(--bad); }
:root[data-theme="ananas"] .kpi.alert .v { color: var(--bad); }
:root[data-theme="ananas"] .filters { background: var(--surface); }
/* Przyciski drugorzędne: granatowa ramka, po najechaniu żółte tło. */
:root[data-theme="ananas"] .btn:not(.primary):not(.zielony):not(.czerwony):not(.ostrzega):not(.groznie):not(.pilne):not(.off) { border-color: #0d1f3c; color: #0d1f3c; font-weight: 650; }
:root[data-theme="ananas"] .btn:not(.primary):not(.zielony):not(.czerwony):not(.ostrzega):not(.groznie):not(.pilne):not(.off):hover { background: #fff3cc; border-color: #0d1f3c; }
:root[data-theme="ananas"] .btn.primary { border-color: #d99a00; box-shadow: 0 2px 0 #b98300; }
:root[data-theme="ananas"] .btn.primary:hover { background: #ffc21a; }
/* Menu: nagłówki grup w żółci, zielony listek przy aktywnej pozycji. */
:root[data-theme="ananas"] .side .grp { color: var(--accent); }
:root[data-theme="ananas"] .side button.nav.on { border-left: 4px solid #3fb03a; }
:root[data-theme="ananas"] ::selection { background: #ffd54d; color: #0d1f3c; }

/* Plakietki w motywie ANANAS: grubsze, w barwach logo. „W trakcie" /
   informacyjne — granat z żółtym napisem, jak nagłówek tabeli. */
:root[data-theme="ananas"] .pill { font-weight: 700; border-width: 1.5px; }
:root[data-theme="ananas"] .pill.info { background: #0d1f3c; color: #ffd24d; border-color: #0d1f3c; }
:root[data-theme="ananas"] .pill.ok   { background: #e3f4d8; color: #1c6a12; border-color: #7dc56b; }
:root[data-theme="ananas"] .pill.warn { background: #ffe8a6; color: #6e4300; border-color: #f5b301; }
:root[data-theme="ananas"] .pill.bad  { background: #ffe1dc; color: #a2170f; border-color: #ef8b80; }
:root[data-theme="ananas"] .pill.mute { background: #f0f0ec; color: #2a3651; border-color: #d2d3cc; }
:root[data-theme="ananas"] .kpi.alert { background: #fff0ec; }

/* TABELE I KAFLE W MOTYWIE ANANAS — każdy blok danych ma własną ramkę
   i nieprzezroczyste tło (19.09.2026, Łukasz: „te tabele nie mogą tak
   wyglądać, muszą mieć obramówki, bo się wszystko zlewa"). Powód był
   konkretny: nieparzyste wiersze były przezroczyste, więc przez tabelę
   prześwitywała kratka tła, a tabele stojące poza kartą nie miały żadnej
   krawędzi. */
:root[data-theme="ananas"] table { background: var(--surface); border: 1px solid var(--line); }
:root[data-theme="ananas"] .card table { border-width: 0; border-top-width: 0; }
:root[data-theme="ananas"] tbody tr { background: var(--surface); }
:root[data-theme="ananas"] tbody tr:hover { background: var(--wiersz-hover); }
/* Tylko poziome linie (20.09.2026) — pionowe kreski cięły wiersz na
   kratki i oko przestawało iść wzdłuż niego. */
:root[data-theme="ananas"] tbody td { border-bottom: 1px solid var(--wiersz-linia); }
/* Kafle (np. „Najnowsze zgłoszenia" w panelu operatora): białe jak karty,
   żółty pasek u góry, pozycje oddzielone kreską. */
:root[data-theme="ananas"] .kafel { background: var(--surface); border: 1px solid var(--line);
  border-top: 4px solid var(--accent); box-shadow: var(--shadow-1); }
:root[data-theme="ananas"] .kafel-hd .nazwa { color: #0d1f3c; }

/* Rozwinięcie akronimu pod znakiem w menu (19.09.2026 — „logo z napisanym
   akronimem w nagłówek"), zielone pierwsze litery jak w logo. */
/* Na całą szerokość logo i zwykłym pismem — krój z logo w 11 px
   zlewał się w plamę (Łukasz, 19.09.2026). Pogrubione są tylko
   zielone pierwsze litery. */
.brand-rozwiniecie { font-family: var(--font); font-weight: 500; font-size: 12.5px; letter-spacing: .01em;
  line-height: 1.45; color: var(--ananas-slowo); opacity: .92; padding: 2px 2px 0 4px; max-width: 100%; }
.brand-rozwiniecie .litera { color: var(--ananas-litera); font-weight: 800; }
:root[data-theme="ananas"] .side { --ananas-litera: #57d15f; }
[data-theme="dark"] .side { --ananas-litera: #3fd06c; }

/* =====================================================================
   KALENDARZ (kalendarz.tsx)
   Kolor rodzaju siedzi w jednej zmiennej `--kc`; tło kafla to jej
   rozcieńczenie na powierzchni motywu, więc ten sam zestaw działa
   w jasnym, ciemnym i ananasowym bez osobnych palet.
   ===================================================================== */
.kal { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.kal-pasek { display: flex; justify-content: space-between; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.kal-nawigacja, .kal-prawa { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.kal-strzalka { width: 34px; padding: 0; font-size: 20px; line-height: 1; }
.kal-tytul { margin: 0 0 0 var(--s2); font-size: var(--fs-lg); font-weight: 650; text-wrap: balance; }
.kal-widoki { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; background: var(--surface); }
.kal-widoki button { border: 0; background: transparent; color: var(--ink-2); font: inherit; font-size: var(--fs-sm);
  padding: 0 14px; height: 34px; cursor: pointer; }
.kal-widoki button + button { border-left: 1px solid var(--line); }
.kal-widoki button:hover { color: var(--ink); background: var(--surface-2); }
.kal-widoki button.wybrany { background: var(--accent-soft); color: var(--accent-text); font-weight: 650; }
.kal-widoki button:focus-visible, .kal-typ:focus-visible, .kal-kafel:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.kal-filtry { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.kal-filtry select.input { width: auto; min-width: 170px; }
.kal-typy { display: flex; gap: 6px; flex-wrap: wrap; }
.kal-typ { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border-radius: var(--radius-pill);
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-3); font: inherit; font-size: var(--fs-sm); cursor: pointer; }
.kal-typ .kropka { width: 9px; height: 9px; border-radius: 50%; background: transparent; border: 2px solid var(--kc); }
.kal-typ.wl { color: var(--ink); border-color: color-mix(in srgb, var(--kc) 45%, var(--line)); }
.kal-typ.wl .kropka { background: var(--kc); }
.kal-typ .ile { font-variant-numeric: tabular-nums; color: var(--ink-3); font-size: var(--fs-xs); }

/* Kolory rodzajów */
.kal-t-termin_it     { --kc: #4f46e5; }
.kal-t-termin_serwis { --kc: #d9730d; }
.kal-t-wizyta        { --kc: #1f7ac2; }
.kal-t-spotkanie     { --kc: #8a4fb8; }
.kal-t-nieobecnosc   { --kc: #7b8494; }
.kal-t-google        { --kc: #0f9aa8; }
.kal-c-gray{--kc:#7b8494}.kal-c-slate{--kc:#55627a}.kal-c-blue{--kc:#1f7ac2}.kal-c-sky{--kc:#1a9fd6}
.kal-c-teal{--kc:#0f9486}.kal-c-green{--kc:#2f9e3a}.kal-c-lime{--kc:#6b9e14}.kal-c-yellow{--kc:#c9a100}
.kal-c-amber{--kc:#d68a00}.kal-c-orange{--kc:#d9730d}.kal-c-red{--kc:#c9302c}.kal-c-pink{--kc:#cc3d86}
.kal-c-purple{--kc:#8a4fb8}.kal-c-indigo{--kc:#4f46e5}
/* Ciemny motyw: te same kolory, jaśniejszy tylko tekst godziny — tło
   i tak jest rozcieńczeniem koloru na ciemnej powierzchni. */
:root[data-theme="dark"] .kal-kafel .czas { color: color-mix(in srgb, var(--kc) 45%, var(--ink)); }

/* Siatka dnia/tygodnia */
.kal-siatka { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.kal-naglowki, .kal-pasek-dnia, .kal-godziny { display: grid; }
.kal-naglowki { border-bottom: 1px solid var(--line); background: var(--surface-2); }
.kal-dzien-nagl { display: flex; align-items: baseline; justify-content: center; gap: 6px; flex-wrap: wrap; padding: 8px 4px;
  border: 0; border-left: 1px solid var(--line-soft); background: transparent; color: var(--ink-2); font: inherit; cursor: pointer; min-width: 0; }
.kal-dzien-nagl:disabled { cursor: default; }
.kal-dzien-nagl:not(:disabled):hover { background: var(--surface); }
.kal-dzien-nagl .dt { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em; }
.kal-dzien-nagl .nr { font-size: var(--fs-md); font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums;
  min-width: 28px; height: 28px; line-height: 28px; border-radius: 50%; text-align: center; }
.kal-dzien-nagl.dzis .nr { background: var(--accent); color: var(--accent-ink); }
.kal-dzien-nagl.wolny .dt { color: var(--bad); }
.kal-dzien-nagl .swieto, .kal-m-gora .swieto { flex-basis: 100%; font-size: var(--fs-xs); color: var(--bad);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }

.kal-pasek-dnia { border-bottom: 1px solid var(--line); }
.kal-os-podpis { font-size: var(--fs-xs); color: var(--ink-3); padding: 6px 6px 0 0; text-align: right; }
.kal-pasek-siatka { display: grid; grid-auto-flow: row dense; gap: 3px 0; padding: 4px 0; min-height: 34px; align-content: start;
  background-image: linear-gradient(to right, var(--line-soft) 1px, transparent 1px); }
.kal-pasek-siatka > * { margin: 0 3px; }

.kal-przewijak { max-height: calc(100vh - 300px); min-height: 320px; overflow-y: auto; }
.kal-godziny { position: relative; }
.kal-os { position: relative; }
.kal-os span { position: absolute; right: 8px; transform: translateY(-50%); font-size: var(--fs-xs); color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.kal-os span:first-child { transform: none; }
.kal-kolumna { position: relative; border-left: 1px solid var(--line-soft); cursor: copy;
  background-image: linear-gradient(to bottom, var(--line-soft) 1px, transparent 1px); }
.kal-kolumna.wolny { background-color: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.kal-kolumna.dzis { background-color: color-mix(in srgb, var(--accent) 5%, transparent); }
.kal-teraz { position: absolute; left: 0; right: 0; height: 2px; background: var(--bad); pointer-events: none; z-index: 3; }
.kal-teraz::before { content: ""; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--bad); }

/* Kafel wpisu */
.kal-kafel { display: flex; flex-direction: column; align-items: stretch; text-align: left; gap: 1px; min-width: 0;
  padding: 3px 6px; border: 0; border-left: 3px solid var(--kc); border-radius: 5px; font: inherit; font-size: var(--fs-xs);
  line-height: 1.3; color: var(--ink); background: color-mix(in srgb, var(--kc) 14%, var(--surface)); cursor: pointer; overflow: hidden; }
.kal-kafel:hover { background: color-mix(in srgb, var(--kc) 24%, var(--surface)); }
.kal-kolumna .kal-kafel { position: absolute; z-index: 2; box-shadow: 0 0 0 1px var(--surface); }
.kal-kafel.ruchomy { cursor: grab; }
.kal-kafel.ruchomy:active { cursor: grabbing; }
.kal-kafel .czas { font-weight: 750; font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--kc) 70%, var(--ink)); }
.kal-kafel .tt { font-weight: 600; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 1; overflow-wrap: anywhere; }
.kal-kafel .pod { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kal-kafel .pod.kto { color: var(--ink-3); }
.kal-kafel.paskowy .tt, .kal-kafel.zwiezly .tt { display: block; white-space: nowrap; text-overflow: ellipsis; }
.kal-kafel.paskowy, .kal-kafel.zwiezly { padding: 2px 6px; min-height: 22px; }
/* Termin: kontur zamiast wypełnienia — to chwila, nie zajęty czas */
.kal-kafel.kal-t-termin_it, .kal-kafel.kal-t-termin_serwis { background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--kc) 55%, var(--line)); border-left: 3px solid var(--kc); }
.kal-kafel.kal-t-termin_it:hover, .kal-kafel.kal-t-termin_serwis:hover { background: color-mix(in srgb, var(--kc) 10%, var(--surface)); }
.kal-kafel.po-terminie { --kc: var(--bad); background: var(--bad-bg); border-color: var(--bad-border); border-left-color: var(--bad); }
/* Nieobecność: szary pas w ukośne kreski; wniosek — przerywany kontur */
.kal-kafel.kal-t-nieobecnosc { background: repeating-linear-gradient(135deg,
    color-mix(in srgb, var(--kc) 16%, var(--surface)) 0 6px, color-mix(in srgb, var(--kc) 8%, var(--surface)) 6px 12px); }
.kal-kafel.wniosek { border: 1px dashed var(--kc); border-left: 3px dashed var(--kc); }

.kal-wiecej { border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: var(--fs-xs);
  font-weight: 600; text-align: left; padding: 2px 6px; cursor: pointer; }
.kal-wiecej:hover { text-decoration: underline; }

/* Miesiąc */
.kal-miesiac { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; background: var(--line-soft); gap: 1px; }
.kal-m-nagl { background: var(--surface-2); padding: 6px 8px; font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-2); }
.kal-m-dzien { background: var(--surface); min-height: 112px; padding: 4px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.kal-m-dzien.wolny { background: color-mix(in srgb, var(--surface-2) 45%, var(--surface)); }
.kal-m-dzien.obcy > * { opacity: .5; }
.kal-m-gora { display: flex; align-items: center; gap: 4px; min-width: 0; }
.kal-m-gora .swieto { flex-basis: auto; text-align: left; }
.kal-m-nr { border: 0; background: transparent; font: inherit; font-weight: 650; font-variant-numeric: tabular-nums;
  min-width: 26px; height: 26px; border-radius: 50%; cursor: pointer; color: var(--ink); }
.kal-m-nr:hover { background: var(--surface-2); }
.kal-m-dzien.dzis .kal-m-nr { background: var(--accent); color: var(--accent-ink); }

.kal-stopka { font-size: var(--fs-xs); margin: 0; }

/* Szczegóły */
.kal-szczegoly .kartahd h2 { flex: 1 1 auto; min-width: 0; }
.kal-znacznik { width: 12px; height: 12px; border-radius: 3px; background: var(--kc); flex: 0 0 auto; }
.kal-znacznik.po-terminie { background: var(--bad); }
.kal-dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: var(--s3) 0 0; }
.kal-dl dt { color: var(--ink-3); font-size: var(--fs-sm); }
.kal-dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.kal-opis { white-space: pre-line; }

@media (max-width: 760px) {
  .kal-tytul { flex-basis: 100%; margin: var(--s1) 0 0; }
  .kal-m-dzien { min-height: 76px; }
  .kal-m-dzien .kal-kafel .czas { display: none; }
  .kal-przewijak { max-height: none; }
}
@media (prefers-reduced-motion: reduce) { .kal * { transition: none !important; } }
.pola.ciasne textarea.input { height: auto; min-height: 72px; }

/* =====================================================================
   NIEOBECNOŚCI (nieobecnosci.tsx)
   ===================================================================== */
.nieob { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }
.nieob-pasek { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.nieob-pasek .rozpychacz { margin-left: auto; }
.nieob-rok { display: flex; align-items: center; gap: var(--s2); }
.nieob-rok h2 { margin: 0 var(--s1); font-size: var(--fs-xl); font-variant-numeric: tabular-nums; }
.nieob-rok .btn { width: 34px; padding: 0; font-size: 20px; line-height: 1; }
.nieob-moje h3 { margin: 0 0 var(--s2); font-size: var(--fs-md); }
.nieob-filtry { padding: var(--s3) var(--pad-card) 0; }
.nieob-grupuj { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--ink-2); }
.nieob-grupuj select.input { width: auto; }
.nieob-opis { padding: var(--s3) var(--pad-card) 0; margin: 0; }
.nieob td.akcje { display: flex; gap: 6px; }
.nieob td.num.zle { color: var(--bad); }
.nieob .input.w-dni { width: 72px; text-align: right; }
.nieob .drobne { font-size: var(--fs-xs); }
tr.grupa-wiersz td { background: var(--surface-2); font-weight: 650; font-size: var(--fs-sm);
  text-transform: capitalize; padding-top: 6px; padding-bottom: 6px; }
.nieob-podglad { margin-top: var(--s3); padding: var(--s3); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--surface-2); display: flex; flex-direction: column; gap: 4px; }
.nieob-podglad.zle { border-left-color: var(--bad); color: var(--bad); background: var(--bad-bg); }
.nieob-kolizje { color: var(--warn); }

/* Kto dostępny — kartki nad widokiem dnia (kalendarz.tsx) */
.kal-ludzie { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); padding: var(--s3); }
.kal-ludzie-hd { display: flex; gap: var(--s2); align-items: baseline; flex-wrap: wrap; margin-bottom: var(--s2); }
.kal-ludzie-hd .muted { font-size: var(--fs-sm); }
.kal-ludzie-lista { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--s2); }
.kal-osoba { display: flex; flex-direction: column; gap: 4px; text-align: left; font: inherit; font-size: var(--fs-sm);
  color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--ok);
  border-radius: var(--radius-sm); padding: 8px 10px; cursor: pointer; min-width: 0; }
.kal-osoba:hover { background: var(--surface-2); }
.kal-osoba:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.kal-osoba.st-zajety { border-left-color: var(--warn); }
.kal-osoba.st-nieobecny, .kal-osoba.st-caly_dzien, .kal-osoba.st-wolne { border-left-color: var(--line); background: var(--surface-2); color: var(--ink-2); }
.kal-osoba.st-poza_godzinami { border-left-color: var(--line); }
.kal-osoba.wybrana { box-shadow: 0 0 0 2px var(--accent); }
.kal-osoba .gora { display: flex; justify-content: space-between; align-items: center; gap: 6px; flex-wrap: wrap; }
.kal-osoba .konflikt { color: var(--bad); font-weight: 600; }
.kal-osoba .kto { font-weight: 650; min-width: 0; overflow-wrap: anywhere; }
.kal-osoba .pill { flex: 0 0 auto; }
.kal-osoba .teraz { font-weight: 600; }
.kal-osoba .plan-dnia { display: flex; flex-direction: column; gap: 1px; }
.kal-osoba .plan-poz { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kal-osoba .czas { font-variant-numeric: tabular-nums; color: var(--ink-3); }
.kal-osoba .liczby { color: var(--ink-3); font-size: var(--fs-xs); }
.kal-osoba .zle { color: var(--bad); }
.kal-osoba .drobne { font-size: var(--fs-xs); }
.przelacznik .tryb-zajetosci { margin-left: auto; width: auto; flex: 0 0 auto; align-self: center; }

/* Kalendarz w telefonie (link .ics) */
.kal-ics-link { display: flex; gap: var(--s2); }
.kal-ics-link .input { flex: 1 1 auto; min-width: 0; font-size: var(--fs-sm); }
.kal-ics-kroki { display: flex; flex-direction: column; gap: 6px; margin-top: var(--s3); font-size: var(--fs-sm); }

/* Przeglądy cykliczne (przeglady.tsx) */
.przeg { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.przeg-pasek { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.przeg-pasek .wyjasnienie { margin: 0; flex: 1 1 420px; }
.przeg td.akcje { display: flex; gap: 6px; }
.przeg .drobne { font-size: var(--fs-xs); }

/* Lista czynności na karcie zgłoszenia (czynnosci.tsx) */
.czynnosci { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.czynnosci li { display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: 6px 0; border-bottom: 1px solid var(--line-soft); }
.czynnosci li:last-child { border-bottom: 0; }
.czynnosci li.zrobione span { color: var(--ink-3); text-decoration: line-through; }
.czynnosci .jak-link { font-size: var(--fs-xs); flex: 0 0 auto; }
.liczba-marki { color: var(--ananas-litera); }

/* Ikony w menu bocznym (ikony-menu.tsx) — kolor napisu, lekko przygaszone */
.side button.nav .ikona-menu { flex: 0 0 auto; opacity: .78; }
.side button.nav.on .ikona-menu, .side button.nav:hover .ikona-menu { opacity: 1; }
.side button.nav.pod .ikona-menu { width: 16px; height: 16px; }
.side button.nav .nav-napis { min-width: 0; }


/* =====================================================================
   WIERSZE, KTÓRE CZEKAJĄ NA RUCH  (20.09.2026)
   =====================================================================
   Łukasz: „żeby naprawy, które są zamknięte lub mają jakiś status typu
   awaria lub wymagający reakcji, w jakiś sposób na tej liście się
   wyróżniały (...) może jakiś pulsujący delikatnie, np. jak jest awaria?"

   Klasy nadaje klasaWiersza() z wiersz-stan.ts:
     w-zamkniete  cichnie: szary tekst, plakietki bez koloru
     w-uwaga      żółtawe tło + żółty pasek przy lewej krawędzi
     w-alarm      czerwonawe tło + czerwony pasek
     w-awaria     jak w-alarm, mocniej
     w-puls       awaria, której nikt nie wziął — pasek i kropka
                  w plakietce pulsują (wolno, 2 s). Całe tło NIE pulsuje:
                  przy kilku awariach migałoby pół ekranu.

   Tło stoi na KOMÓRKACH, nie na wierszu: motyw ananas maluje tło wiersza
   regułą o wyższej wadze, a komórka leży nad nim. Pasek to ::after
   pierwszej komórki (::before zajmuje już pasek „opłacone / zgoda"
   na liście napraw — oba mogą stać naraz). */
:root{
  --w-uwaga-tlo: color-mix(in srgb, var(--warn-bg) 70%, var(--surface));
  --w-uwaga-hover: var(--warn-bg);
  --w-alarm-tlo: color-mix(in srgb, var(--bad-bg) 60%, var(--surface));
  --w-alarm-hover: var(--bad-bg);
  --w-awaria-tlo: var(--bad-bg);
  --w-awaria-hover: color-mix(in srgb, var(--bad-bg) 85%, var(--bad));
}
tbody tr.w-uwaga > td{background:var(--w-uwaga-tlo)}
tbody tr.w-uwaga:hover > td{background:var(--w-uwaga-hover)}
tbody tr.w-alarm > td{background:var(--w-alarm-tlo)}
tbody tr.w-alarm:hover > td{background:var(--w-alarm-hover)}
tbody tr.w-awaria > td{background:var(--w-awaria-tlo)}
tbody tr.w-awaria:hover > td{background:var(--w-awaria-hover)}

tbody tr.w-uwaga > td:first-child,
tbody tr.w-alarm > td:first-child,
tbody tr.w-awaria > td:first-child{position:relative}
tbody tr.w-uwaga > td:first-child::after,
tbody tr.w-alarm > td:first-child::after,
tbody tr.w-awaria > td:first-child::after{
  content:'';position:absolute;left:0;top:0;bottom:0;width:4px;pointer-events:none}
tbody tr.w-uwaga > td:first-child::after{background:var(--warn)}
tbody tr.w-alarm > td:first-child::after{background:var(--bad)}
tbody tr.w-awaria > td:first-child::after{background:var(--bad);width:5px}

/* Kropka w plakietce najwyższego priorytetu — tylko w otwartym wierszu. */
tr.w-awaria .pill.puls::before{content:'';width:7px;height:7px;border-radius:50%;
  background:currentColor;flex:0 0 auto}
.tab-zgloszen tr.w-awaria .pill.puls::before,
.kol-numer .pill.puls::before{display:inline-block;margin-right:5px;vertical-align:1px}

@keyframes w-puls{ 0%,100%{opacity:1} 50%{opacity:.25} }
@media (prefers-reduced-motion: no-preference){
  tbody tr.w-puls > td:first-child::after,
  tr.w-puls .pill.puls::before{animation:w-puls 2s ease-in-out infinite}
}

/* ZGŁOSZENIE Z FORMULARZA, SPRZĘTU JESZCZE NIE MA  (23.09.2026)
   Łukasz: „W NPS taka naprawa pulsowała na liście zgłoszeń całym swoim
   tłem w wierszu. Nie musimy robić identycznie, ale warto, żeby to było
   widoczne." Wybrał pulsowanie całego wiersza — świadomy wyjątek od
   reguły wyżej. Własny kolor (fiolet), żeby nie mylił się z „za późno"
   (czerwień) i „pilne" (żółć): to nie jest spóźnienie, tylko nowa rzecz
   do obsłużenia. Kto ma wyłączone animacje — w systemie albo w programie
   — dostaje stałe tło i pasek. */
:root{
  --w-www: hsl(268 58% 55%);
  --w-www-tlo: color-mix(in srgb, var(--w-www) 10%, var(--surface));
  --w-www-mocno: color-mix(in srgb, var(--w-www) 24%, var(--surface));
}
tbody tr.w-www > td{background:var(--w-www-tlo)}
tbody tr.w-www:hover > td{background:var(--w-www-mocno)}
tbody tr.w-www > td:first-child{position:relative}
tbody tr.w-www > td:first-child::after{
  content:'';position:absolute;left:0;top:0;bottom:0;width:5px;pointer-events:none;
  background:var(--w-www)}
@keyframes w-www-puls{
  0%,100%{background-color:var(--w-www-tlo)}
  50%    {background-color:var(--w-www-mocno)}
}
@media (prefers-reduced-motion: no-preference){
  :root:not([data-ruch="mniej"]) tbody tr.w-www:not(:hover) > td{
    animation:w-www-puls 2.4s ease-in-out infinite}
}

/* Zamknięte cichną. Plakietki tracą kolor, ale zostają czytelne —
   priorytet zamkniętej sprawy to już historia, nie sygnał. */
tbody tr.w-zamkniete > td{color:var(--ink-3)}
tbody tr.w-zamkniete .mono,
tbody tr.w-zamkniete .numer-stanowiska{color:var(--ink-2)}
:root tbody tr.w-zamkniete .pill{background:var(--surface-2);color:var(--ink-3);
  border-color:var(--line-soft)}
tbody tr.w-zamkniete .jak-link{color:var(--ink-2)}

/* =====================================================================
   PLAKIETKA STATUSU Z IKONĄ I POWODEM, PRIORYTET Z IKONĄ  (20.09.2026)
   =====================================================================
   Z makiety ChatGPT, którą przyniósł Łukasz: ikona w plakietce (kształt
   niesie stan także bez koloru), jedno zdanie powodu pod statusem
   i priorytet jako ikona + nazwa z dopiskiem pod spodem. Komponenty:
   plakietki.tsx. */
.pill .ikonka{flex:0 0 auto;margin-left:-2px}
td.kol-status .pill{min-width:0;justify-content:flex-start}
.status-z-powodem{display:flex;flex-direction:column;align-items:flex-start;gap:5px}
.status-z-powodem .powod{font-size:var(--fs-xs);font-weight:700;line-height:1.3;
  max-width:170px;white-space:normal}
.powod.bad{color:var(--bad)}
.powod.warn{color:var(--warn)}
.powod.info{color:var(--ink-3);font-weight:600}

.prio-nazwa{display:flex;align-items:center;gap:6px;white-space:nowrap;
  font-size:var(--fs-sm);font-weight:750;letter-spacing:.03em;text-transform:uppercase;color:var(--ink)}
.prio-ikona{display:inline-flex;color:var(--ink-3)}
.prio-awaria .prio-ikona{color:var(--bad)}
.prio-pilny .prio-ikona{color:var(--warn)}
.prio-dopisek{margin:2px 0 0 21px;font-size:var(--fs-xs);line-height:1.3;color:var(--ink-3);
  white-space:normal;min-width:130px;max-width:190px}
tbody tr.w-zamkniete .prio-nazwa,
tbody tr.w-zamkniete .prio-ikona{color:var(--ink-3)}
@media (prefers-reduced-motion: no-preference){
  tr.w-puls .prio-awaria .prio-ikona,
  tr.w-puls td.kol-status .ikonka{animation:w-puls 2s ease-in-out infinite}
}

/* Na telefonie wiersz jest kartą: kolor i pasek należą do CAŁEJ karty,
   a nie do każdej komórki z osobna (komórki leżą tam jedna pod drugą
   i robiły łaciate tło, a pasek wchodził na tekst powodu). */
@media (max-width:640px){
  .tblwrap table.karty tr.w-uwaga{background:var(--w-uwaga-tlo);box-shadow:inset 4px 0 0 var(--warn)}
  .tblwrap table.karty tr.w-alarm{background:var(--w-alarm-tlo);box-shadow:inset 4px 0 0 var(--bad)}
  .tblwrap table.karty tr.w-awaria{background:var(--w-awaria-tlo);box-shadow:inset 5px 0 0 var(--bad)}
  .tblwrap table.karty tr.w-uwaga > td,
  .tblwrap table.karty tr.w-alarm > td,
  .tblwrap table.karty tr.w-awaria > td{background:transparent}
  .tblwrap table.karty tr > td:first-child::after{display:none}
}

/* =====================================================================
   MENU KONTA POD NAZWISKIEM (monitor)  — 20.09.2026
   ===================================================================== */
.menu-konta{position:relative}
.top-ja.przycisk-ja{font:inherit;color:var(--ink);background:none;cursor:pointer;
  border-top:0;border-right:0;border-bottom:0;padding-top:4px;padding-bottom:4px;
  padding-right:8px;border-radius:0 var(--radius) var(--radius) 0;text-align:left}
.top-ja.przycisk-ja:hover,.top-ja.przycisk-ja.otwarte{background:var(--surface-2)}
.top-ja.przycisk-ja:focus-visible{outline:none;box-shadow:var(--focus)}
.ja-strzalka{color:var(--ink-3);flex:0 0 auto;transition:transform .15s}
.przycisk-ja.otwarte .ja-strzalka{transform:rotate(180deg)}
.menu-konta-lista{position:absolute;right:0;top:calc(100% + 8px);z-index:60;min-width:250px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-2);padding:6px;display:flex;flex-direction:column}
.menu-konta-poz{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;
  border:0;border-radius:var(--radius);background:none;color:var(--ink);
  font:inherit;font-size:var(--fs-base);text-align:left;cursor:pointer}
.menu-konta-poz:hover,.menu-konta-poz:focus-visible{background:var(--surface-2);outline:none}
.menu-konta-ikona{display:inline-flex;width:20px;justify-content:center;color:var(--ink-3)}
.menu-konta-ikona svg{width:18px;height:18px}
.menu-konta-poz.groznie,.menu-konta-poz.groznie .menu-konta-ikona{color:var(--bad)}
.menu-konta-kreska{height:1px;background:var(--line-soft);margin:6px 8px}
@media (prefers-reduced-motion: reduce){ .ja-strzalka{transition:none} }

/* PIONOWE LINIE MIĘDZY KOLUMNAMI — wszystkie tabele, wszystkie motywy
   (20.09.2026). W nagłówku ta sama kreska, żeby kolumna miała jedną
   krawędź od góry do dołu. Na telefonie tabela zgłoszeń jest kartą —
   tam komórki nie mają ramek (reguła .karty w bloku max-width:640px). */
tbody td + td, thead th + th{border-left:1px solid var(--kolumna-linia)}

/* =====================================================================
   NAGŁÓWEK EKRANU I KARTA FILTRÓW  (20.09.2026, makieta Łukasza)
   =====================================================================
   Tytuł ekranu schodzi z górnego paska do treści: po lewej nazwa
   i moduł, po prawej liczba pozycji i główny przycisk. Pasek u góry
   zostaje na rzeczy wspólne dla całego programu (szukajka, zegar,
   powiadomienia, konto). Na telefonie tytuł zostaje w pasku. */
.naglowek-ekranu{display:flex;align-items:flex-end;justify-content:space-between;
  gap:var(--s4);flex-wrap:wrap;margin:0 0 var(--s4)}
.naglowek-tytul{display:flex;flex-direction:column;gap:2px;min-width:0}
.naglowek-tytul h1{margin:0;font-size:var(--fs-2xl);font-weight:700;line-height:1.15;
  letter-spacing:-.01em;text-wrap:balance}
.naglowek-modul{font-size:var(--fs-sm);color:var(--ink-3)}
.akcje-ekranu{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;justify-content:flex-end}
.akcje-ekranu:empty{display:none}
.licznik-ekranu{font-size:var(--fs-base);color:var(--ink-3);font-variant-numeric:tabular-nums;
  white-space:nowrap}
.akcje-ekranu .btn.primary{padding-left:var(--s5);padding-right:var(--s5);font-weight:700}
:root[data-theme="ananas"] .naglowek-tytul h1{color:#0d1f3c}

/* Wyszukiwarka i filtry to JEDNA karta narzędzi: bez kreski i bez
   szarego pasa między polem szukania a listami wyboru. */
.card>.hd:has(+ .filters){border-bottom:0;padding-bottom:0}
.card>.hd + .filters{background:var(--surface)}

/* Lupa w polach szukania — w pasku u góry i w pierwszym polu karty.
   Szary środkowy ton czyta się na jasnym i ciemnym tle. */
.top-lewo .qs{max-width:560px}
.top-lewo .qs input,
.card>.hd > input.input:first-child{
  padding-left:40px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8579' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:13px 50%;background-size:18px}

/* ZEGAR SLA W PANELU OPERATORA — plakietka z ikoną mieści się w kolumnie
   (20.09.2026, Łukasz: „wyjeżdżają plakietki w module operatora").
   `nowrap` + dodana ikona dawały „po terminie o 23 godz." szersze niż
   kolumna „Od kiedy". Teraz ikona stoi w jednym rzędzie z tekstem,
   a tekst w razie potrzeby łamie się do drugiej linii w plakietce. */
.tab-zgloszen .sla-znak .pill{display:inline-flex;align-items:center;gap:4px;
  max-width:100%;white-space:normal;text-align:left;line-height:1.25}
.tab-zgloszen .pill .ikonka{flex:0 0 auto}

/* =====================================================================
   TREŚĆ KOMÓREK NA ŚRODKU — w pionie i w poziomie  (20.09.2026)
   =====================================================================
   Łukasz, na zrzucie „Abonenci": „możemy wycentrować informacje
   w wierszach/komórkach? żeby ładnie się układały po środku dostępnego
   miejsca? — względem lewo-prawo i góra-dół oczywiście".
   Powód był widoczny: w wierszu, który rośnie przez dwuliniowy adres,
   jednolinijkowe komórki przyklejały się do górnej krawędzi i wiersz
   wyglądał na rozjechany.
   Jedna reguła dla wszystkich tabel danych, we wszystkich modułach
   i motywach. Wyjątki niżej: małe tabelki „pole — wartość" (to nie są
   listy) i lista zgłoszeń na telefonie, gdzie wiersz jest kartą. */
:root tbody > tr > td{vertical-align:middle;text-align:center}
:root thead > tr > th{text-align:center;vertical-align:middle}
/* Bloki wewnątrz komórek, które same z siebie stają przy lewej. */
:root tbody td .tnij{margin-left:auto;margin-right:auto}
:root tbody td .status-z-powodem{align-items:center}
:root tbody td .status-z-powodem .powod{text-align:center}
:root tbody td .prio-nazwa{justify-content:center}
:root tbody td .prio-dopisek{margin-left:auto;margin-right:auto;text-align:center}
:root tbody td .stan-lacza{justify-content:center}
:root tbody td .kol-numer .pill + .pill,
:root tbody td.kol-numer .pill + .pill{margin-left:auto;margin-right:auto}
/* Wyjątki: tabelki „pole — wartość" czyta się od lewej, w linii. */
:root .mini-tab td,:root .proby-api td,:root .proby-api th,:root .kn-pozycje td,
:root .robocizna-rozbicie td,:root .scalanie-tabela td,:root .scalanie-tabela th{
  text-align:left;vertical-align:top}
:root .scalanie-tabela td.num,:root .scalanie-tabela th:nth-child(n+2){text-align:right}
@media (max-width:640px){
  :root .tblwrap table.karty td{text-align:left}
  :root .tblwrap table.karty td .status-z-powodem{align-items:flex-start}
  :root .tblwrap table.karty td .status-z-powodem .powod{text-align:left}
  :root .tblwrap table.karty td .prio-nazwa{justify-content:flex-start}
  :root .tblwrap table.karty td .prio-dopisek{margin-left:21px;text-align:left}
  :root .tblwrap table.karty td .tnij{margin-left:0}
}
/* Na telefonie liczba i przycisk zostają w karcie listy — do prawej. */
.card>.hd > .licznik-ekranu{margin-left:auto;font-size:var(--fs-sm)}
/* Kolumna wskazana jako „do lewej" — nazwy, które czyta się jak tekst
   (20.09.2026, Łukasz: „w firmach zdecydowanie od lewej kolumna z nazwą").
   Waga reguły wyższa od wyśrodkowania wszystkich komórek wyżej. */
:root tbody > tr > td.do-lewej,:root thead > tr > th.do-lewej{text-align:left}
:root tbody > tr > td.do-lewej .tnij{margin-left:0}

/* PIERWSZA KOLUMNA OD LEWEJ — we wszystkich tabelach (20.09.2026).
   Łukasz, kolejno na Firmach, Infrastrukturze, Do zrobienia i Klientach:
   „od lewej pierwsza kolumna z nazwą". Pierwsza kolumna to prawie zawsze
   to, po czym szuka się wiersza (nazwa, numer, abonent, urządzenie),
   a czyta się ją jak tekst — od lewej krawędzi. Reszta zostaje na środku.
   Gdy pierwsza kolumna to sam ptaszek zaznaczania, „pierwszą" jest druga. */
:root tbody > tr > td:first-child,
:root thead > tr > th:first-child{text-align:left}
:root tbody > tr > td:first-child:has(> input[type=checkbox]),
:root thead > tr > th:first-child:has(> input[type=checkbox]){text-align:center}
:root tbody > tr:has(> td:first-child > input[type=checkbox]) > td:nth-child(2),
:root thead > tr:has(> th:first-child > input[type=checkbox]) > th:nth-child(2){text-align:left}
:root tbody > tr > td:first-child .tnij,
:root tbody > tr:has(> td:first-child > input[type=checkbox]) > td:nth-child(2) .tnij{margin-left:0}
:root tbody > tr > td:first-child .status-z-powodem{align-items:flex-start}
:root tbody > tr > td:first-child .status-z-powodem .powod{text-align:left}

/* Magazyn: nazwa towaru stoi w DRUGIEJ kolumnie (po kodzie) i bywa
   długa — od lewej, żeby nie rozpychała tabeli na środku
   (20.09.2026, Łukasz). */
:root table.nazwa-od-lewej > tbody > tr > td:nth-child(2),
:root table.nazwa-od-lewej > thead > tr > th:nth-child(2){text-align:left}
:root table.nazwa-od-lewej > tbody > tr > td:nth-child(2) .tnij{margin-left:0}
/* Przyciski w nagłówku karty nie łamią napisu na dwie linie
   („Numer / seryjny" w Magazynie). */
.card>.hd .btn{white-space:nowrap;flex:0 0 auto}

/* PANEL OPERATORA — kolumna „Od kiedy" zostaje wyśrodkowana (to data,
   nie nazwa), plakietka SLA i jej tekst na środku; „nietknięte"
   w kolumnie usterki też na środku (20.09.2026, Łukasz). */
:root .tab-zgloszen > tbody > tr > td:first-child,
:root .tab-zgloszen > thead > tr > th:first-child{text-align:center}
.tab-zgloszen .sla-znak .pill{justify-content:center;text-align:center}
.tab-zgloszen .znak-ruch{justify-content:center}
/* Abonenci — pierścienie „Sesje / limit" na środku komórki, jak reszta
   (20.09.2026). `.zajetosc-kola` to flex, który sam z siebie stał
   przy lewej krawędzi. */
:root tbody td .zajetosc-kola{justify-content:center}

/* =====================================================================
   LISTY NA PANELU (widgety) — TAK JAK TABELE  (20.09.2026)
   =====================================================================
   Łukasz: „dopracuj też tabele na głównym ekranie IT — tak samo jak na
   pozostałych". Widgety to siatka, nie <table>, więc wspólne reguły
   tabel ich nie łapały. Ten sam nagłówek, te same linie (poziome
   i pionowe), treść na środku komórki; opis zgłoszenia — kolumna, którą
   się czyta — od lewej. Plakietka stanu mieści się w kolumnie. */
.lista-widget .nagl > span{background:var(--naglowek);font-size:var(--fs-xs);
  letter-spacing:.06em;font-weight:750;text-align:center;padding:10px 12px}
.lista-widget .nagl > span:first-child{text-align:center}
.lista-widget .nagl > span + span{border-left:1px solid var(--kolumna-linia)}
.lista-widget .wrs > *{border-bottom-color:var(--wiersz-linia);padding:12px}
.lista-widget .wrs > * + *{border-left:1px solid var(--kolumna-linia)}
.lista-widget .wrs.klik:hover > *{background:var(--wiersz-hover)}
.lista-widget .wrs > *{align-items:center;text-align:center}
.lista-widget .kiedy,.lista-widget .numer,.lista-widget .stan,
.lista-widget .stan-lewo{align-items:center;text-align:center}
.lista-widget .stan .pill{align-self:center;max-width:100%;white-space:normal;
  height:auto;min-height:26px;text-align:center;justify-content:center}
.lista-widget .opis{align-items:stretch;text-align:left}
/* Nagłówek nad opisem też od lewej — stoi nad tekstem, który czyta się
   od lewej krawędzi. Opis jest kolumną z `minmax(0,1fr)`, zwykle drugą. */
.lista-widget:has(.wrs > .opis:nth-child(2)) .nagl > span:nth-child(2){text-align:left}
@media (max-width:760px){
  .lista-widget .wrs > *{align-items:flex-start;text-align:left;border-left:0}
  .lista-widget .stan .pill{align-self:flex-start}
}
.lista-widget .stan .pill{display:inline-flex;align-items:center;gap:5px}
/* Widget panelu: plakietka stanu z ikoną — ikona i napis w jednym rzędzie,
   dłuższy status łamie się w plakietce zamiast urywać wielokropkiem. */
.widget .lista-widget .stan .pill{display:inline-flex;align-items:center;gap:5px;
  white-space:normal;text-overflow:clip;overflow:visible}

/* Kolumna STATUSU na liście zgłoszeń — na środku, razem z powodem pod
   plakietką („Brak przypisanego technika", „SLA przekroczone o…").
   Łukasz, 20.09.2026: „brak przypisanego technika się nie centruje,
   tak samo jak inne komunikaty". Reguła „pierwsza kolumna od lewej"
   jest dla nazw; status nazwą nie jest. */
:root tbody > tr > td.kol-status{text-align:center}
:root tbody > tr > td.kol-status .status-z-powodem{align-items:center}
:root tbody > tr > td.kol-status .status-z-powodem .powod{text-align:center}
:root table:has(> tbody > tr > td.kol-status:first-child) > thead > tr > th:first-child{text-align:center}
@media (max-width:640px){
  :root .tblwrap table.karty td.kol-status .status-z-powodem{align-items:flex-start}
  :root .tblwrap table.karty td.kol-status .status-z-powodem .powod{text-align:left}
}

/* =====================================================================
   KAFLE Z WYKRESAMI NA PANELU — wzór z konceptu Łukasza (20.09.2026)
   ===================================================================== */
/* Pierścień u góry, pod nim „N łącznie", pod tym liczby. Pierścień
   bierze wysokość, która zostaje — na niskim kaflu maleje, zamiast
   wypychać liczby za krawędź. */
.wykres-kolo.karta-kola{display:flex;flex-direction:column;flex-wrap:nowrap;align-items:stretch;
  justify-content:flex-start;gap:6px;height:100%;min-height:0;overflow:hidden;padding:var(--s2) 0 0}
.karta-kola .kolo-svg{flex:1 1 auto;min-height:110px;width:100%;height:100%;max-width:none}
.karta-kola .kolo-kawalek.klik:hover{stroke-width:38}
.kolo-w-wycinku{text-anchor:middle;dominant-baseline:central;font-size:14px;font-weight:750;
  font-variant-numeric:tabular-nums;cursor:pointer}
.kolo-liczba.karta{font-size:40px;font-weight:800;letter-spacing:-.02em}
.kolo-svg text.kolo-liczba.karta[data-dlugi="1"]{font-size:30px}
.kolo-podpis.karta{font-size:10.5px;letter-spacing:.14em}
.kolo-lacznie{text-align:center;font-size:var(--fs-sm);color:var(--ink-3);flex:0 0 auto}

.kolo-liczby{flex:0 0 auto;border-top:1px solid var(--line-soft);padding-top:8px;margin:0 var(--s3)}
.kolo-liczby.kolumny{display:grid}
.kolo-liczby.kolumny .kolo-liczba-poz{display:flex;flex-direction:column;align-items:center;
  gap:2px;padding:4px 6px;text-align:center}
.kolo-liczby.kolumny .kolo-liczba-poz + .kolo-liczba-poz{border-left:1px solid var(--line-soft)}
.kolo-liczby.kolumny strong{font-size:var(--fs-2xl);font-weight:800;line-height:1.1;
  font-variant-numeric:tabular-nums}
.kolo-liczby.kolumny .slowo{font-size:var(--fs-sm);color:var(--ink-2);line-height:1.25;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kolo-liczby.lista{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 12px}
.kolo-liczby.lista .kolo-liczba-poz{display:flex;align-items:baseline;gap:7px;padding:4px 6px;
  text-align:left;min-width:0}
.kolo-liczby.lista strong{font-variant-numeric:tabular-nums;font-weight:800;min-width:1.6em;text-align:right}
.kolo-liczby.lista .slowo{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:var(--fs-sm);color:var(--ink-2)}
.kolo-liczby .kropka{width:10px;height:10px;border-radius:3px;flex:0 0 auto;align-self:center}
.kolo-liczby .kropka.zle{background-image:repeating-linear-gradient(45deg,
  var(--bad-solid) 0 2px, var(--surface) 2px 4px) !important;border:1px solid var(--bad-solid)}
.kolo-liczba-poz{border:0;background:none;font:inherit;color:inherit;border-radius:var(--radius-sm);cursor:pointer}
.kolo-liczba-poz:disabled{cursor:default}
.kolo-liczba-poz:not(:disabled):hover{background:var(--surface-2)}
.kolo-liczba-poz:focus-visible{outline:none;box-shadow:var(--focus)}
.kolo-liczba-poz .legenda-uwaga{font-size:var(--fs-xs)}

/* „Co wymaga uwagi": duże kółko po lewej, opis na środku, kreska
   między pozycjami. */
.krazki{grid-template-columns:max-content minmax(0,1fr);gap:0 var(--s5);
  justify-content:stretch;align-content:center;padding:0 var(--s3)}
.krazek{padding:10px 0;border-radius:0}
.krazek + .krazek{border-top:1px solid var(--line-soft)}
.krazek .tor{stroke:var(--line-soft)}
.krazek-proc{font-size:16px;font-weight:800}
.krazek-opis{align-items:center;text-align:center}
.krazek-opis strong{font-size:var(--fs-2xl);font-weight:800}
.krazek-nazwa{font-size:var(--fs-base);color:var(--ink-2)}
.krazek-z{font-size:var(--fs-sm)}
/* Wąskie kolumny liczb: nazwa łamie się na dwie linie zamiast „Windows …". */
.kolo-liczby.kolumny .slowo{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow-wrap:anywhere}
.kolo-liczby.kolumny .legenda-uwaga{font-style:normal;color:var(--bad);font-weight:650}
/* Lista (więcej niż 4 pozycje): w kaflu jednej szerokości — jedna
   kolumna, nazwa firmy w całości, dopisek („1 po terminie") po prawej. */
.panel>.w1 .kolo-liczby.lista{grid-template-columns:minmax(0,1fr)}
.kolo-liczby.lista .kolo-liczba-poz{align-items:center;padding:3px 6px}
.kolo-liczby.lista .slowo{flex:1 1 auto}
.kolo-liczby.lista .legenda-uwaga{margin-left:auto;flex:0 0 auto;white-space:nowrap;
  font-style:normal;color:var(--bad);font-weight:650}
.kolo-reszta{padding:3px 6px 0 23px;font-size:var(--fs-xs);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.karta-kola .kolo-svg{min-height:150px}
/* „Co wymaga uwagi": kółko + opis jako JEDEN blok na środku kafla —
   równe marginesy z lewej i z prawej (Łukasz, 20.09.2026). Opis ma
   wspólną szerokość dla wszystkich wierszy, więc kółka stoją w jednej
   pionowej linii. */
.krazki{grid-template-columns:max-content minmax(11em,max-content);
  justify-content:center;justify-content:safe center;padding:0}

/* =====================================================================
   KAFLE LICZB NA PANELU — nowy układ (20.09.2026)
   =====================================================================
   Koncept Łukasza + poprawki: trzy stałe strefy, więc liczby w całym
   rzędzie stoją na jednej linii; większa ikona, tytuł i liczba;
   czerwień tylko przy robocie; widać, że kafel prowadzi do listy. */
.kpi.kpi2{position:relative;display:grid;
  grid-template-rows:auto minmax(58px,1fr) auto auto auto;
  align-items:center;text-align:center;padding:var(--s4) var(--s4) var(--s3);overflow:hidden}
.kpi2 .kpi-glowa{display:flex;align-items:flex-start;gap:10px;text-align:left;
  min-height:calc(2 * 1.25em);align-self:start;font-size:var(--fs-base)}
.kpi2 .kpi-ikona{flex:0 0 auto;width:38px;height:38px;border-radius:10px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--surface-2);color:var(--ink-2)}
.kpi2 .l{font-size:var(--fs-base);line-height:1.25;font-weight:750;letter-spacing:.04em;
  color:var(--ink);align-self:center}
.kpi2 .v{font-size:42px;font-weight:800;line-height:1;margin:0;letter-spacing:-.02em;
  display:flex;align-items:center;justify-content:center}
.kpi2 .v .kwota{font-size:32px;white-space:nowrap}
.kpi2 .kpi-zmiana{font-size:var(--fs-sm);font-weight:650;color:var(--ink-3);
  min-height:1.4em;margin-top:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi2 .kpi-zmiana.gorzej{color:var(--bad)}
.kpi2 .kpi-zmiana.lepiej{color:var(--ok)}
.kpi2 .d{font-size:var(--fs-sm);color:var(--ink-3);margin-top:2px;min-height:1.4em}
.kpi2 .d.spokojnie{color:var(--ok);font-weight:650}
.kpi2 .kpi-trend{display:block;width:100%;height:26px;margin-top:8px;color:var(--ink-3)}
.kpi2 .kpi-trend .krzywa{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round}
.kpi2 .kpi-trend .pole{fill:currentColor;opacity:.12}
.kpi2.alert .kpi-trend{color:var(--bad)}
/* Alarm: czerwony pasek u góry, jasnoczerwone tło, ikona w czerwieni. */
.kpi2.alert{box-shadow:inset 0 4px 0 var(--bad-solid),var(--shadow-1)}
.kpi2.alert .kpi-ikona{background:color-mix(in srgb,var(--bad) 14%,transparent);color:var(--bad)}
.kpi2.spokoj .kpi-ikona{background:color-mix(in srgb,var(--ok) 12%,transparent);color:var(--ok)}
/* Klikalny: podniesienie i „Pokaż listę →" w prawym dolnym rogu —
   poza przepływem, więc nie przesuwa liczb. */
.kpi2.kpi-klik{transition:transform .12s ease,box-shadow .12s ease}
.kpi2.kpi-klik:hover{transform:translateY(-2px)}
.kpi2 .kpi-pokaz{position:absolute;right:12px;bottom:8px;font-size:var(--fs-xs);font-weight:700;
  color:var(--accent-text);opacity:0;transition:opacity .12s}
.kpi2.kpi-klik:hover .kpi-pokaz,.kpi2.kpi-klik:focus-visible .kpi-pokaz{opacity:1}
@media (prefers-reduced-motion: reduce){ .kpi2.kpi-klik,.kpi2 .kpi-pokaz{transition:none} .kpi2.kpi-klik:hover{transform:none} }
/* Ananas: górna krawędź kafla już jest pogrubiona — alarm ją przejmuje. */
:root[data-theme="ananas"] .kpi2.alert{box-shadow:var(--shadow-1)}
:root[data-theme="ananas"] .kpi2 .kpi-ikona{background:#fff3cc;color:#0d1f3c}
:root[data-theme="ananas"] .kpi2.alert .kpi-ikona{background:#fde2de;color:var(--bad)}
@media (max-width:760px){
  .kpi2 .v{font-size:32px} .kpi2 .v .kwota{font-size:24px}
  .kpi2 .kpi-ikona{width:30px;height:30px}
}
/* Poprawka układu: strefy o STAŁEJ wysokości (nie `1fr`), inaczej kafel
   z linią trendu miał niżej liczbę niż kafel bez niej. Tytuł zawsze
   dokładnie na dwie linie. */
.kpi.kpi2{grid-template-rows:auto 60px auto auto auto;align-content:start;
  padding:14px 14px 10px}
.kpi2 .kpi-glowa{height:calc(2 * 1.25 * 14px);min-height:0;gap:8px;align-items:center}
.kpi2 .kpi-ikona{width:34px;height:34px}
.kpi2 .l{font-size:14px;letter-spacing:.02em;hyphens:auto;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
/* Pasek przycisków panelu jest pusty, gdy przyciski poszły do nagłówka. */
.pasek-glowny:empty{display:none}
/* Tytuł kafla: długie jedno słowo („ZAFAKTUROWANIA") ma się zmieścić. */
.kpi2 .kpi-ikona{width:30px;height:30px}
.kpi2 .kpi-glowa{gap:8px}
.kpi2 .l{font-size:13.5px;letter-spacing:.01em;overflow-wrap:anywhere}
.kpi2 .l{font-size:13px;letter-spacing:0}
/* W nagłówku ekranu przyciski mają jedną wysokość — „Szybki serwis"
   ma w panelu klasę dużego przycisku, tu byłby wyższy od sąsiadów. */
.akcje-ekranu .btn{height:var(--control-h);font-size:var(--fs-base);padding-top:0;padding-bottom:0}
.akcje-ekranu .btn.sm{height:34px;font-size:var(--fs-sm)}

/* =====================================================================
   JEDNO PISMO W CAŁYM PROGRAMIE  (20.09.2026)
   =====================================================================
   Łukasz: „czcionki w najnowszych zgłoszeniach, w datach, monitoring
   wydają się inne. Trochę dziwnie wygląda, jak co kolumna czy wiersz
   jest inny styl czcionki". Źródłem była klasa `.mono` (pismo maszynowe)
   na datach, godzinach, „291 dni", numerach zgłoszeń i kodach stanowisk
   — obok zwykłego pisma w tym samym wierszu.
   Teraz `.mono` to TO SAMO pismo co reszta (Inter / w ananasie Nunito),
   z cyframi o stałej szerokości (kolumny liczb układają się równo),
   przekreślonym zerem i rozróżnionymi I/l/1 — czyli to, dla czego
   w ogóle sięgało się po maszynowe przy IP, MAC-u czy numerze seryjnym.
   Prawdziwe pismo maszynowe zostaje tylko tam, gdzie jest kodem:
   bloki `code`, klucze, treść logów. */
.mono{font-family:var(--font);font-variant-numeric:tabular-nums slashed-zero;
  font-feature-settings:"tnum" 1,"zero" 1,"ss02" 1;letter-spacing:.01em}
.kpi.kpi2{padding-left:12px;padding-right:12px}
.kpi2 .l{font-weight:700;word-break:break-word}
/* Linia trendu także w zwykłych kafelkach (kasa, karta firmy). */
.kpi .kpi-trend{display:block;width:100%;height:26px;margin-top:8px;color:var(--ink-3)}
.kpi .kpi-trend .krzywa{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round}
.kpi .kpi-trend .pole{fill:currentColor;opacity:.12}
.kpi.alert .kpi-trend{color:var(--bad)}
.obc-trend{width:100%;max-width:120px;margin:4px auto 0;color:var(--ink-3)}
.obc-trend.ton-zle{color:var(--bad)} .obc-trend.ton-uwaga{color:var(--warn)}
.obc-trend .kpi-trend,.kopia-trend .kpi-trend,.pasek-kafli .kpi-trend{display:block;width:100%;height:22px}
.obc-trend .krzywa,.kopia-trend .krzywa,.pasek-kafli .krzywa{fill:none;stroke:currentColor;stroke-width:1.6}
.obc-trend .pole,.kopia-trend .pole,.pasek-kafli .pole{fill:currentColor;opacity:.12}
.kopia-trend{margin-top:6px;color:var(--ink-3)}
.kopie-maszyna.ton-zle .kopia-trend{color:var(--bad)}

/* Strzałka „pokaż listę" — prawy górny róg, w kółku o tle karty,
   więc nie zlewa się z niczym pod spodem (20.09.2026). */
.kpi2 .kpi-pokaz{top:10px;right:10px;bottom:auto;width:24px;height:24px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;font-size:14px;line-height:1;
  background:var(--surface);border:1px solid var(--line);color:var(--ink)}
.kpi2.kpi-klik .kpi-glowa{padding-right:22px}

/* LICZBA „W CZYMŚ" (20.09.2026, Łukasz: „cyfry są takie gołe w kaflu —
   może w kołeczku, prostokącie?"). Delikatny zaokrąglony prostokąt
   w odcieniu kafla: liczba dostaje swoje miejsce, a kafel nie robi się
   cięższy. Szerokość z treści, więc „4" i „13 040 zł" mają ten sam
   kształt w różnych rozmiarach. */
.kpi2 .v{justify-self:center;align-self:center;height:54px;min-width:72px;padding:0 18px;
  border-radius:14px;background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--line-soft)}
.kpi2.alert .v{background:color-mix(in srgb,var(--bad) 9%,var(--surface));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--bad) 22%,transparent)}
.kpi2.spokoj .v{background:color-mix(in srgb,var(--ok) 8%,var(--surface));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ok) 20%,transparent)}
.kpi2 .v{font-size:38px}
.kpi2 .v .kwota{font-size:28px}
:root[data-theme="ananas"] .kpi2 .v{background:#faf8f1}
:root[data-theme="ananas"] .kpi2.alert .v{background:#fff3f1}
/* Strzałka pokazuje się tylko po najechaniu — tytuł nie oddaje jej
   miejsca na stałe (inaczej „DO ZAFAKTUROWANIA" ucinało się). Siedzi
   nad samym narożnikiem, na tle karty. */
.kpi2.kpi-klik .kpi-glowa{padding-right:0}
.kpi2 .kpi-pokaz{top:6px;right:6px;width:22px;height:22px;font-size:13px;box-shadow:var(--shadow-1)}
.kafel-liczby .kpi-trend{display:block;width:100%;height:22px;margin-top:6px;color:var(--ink-3)}
.kafel-liczby .kpi-trend .krzywa{fill:none;stroke:currentColor;stroke-width:1.6}
.kafel-liczby .kpi-trend .pole{fill:currentColor;opacity:.12}
.kafel-liczby.ok .kpi-trend{color:var(--ok)} .kafel-liczby.bad .kpi-trend{color:var(--bad)}
.kafel-liczby.warn .kpi-trend{color:var(--warn)}

/* CYTAT DNIA (20.09.2026) — ma być smaczkiem, nie kaflem: mała kursywa
   w kolorze tekstu pomocniczego, między tytułem a przyciskami. Przy
   wąskim oknie znika, zamiast spychać przyciski. */
.naglowek-ekranu{flex-wrap:nowrap}
.cytat-dnia{flex:1 1 auto;min-width:0;max-width:640px;margin:0 auto;padding:0 var(--s5);
  text-align:center;align-self:center;color:var(--ink-3)}
.cytat-dnia blockquote{margin:0;font-style:italic;font-size:var(--fs-base);line-height:1.4;
  color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  text-wrap:balance}
.cytat-dnia figcaption{margin-top:3px;font-size:var(--fs-sm);display:flex;justify-content:center;
  align-items:center;gap:8px}
.cytat-dalej{border:0;background:none;color:var(--ink-3);cursor:pointer;font:inherit;
  padding:0 4px;border-radius:var(--radius-sm);opacity:0;transition:opacity .15s}
.cytat-dnia:hover .cytat-dalej,.cytat-dalej:focus-visible{opacity:1}
.cytat-dalej:hover{color:var(--ink);background:var(--surface-2)}
@media (max-width:1350px){ .cytat-dnia{display:none} }

/* POWIADOMIENIA W RÓWNYCH KOLUMNACH (20.09.2026, Łukasz: „takie trochę
   rozjechane"). Plakietki mają różną szerokość („info" / „krytyczne")
   i do tego czasem licznik „79. raz", więc każdy tytuł zaczynał się
   gdzie indziej. Teraz trzy kolumny: znaki (stała szerokość, plakietka
   nad licznikiem, wyśrodkowane) | tytuł | godzina; firma pod tytułem
   zaczyna się tam, gdzie tytuł. */
.powiadomienie .powiad-glowa{display:grid;grid-template-columns:86px minmax(0,1fr) auto;
  align-items:center;gap:4px 12px}
.powiad-znaki{display:flex;flex-direction:column;align-items:center;gap:3px}
.powiad-znaki .pill{width:100%;justify-content:center}
.powiad-znaki .powiad-licznik{margin:0}
/* Plakietka modułu przy powiadomieniu — ta sama co przy logo (26.09.2026). */
.plakietka-modulu { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 700; font-size: 12px;
  line-height: 1; padding: 4px 7px; border-radius: 6px; white-space: nowrap; }
.plakietka-modulu.w-it { background: var(--ananas-it); color: var(--ananas-it-ink); }
.plakietka-modulu.w-serwis { background: var(--ananas-serwis); color: var(--ananas-serwis-ink); }
.plakietka-modulu.w-isp { background: var(--ananas-isp); color: var(--ananas-isp-ink); }
.powiadomienie .powiad-glowa > .muted{margin-left:0 !important;align-self:center}
.powiadomienie .powiad-tresc{padding-left:98px}

/* Odstęp liczby od tytułu (20.09.2026, Łukasz: „wygląda, jakby miało
   na niego wjechać, a dół jest pusty"). Kafel jako kolumna: tytuł
   (stała wysokość) → liczba z oddechem nad i pod → zmiana → podpis,
   a linia trendu dociśnięta do dołu. Liczby dalej stoją w jednej
   linii, bo wszystko nad nimi ma stałą wysokość. */
.kpi.kpi2{display:flex;flex-direction:column;align-items:stretch;padding:14px 12px 12px}
.kpi2 .v{margin:16px auto 10px;flex:0 0 auto}
.kpi2 .kpi-zmiana{margin-top:0}
.kpi2 .kpi-trend{margin-top:auto;padding-top:8px}
/* Kolejność kolumn w powiadomieniu (20.09.2026, Łukasz): najpierw
   godzina, potem treść, na końcu plakietka. Zmiana samego układu —
   znaczniki zostają w tej samej kolejności (czytnik ekranu czyta
   najpierw wagę). */
.powiadomienie .powiad-glowa{grid-template-columns:48px minmax(0,1fr) 86px}
.powiadomienie .powiad-glowa > .muted{order:1;text-align:left;font-variant-numeric:tabular-nums}
.powiadomienie .powiad-glowa > .powiad-tytul{order:2}
.powiadomienie .powiad-glowa > .powiad-znaki{order:3}
.powiadomienie .powiad-tresc{padding-left:60px;padding-right:98px}
.powiadomienie .powiad-tresc{padding-right:0}

/* CYTAT DNIA W GÓRNYM PASKU (20.09.2026). Szukajka węższa (była
   za duża), cytat bierze miejsce między nią a zegarem: dwie linie
   kursywy, autor w trzeciej, drobniej. Przy wąskim oknie znika. */
.top-lewo .qs{flex:0 1 360px;max-width:360px}
.topbar .cytat-dnia{flex:1 1 auto;max-width:520px;margin:0;padding:0 var(--s2);text-align:left;
  display:block}
.topbar .cytat-dnia blockquote{font-size:13px;line-height:1.35;text-wrap:pretty}
.topbar .cytat-dnia figcaption{justify-content:flex-start;font-size:12px;margin-top:1px}
@media (max-width:1500px){ .topbar .cytat-dnia{display:none} }
@media (min-width:1501px){ .topbar .cytat-dnia{display:block} }
.top-lewo .qs{flex:0 0 340px;max-width:340px}
.top-lewo .qs{flex:0 0 270px;max-width:270px}
.topbar .cytat-dnia{position:relative;padding-right:22px}
.topbar .cytat-dnia blockquote{-webkit-line-clamp:3;font-size:12.5px;line-height:1.32}
.cytat-autor{font-style:normal;color:var(--ink-3);white-space:nowrap}
.topbar .cytat-dnia figcaption{position:absolute;right:0;top:50%;transform:translateY(-50%);margin:0}

/* „Zobacz wszystkie" w panelach (20.09.2026). Tytuł jest linkiem,
   w nagłówku przycisk po prawej, a „…i jeszcze N" prowadzi tam samo. */
.tytul-widgetu{all:unset;cursor:pointer;border-radius:4px}
.tytul-widgetu:hover{text-decoration:underline;text-underline-offset:3px}
.tytul-widgetu:focus-visible{box-shadow:var(--focus)}
.widget > .hd .zobacz-wszystkie{margin-left:auto;font-size:var(--fs-sm);font-weight:650;
  white-space:nowrap;color:var(--accent-text)}
.widget-reszta.klik{display:block;width:100%;border:0;background:none;font:inherit;
  color:var(--accent-text);cursor:pointer;font-weight:650}
.widget-reszta.klik:hover{background:var(--surface-2);text-decoration:underline}
.widget > .hd{flex-wrap:wrap}
.widget > .hd .zobacz-wszystkie{order:99;margin-left:auto}
.brandbar.klik{cursor:pointer}
.brandbar.klik:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--radius)}
/* Cytat na środku wolnego miejsca między szukajką a zegarem. */
.topbar .cytat-dnia{margin:0 auto;text-align:center;padding:0 22px}

/* ===================================================================
   PANEL OPERATORA — DOMKNIĘCIE DO WYGLĄDU PANELU IT (20.09.2026)
   ===================================================================
   Łukasz: „panel operatora w porównaniu do Panelu IT wygląda jak kupa,
   a panel IT wygląda jak milion dolarów". Kafle dostały ikony i linie
   trendu z tego samego zestawu, co panel IT, a pasek stanu przeniósł
   się obok tytułu ekranu — tak jak tam przyciski.
   =================================================================== */
.akcje-ekranu .panel-operatora-stan{max-width:38ch;text-align:right;line-height:1.35}
/* Na telefonie slotu nie ma i pasek zostaje w treści — wtedy ma stać
   w jednej linii z przyciskiem, a nie sklejać się z pierwszym blokiem. */
.panel-operatora > .panel-operatora-stan{display:block;margin-bottom:calc(var(--s2) * -1)}
.panel-operatora > .btn.sm{align-self:flex-start}
/* Nagłówki bloków: kreska pod napisem, żeby trzy rzędy kafli czytały
   się jako trzy sekcje, a nie jako jedna ściana liczb. */
.panel-operatora-blok h3{display:flex;align-items:center;gap:var(--s3)}
.panel-operatora-blok h3::after{content:"";flex:1;height:1px;background:var(--line-soft)}
/* Płaska seria: sama linia, delikatniej niż zwykła krzywa — informuje
   „bez zmian", ale nie udaje wykresu. */
.kpi-trend.plasko .krzywa{opacity:.45}

/* Wiersz dziennika: plakietka rodzaju i numer zgłoszenia w jednej linii
   nad treścią — tak jak numer zlecenia nad opisem na Panelu IT. */
.lista-widget .opis .rodzaj-wpisu{display:flex;align-items:center;gap:8px;
  flex-wrap:wrap;min-width:0}
.lista-widget .opis .rodzaj-wpisu .numer-w-opisie{white-space:nowrap}
/* Listy panelu operatora rosną z treścią — nie siedzą w siatce widgetów
   Panelu IT, więc nie mają narzuconej wysokości i nic się nie przycina. */
.panel-operatora-listy .widget{overflow:visible}
.panel-operatora-listy .widget > .widget-tresc{overflow:visible}

/* ===================================================================
   WPISY Z KALENDARZA BEZ OSOBY (20.09.2026)
   ===================================================================
   Pasek nad siatką kalendarza. Zwinięty domyślnie — ma przypominać,
   a nie zabierać miejsca planowaniu dnia.
   =================================================================== */
.kal-bez-osoby{border:1px solid var(--warn-line, var(--line));border-radius:var(--radius);
  background:var(--surface-2);margin-bottom:var(--s4);overflow:hidden}
.kal-bez-osoby-hd{display:flex;align-items:center;gap:var(--s3);width:100%;
  padding:10px var(--s4);background:none;border:0;cursor:pointer;text-align:left;
  font:inherit;color:inherit}
.kal-bez-osoby-hd:hover{background:var(--surface-3, var(--surface-2))}
.kal-bez-osoby-hd .muted{font-size:var(--fs-sm)}
.kal-bez-osoby-hd .strzalka{margin-left:auto;color:var(--ink-2)}
.kal-bez-osoby-lista{list-style:none;margin:0;padding:0;border-top:1px solid var(--line-soft)}
.kal-bez-osoby-lista li{display:grid;grid-template-columns:150px minmax(0,1fr) 220px;
  align-items:center;gap:var(--s3);padding:8px var(--s4);
  border-bottom:1px solid var(--line-soft)}
.kal-bez-osoby-lista li:last-child{border-bottom:0}
.kal-bez-osoby-lista .kiedy{color:var(--ink-2);font-size:var(--fs-sm);white-space:nowrap;
  font-variant-numeric:tabular-nums}
.kal-bez-osoby-lista .tytul{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:760px){
  .kal-bez-osoby-lista li{grid-template-columns:1fr;gap:4px}
}

/* Przycisk zamknięcia rozmowy — po prawej w wierszu listy rozmów.
   Widoczny dopiero po najechaniu albo po wejściu klawiaturą, żeby lista
   nie zamieniła się w ścianę przycisków; przy dotyku pokazujemy zawsze,
   bo tam nie ma najechania. */
.rozmowa-poz .rozmowa-zamknij{margin-left:8px;flex:0 0 auto;opacity:0;
  transition:opacity .12s ease}
.rozmowa-poz:hover .rozmowa-zamknij,
.rozmowa-poz:focus-within .rozmowa-zamknij{opacity:1}
@media (hover:none){ .rozmowa-poz .rozmowa-zamknij{opacity:1} }

/* ===================================================================
   STATYSTYKI (20.09.2026)
   ===================================================================
   Trzy ekrany o tym samym układzie: filtr, założenia, kafle, wykres,
   tabele. Osobne dla Panelu IT, Napraw i Operatora — patrz komentarz
   w [[statystyki.tsx]].
   =================================================================== */
.statystyki{display:flex;flex-direction:column;gap:var(--s5)}
.statystyki > .card > .bd{padding:var(--s4)}

.filtry-statystyk{display:flex;align-items:flex-end;gap:var(--s4);flex-wrap:wrap;
  padding:var(--s4)}
.filtry-statystyk .presety{display:flex;gap:6px;flex-wrap:wrap}
.filtry-statystyk .pole{margin:0}
.filtry-statystyk input[type=date]{min-width:150px}

/* Założenia zwinięte: mają być pod ręką, nie na wierzchu. Człowiek
   zagląda tam raz — gdy liczba go zaskoczy. */
.zalozenia{border:1px solid var(--line-soft);border-radius:var(--radius);
  background:var(--surface-2);padding:10px var(--s4)}
.zalozenia > summary{cursor:pointer;font-weight:660;font-size:var(--fs-sm);
  color:var(--ink-2)}
.zalozenia > summary:hover{color:var(--ink)}
.zalozenia .lista{margin:var(--s3) 0 4px;padding-left:1.1em;
  font-size:var(--fs-sm);line-height:1.6;color:var(--ink-2)}
.zalozenia .lista li{margin-bottom:4px}

/* ------------------------------------------------------------------
   WYKRES DWÓCH SERII
   ------------------------------------------------------------------
   Kolory z tokenów `--seria-*` — osobnych od akcentu i od kolorów
   stanu, zwalidowanych pod kątem daltonizmu i kontrastu (tokens.css).
   Siatka i osie są RECESYWNE: mają prowadzić oko, nie rywalizować
   z danymi.
   ------------------------------------------------------------------ */
.wykres-rytmu{position:relative}
.wykres-rytmu svg{width:100%;height:190px;display:block;overflow:visible}
.wykres-rytmu .siatka{stroke:var(--line-soft);stroke-width:1;vector-effect:non-scaling-stroke}
.wykres-rytmu .opis-osi{fill:var(--ink-3);font-size:11px;
  font-variant-numeric:tabular-nums}
.wykres-rytmu .linia{fill:none;vector-effect:non-scaling-stroke;
  stroke-linejoin:round;stroke-linecap:round}
/* PIERWSZA SERIA GRUBSZA, DRUGA CIEŃSZA I KRESKOWANA — po to, żeby przy
   pokrywających się wartościach było widać OBIE.
   Sama kreska nie wystarczyła: przy grubości 2 px w przerwach kreski
   prześwitywał kolor pierwszej serii i obie zlewały się w jeden, trzeci
   odcień — wykres wyglądał, jakby serii była jedna, tylko w dziwnym
   kolorze. Przy 3 px pod spodem i 2 px na wierzchu widać wyraźnie
   kreskowaną linię LEŻĄCĄ NA grubszej. */
/* Pierwsza seria to SŁUPKI — zaokrąglone końce przy górze, osadzone
   na linii zera. Lekko przygaszone, bo to tło dla linii, nie rywal. */
.wykres-rytmu .slupek.s1{fill:var(--seria-1);opacity:.55}
/* DRUGA SERIA KRESKOWANA — i to nie jest ozdoba.
   Przy zdrowej firmie obie linie leżą NA SOBIE („wpłynęło 5, zamknięte
   5"), a wtedy rysowana na wierzchu zasłania tę pod spodem i wykres
   kłamie: wygląda, jakby jednej serii nie było wcale. Kreska pokazuje
   obie naraz i przy okazji daje tożsamość serii niezależną od koloru —
   potrzebną przy tritanopii, gdzie te dwa odcienie zlewają się w jeden. */
.wykres-rytmu .linia.s2{stroke:var(--seria-2);stroke-width:2.5}
/* Podpis przy ostatnim punkcie — druga tożsamość serii obok koloru.
   Tekst w kolorze serii jest tu WYJĄTKIEM od zasady „tekst nosi tokeny
   tekstu": ten napis JEST etykietą marki, a nie treścią. */
.wykres-rytmu .podpis-serii{font-size:11px;font-weight:700}
.wykres-rytmu .podpis-serii.s1{fill:var(--seria-1)}
.wykres-rytmu .podpis-serii.s2{fill:var(--seria-2)}
.wykres-rytmu .krzyzyk{stroke:var(--line);stroke-width:1;stroke-dasharray:3 3;
  vector-effect:non-scaling-stroke}
/* Obwódka w kolorze tła oddziela kropkę od linii pod nią. */
.wykres-rytmu .kropka{stroke:var(--surface);stroke-width:2}
.wykres-rytmu .kropka.s1{fill:var(--seria-1)}
.wykres-rytmu .kropka.s2{fill:var(--seria-2)}

.wykres-rytmu .legenda{display:flex;gap:var(--s4);flex-wrap:wrap;
  margin-bottom:var(--s3);font-size:var(--fs-sm);color:var(--ink-2)}
.wykres-rytmu .legenda .poz,
.dymek-wykresu .poz{display:inline-flex;align-items:center;gap:6px}
.wykres-rytmu .znacznik,
.dymek-wykresu .znacznik{width:12px;height:3px;border-radius:2px;flex:0 0 auto;
  padding:0;border:0;vertical-align:middle}
.wykres-rytmu .znacznik.s1,.dymek-wykresu .znacznik.s1{background:var(--seria-1)}
.wykres-rytmu .znacznik.s2,.dymek-wykresu .znacznik.s2{background:var(--seria-2)}
/* Znacznik serii słupkowej wygląda jak słupek, nie jak kreska. */
.wykres-rytmu .znacznik.jak-slupek,.dymek-wykresu .znacznik.jak-slupek{
  width:10px;height:12px;border-radius:2px;opacity:.55}

.dymek-wykresu{position:absolute;top:0;right:0;display:flex;flex-direction:column;
  gap:2px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:8px 10px;font-size:var(--fs-sm);
  box-shadow:var(--cien-1);pointer-events:none}

/* Udział procentowy jako pasek w komórce — czyta się szybciej niż
   sama liczba, a nie zabiera osobnej kolumny. */
td.udzial{position:relative;min-width:140px}
td.udzial .pasek{display:inline-block;height:8px;border-radius:4px;
  background:var(--seria-1);opacity:.35;vertical-align:middle;margin-right:8px;
  max-width:60%}
td.udzial .mini{color:var(--ink-2)}
td.zle{color:var(--bad);font-weight:700}

@media (max-width:760px){
  .filtry-statystyk{gap:var(--s3)}
  .filtry-statystyk .presety{width:100%}
  .dymek-wykresu{position:static;margin-top:var(--s3)}
}

/* ===================================================================
   KAFLE — DŁUGIE WARTOŚCI I ZNACZNIK MODUŁU (21.09.2026)
   ===================================================================
   Łukasz: „wyjeżdżają wartości z kafli w profilu firmy". Klasy nadaje
   `rozmiarWartosci()` w [[ui.tsx]] po długości napisu — dotyczy każdego
   kafla w programie, nie tylko karty firmy.
   `nowrap`, bo wartość złamana na dwie linie w polu o stałej wysokości
   wychodzi górą i dołem poza tło („3 lat / temu"). */
.kpi2 .v{white-space:nowrap}
.kpi2 .v.v-s{font-size:28px;letter-spacing:-.01em}
.kpi2 .v.v-xs{font-size:22px;letter-spacing:0}

/* Znacznik modułu w nagłówku kafla: „IT" / „Serwis". Mały i stonowany —
   ma rozstrzygać wątpliwość, a nie konkurować z liczbą. Kolory NIE są
   kolorami stanu (zielony/czerwony znaczą tu „dobrze/źle"), tylko
   neutralne odcienie informacji i tła. */
.kpi-glowa .kpi-znacznik{margin-left:auto;flex:0 0 auto;font-size:10px;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-pill,6px);
  line-height:1.4;border:1px solid var(--line)}
.kpi-znacznik.z-it{color:var(--info);background:var(--info-bg);border-color:var(--info-border)}
.kpi-znacznik.z-serwis{color:var(--ink-2);background:var(--surface-2)}

/* Karta firmy: wybór widocznych kafli */
.kafle-karty-hd{display:flex;justify-content:flex-end;margin-bottom:var(--s2)}
.wybor-kafli-karty{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);align-items:flex-start;
  margin-bottom:var(--s3)}
.wybor-kafli-karty .grupa{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);align-items:center}
.wybor-kafli-karty .grupa .kpi-znacznik{font-size:10px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-pill,6px);line-height:1.4;
  border:1px solid var(--line)}
.wybor-kafli-karty .ptaszek{display:inline-flex;gap:6px;align-items:center;cursor:pointer;
  font-size:var(--fs-sm)}
.wybor-kafli-karty > .mini{flex-basis:100%}

/* Statystyki napraw — zakładki i rozliczenia (22.09.2026) */
.statystyki-zakladki{padding-bottom:0}
.statystyki-zakladki .zakladki{flex-wrap:wrap}
.przelacznik-kwot{display:inline-flex;gap:4px;align-self:flex-end}
.rok-biezacy{font-size:var(--fs-lg);font-variant-numeric:tabular-nums;padding:0 var(--s2)}
.tabela-rozliczen td.mocno{font-weight:700}
.tabela-rozliczen tfoot td{font-weight:700;border-top:2px solid var(--line)}
.tabela-rozliczen tr.wyszarzony td{color:var(--ink-3)}
.tabela-rozliczen.macierz td .pod{display:block;line-height:1.2}
.tabela-rozliczen.macierz td,.tabela-rozliczen.macierz th{white-space:nowrap}
.dwie-kolumny-statystyk{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(min(100%,600px),1fr))}
.dwie-kolumny-statystyk > .card{margin:0}
.tabela-rozliczen td .pod{display:block;line-height:1.2;font-family:var(--font, inherit)}
.tabela-rozliczen td.nazwa-osoby{white-space:nowrap}
.tabela-rozliczen th,.tabela-rozliczen td{padding-left:10px;padding-right:10px}

/* POMIAR ŁĄCZA Z ROUTERA (22.09.2026) — blok pod danymi routera
   w karcie abonenta. Kreska u góry oddziela pomiar (rzecz, którą
   ROBIMY) od odczytów z ACS-a (rzeczy, które tylko widzimy). */
.pomiar-lacza{margin-top:10px;padding-top:10px;border-top:1px solid var(--line);
              display:flex;flex-direction:column;gap:6px}
.pomiar-lacza .pomiar-hd{display:flex;align-items:center;gap:8px;justify-content:space-between}
.pomiar-lacza .nazwa{font-weight:640}
.pomiar-lacza table td{vertical-align:top}

/* WIADOMOŚCI OD ABONENTÓW (22.09.2026) — skrzynka spraw, nie komunikator.
   Wiadomość abonenta po lewej, nasza po prawej, NORA wyszarzona: technik
   ma w pierwszej sekundzie widzieć, kto co napisał. */
.tab-watkow tr.nieprzeczytany td{background:var(--surface-2)}
.rozmowa-watku{display:flex;flex-direction:column;gap:10px;margin:8px 0 14px;
               max-height:46vh;overflow-y:auto;padding-right:4px}
.rozmowa-watku .wiad{border:1px solid var(--line);border-radius:var(--radius);
                     padding:8px 10px;max-width:78%}
.rozmowa-watku .wiad-kto{font-size:var(--fs-s);font-weight:640;margin-bottom:3px}
.rozmowa-watku .wiad-tresc{white-space:pre-wrap}
.rozmowa-watku .wiad-abonent{align-self:flex-start;background:var(--surface-2)}
.rozmowa-watku .wiad-serwis{align-self:flex-end;background:var(--surface);
                            border-color:var(--granat-2,var(--line))}
.rozmowa-watku .wiad-nora{align-self:flex-start;background:transparent;opacity:.8;
                          border-style:dashed}

/* =====================================================================
   CZAT ZESPOŁU (A6, 23.09.2026) — czat-zespolu.tsx
   Dwie kolumny: lista rozmów i rozmowa. Na telefonie jedna na raz.
   Kolory wyłącznie z tokenów — działa w jasnym, ciemnym i ANANAS.
   ===================================================================== */
:root{--cz-lit-tlo:86%;--cz-lit-tekst:28%;--cz-moja:var(--accent-soft);--cz-o-mnie:var(--warn-bg)}
:root[data-theme="dark"]{--cz-lit-tlo:30%;--cz-lit-tekst:86%}

.cz{display:grid;grid-template-columns:minmax(260px,330px) minmax(0,1fr);min-height:420px;
  border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--surface);
  overflow:hidden;position:relative}
.cz.telefon{grid-template-columns:minmax(0,1fr);border-radius:var(--radius)}
.cz-historia{padding:var(--s2) 0;border-bottom:1px solid var(--line-soft)}
.cz-historia:last-child{border-bottom:0}

.cz-awatar{display:inline-flex;align-items:center;justify-content:center;flex:none;
  border-radius:50%;object-fit:cover;background:var(--surface-2);font-weight:700;
  letter-spacing:.02em;user-select:none}
.cz-awatar-litery{background:hsl(var(--cz-h,220) 45% var(--cz-lit-tlo));
  color:hsl(var(--cz-h,220) 55% var(--cz-lit-tekst))}
.cz-awatar-znak{background:var(--accent-soft);color:var(--accent-text)}
.cz-awatar-znak svg{width:55%;height:55%}

/* --- lewa kolumna --- */
.cz-lewa{display:flex;flex-direction:column;min-height:0;min-width:0;border-right:1px solid var(--line);
  background:var(--surface-2)}
.cz.telefon .cz-lewa{border-right:0}
.cz-lewa-gora{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3);
  border-bottom:1px solid var(--line)}
.cz-szukaj{display:flex;align-items:center;gap:8px;height:var(--control-h);padding:0 10px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink-3)}
.cz-szukaj:focus-within{border-color:var(--accent);box-shadow:var(--focus)}
.cz-szukaj input{flex:1;min-width:0;border:0;background:none;color:var(--ink);font:inherit;outline:none}
.cz-lewa-akcje{display:flex;gap:var(--s2)}
.cz-lewa-akcje .btn{flex:1}
.cz-lewa-lista{flex:1;overflow:auto;padding:var(--s2) 0}
.cz-sekcja + .cz-sekcja{margin-top:var(--s2)}
.cz-sekcja-tytul{padding:var(--s2) var(--s4) 4px;font-size:var(--fs-xs);font-weight:750;
  text-transform:uppercase;letter-spacing:.08em;color:var(--ink-3)}
.cz-pusto{padding:var(--s4)}
.cz-podpowiedz-pusto{margin:var(--s3);padding:var(--s3);border:1px dashed var(--line);
  border-radius:var(--radius-sm);color:var(--ink-3);font-size:var(--fs-sm)}
.cz-kanal{display:flex;align-items:center;gap:10px;width:100%;padding:8px var(--s4);
  border:0;border-left:3px solid transparent;background:none;color:var(--ink);font:inherit;
  text-align:left;cursor:pointer}
.cz-kanal:hover{background:var(--surface)}
.cz-kanal:focus-visible{outline:none;box-shadow:inset var(--focus)}
.cz-kanal.on{background:var(--surface);border-left-color:var(--accent)}
.cz-kanal-opis{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.cz-kanal-glowa,.cz-kanal-dol{display:flex;align-items:center;gap:6px;min-width:0}
.cz-kanal-nazwa{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.cz-kanal.nowe .cz-kanal-nazwa{font-weight:780}
.cz-kanal-czas{font-size:var(--fs-xs);color:var(--ink-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.cz-kanal-podglad{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:var(--fs-sm);color:var(--ink-3)}
.cz-kanal.nowe .cz-kanal-podglad{color:var(--ink-2)}
.cz-znaczek{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;
  padding:0 6px;border-radius:999px;background:var(--accent);color:var(--accent-ink);
  font-size:var(--fs-xs);font-weight:800;font-variant-numeric:tabular-nums}
.cz-znaczek.cichy{background:var(--g4);color:var(--ink-2)}
.cz-znaczek.wzmianka{background:var(--bad-solid);color:var(--bad-solid-ink)}
.cz-wyciszony{display:inline-flex;color:var(--ink-3)}
.cz-wynik{display:flex;flex-direction:column;gap:2px;width:100%;padding:8px var(--s4);border:0;
  background:none;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.cz-wynik:hover{background:var(--surface)}
.cz-wynik-glowa{display:flex;justify-content:space-between;gap:8px}
.cz-wynik-tresc{font-size:var(--fs-sm);color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden}
.cz-lewa-stopka{padding:var(--s2) var(--s3);border-top:1px solid var(--line)}
.cz-dzwiek{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border:0;
  border-radius:var(--radius-sm);background:none;color:var(--ink-2);font:inherit;
  font-size:var(--fs-sm);cursor:pointer;text-align:left}
.cz-dzwiek:hover{background:var(--surface)}

/* --- prawa kolumna --- */
.cz-prawa{display:flex;flex-direction:column;min-width:0;min-height:0;position:relative}
.cz-nic{align-items:center;justify-content:center}
.cz-glowa{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line);background:var(--surface)}
.cz-glowa-opis{flex:1;min-width:0;display:flex;flex-direction:column}
.cz-glowa-opis h2{margin:0;font-size:var(--fs-md);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cz-glowa-akcje{display:flex;gap:var(--s2)}
.cz-glowa-akcje .btn{display:inline-flex;align-items:center;gap:6px}
.cz.telefon .cz-glowa-akcje .etykieta{display:none}

.cz-wiadomosci{flex:1;overflow-y:auto;overflow-x:hidden;padding:var(--s3) 0 var(--s4);
  overscroll-behavior:contain}
.cz-starsze{display:flex;justify-content:center;padding:var(--s2)}
.cz-poczatek{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--s8) var(--s4);
  text-align:center}
.cz-dzien,.cz-nowe{display:flex;align-items:center;gap:var(--s3);margin:var(--s4) var(--s4) var(--s2);
  font-size:var(--fs-xs);font-weight:700;color:var(--ink-3)}
.cz-dzien::before,.cz-dzien::after,.cz-nowe::before,.cz-nowe::after{content:'';flex:1;height:1px;background:var(--line)}
.cz-dzien span{text-transform:capitalize}
.cz-nowe{color:var(--bad)}
.cz-nowe::before,.cz-nowe::after{background:var(--bad-border)}
.cz-systemowa{margin:var(--s2) var(--s4);text-align:center;font-size:var(--fs-xs);color:var(--ink-3)}

.cz-wiad{display:grid;grid-template-columns:36px 1fr;gap:10px;padding:6px var(--s4) 2px;position:relative}
.cz-wiad.ciag{padding-top:1px}
.cz-wiad:hover{background:var(--surface-2)}
.cz-wiad.o-mnie{background:var(--cz-o-mnie);box-shadow:inset 3px 0 0 var(--warn)}
.cz-wiad-cialo{min-width:0}
.cz-wiad-glowa{display:flex;align-items:baseline;gap:8px}
.cz-wiad-glowa time{font-size:var(--fs-xs);color:var(--ink-3);font-variant-numeric:tabular-nums}
.cz-tresc{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.5}
.cz-tresc.duze{font-size:2rem;line-height:1.25}
.cz-tresc a{text-decoration:underline;text-underline-offset:2px}
.cz-wzmianka{padding:0 3px;border-radius:4px;background:var(--accent-soft);color:var(--accent-text);font-weight:650}
.cz-wzmianka.ja{background:var(--warn-bg);color:var(--warn);box-shadow:inset 0 0 0 1px var(--warn-border)}
.cz-zlecenie{padding:0 4px;border:1px solid var(--accent-border);border-radius:4px;background:var(--accent-soft);
  color:var(--accent-text);font:inherit;font-family:var(--mono);font-size:.92em;cursor:pointer}
.cz-zlecenie:hover{border-color:var(--accent)}
.cz-usunieta{font-style:italic;color:var(--ink-3)}
.cz-edytowana{font-size:var(--fs-xs);color:var(--ink-3)}
.cz-edycja textarea{width:100%;height:auto;min-height:60px;padding:8px 10px;resize:vertical;font:inherit}
.cz-edycja-akcje{display:flex;align-items:center;gap:var(--s2);margin-top:4px}
.cz-edycja-akcje .muted{margin-right:auto}

.cz-obrazy{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.cz-obraz{padding:0;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2);
  overflow:hidden;cursor:zoom-in;line-height:0}
.cz-obraz img{display:block;max-width:min(320px,100%);max-height:260px;object-fit:contain}
.cz-obrazy.kilka .cz-obraz img{width:150px;height:150px;object-fit:cover}
.cz-pliki{display:flex;flex-direction:column;gap:6px;margin-top:6px;align-items:flex-start}
.cz-plik{display:inline-flex;align-items:center;gap:8px;max-width:100%;padding:8px 12px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);color:var(--ink);
  text-decoration:none}
.cz-plik:hover{border-color:var(--accent)}
.cz-plik svg{flex:none;color:var(--accent-text)}
.cz-plik-nazwa{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}

.cz-reakcje{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}
.cz-reakcja{display:inline-flex;align-items:center;gap:4px;height:26px;padding:0 8px;
  border:1px solid var(--line);border-radius:999px;background:var(--surface);color:var(--ink-2);
  font:inherit;font-size:var(--fs-sm);cursor:pointer}
.cz-reakcja:hover{border-color:var(--g5)}
.cz-reakcja.ja{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-text)}
.cz-reakcja-ile{font-weight:700;font-variant-numeric:tabular-nums}

.cz-wiad-akcje{position:absolute;top:-14px;right:var(--s4);display:none;align-items:center;gap:2px;
  padding:2px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface);
  box-shadow:var(--shadow-1);z-index:2}
.cz-wiad:hover .cz-wiad-akcje,.cz-wiad:focus-within .cz-wiad-akcje{display:flex}
.cz-akcja{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:28px;
  padding:0 6px;border:0;border-radius:6px;background:none;color:var(--ink-2);font:inherit;
  font-size:var(--fs-sm);cursor:pointer}
.cz-akcja:hover{background:var(--surface-2);color:var(--ink)}
.cz-akcja.emoji{font-size:16px}
.cz-akcja.tekst{font-weight:600}
/* Na dotyku nie ma najechania — akcje stoją pod wiadomością zawsze,
   ale tylko w wersji skróconej. */
@media (hover:none){
  .cz-wiad-akcje{position:static;display:flex;grid-column:2;width:max-content;margin-top:4px;
    box-shadow:none;background:transparent;border-color:transparent}
  .cz-akcja.emoji{display:none}
}

/* --- dymki: emotki, reakcje, GIF-y, @podpowiedź --- */
.cz-dymek{position:absolute;z-index:45;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow-3);padding:var(--s2)}
.cz-dymek-naglowek{padding:6px 4px 4px;font-size:var(--fs-xs);font-weight:700;color:var(--ink-3)}
.cz-emotki{bottom:calc(100% + 8px);left:0;width:min(340px,86vw);max-height:320px;overflow:auto}
.cz-emotki.przy-wiadomosci{bottom:auto;top:calc(100% + 6px);left:auto;right:0}
.cz-emotki-siatka{display:grid;grid-template-columns:repeat(8,1fr);gap:2px}
.cz-emotka{display:inline-flex;align-items:center;justify-content:center;height:36px;border:0;
  border-radius:8px;background:none;font-size:22px;line-height:1;cursor:pointer}
.cz-emotka:hover,.cz-emotka:focus-visible{background:var(--surface-2);outline:none}
.cz-emotka.wiecej{font-size:18px;font-weight:700;color:var(--ink-2)}
.cz-reakcje-wybor{top:calc(100% + 6px);right:0;display:flex;gap:2px;padding:4px}
.cz-gify{bottom:calc(100% + 8px);left:0;width:min(420px,90vw);display:flex;flex-direction:column;gap:var(--s2)}
.cz-gify-siatka{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;max-height:300px;overflow:auto}
.cz-gif{position:relative;padding:0;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  background:var(--surface-2);cursor:pointer;aspect-ratio:1}
.cz-gif img{width:100%;height:100%;object-fit:cover;display:block}
.cz-gif:hover{border-color:var(--accent)}
.cz-gif-wysylam{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--surface) 80%,transparent);font-size:var(--fs-sm);font-weight:700}
.cz-giphy{font-size:var(--fs-xs);color:var(--ink-3);text-align:right}
.cz-podpowiedz{bottom:calc(100% + 4px);left:var(--s4);width:min(320px,80vw);padding:4px}

/* --- pole do pisania --- */
.cz-pisz{position:relative;padding:var(--s2) var(--s3) var(--s3);border-top:1px solid var(--line);
  background:var(--surface)}
.cz-pisz-rzad{display:flex;align-items:flex-end;gap:4px}
.cz-narzedzie-blok{position:relative}
.cz-narzedzie{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
  border:0;border-radius:var(--radius-sm);background:none;color:var(--ink-2);cursor:pointer;font:inherit}
.cz-narzedzie:hover{background:var(--surface-2);color:var(--ink)}
.cz-narzedzie.gif{font-size:11px;font-weight:850;letter-spacing:.04em}
.cz-pole-tekstu{flex:1;min-width:0;min-height:38px;max-height:160px;padding:8px 12px;resize:none;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);color:var(--ink);
  font:inherit;line-height:1.45}
.cz-pole-tekstu:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus)}
.cz-wyslij{display:inline-flex;align-items:center;gap:6px;height:38px}
.cz.telefon .cz-wyslij .etykieta{display:none}
.cz-do-wyslania{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:var(--s2)}
.cz-zalacznik{display:flex;align-items:center;gap:8px;max-width:260px;padding:4px 6px 4px 4px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2)}
.cz-zalacznik-obraz{width:40px;height:40px;border-radius:6px;object-fit:cover}
.cz-zalacznik-ikona{display:inline-flex;width:40px;height:40px;align-items:center;justify-content:center;
  color:var(--accent-text)}
.cz-zalacznik-nazwa{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--fs-sm)}
.cz-zalacznik-x{border:0;background:none;color:var(--ink-3);font-size:18px;line-height:1;cursor:pointer;padding:0 4px}
.cz-zalacznik-x:hover{color:var(--bad)}

.cz-prawa.upuszczanie{outline:2px dashed var(--accent);outline-offset:-6px}
.cz-upusc{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--surface) 85%,transparent);font-weight:700;color:var(--accent-text);
  pointer-events:none;z-index:5}
.cz-blad{position:absolute;left:50%;bottom:var(--s4);transform:translateX(-50%);z-index:6;
  display:flex;gap:var(--s3);align-items:center;background:var(--surface)}
.cz-blad-rozmowy{margin:0 var(--s3) var(--s2);display:flex;gap:var(--s3);justify-content:space-between}

/* --- wybór ludzi --- */
.cz-ludzie{display:flex;flex-direction:column;gap:var(--s2)}
.cz-ludzie-lista,.cz-lista-osob{display:flex;flex-direction:column;max-height:46vh;overflow:auto;
  border:1px solid var(--line);border-radius:var(--radius-sm)}
.cz-osoba{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;
  border-bottom:1px solid var(--line-soft);background:none;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.cz-osoba:last-child{border-bottom:0}
.cz-osoba:hover,.cz-osoba.on{background:var(--accent-soft)}
.cz-osoba.statyczna{cursor:default}
.cz-osoba.statyczna:hover{background:none}
.cz-podpowiedz .cz-osoba{border-bottom:0;border-radius:6px;padding:6px 8px}
.cz-osoba-opis{flex:1;min-width:0;display:flex;flex-direction:column}
.cz-ptaszek{width:20px;height:20px;border:2px solid var(--g5);border-radius:6px;flex:none}
.cz-ptaszek.on{background:var(--accent);border-color:var(--accent);
  box-shadow:inset 0 0 0 3px var(--surface)}
.cz-pole{display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm);font-weight:600;color:var(--ink-2)}
.cz-wiersz-formularza{display:flex;gap:var(--s2)}
.cz-wiersz-formularza .input{flex:1;min-width:0}

/* --- podgląd zdjęcia --- */
.cz-podglad{position:fixed;inset:0;z-index:80;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:var(--s3);padding:var(--s5);background:rgba(8,10,14,.86);cursor:zoom-out}
.cz-podglad img{max-width:100%;max-height:calc(100vh - 120px);object-fit:contain;border-radius:var(--radius);cursor:default}
.cz-podglad-pasek{display:flex;align-items:center;gap:var(--s2);cursor:default}
.cz-podglad-nazwa{color:#fff;max-width:50vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* --- przycisk w pasku i okienka --- */
.cz-przycisk.on{border-color:var(--accent);color:var(--accent-text)}
.cz-przycisk.nowe{border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent-text)}
.cz-przycisk.nowe .czatnik-licznik{background:var(--accent);color:var(--accent-ink)}
.cz-okienka{position:fixed;right:var(--s5);bottom:var(--s5);z-index:70;display:flex;flex-direction:column;
  gap:var(--s2);width:min(360px,calc(100vw - 32px))}
.cz-okienko{display:flex;align-items:flex-start;background:var(--surface);border:1px solid var(--line);
  border-left:3px solid var(--accent);border-radius:var(--radius);box-shadow:var(--shadow-3);
  animation:cz-wjazd .22s ease-out}
.cz-okienko-tresc{flex:1;min-width:0;display:flex;gap:10px;padding:var(--s3);border:0;background:none;
  color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.cz-okienko-tekst{min-width:0;display:flex;flex-direction:column;gap:2px}
.cz-okienko-kto{font-size:var(--fs-sm)}
.cz-okienko-wiad{font-size:var(--fs-sm);color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.cz-okienko-x{border:0;background:none;color:var(--ink-3);font-size:20px;line-height:1;padding:8px 10px;cursor:pointer}
.cz-okienko-x:hover{color:var(--ink)}
@keyframes cz-wjazd{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.cz-okienko{animation:none}}
:root[data-ruch="mniej"] .cz-okienko{animation:none}
@media (max-width:760px){
  .cz-okienka{right:16px;left:16px;bottom:16px;width:auto}
  .cz-wiad{padding-left:var(--s3);padding-right:var(--s3)}
  .cz-obraz img{max-width:100%}
}

/* =====================================================================
   CZAT ZESPOŁU — OKIENKA W ROGU (jak Messenger), 23.09.2026
   Dymek po prawej na dole, lista rozmów i okienka rozmów na lewo od
   niego. Powiadomienia przeniesione pod górny pasek, żeby nie wchodziły
   na okienka.
   ===================================================================== */
.cz-okienka{top:92px;bottom:auto}
@media (max-width:760px){.cz-okienka{top:auto;bottom:16px}}

.cz-dok{position:fixed;bottom:0;z-index:55;display:flex;flex-direction:row-reverse;
  align-items:flex-end;gap:10px;pointer-events:none}
.cz-dok > *{pointer-events:auto}
.cz-okno,.cz-dok-lista{display:flex;flex-direction:column;background:var(--surface);
  border:1px solid var(--line);border-bottom:0;border-radius:var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow:var(--shadow-3)}
.cz-okno{width:380px;height:min(660px,calc(100vh - 90px))}
.cz-okno.zwiniete{height:auto}
.cz-dok-lista{width:340px;height:min(520px,calc(100vh - 110px))}
.cz-okno-glowa{display:flex;align-items:center;gap:8px;min-height:48px;padding:6px 6px 6px 12px;
  border-bottom:1px solid var(--line);border-radius:var(--radius-lg) var(--radius-lg) 0 0;
  background:var(--surface);cursor:pointer;user-select:none}
.cz-okno-glowa.stala{cursor:default}
.cz-okno.zwiniete .cz-okno-glowa{border-bottom:0}
.cz-okno.nowe .cz-okno-glowa{background:var(--accent-soft)}
.cz-okno-tytul{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:700}
.cz-okno-przycisk{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
  flex:none;border:0;border-radius:6px;background:none;color:var(--ink-2);cursor:pointer}
.cz-okno-przycisk:hover{background:var(--surface-2);color:var(--ink)}
.cz-okno-przycisk:focus-visible{outline:none;box-shadow:var(--focus)}
.cz-dok-lista-gora{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s2) var(--s3);
  border-bottom:1px solid var(--line)}
.cz-dok-lista .cz-lewa-lista{flex:1;min-height:0;overflow:auto;padding:4px 0}
.cz-dok-lista .cz-kanal{padding:7px var(--s3)}

/* Rozmowa w wąskim okienku — ciaśniej, mniejsze twarze. */
.cz-okno .cz-prawa{flex:1;min-height:0}
.cz-okno .cz-wiadomosci{padding-top:var(--s2)}
.cz-okno .cz-wiad{grid-template-columns:28px 1fr;gap:8px;padding-left:10px;padding-right:10px}
.cz-okno .cz-wiad-awatar .cz-awatar{width:28px !important;height:28px !important;font-size:11px !important}
.cz-okno .cz-wiad-akcje{right:8px}
.cz-okno .cz-dzien,.cz-okno .cz-nowe{margin-left:10px;margin-right:10px}
.cz-okno .cz-systemowa{margin-left:10px;margin-right:10px}
.cz-okno .cz-obraz img{max-width:100%;max-height:180px}
.cz-okno .cz-obrazy.kilka .cz-obraz img{width:108px;height:108px}
.cz-okno .cz-tresc.duze{font-size:1.6rem}
.cz-okno .cz-pisz{padding:6px 8px 8px}
.cz-okno .cz-narzedzie{width:34px}
.cz-okno .cz-wyslij{padding:0 10px}
.cz-okno .cz-wyslij .etykieta{display:none}
.cz-okno .cz-emotki{left:-40px;width:352px;max-height:300px}
.cz-okno .cz-gify{left:-78px;width:352px}
.cz-okno .cz-gify-siatka{grid-template-columns:repeat(3,1fr);max-height:260px}
/* Pole wiadomości na całą szerokość okienka (Łukasz, 23.09.2026:
   „miejsce na wpisanie wiadomości żeby było większe, szersze").
   Narzędzia i „Wyślij" schodzą do rzędu pod polem. */
.cz-okno .cz-pisz-rzad{flex-wrap:wrap;align-items:center;row-gap:4px}
.cz-okno .cz-pole-tekstu{order:-1;flex:1 1 100%;min-height:44px}
.cz-okno .cz-wyslij{margin-left:auto;height:32px}
/* „Za mało widać wiadomości" (23.09.2026) — ciaśniej wszystko wokół
   rozmowy, żeby okno oddało wysokość wiadomościom. */
.cz-okno .cz-narzedzie{width:32px;height:30px}
.cz-okno .cz-okno-glowa{min-height:44px;padding-top:4px;padding-bottom:4px}
.cz-okno .cz-dzien,.cz-okno .cz-nowe{margin-top:var(--s2);margin-bottom:4px}
.cz-okno .cz-wiad{padding-top:4px}
.cz-okno .cz-podpowiedz{left:8px}
.cz-okno .cz-blad-rozmowy{margin:0 8px 6px}

.cz-babel{position:fixed;right:18px;bottom:14px;z-index:56;display:inline-flex;align-items:center;
  justify-content:center;padding:0;border:0;background:none;cursor:pointer;line-height:0;
  border-radius:40% 40% 46% 46%;filter:drop-shadow(0 6px 10px rgba(60,35,0,.28))}
.cz-babel .ananasek{display:block;transition:transform .18s ease}
.cz-babel:hover .ananasek{transform:translateY(-2px) scale(1.04)}
.cz-babel.otwarty .ananasek{transform:scale(.94)}
.cz-babel:focus-visible{outline:none;box-shadow:var(--focus)}
.cz-babel-licznik{position:absolute;top:24px;right:-8px;display:inline-flex;align-items:center;
  justify-content:center;min-width:22px;height:22px;padding:0 6px;border:2px solid var(--surface);
  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;line-height:1}
/* Korona kołysze się przy najechaniu; przy nieprzeczytanych oczka
   „piszą" — podskakują po kolei, jak kropki w komunikatorze. */
.ananasek-korona{transform-origin:625px 390px;transform-box:view-box}
.ananasek-kropki circle{transform-box:fill-box;transform-origin:center}
.cz-babel:hover .ananasek-korona{animation:cz-korona .9s ease-in-out}
.cz-babel.nowe .ananasek-korona{animation:cz-korona 2.4s ease-in-out infinite}
.cz-babel.nowe .ananasek-kropki circle{animation:cz-kropka 1.4s ease-in-out infinite}
.cz-babel.nowe .ananasek-kropki circle:nth-child(2){animation-delay:.18s}
.cz-babel.nowe .ananasek-kropki circle:nth-child(3){animation-delay:.36s}
@keyframes cz-korona{0%,100%{transform:rotate(0)}25%{transform:rotate(-6deg)}75%{transform:rotate(6deg)}}
@keyframes cz-kropka{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(-3.5px)}}
@media (prefers-reduced-motion:reduce){
  .cz-babel .ananasek,.ananasek-korona,.ananasek-kropki circle{animation:none !important;transition:none}}
:root[data-ruch="mniej"] .ananasek-korona,:root[data-ruch="mniej"] .ananasek-kropki circle{animation:none !important}
.cz-okno-glowa .ananasek{flex:none}
/* Na ciemnym tle granatowy obrys ananasa ginie — delikatna jasna
   poświata oddziela go od tła. */
:root[data-theme="dark"] .cz-babel{filter:drop-shadow(0 0 1.5px rgba(255,255,255,.45)) drop-shadow(0 6px 10px rgba(0,0,0,.5))}
@media (prefers-color-scheme:dark){:root:not([data-theme]) .cz-babel{filter:drop-shadow(0 0 1.5px rgba(255,255,255,.45)) drop-shadow(0 6px 10px rgba(0,0,0,.5))}}

/* Tożsamość rozmowy: zdjęcie i nazwa (migracja 268). */
.cz-tozsamosc{display:flex;gap:var(--s4);align-items:flex-start;padding:var(--s3);
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}
.cz-tozsamosc-foto{display:flex;flex-direction:column;align-items:center;gap:var(--s2)}
.cz-tozsamosc-akcje{display:flex;flex-direction:column;gap:4px;align-items:stretch}
.cz-tozsamosc .cz-pole{flex:1;min-width:0}
@media (max-width:520px){.cz-tozsamosc{flex-direction:column;align-items:stretch}}
@media print{.cz-dok,.cz-babel,.cz-okienka{display:none}}

/* =====================================================================
   BAZA WIEDZY (A5, 23.09.2026) — wiedza.tsx
   ===================================================================== */
.wz-filtry > .bd{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.wz-filtry .wz-szukaj{flex:1 1 280px;min-width:0}
.wz-filtry select.input{flex:0 1 auto;width:auto}
.wz-ptaszek{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--ink-2);
  white-space:nowrap;cursor:pointer}
.card > .bd.flush{padding:0;overflow-x:auto}
.wz-tabela{width:100%}
.wz-tabela tr.klik{cursor:pointer}
.wz-tabela tr.klik:hover td{background:var(--wiersz-hover, var(--surface-2))}
.wz-tabela tr.klik:focus-visible{outline:none;box-shadow:inset var(--focus)}
.wz-wiersz-tytul{font-weight:650;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.wz-wiersz-opis{margin-top:2px;max-width:70ch}
.wz-dotyczy-kol{max-width:280px;font-size:var(--fs-sm)}
.wz-tagi{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}
.wz-tag{font-size:var(--fs-xs);color:var(--accent-text);background:var(--accent-soft);
  border-radius:var(--radius-pill,6px);padding:1px 8px}
.wz-pusto{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s2);padding:var(--s6) var(--pad-card)}

/* Artykuł */
.wz-artykul{max-width:920px}
.wz-wroc{margin-bottom:var(--s3)}
.wz-art-glowa{display:flex;gap:var(--s4);align-items:flex-start;justify-content:space-between;
  flex-wrap:wrap;padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
.wz-art-tytul h2{margin:0 0 6px;font-size:var(--fs-2xl);text-wrap:balance}
.wz-meta{display:flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:var(--fs-sm)}
.wz-art-akcje{display:flex;gap:var(--s2);flex-wrap:wrap}
.wz-dotyczy{display:flex;gap:var(--s3);align-items:baseline;margin-top:var(--s3);flex-wrap:wrap}
.wz-etykieta{font-size:var(--fs-xs);font-weight:750;text-transform:uppercase;letter-spacing:.06em;
  color:var(--ink-3);min-width:80px}
.wz-chipy{display:inline-flex;flex-wrap:wrap;gap:6px}
.wz-chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;border:1px solid var(--line);
  border-radius:var(--radius-pill,6px);background:var(--surface-2);font-size:var(--fs-sm)}
.wz-chip-rodzaj{font-size:var(--fs-xs);color:var(--ink-3)}
.wz-chip-x{border:0;background:none;color:var(--ink-3);cursor:pointer;font-size:16px;line-height:1;padding:0}
.wz-chip-x:hover{color:var(--bad)}
.wz-lead{font-size:var(--fs-md);color:var(--ink-2);margin:var(--s4) 0 0;max-width:70ch}
.wz-tresc{margin-top:var(--s4);line-height:1.65;max-width:75ch;overflow-wrap:anywhere}
.wz-tresc h2{font-size:var(--fs-xl);margin:var(--s5) 0 var(--s2)}
.wz-tresc h3{font-size:var(--fs-lg);margin:var(--s4) 0 var(--s2)}
.wz-tresc h4{font-size:var(--fs-md);margin:var(--s3) 0 var(--s1)}
.wz-tresc p{margin:0 0 var(--s3)}
.wz-tresc ul,.wz-tresc ol{margin:0 0 var(--s3);padding-left:1.4em}
.wz-tresc li + li{margin-top:3px}
.wz-tresc code{font-family:var(--mono);font-size:.92em;background:var(--surface-2);
  border:1px solid var(--line-soft);border-radius:4px;padding:0 4px}
.wz-kod{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s3);overflow-x:auto;margin:0 0 var(--s3)}
.wz-kod code{border:0;background:none;padding:0}
.wz-uwaga{margin:0 0 var(--s3);padding:var(--s3) var(--s4);border-left:3px solid var(--warn);
  background:var(--warn-bg);border-radius:0 var(--radius) var(--radius) 0}
.wz-uwaga .wz-tresc{margin:0}
.wz-uwaga p:last-child,.wz-uwaga ul:last-child{margin-bottom:0}
.wz-obraz{display:inline-block;max-width:100%}
.wz-obraz img{max-width:100%;max-height:480px;border:1px solid var(--line);border-radius:var(--radius);
  display:block;margin:var(--s2) 0}
.wz-zalaczniki{margin-top:var(--s5);padding-top:var(--s3);border-top:1px solid var(--line)}
.wz-zalaczniki h3{font-size:var(--fs-md);margin:0 0 var(--s2)}
.wz-galeria{display:flex;flex-wrap:wrap;gap:var(--s2);margin-bottom:var(--s2)}
.wz-galeria img{width:120px;height:120px;object-fit:cover;border-radius:var(--radius);border:1px solid var(--line)}
.wz-plik{display:block;padding:4px 0}

/* Historia */
.wz-hist-pasek{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.okienko tr.klik{cursor:pointer}
.okienko tr.klik:hover td{background:var(--surface-2)}

/* Edytor */
.wz-edytor-tytul{margin:0 0 var(--s3)}
.wz-edytor-siatka{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--s5)}
@media (max-width:1000px){.wz-edytor-siatka{grid-template-columns:minmax(0,1fr)}}
.wz-edytor-glowna,.wz-edytor-boczna{display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.wz-edytor-boczna{padding:var(--s3);border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface-2);align-self:start}
.wz-pole{display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm)}
.wz-pole > span:first-child{font-weight:650;color:var(--ink-2)}
.wz-tytul{font-size:var(--fs-lg);font-weight:650;height:auto;padding:8px 12px}
.wz-tresc-glowa{display:flex;align-items:center;gap:var(--s3)}
.wz-zakladki{display:inline-flex;border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden;
  margin-left:auto}
.wz-zakladki button{border:0;background:var(--surface);padding:3px 12px;font:inherit;font-size:var(--fs-sm);
  color:var(--ink-2);cursor:pointer}
.wz-zakladki button.on{background:var(--accent-soft);color:var(--accent-text);font-weight:650}
.wz-pasek{display:flex;flex-wrap:wrap;gap:2px;padding:4px;border:1px solid var(--line);border-bottom:0;
  border-radius:var(--radius-sm) var(--radius-sm) 0 0;background:var(--surface-2)}
.wz-pasek button{min-width:32px;height:28px;padding:0 8px;border:0;border-radius:4px;background:none;
  color:var(--ink-2);font:inherit;font-size:var(--fs-sm);font-weight:700;cursor:pointer}
.wz-pasek button:hover{background:var(--surface);color:var(--ink)}
.wz-edytor textarea.wz-pole-tresci{min-height:340px;height:auto;padding:10px 12px;resize:vertical;font-family:var(--mono);
  font-size:var(--fs-sm);line-height:1.55;border-top-left-radius:0;border-top-right-radius:0}
.wz-podglad{min-height:320px;padding:var(--s3) var(--s4);border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface)}
.wz-podglad .wz-tresc{margin-top:0}
.wz-lista-plikow{display:flex;flex-direction:column;gap:4px}
.wz-plik-wiersz{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
.wz-wybor{display:flex;flex-direction:column;gap:4px;max-height:180px;overflow:auto}
.wz-szukajka{position:relative}
.wz-wyniki{position:absolute;left:0;right:0;top:calc(100% + 2px);z-index:30;display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);box-shadow:var(--shadow-2);
  max-height:240px;overflow:auto}
.wz-wyniki button{border:0;background:none;text-align:left;padding:6px 10px;font:inherit;font-size:var(--fs-sm);
  color:var(--ink);cursor:pointer}
.wz-wyniki button:hover{background:var(--accent-soft)}
.wz-tagi-pole{display:flex;flex-direction:column;gap:4px}
.wz-okno-edytora{width:min(1100px,96vw)}
.wz-okno-artykulu .wz-artykul{max-width:none}

/* „Co wiemy" na karcie zlecenia */
.wz-podpowiedzi{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.wz-podpowiedz{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
  padding:8px 10px;border:1px solid var(--line-soft);border-radius:var(--radius);background:var(--surface);
  font:inherit;text-align:left;color:var(--ink);cursor:pointer}
.wz-podpowiedz:hover{border-color:var(--accent);background:var(--accent-soft)}
.wz-podpowiedz-tytul{font-weight:650}
.wz-powod{font-size:var(--fs-xs);color:var(--accent-text)}

/* ===================================================================
   ASYSTENT AI NA KARCIE ZLECENIA (ai-karta.tsx, migracja 270)
   =================================================================== */
.ai-wraca{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);
  padding:8px 10px;margin-bottom:var(--s3);border:1px solid var(--warn-border);
  border-radius:var(--radius);background:var(--warn-bg);font-size:var(--fs-sm)}
.ai-wraca > div{flex:1 1 240px;min-width:0;overflow-wrap:anywhere}
.ai-narzedzia{display:flex;flex-wrap:wrap;gap:4px}
.ai-narzedzie{font:inherit;font-size:var(--fs-sm);padding:4px 10px;border-radius:var(--radius-pill);
  border:1px solid var(--line);background:var(--surface);color:var(--ink-2);cursor:pointer}
.ai-narzedzie:hover{border-color:var(--accent);color:var(--ink)}
.ai-narzedzie.on{background:var(--accent-soft);border-color:var(--accent-border);color:var(--accent-text);font-weight:600}
.ai-narzedzie:focus-visible{outline:2px solid var(--focus);outline-offset:1px}
.ai-panel{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3);
  padding-top:var(--s3);border-top:1px solid var(--line-soft)}
/* W panelu asystenta przyciski stoją przy polach, bez własnej kreski. */
.ai-panel .pasek-akcji{margin-top:0;padding-top:0;border-top:0}
.ai-pytanie{display:flex;gap:var(--s2);align-items:flex-start}
.ai-pytanie textarea{flex:1 1 auto;min-width:0;resize:vertical}
.ai-wynik{display:flex;flex-direction:column;gap:var(--s2)}
.ai-wynik .wz-tresc{margin-top:0;max-width:none;font-size:var(--fs-sm);
  padding:var(--s3);border-radius:var(--radius);background:var(--surface-2)}
.ai-wynik .wz-tresc h2,.ai-wynik .wz-tresc h3{font-size:var(--fs-base);font-weight:650;margin:var(--s3) 0 4px}
.ai-wynik .wz-tresc h2:first-child{margin-top:0}
.ai-wynik textarea{resize:vertical}
.ai-wycena{display:flex;flex-direction:column;border:1px solid var(--line-soft);border-radius:var(--radius)}
.ai-pozycja{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:4px var(--s2);
  align-items:start;padding:8px 10px;border-bottom:1px solid var(--line-soft)}
.ai-pozycja > input[type=checkbox]{margin-top:4px}
.ai-pozycja.nieczynne .ai-pozycja-opis{color:var(--ink-3)}
.ai-pozycja-nazwa{overflow-wrap:anywhere}
.ai-pozycja-pole{display:flex;flex-direction:column;gap:2px}
.ai-liczba{width:84px;text-align:right;font-variant-numeric:tabular-nums}
.ai-wycena-suma{display:flex;justify-content:space-between;gap:var(--s2);padding:8px 10px;
  background:var(--surface-2);font-size:var(--fs-sm);font-variant-numeric:tabular-nums}
@media (max-width:520px){
  .ai-pozycja{grid-template-columns:auto 1fr 1fr}
  .ai-pozycja-opis{grid-column:2 / -1}
  .ai-pozycja-pole:first-of-type{grid-column:2}
}
.ai-stopka{margin:var(--s2) 0 0}
@media (max-width:600px){
  .ai-pytanie{flex-direction:column;align-items:stretch}
}

/* ===================================================================
   CENY PER MODEL (ceny-per-model.tsx, D3, migracja 272)
   =================================================================== */
.cpm{display:flex;flex-direction:column;gap:var(--s3);padding-bottom:0}
.cpm .kartahd{display:flex;align-items:flex-start;gap:var(--s3)}
.cpm .kartahd h3{margin:0 0 2px}
.cpm .wyjasnienie{margin:0}
.cpm-sekcja{display:flex;flex-direction:column;gap:var(--s2);padding-top:var(--s3);border-top:1px solid var(--line-soft)}
.cpm-sekcja-hd{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
.cpm .filters{margin:0}
.cpm-tabela th,.cpm-tabela td{white-space:nowrap}
.cpm-tabela td{vertical-align:middle;padding-top:4px;padding-bottom:4px}
.cpm-tabela tr.cpm-zmieniony td{background:var(--accent-soft)}
.cpm-liczba{width:110px;text-align:right;font-variant-numeric:tabular-nums}
.cpm-czas{width:80px;text-align:right;font-variant-numeric:tabular-nums}
.cpm input.zle{border-color:var(--bad);background:var(--bad-bg)}
.cpm input::placeholder{color:var(--ink-3);opacity:.8}
.cpm-wklejka{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3);
  border:1px solid var(--line-soft);border-radius:var(--radius);background:var(--surface-2)}
.cpm-wklejka .pasek-akcji,.cpm-stopka .pasek-akcji{margin-top:0;padding-top:0;border-top:0}
.cpm-wklejka textarea{resize:vertical;font-size:var(--fs-sm)}
.cpm-lista{margin:4px 0 0;padding-left:18px;font-size:var(--fs-sm)}
.cpm-podglad{display:flex;flex-direction:column;gap:var(--s2)}
/* Przycisk zapisu zawsze na wierzchu — lista modeli bywa długa. */
.cpm-stopka{position:sticky;bottom:0;display:flex;flex-direction:column;gap:var(--s2);
  margin:0 calc(-1 * var(--s6));padding:var(--s3) var(--s6);
  background:var(--surface);border-top:1px solid var(--line)}
.cpm .kartahd .rozpychacz{margin-left:auto}
.cpm-wklejka select.input{width:auto;max-width:100%}

/* Szablony SMS z licznikiem (migracja 276) */
.sms-szablony td.clip{max-width:420px}
.sms-edytor{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3);padding:var(--s3);
  border:1px solid var(--line-soft);border-radius:var(--radius);background:var(--surface-2)}
.sms-edytor .note{margin:0}
.umowy-daty{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-sm);color:var(--ink-3)}
.umowy-daty .input{width:auto}
/* Kilka usług naraz (helpdesk NPS #18) */
.podpowiedz-wiersz{display:flex;align-items:stretch}
.podpowiedz-wiersz > .podpowiedz-cennik{flex:1 1 auto;min-width:0}
.podpowiedz-zaznacz{margin:0 6px 0 10px;align-self:center;flex:0 0 auto}
.podpowiedz-wiersz.zaznaczony{background:var(--accent-soft)}
.podpowiedz-wiele{display:flex;align-items:center;gap:var(--s2);padding:8px 10px;
  border-top:1px solid var(--line-soft);background:var(--surface-2);position:sticky;bottom:0}
/* Przepływ statusów (helpdesk NPS #22) */
.przeplyw-statusow{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:var(--s2) 0}
.przeplyw-status{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border:1px solid var(--line);
  border-left-width:3px;border-radius:var(--radius-sm);background:var(--surface);font-size:var(--fs-sm)}
.przeplyw-status em{font-style:normal;font-size:var(--fs-xs);color:var(--ink-3)}
.przeplyw-status.zamyka{background:var(--surface-2)}
.przeplyw-strzalka{color:var(--ink-3)}
.podpowiedz-wiele .btn{white-space:nowrap;flex:0 0 auto}

/* --- Okno „Co nowego" (helpdesk NPS #98, #118) -----------------------
   Numer wersji w stopce jest przyciskiem, który je otwiera — wygląda
   jak dotąd (przygaszona plakietka), ale reaguje na najechanie. */
button.wersja{font:inherit;line-height:inherit;cursor:pointer}
.sidefoot button.wersja:hover,.sidefoot button.wersja:focus-visible{color:var(--ink-2);border-color:var(--line)}
.co-nowego .kartahd h3{margin:0}
.co-nowego-wstep{margin:var(--s2) 0 var(--s4)}
.co-nowego-grupa + .co-nowego-grupa{margin-top:var(--s4)}
.co-nowego-grupa h4{margin:0 0 var(--s2);font-size:var(--fs-sm);letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-3)}
.co-nowego-grupa ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--s3)}
.co-nowego-grupa li{display:grid;gap:2px;padding-left:var(--s3);border-left:2px solid var(--line)}
.co-nowego-tytul{display:block}
.co-nowego-gdzie{font-size:var(--fs-sm);color:var(--ink-3)}
.co-nowego-stopka{display:flex;gap:var(--s3);align-items:center;justify-content:flex-end;flex-wrap:wrap}
.co-nowego-stopka select{width:auto;margin-right:auto}

/* --- Własne pola zlecenia (helpdesk NPS #46) ------------------------- */
.pola-wlasne-edycja{margin:var(--s3) 0 var(--s5)}
.pola-wlasne-ptaszki{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s6);margin:var(--s3) 0}
.pola-wlasne-sprzet{display:grid;gap:var(--s2);margin:var(--s3) 0}
.pola-wlasne-sprzet .input{max-width:320px}
.pola-wlasne-siatka{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  gap:4px var(--s4);max-height:220px;overflow:auto;padding:var(--s2);
  border:1px solid var(--line-soft);border-radius:var(--radius-sm)}
.pola-wlasne-tabela td{vertical-align:top}
.pola-wlasne-strzalki{display:inline-flex;gap:4px}
.pola-wlasne-znaczniki{display:inline-flex;flex-wrap:wrap;gap:4px}
.pola-wlasne-akcje{white-space:nowrap}
.pola-wlasne-akcje .btn + .btn{margin-left:4px}
.pola-wlasne-tabela tr.wylaczony td{color:var(--ink-3)}
.pola-wlasne-nazwa{min-width:220px}

/* --- Kopia danych (helpdesk NPS #25) --------------------------------- */
.kopia-pliki{display:inline-flex;flex-wrap:wrap;gap:4px}
.kopia-danych code{font-size:var(--fs-sm)}

/* Komunikat po zeskanowaniu kodu — na dole ekranu, znika sam. */
.skan-komunikat{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:80;
  background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-3);padding:var(--s3) var(--s5);max-width:min(560px,92vw)}

/* --- Przełącznik punktów w nagłówku (migracja 280) ------------------- */
.przelacznik-punktu{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto}
.przelacznik-punktu .etykieta{font-size:var(--fs-sm);color:var(--ink-3)}
.przelacznik-punktu select{max-width:190px}
/* Zawężony widok ma być widać kątem oka — inaczej ktoś po tygodniu
   szuka naprawy z Radomia na liście przełączonej na Kielce. */
.przelacznik-punktu.zawezony select{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
@media (max-width: 700px){ .przelacznik-punktu .etykieta{display:none} .przelacznik-punktu select{max-width:130px} }

/* =====================================================================
   PULPIT NAPRAW — CENTRUM DOWODZENIA (24.09.2026)
   Kafle w tym samym kształcie co Panel IT (Kpi .kpi2), wykresy 30 dni,
   sześć list w siatce o równych wysokościach — lista przewija się
   w środku, żeby karty w rzędzie kończyły się w jednej linii.
   ===================================================================== */
.pulpit-napraw{display:flex;flex-direction:column;gap:var(--s4)}
.pulpit-glowa{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.pulpit-sekcja{margin:var(--s2) 0 0;font-size:var(--fs-sm);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-3)}
.pulpit-kafle{margin-bottom:0;grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}
.pulpit-wykresy{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(420px,1fr))}
.pulpit-wykresy .card{margin:0}
.pulpit-listy{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fill,minmax(340px,1fr))}
.pulpit-lista{margin:0;display:flex;flex-direction:column;height:360px}
.pulpit-lista .hd{display:flex;align-items:center;gap:var(--s3)}
.pulpit-lista .hd .zobacz-wszystkie{margin-left:auto;white-space:nowrap}
.pulpit-lista .bd{flex:1 1 auto;min-height:0;overflow:auto}
.pulpit-opis{margin-bottom:6px}
.pulpit-pusto{padding:var(--s4) 0;text-align:center}
.pulpit-lista .pulpit-wiersz{width:100%;background:none;border:0;border-top:1px solid var(--line-soft);
  font:inherit;color:inherit;text-align:left;cursor:pointer;padding:7px 4px;border-radius:0}
.pulpit-lista .pulpit-wiersz:first-of-type{border-top:0}
.pulpit-lista .pulpit-wiersz:hover{background:var(--surface-2)}
.pulpit-lista .pulpit-wiersz:focus-visible{outline:none;box-shadow:var(--focus)}
.pulpit-lista .pulpit-wiersz .numer{flex:0 0 auto;min-width:9ch}
.pulpit-lista .pulpit-wiersz .prawa{flex:0 0 auto}
.pulpit-lista .pulpit-notatka{display:flex;flex-direction:column;gap:2px;width:100%;background:none;
  border:0;border-top:1px solid var(--line-soft);font:inherit;color:inherit;text-align:left;cursor:pointer;padding:7px 4px}
.pulpit-lista .pulpit-notatka:first-of-type{border-top:0}
.pulpit-lista .pulpit-notatka:hover{background:var(--surface-2)}
.pulpit-lista .pulpit-notatka .glowa{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
@media (max-width: 700px){
  .pulpit-wykresy{grid-template-columns:1fr}
  .pulpit-listy{grid-template-columns:1fr}
  .pulpit-lista{height:auto;max-height:420px}
}
/* Wiersz listy pulpitu: numer i stan w pierwszej linii, opis w drugiej. */
.pulpit-lista .pulpit-wiersz{display:grid;grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"numer prawa" "opis opis";column-gap:var(--s3);row-gap:1px;align-items:center}
.pulpit-lista .pulpit-wiersz .numer{grid-area:numer;min-width:0}
.pulpit-lista .pulpit-wiersz .prawa{grid-area:prawa}
.pulpit-lista .pulpit-wiersz .clip{grid-area:opis}
.pulpit-lista .hd h3{white-space:nowrap}
.menu-punkt{padding:var(--s2) 10px var(--s3)}
.menu-punkt .przelacznik-punktu{width:100%}
.menu-punkt .przelacznik-punktu .etykieta{display:inline}
.menu-punkt .przelacznik-punktu select{max-width:none;flex:1 1 auto}

/* Status w menu napraw (migracja 282): ptaszek i krótka nazwa obok siebie. */
.status-w-menu{display:inline-flex;align-items:center;gap:6px}
.status-w-menu .input{width:15ch}

/* --- Pulpit napraw: pierwszy ekran bez przewijania (24.09.2026) --------
   Łukasz: „kafle zoptymalizować, żeby były równo, wypełniały dostępną
   przestrzeń (…) większość najważniejszych informacji powinna być
   widoczna już na pierwszym ekranie". Kafle niższe niż na Panelu IT,
   rząd ma tyle kolumn, ile kafli, wykresy niższe. */
.pulpit-napraw{gap:var(--s3)}
.pulpit-sekcja{margin:0 0 -4px;font-size:11px;letter-spacing:.08em}
.kpis.pulpit-kafle{grid-template-columns:repeat(var(--kafli, 6), minmax(0,1fr));gap:var(--s3)}
.pulpit-kafle .kpi.kpi2{grid-template-rows:auto 44px auto auto auto;padding:10px 12px 8px}
.pulpit-kafle .kpi2 .kpi-glowa{height:calc(2 * 1.2 * 12.5px);gap:7px}
.pulpit-kafle .kpi2 .kpi-ikona{width:26px;height:26px;border-radius:8px}
.pulpit-kafle .kpi2 .kpi-ikona svg{width:18px;height:18px}
.pulpit-kafle .kpi2 .l{font-size:12.5px;line-height:1.2}
.pulpit-kafle .kpi2 .v{font-size:30px}
.pulpit-kafle .kpi2 .v.v-s{font-size:24px}
.pulpit-kafle .kpi2 .v.v-xs{font-size:20px}
.pulpit-kafle .kpi2 .kpi-zmiana{margin-top:2px;font-size:12px}
.pulpit-kafle .kpi2 .d{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:1.3em}
.pulpit-kafle .kpi2 .kpi-trend{height:16px;margin-top:4px}
.pulpit-wykresy .card .hd{padding-top:8px;padding-bottom:8px}
.pulpit-wykresy .card .bd{padding-top:6px;padding-bottom:6px}
.pulpit-wykresy .wykres-rytmu .legenda{margin-bottom:2px}
.pulpit-lista{height:300px}
@media (max-width: 1200px){
  .kpis.pulpit-kafle{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
}
/* Podpis kafla na pulpicie: najwyżej dwie linijki zamiast ucięcia w pół
   słowa — rząd i tak wyrównuje wysokość kafli. */
.pulpit-kafle .kpi2 .d{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;line-height:1.3}
.pulpit-lista .pulpit-opis{font-size:12px;line-height:1.35}
.pulpit-lista .hd{padding-top:10px;padding-bottom:10px}

/* =====================================================================
   WERSJA MOBILNA — tryb „technik w terenie" (mobilna.tsx, 24.09.2026)
   Dolny pasek, duże cele dotyku (min. 48 px), bez niczego, co wymaga
   najechania kursorem. Kolory tylko z tokenów — oba motywy.
   ===================================================================== */
.mob{min-height:100dvh;display:flex;flex-direction:column;background:var(--bg);color:var(--ink)}
.mob-gora{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:var(--s2);
  min-height:52px;padding:6px 12px;padding-top:max(6px,env(safe-area-inset-top));
  background:var(--surface);border-bottom:1px solid var(--line)}
.mob-tytul{font-size:var(--fs-lg);flex:1}
.mob-wstecz{flex:1;display:flex;align-items:center;gap:4px;min-height:44px;background:none;border:0;
  color:var(--accent-text);font:inherit;font-weight:600;padding:0;cursor:pointer;text-align:left}
.mob-ja{width:40px;height:40px;border-radius:50%;border:1px solid var(--line);background:var(--surface-2);
  color:var(--ink);font:inherit;font-weight:600;font-size:13px;cursor:pointer}
.mob-menu{position:absolute;right:12px;top:calc(100% + 4px);min-width:220px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-2);padding:6px;z-index:30}
.mob-menu-kto{padding:8px 10px;color:var(--ink-3);font-size:var(--fs-sm)}
.mob-menu button{display:block;width:100%;min-height:44px;text-align:left;padding:0 10px;background:none;
  border:0;border-radius:var(--radius-sm);font:inherit;color:var(--ink);cursor:pointer}
.mob-menu button:hover,.mob-menu button:focus-visible{background:var(--surface-2);outline:none}
.mob-tresc{flex:1;padding:12px 12px calc(84px + env(safe-area-inset-bottom))}
.mob-pasek{position:fixed;left:0;right:0;bottom:0;z-index:20;display:grid;grid-template-columns:repeat(4,1fr);
  background:var(--surface);border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom)}
.mob-pasek-poz{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  min-height:60px;background:none;border:0;color:var(--ink-3);font:inherit;font-size:11px;cursor:pointer}
.mob-pasek-poz.wybrana{color:var(--accent-text)}
.mob-pasek-poz:focus-visible{outline:none;box-shadow:inset var(--focus)}
.mob-ikona{position:relative;display:inline-flex}
.mob-licznik{position:absolute;top:-6px;left:14px;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:var(--bad-solid);color:var(--bad-solid-ink);font-size:11px;font-weight:700;line-height:18px;
  text-align:center;font-variant-numeric:tabular-nums}
.mob-listy{display:flex;flex-direction:column;gap:10px}
.mob-sekcja{margin:8px 0 6px;font-size:var(--fs-base);font-weight:600;display:flex;gap:6px;align-items:baseline}
.mob-pusto{color:var(--ink-3);margin:4px 0 8px}
.mob-wiersz,.mob-pow{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:12px;display:flex;flex-direction:column;gap:4px;cursor:pointer;margin-bottom:8px}
.mob-wiersz:focus-visible,.mob-pow:focus-visible{outline:none;box-shadow:var(--focus)}
.mob-wiersz-gora{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
.mob-numer{font-weight:600}
.mob-wiersz-kto{font-weight:600;overflow-wrap:anywhere}
.mob-wiersz-opis{color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.mob-wiersz-dol{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:var(--fs-sm)}
.mob-wiersz-adres{font-size:var(--fs-sm)}
.mob-wiersz-akcja{margin-top:6px}
.mob-biore{width:100%;min-height:44px}
.mob-duzy{width:100%;min-height:48px;justify-content:center;display:inline-flex;align-items:center;gap:4px;
  text-decoration:none;flex-wrap:wrap;text-align:center}
.mob-pole{width:100%;min-height:48px;font-size:16px}  /* 16 px: iOS nie powiększa ekranu przy wpisywaniu */
textarea.mob-pole{min-height:auto;padding-top:10px}
.mob-etykieta{font-weight:600}
.mob-skanuj{display:flex;flex-direction:column;gap:10px;padding-top:8px}
.mob-pow.nowe{border-left:3px solid var(--accent)}
.mob-pow.nowe.waga-blad{border-left-color:var(--bad)}
.mob-pow.nowe.waga-uwaga{border-left-color:var(--warn)}
.mob-pow-tytul{font-weight:600}
.mob-pow-tresc{color:var(--ink-2);font-size:var(--fs-sm)}
.mob-pow-kiedy{font-size:var(--fs-xs)}
.mob-wszystkie{align-self:flex-end}
.mob-czat{margin:-12px}
.mob-karta{display:flex;flex-direction:column;gap:12px}
.mob-karta-naglowek{display:flex;flex-direction:column;gap:4px}
.mob-karta-kto{font-size:var(--fs-lg);font-weight:600;overflow-wrap:anywhere}
.mob-blok{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:12px;
  display:flex;flex-direction:column;gap:8px}
.mob-blok .mob-sekcja{margin:0}
.mob-kontakt .btn{justify-content:flex-start;text-align:left}
.mob-opis{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}
.mob-maly{font-size:var(--fs-sm);margin:0}
.mob-ptaszek{display:flex;align-items:center;gap:10px;min-height:44px}
.mob-ptaszek input{width:22px;height:22px}
.mob-os{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.mob-os li{border-left:2px solid var(--line);padding-left:10px}
.mob-os-tytul{font-weight:600;font-size:var(--fs-sm)}
.mob-os-tresc{white-space:pre-wrap;overflow-wrap:anywhere}
/* Wersja mobilna — zdjęcia (etap 2) */
.mob-wysylka{position:sticky;top:52px;z-index:15;padding:8px 12px;font-size:var(--fs-sm);
  background:var(--surface-2);border-bottom:1px solid var(--line);color:var(--ink-2)}
.mob-wysylka.blad{color:var(--bad)}
.mob-zdj-przyciski{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.mob-zdj-siatka{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.mob-zdj{display:flex;flex-direction:column;gap:4px;min-width:0}
.mob-zdj img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--radius-sm);
  border:1px solid var(--line);background:var(--surface-2);display:block}
.mob-zdj.oczekuje img{opacity:.6}
.mob-zdj.blad img{outline:2px solid var(--bad);outline-offset:-2px}
.mob-zdj-stan{font-size:var(--fs-xs);color:var(--ink-2);overflow-wrap:anywhere}
.mob-zdj.blad .mob-zdj-stan{color:var(--bad)}
.mob-zdj-akcje{display:flex;gap:6px}
.mob-zdj-akcje .btn{flex:1;min-height:40px}
.mob-zdj-klient{min-height:40px;border-radius:var(--radius-sm);border:1px solid var(--line);
  background:var(--surface);color:var(--ink-2);font:inherit;font-size:var(--fs-sm);cursor:pointer}
.mob-zdj-klient.widzi{border-color:var(--ok);color:var(--ok);font-weight:600}
.mob-zdj-klient:focus-visible{outline:none;box-shadow:var(--focus)}
.mob-zdj-kto{font-size:var(--fs-xs)}
/* Wersja mobilna — skan aparatem (etap 3) */
.mob-aparat{position:relative;width:100%;aspect-ratio:4/3;border-radius:var(--radius);overflow:hidden;
  background:var(--surface-2);border:1px solid var(--line)}
.mob-aparat video{width:100%;height:100%;object-fit:cover;display:block}
.mob-aparat-zaslona{position:absolute;inset:0;display:grid;place-items:center;padding:16px;color:var(--ink-2)}
.mob-aparat-zaslona .btn{max-width:280px}
.mob-celownik{position:absolute;left:8%;right:8%;top:30%;bottom:30%;border:2px solid rgba(255,255,255,.9);
  border-radius:10px;box-shadow:0 0 0 999px rgba(0,0,0,.35)}
.mob-aparat-przyciski{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.mob-aparat-przyciski .mob-maly{flex:1 1 100%}
.mob-skanuj-reka{display:flex;flex-direction:column;gap:8px;margin-top:8px;padding-top:12px;border-top:1px solid var(--line)}
/* Wersja mobilna — powiadomienia i urządzenia (etap 4) */
.mob-sesje{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.mob-sesje li{display:flex;align-items:center;gap:10px;padding:10px 0;border-top:1px solid var(--line-soft)}
.mob-sesje li:first-child{border-top:0}
.mob-sesja-opis{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.mob-sesja-opis .mob-maly{flex-basis:100%}
.mob-sesje .btn{min-height:40px}
/* Ustawienia → Płatności online (24.09.2026, przebudowa) */
.bad-tekst{color:var(--bad)}
.bramki{display:flex;flex-direction:column;gap:16px;padding:18px 20px 22px}
.bramki-wstep{margin:0;color:var(--ink-2);max-width:75ch}
.bramka-karta{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);overflow:hidden}
.bramka-karta.czynna{border-color:var(--accent-border, var(--line))}
.bramka-glowa{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 16px;
  padding:14px 18px;border-bottom:1px solid var(--line-soft);background:var(--surface-2)}
.bramka-glowa h3{margin:0;font-size:var(--fs-lg)}
.bramka-stan{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:var(--fs-sm);min-width:0}
.bramka-blad{color:var(--bad);max-width:520px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bramka-pola{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;padding:18px}
@media (max-width:900px){.bramka-pola{grid-template-columns:minmax(0,1fr)}}
.bramka-pole{display:flex;flex-direction:column;gap:6px;min-width:0}
.bramka-pole > span{font-weight:600;font-size:var(--fs-sm);display:flex;align-items:center;gap:8px}
.bramka-pole small{color:var(--ink-3);font-size:var(--fs-xs);line-height:1.4}
.bramka-webhook{margin:0 18px 16px;padding:12px 14px;border-radius:var(--radius-sm);background:var(--surface-2);
  display:flex;flex-direction:column;gap:8px;font-size:var(--fs-sm)}
.bramka-adres{display:flex;align-items:center;gap:8px;min-width:0}
.bramka-adres code{flex:1;min-width:0;overflow-x:auto;white-space:nowrap;font-family:var(--mono);padding:6px 8px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm)}
.bramka-przelaczniki{display:flex;flex-wrap:wrap;gap:8px 28px;padding:0 18px 16px}
.bramka-stopka{display:flex;flex-wrap:wrap;align-items:center;gap:10px 12px;padding:12px 18px;
  border-top:1px solid var(--line-soft);background:var(--surface-2)}
.bramki-dodaj{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.bramki-proby .sekcja-tytul{margin-top:8px}
.bramki-uwagi{color:var(--ink-3);font-size:var(--fs-sm);max-width:360px}

/* Znaczniki w szablonach wiadomości (25.09.2026) — lista pod treścią,
   każdy znacznik to przycisk wstawiający go w miejscu kursora. */
.znaczniki { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s2); }
.znaczniki-hd { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.znaczniki-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.znaczniki-lista li { display: grid; grid-template-columns: minmax(150px, auto) 1fr; gap: var(--s3);
  align-items: start; padding: 8px 10px; border-top: 1px solid var(--line-soft); }
.znaczniki-lista li:first-child { border-top: 0; }
.znaczniki-lista li.uzyty { background: var(--surface-2); }
.znaczniki-lista .znacznik { justify-self: start; }
.znacznik-opis { font-size: var(--fs-sm); line-height: 1.4; min-width: 0; }
.znacznik-przyklad { white-space: pre-line; overflow-wrap: anywhere; margin-top: 2px; }
.znacznik-uzyty { margin-left: 8px; font-size: var(--fs-xs); color: var(--ok); font-weight: 600; }
.znacznik { font: inherit; font-family: var(--mono, ui-monospace, monospace); font-size: var(--fs-sm);
  padding: 3px 8px; border: 1px solid var(--accent-border, var(--line)); border-radius: var(--radius-sm);
  background: var(--accent-soft); color: var(--accent-text); cursor: pointer; }
.znacznik:hover:not(:disabled) { border-color: var(--accent); }
.znacznik:disabled { cursor: default; }
.znacznik.nie-dziala { background: var(--surface-2); color: var(--ink-3); border-color: var(--line); }

/* Ikonka SOK (portal klienta) przed napisem przycisku — 25.09.2026. */
.ikona-sok { display: inline-block; vertical-align: -4px; margin-right: 6px; flex: none; }
/* Przycisk z ikoną SOK — ikona i tekst na jednej osi (26.09.2026: tekst
   stał niżej niż ikona). */
.btn:has(> .ikona-sok) { display: inline-flex; align-items: center; gap: 6px; }
.btn > .ikona-sok { margin: -2px 0; vertical-align: middle; }
h3 .ikona-sok { vertical-align: -6px; margin-right: 8px; }

/* Wycena w dymku czatu — zwarta karta zamiast paska na całą szerokość
   rozmowy (Łukasz, 25.09.2026: „zobacz, jaka jest szeroka"). Szerokość
   z treści, z górną granicą; stan jako plakietka po prawej w nagłówku. */
.wiad-wycena{width:fit-content;min-width:230px;max-width:min(100%,360px);box-sizing:border-box}
.wiad-wycena-hd{display:flex;align-items:center;justify-content:space-between;gap:10px}
.wiad-wycena-hd b{text-transform:none;letter-spacing:0;font-weight:650;padding:1px 8px;border-radius:var(--radius-pill,6px);
  white-space:nowrap;font-size:.72rem}
.wiad-wycena-hd b.ok{background:#e3f4d8;color:#1c6a12}
.wiad-wycena-hd b.zle{background:#fde8e6;color:#a2170f}
.wiad-wycena-hd b.czeka{background:#fff2d6;color:#7a4b00}

/* =====================================================================
   GÓRNY PASEK PO DOJŚCIU PRZEŁĄCZNIKA PUNKTÓW (25.09.2026).
   Łukasz: „jak doszedł wybór punktu, to trochę się złamała góra" —
   prawa kolumna siatki miała tyle samo miejsca co lewa (1fr), a jej
   zawartość urosła o przełącznik; nazwisko spadało do drugiego wiersza.
   Teraz prawa kolumna bierze tyle, ile potrzebuje, zegar zostaje między
   nimi, a na węższych monitorach najpierw chowają się podpisy (słowo
   „Punkt", „nowe informacje", „Zalogowany …"), dopiero potem cokolwiek
   się zawija.
   ===================================================================== */
@media (min-width: 900px) {
  .topbar { grid-template-columns: minmax(0, 1fr) auto max-content; }
  .top-prawo { flex-wrap: nowrap; gap: var(--s3); }
  .top-ja { flex-wrap: nowrap; }
}
@media (min-width: 900px) and (max-width: 2150px) {
  .przelacznik-punktu .etykieta { display: none; }
  .czatnik.pilne .czatnik-opis { display: none; }
}
@media (min-width: 900px) and (max-width: 1800px) {
  .topbar .cytat-dnia { display: none; }
}
@media (min-width: 900px) and (max-width: 1500px) {
  .top-ja .ja-rola { display: none; }
  .przycisk-centrum .etykieta { display: none; }
}
@media (min-width: 900px) and (max-width: 1250px) {
  .top-ja .ja-opis { display: none; }
}
/* Pole szukania oddaje miejsce, zamiast wchodzić pod zegar.
   Tylko w poziomie: `overflow:hidden` ucinał też w pionie i lista
   wyników szukajki (pod polem) była niewidoczna — „nic się nie
   dzieje" (26.09.2026). `clip` w jednej osi pozwala drugiej zostać
   `visible`. */
@media (min-width: 900px) {
  .top-lewo { overflow-x: clip; overflow-y: visible; }
  .top-lewo .qs { flex: 1 1 auto; min-width: 140px; max-width: 360px; }
}

/* --- zdjęcie przy pozycji wyceny (migracja 285) -----------------------
   Stały kwadrat 44 px, zdjęcie WPASOWANE (contain) — pionowe z telefonu
   i poziome katalogowe zajmują tyle samo, wiersz się nie rozjeżdża. */
.tab-pozycji .poz-z-foto{display:flex;gap:10px;align-items:flex-start}
.tab-pozycji .poz-foto{flex:0 0 44px;width:44px;height:44px;border:1px solid var(--line);
  border-radius:6px;background:#fff;display:flex;align-items:center;justify-content:center;
  overflow:hidden}
.tab-pozycji .poz-foto img{max-width:100%;max-height:100%;object-fit:contain;display:block}
.tab-pozycji .kol-akcje-poz label.jak-link{cursor:pointer;margin-left:12px}
.tab-pozycji .kol-akcje-poz label.jak-link.wylaczony{opacity:.5;pointer-events:none}
.tab-pozycji .poz-foto.pusta{border-color:transparent;background:none}
.tab-pozycji .poz-z-foto{text-align:left}

/* --- oferta z wariantami (migracja 286) --------------------------------
   Każdy wariant to osobny blok z własną sumą po prawej. Wybrany przez
   klienta dostaje zieloną krawędź, polecany — akcent; wspólne są
   przerywaną ramką, bo to dodatek do każdego, a nie osobna propozycja. */
.dok-przelacznik{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);
  margin-left:auto;cursor:pointer;white-space:nowrap}
.dok-warianty{display:flex;flex-direction:column;gap:14px}
.dok-wariant{border:1px solid var(--line);border-radius:10px;padding:12px 14px;
  display:flex;flex-direction:column;gap:10px;background:var(--surface)}
.dok-wariant.polecany{border-color:color-mix(in srgb,var(--accent) 55%,var(--line))}
.dok-wariant.wybrany{border-color:var(--ok);box-shadow:0 0 0 1px var(--ok) inset}
.dok-wariant.wspolne{border-style:dashed;background:none}
.dok-wariant-glowa{display:flex;gap:16px;align-items:flex-start;justify-content:space-between}
.dok-wariant-pola{display:flex;flex-direction:column;gap:6px;flex:1 1 auto;min-width:0;max-width:640px}
.dok-wariant-nazwa{font-weight:700;font-size:var(--fs-md, 15px)}
.dok-wariant-opis{font-size:var(--fs-sm)}
.dok-wariant-suma{display:flex;flex-direction:column;align-items:flex-end;gap:2px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.dok-wariant-suma strong{font-size:1.25rem;font-weight:750}
.dok-wariant-akcje{display:flex;align-items:center;gap:14px;flex-wrap:wrap;font-size:var(--fs-sm)}
.dok-wariant-polecany{display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.dok-wariant-pusty{font-size:var(--fs-sm);padding:6px 0}
.dok-wariant .tblwrap{margin:0}
.dok-wybrany-wariant{font-size:var(--fs-xs);font-weight:650;color:var(--ok)}
@media (max-width:700px){
  .dok-wariant-glowa{flex-direction:column}
  .dok-wariant-suma{align-items:flex-start}
  .dok-przelacznik{margin-left:0}
}

/* --- PAKT — nagłówek modułu dokumentów (25.09.2026) --------------------
   Ten sam układ co SOK w portalu i KROPLA w formularzu: znak, słowo
   krojem Fredoka i rozwinięcie z zaznaczonymi literami skrótu. Kolory
   z tokenów znaku ANANAS — każdy motyw programu już je ustawia. */
.pakt-glowa{display:flex;align-items:center;gap:12px;padding:14px 18px 0}
.pakt-glowa img{width:46px;height:46px;display:block;flex:none}
.pakt-slowo{font-family:'Fredoka',system-ui,sans-serif;font-weight:700;font-size:26px;
  line-height:1;letter-spacing:.05em;color:var(--ananas-slowo)}
.pakt-rozw{font-size:12.5px;line-height:1.35;color:var(--ink-2);margin-top:3px}
.pakt-rozw span{color:var(--ananas-litera);font-weight:800}

/* --- AI w wycenach PAKT (migracja 287) -----------------------------------
   Propozycja AI zawsze w osobnej ramce z przerywaną krawędzią — to, co
   jeszcze NIE jest częścią oferty, ma wyglądać inaczej niż oferta. */
.ai-pod-polem{display:flex;align-items:center;gap:10px;margin-top:4px}
.jak-link.ai-link{color:var(--ananas-litera, #16a34a);font-weight:650}
.ai-propozycja{display:flex;flex-direction:column;gap:8px;margin-top:6px;padding:10px 12px;
  border:1px dashed color-mix(in srgb,var(--ananas-litera, #16a34a) 60%,var(--line));
  border-radius:8px;background:color-mix(in srgb,var(--ananas-litera, #16a34a) 5%,var(--surface))}
.ai-propozycja .ai-glowa{display:flex;align-items:baseline;gap:10px}
.ai-propozycja .ai-wiersz{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.ai-propozycja .ai-wiersz .input{flex:1 1 260px;min-width:0}
.ai-propozycja .ai-tekst{white-space:pre-wrap;line-height:1.5;padding:8px 10px;border-radius:6px;
  background:var(--surface);border:1px solid var(--line-soft, var(--line))}
.ai-zrodla{display:flex;flex-wrap:wrap;gap:6px 12px;align-items:baseline;font-size:var(--fs-sm)}
.ai-zrodla a{max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tab-pozycji tr.wiersz-ai td{background:none;padding-top:0}
.dok-wariant-akcje .ai-wariant{flex:1 1 100%}
/* Tabela pozycji bywa szersza niż ekran i przewija się w bok — ramka AI
   trzyma się lewej krawędzi widoku, zamiast rozciągać na całą tabelę. */
.tab-pozycji tr.wiersz-ai td > .ai-propozycja{position:sticky;left:0;max-width:min(760px,86vw)}

/* --- dzwonek: zakładki Ważne / Monitoring IT (migracja 288) ------------
   Monitoring ma swój licznik na przycisku — mały i szary, żeby było go
   widać, ale żeby nie udawał, że pali się coś w pracy firmy. */
.czatnik-monitoring{display:inline-flex;align-items:center;justify-content:center;
  min-width:18px;height:18px;padding:0 5px;border-radius:999px;
  background:var(--g3, #e5e7eb);color:var(--ink-2);
  font-size:10.5px;font-weight:750;font-variant-numeric:tabular-nums}
.dzwonek-zakladki{display:flex;align-items:center;gap:4px;padding:6px 8px;
  border-bottom:1px solid var(--linia,rgba(127,127,127,.2));position:sticky;top:0;
  background:var(--surface);z-index:1}
.dzwonek-zakladki button[role=tab]{border:0;background:none;padding:6px 10px;border-radius:6px;
  font:inherit;font-size:var(--fs-sm);font-weight:650;color:var(--ink-2);cursor:pointer;
  display:inline-flex;align-items:center;gap:6px}
.dzwonek-zakladki button[role=tab].on{background:var(--g2, #f1f3f5);color:var(--ink)}
.dzwonek-zakladki button[role=tab]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.zakl-licznik{min-width:18px;height:18px;padding:0 5px;border-radius:999px;display:inline-flex;
  align-items:center;justify-content:center;background:var(--bad-solid);color:var(--bad-solid-ink);
  font-size:10.5px;font-weight:800}
.zakl-licznik.szary{background:var(--g3, #e5e7eb);color:var(--ink-2)}

/* Imienne — „dla Ciebie" (migracja 288). */
.dzwonek-lista .podpowiedz.osobiste{box-shadow:inset 3px 0 0 var(--accent)}
.powiad-dla-ciebie{font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;
  color:var(--accent);white-space:nowrap}

/* Dymki w rogu — raz, nie znikają same (migracja 288). */
.dymki-osobiste{position:fixed;right:18px;bottom:18px;z-index:60;display:flex;flex-direction:column;
  gap:10px;width:min(360px,calc(100vw - 32px))}
.dymek-osobisty{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--accent);
  border-radius:10px;padding:10px 12px;box-shadow:0 10px 28px rgba(0,0,0,.18);
  display:flex;flex-direction:column;gap:4px}
.dymek-osobisty.uwaga{border-left-color:var(--warn, #d97706)}
.dymek-glowa{display:flex;align-items:center;justify-content:space-between}
.dymek-glowa .jak-link{font-size:18px;line-height:1;text-decoration:none;color:var(--ink-3)}
.dymek-akcje{display:flex;gap:8px;margin-top:4px}
.dymek-wiecej{text-align:right}
@media (prefers-reduced-motion:no-preference){
  .dymek-osobisty{animation:dymek-wjazd .18s ease-out}
  @keyframes dymek-wjazd{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}
}

/* Kilka osób we wpisie kalendarza (migracja 288). */
.wybor-osob{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.osoba-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 6px 4px 10px;border-radius:999px;
  background:var(--g2, #f1f3f5);border:1px solid var(--line);font-size:var(--fs-sm);font-weight:600}
.osoba-chip button{border:0;background:none;cursor:pointer;font-size:15px;line-height:1;
  color:var(--ink-3);padding:0 4px}
.osoba-chip button:hover{color:var(--bad)}
.wybor-osob .input.sm{width:auto;min-width:170px}

/* =====================================================================
   KOLEJKI Z IPOTA (migracja 289) — zakładki nad listą zgłoszeń abonentów
   ===================================================================== */
/* Liczba przy zakładce kolejki — informacja, nie wezwanie. Wezwaniem
   (kolorowa bańka `.licznik`) jest tylko „Dla mnie". */
.zakladki button .ile{margin-left:6px;color:var(--ink-3);font-weight:500;
  font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.zakladki button.on .ile{color:var(--accent-text);opacity:.75}
/* Kogo BOK oznaczył — pod kategorią. „Ty" mocniej, bo to odpowiedź
   na „czemu to widzę w »Dla mnie«". */
.osoby-ipota{margin-top:3px;line-height:1.35}
.osoby-ipota .osoba-ja{color:var(--accent-text);font-weight:650}

/* =====================================================================
   PODRÓŻ PACZKI (migracja 290) — ten sam blok w app.css i portal.css,
   bo karta naprawy i SOK pokazują tę samą paczkę tym samym widokiem.
   ===================================================================== */
.podroz{display:flex;flex-direction:column;gap:10px;margin-top:8px}
.podroz-etapy{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));gap:0}
.podroz-etap{position:relative;display:flex;flex-direction:column;gap:3px;
  padding:0 6px 0 0;min-width:0}
/* Kreska do następnego kroku — od kropki do kropki. */
.podroz-etap:not(:last-child)::after{content:'';position:absolute;left:14px;right:0;
  top:6px;height:2px;background:var(--line)}
.podroz-etap.zrobiony:not(:last-child)::after{background:var(--ok)}
.podroz-kropka{position:relative;z-index:1;width:14px;height:14px;border-radius:50%;
  border:2px solid var(--line);background:var(--surface);box-sizing:border-box}
.podroz-etap.zrobiony .podroz-kropka{background:var(--ok);border-color:var(--ok)}
.podroz-etap.teraz .podroz-kropka{border-color:var(--accent);background:var(--accent);
  box-shadow:0 0 0 4px var(--accent-soft)}
.podroz-etap.teraz.uwaga .podroz-kropka{border-color:var(--warn);background:var(--warn);
  box-shadow:0 0 0 4px var(--warn-bg)}
.podroz-nazwa{font-size:var(--fs-sm);color:var(--ink-3);line-height:1.3;
  overflow-wrap:anywhere;padding-right:4px}
.podroz-etap.zrobiony .podroz-nazwa{color:var(--ink-2)}
.podroz-etap.teraz .podroz-nazwa{color:var(--ink);font-weight:650}
.podroz-kiedy{font-size:var(--fs-xs);color:var(--ink-3);font-variant-numeric:tabular-nums}
.podroz-uwaga{padding:8px 10px;border-radius:var(--radius-sm);background:var(--warn-bg);
  border:1px solid var(--warn-border);font-size:var(--fs-sm)}
.podroz-numer{display:flex;flex-wrap:wrap;gap:4px 12px;align-items:baseline;
  font-size:var(--fs-sm);color:var(--ink-2)}
.podroz-numer .mono{font-family:var(--mono,ui-monospace,monospace);color:var(--ink)}
.podroz-droga{list-style:none;margin:0;padding:0 0 0 12px;border-left:2px solid var(--line-soft);
  display:flex;flex-direction:column;gap:6px}
.podroz-droga li{position:relative;display:grid;grid-template-columns:96px 1fr;gap:10px;
  font-size:var(--fs-sm);color:var(--ink-2)}
.podroz-droga li::before{content:'';position:absolute;left:-17px;top:6px;width:8px;height:8px;
  border-radius:50%;background:var(--line)}
.podroz-droga li.krok::before{background:var(--ok)}
.podroz-droga li.ostatnie{color:var(--ink)}
.podroz-droga li.ostatnie::before{background:var(--accent)}
.podroz-droga li.problem{color:var(--ink)}
.podroz-droga li.problem::before{background:var(--warn)}
.podroz-droga-kiedy{color:var(--ink-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.podroz-droga-gdzie{color:var(--ink-3)}
.podroz-pusto{font-size:var(--fs-sm);color:var(--ink-3)}
.podroz-wiecej{align-self:flex-start;border:0;background:none;padding:0;cursor:pointer;
  font:inherit;font-size:var(--fs-sm);color:var(--accent-text)}
.podroz-stopka{font-size:var(--fs-xs);color:var(--ink-3);display:flex;flex-wrap:wrap;gap:4px 8px;
  align-items:baseline}
.podroz-blad{color:var(--bad)}
/* Wąsko: pięć kroków w poziomie nie mieści nazw — idą w pion. */
@media (max-width:560px){
  .podroz-etapy{grid-template-columns:1fr;gap:10px}
  .podroz-etap{flex-direction:row;flex-wrap:wrap;align-items:center;gap:4px 10px;padding:0}
  .podroz-etap:not(:last-child)::after{left:6px;right:auto;top:14px;width:2px;height:calc(100% - 4px)}
  .podroz-kiedy{flex-basis:100%;padding-left:24px}
  .podroz-droga li{grid-template-columns:1fr;gap:0}
}

/* =====================================================================
   STOPER W ZGŁOSZENIU ABONENTA (migracja 291)
   ===================================================================== */
.zgl-stoper{display:flex;flex-direction:column;gap:6px;padding:8px 10px;margin:8px 0;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2)}
.zgl-stoper.chodzi{border-color:var(--accent-border);background:var(--accent-soft)}
.zgl-stoper-rzad{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px}
.zgl-stoper-czas{font-family:var(--mono,ui-monospace,monospace);font-size:var(--fs-lg);
  font-weight:650;font-variant-numeric:tabular-nums;color:var(--accent-text)}
.zgl-stoper-lista{font-size:var(--fs-sm)}
.zgl-stoper-lista td{padding:3px 8px 3px 0}
.zamkniecie-akcji{display:flex;flex-direction:column;gap:6px;margin-top:var(--s3);
  padding-top:var(--s3);border-top:1px solid var(--line-soft)}

/* Ustawienia → Statusy i priorytety (25.09.2026, przebudowa): lista
   w kolejności przepływu po lewej, edytor klikniętego po prawej. */
.st-ekran{display:flex;flex-direction:column;gap:12px;padding:0 20px 22px}
.st-ekran > .zakladki{margin-bottom:0}
.st-wstep{margin:0;color:var(--ink-2);max-width:80ch;font-size:var(--fs-sm)}
.st-uklad{display:grid;grid-template-columns:minmax(260px,340px) minmax(0,1fr);gap:18px;align-items:start}
@media (max-width:980px){.st-uklad{grid-template-columns:minmax(0,1fr)}}
.st-kolumna-lista{display:flex;flex-direction:column;gap:10px;position:sticky;top:12px}
@media (max-width:980px){.st-kolumna-lista{position:static}}
.st-lista{list-style:none;margin:0;padding:0;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);overflow:hidden}
.st-wiersz{display:flex;align-items:stretch;border-bottom:1px solid var(--line-soft)}
.st-wiersz:last-child{border-bottom:0}
.st-wiersz.on{background:var(--accent-soft, var(--surface-2));box-shadow:inset 3px 0 0 var(--accent)}
.st-wiersz.ciagniety{opacity:.55}
.st-uchwyt{display:flex;align-items:center;justify-content:center;width:26px;flex:0 0 26px;
  color:var(--ink-3);cursor:grab;border-radius:var(--radius-sm)}
.st-uchwyt:hover{color:var(--ink)}
.st-uchwyt:focus-visible{outline:2px solid var(--accent-border);outline-offset:-2px}
.st-wiersz-tresc{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:9px 12px 9px 2px;
  border:0;background:transparent;text-align:left;cursor:pointer;color:var(--ink);font:inherit}
.st-wiersz-tresc:focus-visible{outline:2px solid var(--accent-border);outline-offset:-2px}
.st-kropka{flex:0 0 auto;width:10px;height:10px;border-radius:50%;background:var(--kc,#7b8494)}
.st-kropka.duza{width:14px;height:14px}
.st-nazwa{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.st-nazwa-tekst{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.st-plakietki{display:flex;flex-wrap:wrap;gap:4px}
.st-rola,.st-cecha,.st-kod{font-size:11px;line-height:1.5;padding:0 6px;border-radius:var(--radius-pill,6px);white-space:nowrap}
.st-rola{font-weight:600;background:var(--surface-2);border:1px solid var(--line);color:var(--ink-2)}
.st-rola.r-start{border-color:var(--accent);color:var(--accent-text)}
.st-rola.r-zamyka{background:var(--ink);border-color:var(--ink);color:var(--surface)}
.st-rola.r-gotowe{border-color:#c9a100;color:var(--ink)}
.st-cecha{color:var(--ink-3);border:1px dashed var(--line)}
.st-cecha.wyl{border-style:solid;background:var(--surface-2)}
.st-kod{color:var(--ink-3);border:1px solid var(--line-soft);padding:0 5px}
.st-ile{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-end;font-variant-numeric:tabular-nums;
  font-size:var(--fs-sm);color:var(--ink-2)}
.st-ile small{font-size:11px;color:var(--ink-3)}
.st-dodaj{display:flex;gap:8px}
.st-dodaj .input{flex:1;min-width:0}
.st-dodaj .st-dodaj-kod{flex:0 0 96px}
.st-edytor-tytul{display:flex;align-items:center;gap:10px;min-width:0}
.st-kod-tytul{font-size:var(--fs-sm);font-weight:400}
.st-uwaga{margin:14px 18px 0}
.probki-koloru{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.probka{width:24px;height:24px;border-radius:50%;border:2px solid var(--surface);background:var(--kc);
  box-shadow:0 0 0 1px var(--line);cursor:pointer;padding:0}
.probka.on{box-shadow:0 0 0 2px var(--ink)}
.probka:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.probki-nazwa{margin-left:4px}
.st-role{margin:0 18px 16px;padding:0;border:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
@media (max-width:900px){.st-role{grid-template-columns:minmax(0,1fr)}}
.st-role legend{font-weight:600;font-size:var(--fs-sm);margin-bottom:6px;padding:0}
.st-rola-opcja{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border:1px solid var(--line);
  border-radius:var(--radius-sm);cursor:pointer;background:var(--surface)}
.st-rola-opcja:hover{border-color:var(--ink-3)}
.st-rola-opcja.on{border-color:var(--accent);background:var(--accent-soft, var(--surface-2))}
.st-rola-opcja.nieczynna{opacity:.5;cursor:not-allowed}
.st-rola-opcja input{margin-top:3px;flex:0 0 auto}
.st-rola-tresc{display:flex;flex-direction:column;gap:2px;min-width:0}
.st-rola-tresc > span{font-size:var(--fs-sm);color:var(--ink-3);line-height:1.4}
.st-rola-tresc .st-rola-dopisek{color:var(--ink-2);font-size:var(--fs-xs)}
.st-role-uwaga{grid-column:1/-1;margin:2px 0 0}
.st-przelaczniki{padding-top:4px}
.st-pola-waskie{padding-top:0;grid-template-columns:minmax(0,320px)}
.st-wiadomosc{border-top:1px solid var(--line-soft);padding:16px 18px;display:flex;flex-direction:column;gap:12px}
.st-wiadomosc-wstep{margin:0;font-size:var(--fs-sm);max-width:80ch}
.st-pola-wiadomosci{padding:0}
.st-pole-mail{grid-column:1/-1}
.st-pole-mail-etykieta{justify-content:space-between}
.st-pole-mail-etykieta .jak-link{font-weight:400}
.st-pole-sms{grid-row:span 1}
.st-licznik{font-variant-numeric:tabular-nums}
.st-licznik.uwaga{color:var(--warn-text, #8a6400)}
.st-kod-pole{padding:8px 0}

/* Kurierzy i paczki (25.09.2026, przebudowa na karty jak Płatności). */
.pole-z-okiem{display:flex;gap:8px;align-items:center;min-width:0}
.pole-z-okiem .input{flex:1;min-width:0}
.pole-z-okiem .btn{flex:0 0 auto}
.pole-klucza .pole-etykieta{display:flex;align-items:center;gap:8px}
.gab-wstep{margin:0;padding:14px 18px 4px;color:var(--ink-2);font-size:var(--fs-sm);max-width:80ch}
.gab-tabela{margin:8px 18px 16px}
.gab-wymiary{display:inline-flex;align-items:center;gap:4px}
.gab-wymiary .input{width:64px;text-align:right}
.gab-waga{width:72px;text-align:right}
.gab-domyslny{display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.gab-akcje{display:inline-flex;gap:6px;justify-content:flex-end}
.gab-akcje-kom{text-align:right}
.bramki-dodaj .input{width:auto;flex:0 1 240px}
.rodzaj-notatki{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;color:var(--ink-2)}

/* Lista napraw: „Numer i status" do lewej, plakietki i szybkie akcje
   po prawej w tej samej komórce (26.09.2026). */
:root tbody td.kol-numer.lewo{text-align:left;padding-left:18px}
:root thead th.kol-numer-hd, .lista-napraw thead th:nth-child(1){text-align:left;padding-left:18px}
.kol-numer.lewo .kn-uklad{display:flex;align-items:center;justify-content:space-between;gap:12px}
.kol-numer.lewo .kn-glowny{display:flex;flex-direction:column;align-items:flex-start;min-width:0}
:root tbody td.kol-numer.lewo .status-z-powodem{align-items:flex-start}
.kol-numer.lewo .kn-boczne{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:0 0 auto}
:root tbody td.kol-numer.lewo .kn-boczne .pill{margin:0;display:inline-flex}
.kol-numer.lewo .kn-akcje{display:flex;flex-direction:column;align-items:stretch;gap:4px}
.kol-numer.lewo .kn-akcje .btn{white-space:nowrap}

/* Okienko wyniku — potwierdzenie po czynności (26.09.2026). */
.scrim-3{z-index:80}
.okienko-3{z-index:81}
.okienko-wyniku{text-align:center;padding:28px 28px 22px}
.okienko-wyniku .wynik-znak{width:48px;height:48px;margin:0 auto 10px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;background:var(--ok-bg);color:var(--ok)}
.okienko-wyniku.uwaga .wynik-znak{background:var(--warn-bg);color:var(--warn)}
.okienko-wyniku.blad .wynik-znak{background:var(--bad-bg);color:var(--bad)}
.okienko-wyniku h3{margin:0;font-size:var(--fs-lg);text-wrap:balance}
.okienko-wyniku .wynik-tresc{color:var(--ink-2);line-height:1.5;text-wrap:pretty}
.okienko-wyniku .wynik-tresc p{margin:0}
.okienko-wyniku .wynik-tresc p + p{margin-top:8px}
.okienko-wyniku .wynik-fakty{display:inline-grid;grid-template-columns:auto auto;gap:4px 14px;
  margin-top:12px;padding:10px 14px;border-radius:var(--radius-sm);background:var(--surface-2);text-align:left;
  font-size:var(--fs-sm)}
.okienko-wyniku .wynik-fakty dt{color:var(--ink-3)}
.okienko-wyniku .wynik-fakty dd{margin:0;font-weight:600}
.okienko-wyniku .pasek-akcji{justify-content:center;margin-top:18px}
.okienko-wyniku .pasek-akcji .btn{min-width:120px}

/* Szybkie akcje przy naprawie na liście (26.09.2026): przycisk z ikoną
   zamiast gołego tekstu, plakietka kuriera z datą odbioru. */
.akcja-wiersza{display:inline-flex;align-items:center;gap:8px;height:32px;padding:0 12px 0 4px;
  border:1px solid var(--line);border-radius:999px;background:var(--surface);color:var(--ink);
  font:inherit;font-size:var(--fs-sm);font-weight:600;cursor:pointer;white-space:nowrap;
  transition:border-color .15s,background-color .15s,box-shadow .15s}
.akcja-wiersza .akcja-ikona{width:24px;height:24px;border-radius:50%;display:inline-flex;
  align-items:center;justify-content:center;background:var(--accent);color:var(--accent-ink)}
.akcja-wiersza:hover:not(:disabled){border-color:var(--accent);box-shadow:0 1px 3px rgba(0,0,0,.08)}
.akcja-wiersza:focus-visible{outline:none;box-shadow:var(--focus)}
.akcja-wiersza:disabled{cursor:not-allowed;color:var(--ink-3);background:var(--surface-2);border-style:dashed}
.akcja-wiersza:disabled .akcja-ikona{background:var(--line);color:var(--ink-3)}
.akcja-wiersza.drugorzedna .akcja-ikona{background:var(--surface-2);color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line)}
@media (prefers-reduced-motion:reduce){.akcja-wiersza{transition:none}}
.kurier-chip{display:inline-flex;align-items:center;gap:8px;padding:3px 10px 3px 3px;border-radius:999px;
  background:var(--info-bg, var(--surface-2));color:var(--info, var(--ink));font-size:var(--fs-xs);line-height:1.2;
  white-space:nowrap;text-align:left}
.kurier-chip .akcja-ikona{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;
  justify-content:center;background:var(--surface);color:inherit}
.kurier-chip strong{display:block;font-weight:650}
.kurier-chip small{display:block;opacity:.8;font-size:11px}
.kurier-chip.jedzie{background:var(--ok-bg);color:var(--ok)}
/* Paczka na liście napraw (26.09.2026): kierunek, etap i pięć kresek drogi. */
.kurier-chip .kc-tekst{min-width:0}
.kurier-chip .kc-droga{display:inline-flex;gap:2px;margin-left:2px;align-self:center}
.kurier-chip .kc-droga i{display:block;width:7px;height:3px;border-radius:2px;background:currentColor;opacity:.22}
.kurier-chip .kc-droga i.jest{opacity:.9}
.kurier-chip.do-klienta{background:var(--surface-2);color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line)}
.kurier-chip.dotarla{background:var(--ok-bg);color:var(--ok)}
.kurier-chip.problem{background:var(--warn-bg, var(--surface-2));color:var(--warn, var(--ink))}
.kn-paczka-terminy{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.okienko-wyniku .pasek-akcji{border-top:0;padding-top:0}

/* Lista rodzajów na formularzu — pozycja z przyciskiem usunięcia (26.09.2026). */
.rodzaj-poz{display:flex;align-items:center;justify-content:space-between;gap:6px;min-width:0;
  padding:2px 4px 2px 0;border-radius:var(--radius-sm)}
.rodzaj-poz label{display:flex;gap:8px;align-items:center;min-width:0;cursor:pointer}
.rodzaj-poz label span{overflow-wrap:anywhere}
.rodzaj-poz.poza label{opacity:.7}
.rodzaj-poz:hover{background:var(--surface-2)}
.rodzaj-usun{flex:0 0 auto;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;background:transparent;color:var(--ink-3);cursor:pointer;opacity:0;
  transition:opacity .12s,background-color .12s,color .12s}
.rodzaj-poz:hover .rodzaj-usun,.rodzaj-usun:focus-visible{opacity:1}
.rodzaj-usun:hover{background:var(--bad-bg);color:var(--bad)}
.rodzaj-usun:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
@media (hover:none){.rodzaj-usun{opacity:.7}}
@media (prefers-reduced-motion:reduce){.rodzaj-usun{transition:none}}

/* Szukajka ustawień (26.09.2026) — nad menu, wyniki pod polem. */
.ust-szukaj{position:relative;margin-bottom:var(--s3)}
.ust-szukaj .input{width:100%}
.ust-szukaj-wyniki{list-style:none;margin:6px 0 0;padding:4px;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow-2, 0 4px 14px rgba(0,0,0,.08));
  display:flex;flex-direction:column;gap:2px;max-height:60vh;overflow:auto}
.ust-szukaj-wynik{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
  padding:8px 10px;border:0;border-radius:var(--radius-sm);background:transparent;text-align:left;
  font:inherit;color:var(--ink);cursor:pointer}
.ust-szukaj-wynik.on{background:var(--accent-soft, var(--surface-2))}
.ust-szukaj-wynik strong{font-weight:600}
.ust-szukaj-gdzie{font-size:var(--fs-xs);color:var(--ink-3)}
.ust-szukaj-gdzie em{font-style:normal;color:var(--ink-2);font-weight:600}
.ust-szukaj-pusto{padding:8px 10px;color:var(--ink-3);font-size:var(--fs-sm)}

/* Przypięte filtry (26.09.2026) — plakietka z pinezką. */
.filtr-chip{display:inline-flex;align-items:stretch;border-radius:999px;background:var(--info-bg);
  color:var(--info);font-size:var(--fs-sm);line-height:1;overflow:hidden;border:1px solid transparent}
.filtr-chip button{border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}
.filtr-chip-pin{display:inline-flex;align-items:center;padding:0 4px 0 9px;opacity:.55}
.filtr-chip-pin:hover,.filtr-chip.przypiety .filtr-chip-pin,.filtr-chip.uspiony .filtr-chip-pin{opacity:1}
.filtr-chip-tekst{padding:6px 11px 6px 4px;font-weight:600}
.filtr-chip button:focus-visible{outline:2px solid var(--accent-border);outline-offset:-2px}
.filtr-chip.przypiety{border-color:var(--info-border)}
.filtr-chip.uspiony{background:transparent;border:1px dashed var(--line);color:var(--ink-3)}
.filtr-chip.uspiony .filtr-chip-tekst{font-weight:500}

/* =====================================================================
   PRZYJĘCIE SPRZĘTU — OKNO Z KROKAMI (26.09.2026)
   =====================================================================
   Okno na środku zamiast szuflady z czterema kaflami. Stała wysokość:
   przejście między krokami nie może skakać oknem po ekranie, a stopka
   z „Dalej" zostaje zawsze w tym samym miejscu pod ręką.
   Przesłona i okno stoją POD okienkiem wzoru blokady (59/60), żeby to
   mogło się otworzyć nad formularzem. */
.scrim.przyjecie-tlo{z-index:55}
.okienko.przyjecie-okno{z-index:56;width:min(840px,96vw);height:min(780px,92vh);max-height:none;
  display:flex;flex-direction:column;padding:0;overflow:hidden}
.okienko.przyjecie-okno > * + *{margin-top:0}
.przyjecie-okno > .kartahd{padding:var(--s4) var(--s6) 0;flex:0 0 auto}
.przyjecie-okno > .note{margin:var(--s3) var(--s6) 0;flex:0 0 auto}
.przyjecie-okno > .kroki-przyjecia{margin:var(--s3) var(--s6) 0;flex:0 0 auto}
/* Tylko w oknie przyjęcia: klasa .pz-tresc jest też na osi Przebiegu
   (przebieg.tsx) i bez zawężenia dokładała tam wielkie odstępy. */
.przyjecie-okno > .pz-tresc{flex:1 1 auto;min-height:0;overflow:auto;padding:var(--s4) var(--s6) var(--s5)}
.pz-krok-hd{margin-bottom:var(--s4)}
.pz-krok-hd h3{margin:0;font-size:var(--fs-lg, 1.2rem);font-weight:680;text-wrap:balance}
.pz-krok-hd p{margin:4px 0 0;color:var(--ink-3);font-size:var(--fs-sm)}
.przyjecie-okno > .pz-tresc .podsekcja:first-child{margin-top:0}
.pz-stopka{flex:0 0 auto;display:flex;align-items:center;gap:var(--s3);
  padding:var(--s3) var(--s6);border-top:1px solid var(--line);background:var(--surface);
  box-shadow:0 -6px 18px rgba(20,18,14,.05)}
.pz-stopka .grow{flex:1 1 auto;min-width:0;font-size:var(--fs-sm)}
.pz-stopka .btn.primary{min-width:120px}

/* Podsumowanie: cztery bloki, każdy z „zmień" przy tytule. */
.pz-sekcja{padding:var(--s3) 0;border-top:1px solid var(--line-soft, var(--line))}
.pz-sekcja:first-of-type{border-top:0;padding-top:0}
.pz-sekcja-hd{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);margin-bottom:var(--s2)}
.pz-sekcja-hd h4{margin:0;font-size:var(--fs-sm);font-weight:680;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2)}
.pz-fakty{display:grid;grid-template-columns:minmax(120px,190px) 1fr;gap:6px var(--s4);margin:0;font-size:var(--fs-sm)}
.pz-fakty dt{color:var(--ink-3)}
.pz-fakty dd{margin:0;color:var(--ink);min-width:0;overflow-wrap:anywhere}
.pz-dlugi{white-space:pre-wrap}

@media (max-width:720px){
  .okienko.przyjecie-okno{left:0;top:0;transform:none;width:100vw;height:100dvh;border-radius:0;border:0}
  .przyjecie-okno > .kartahd,.przyjecie-okno > .pz-tresc,.pz-stopka{padding-left:var(--s4);padding-right:var(--s4)}
  .przyjecie-okno > .note,.przyjecie-okno > .kroki-przyjecia{margin-left:var(--s4);margin-right:var(--s4)}
  .pz-fakty{grid-template-columns:1fr}
  .pz-fakty dt{margin-top:4px}
}
/* Pole, w którym jest brak — mruga po przeskoku (26.09.2026). */
.mrugnij{border-radius:var(--radius-sm);animation:mrugnij 1.4s ease-out 1}
@keyframes mrugnij{0%,40%{box-shadow:0 0 0 3px var(--bad-border),0 0 0 7px var(--bad-bg)}100%{box-shadow:0 0 0 0 transparent}}
@media (prefers-reduced-motion:reduce){.mrugnij{animation:none;box-shadow:0 0 0 3px var(--bad-border)}}

/* ---------------------------------------------------------------------
   DROGA PACZKI — ANIMOWANY PASEK (26.09.2026, Łukasz: „zrobisz ładniejsze,
   animowane te paski? I to samo z kurierem"). Przebyte odcinki wypełniają
   się po kolei przy wejściu, odcinek za bieżącym etapem „płynie" — paczka
   jest w drodze do następnego etapu. Zrobione etapy mają ptaszek.
   --------------------------------------------------------------------- */
.podroz-kropka{width:18px;height:18px;display:grid;place-items:center;border-width:2px}
.podroz-kropka svg{width:10px;height:10px;fill:none;stroke:#fff;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
.podroz-etap:not(:last-child)::after{left:18px;top:7px;height:4px;border-radius:4px}
.podroz-etap.zrobiony:not(:last-child)::after{
  background:var(--line) linear-gradient(var(--ok),var(--ok)) no-repeat;background-size:100% 100%}
.podroz-etap.w-toku:not(:last-child)::after{
  background:var(--line) linear-gradient(90deg,transparent,var(--accent),transparent) no-repeat;
  background-size:38% 100%;background-position:50% 0}
.podroz-etap.teraz .podroz-kropka{box-shadow:0 0 0 4px var(--accent-soft)}
@media (prefers-reduced-motion:no-preference){
  .podroz-etap.zrobiony:not(:last-child)::after{animation:podroz-wypelnij .6s cubic-bezier(.3,.7,.3,1) both;
    animation-delay:calc(var(--i,0) * .14s)}
  .podroz-etap.zrobiony .podroz-kropka{animation:podroz-kropka .35s cubic-bezier(.3,1.4,.5,1) both;
    animation-delay:calc(var(--i,0) * .14s)}
  .podroz-etap.w-toku:not(:last-child)::after{animation:podroz-plynie 1.9s ease-in-out infinite}
  .podroz-etap.teraz:not(.uwaga) .podroz-kropka{animation:podroz-puls 2.2s ease-out infinite}
}
@keyframes podroz-wypelnij{from{background-size:0% 100%}}
@keyframes podroz-kropka{from{transform:scale(.55);opacity:.4}}
@keyframes podroz-plynie{from{background-position:-60% 0}to{background-position:160% 0}}
@keyframes podroz-puls{0%{box-shadow:0 0 0 0 var(--accent-soft),0 0 0 4px var(--accent-soft)}
  70%{box-shadow:0 0 0 10px transparent,0 0 0 4px var(--accent-soft)}
  100%{box-shadow:0 0 0 0 transparent,0 0 0 4px var(--accent-soft)}}
@media (max-width:560px){
  .podroz-etap:not(:last-child)::after{left:7px;top:18px;width:4px;height:calc(100% - 6px)}
  .podroz-etap.zrobiony:not(:last-child)::after{background-size:100% 100%}
  .podroz-etap.w-toku:not(:last-child)::after{
    background:var(--line) linear-gradient(180deg,transparent,var(--accent),transparent) no-repeat;
    background-size:100% 40%}
  @keyframes podroz-plynie{from{background-position:0 -60%}to{background-position:0 160%}}
  @keyframes podroz-wypelnij{from{background-size:100% 0%}}
}

/* Znak przewoźnika (26.09.2026) — barwy i nazwa, nie logotyp. */
.przewoznik-znak-wiersz{display:inline-flex;align-items:center;gap:6px;vertical-align:middle}
.przewoznik-znak{display:inline-flex;align-items:center;height:20px;padding:0 7px;border-radius:4px;
  font-size:12px;font-weight:800;letter-spacing:.02em;line-height:1;white-space:nowrap}
.przewoznik-znak.dhl{background:#FFCC00;color:#D40511;font-style:italic;letter-spacing:.04em}
.przewoznik-znak.inpost{background:#FFCD00;color:#1D1D1B}
.przewoznik-znak.dpd{background:#DC0032;color:#fff;text-transform:lowercase}
.przewoznik-znak.furgonetka{background:#1F2937;color:#fff}
.przewoznik-nazwa{color:var(--ink-2)}

/* Naprawa wysyłkowa i punkt na liście napraw (26.09.2026). */
.kn-numer-wiersz{display:flex;align-items:center;gap:7px}
.znak-wysylkowa{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
  border-radius:6px;background:var(--accent-soft,var(--surface-2));color:var(--accent);flex:0 0 auto;
  margin-bottom:3px}
.kol-punkt{white-space:nowrap}
.punkt-skrot{display:inline-block;padding:2px 8px;border-radius:var(--radius-pill,6px);background:var(--surface-2);
  border:1px solid var(--line);font-size:var(--fs-xs);font-weight:650;color:var(--ink-2);letter-spacing:.03em}

/* KOLEJKI ROBOCZE na liście napraw („Nikt nie wziął", zakres dat) —
   te same wcięcia co pasek filtrów nad nimi, żeby przyciski nie
   dotykały krawędzi karty. 26.09.2026 */
.card > .kolejki-robocze{gap:6px;padding:var(--s3) var(--pad-card);
  border-bottom:1px solid var(--line-soft);margin:0}
@media (max-width:640px){ .card > .kolejki-robocze{padding:var(--s3)} }

/* =====================================================================
   OGLĘDZINY PRZESYŁKI (migracja 299, 26.09.2026)
   Jedno okienko: opis klienta, zgodny / są różnice, QR + zdjęcia.
   ===================================================================== */
.scrim.og-tlo{z-index:57}
.okienko.og-okno{z-index:58;height:auto;max-height:min(760px,94vh);width:min(760px,96vw)}
.og-tresc{display:flex;flex-direction:column;gap:var(--s4)}
.og-etykieta{display:block;font-size:var(--fs-xs);font-weight:680;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:6px}
.og-opis-klienta{padding:var(--s3) var(--s4);border-radius:var(--radius-sm);
  background:var(--surface-2);border:1px solid var(--line-soft)}
.og-opis-klienta p{margin:0;font-size:var(--fs-md, 1rem);overflow-wrap:anywhere}
.og-wybor{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
.og-opcja{display:flex;align-items:center;justify-content:center;gap:10px;min-height:56px;
  padding:var(--s3);border:1.5px solid var(--line);border-radius:var(--radius);
  background:var(--surface);color:var(--ink);font:inherit;font-weight:650;font-size:1rem;cursor:pointer;
  transition:border-color .15s, background-color .15s}
.og-opcja svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
.og-opcja:hover{border-color:var(--ink-3)}
.og-opcja:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.og-opcja.wybrana.ok{border-color:var(--ok, #2f8a4f);background:var(--ok-bg, #eaf6ee);color:var(--ok-ink, #1f6b3a)}
.og-opcja.wybrana.zle{border-color:var(--bad-border, #d9a3a3);background:var(--bad-bg, #fbeeee);color:var(--bad, #b3261e)}
.og-roznice{display:flex;flex-direction:column;gap:var(--s2)}
.og-znaczniki{display:flex;flex-wrap:wrap;gap:8px}
.og-znacznik{padding:7px 12px;border-radius:999px;border:1px solid var(--line);background:var(--surface);
  color:var(--ink);font:inherit;font-size:var(--fs-sm);cursor:pointer}
.og-znacznik:hover{border-color:var(--ink-3)}
.og-znacznik.on{border-color:var(--bad, #b3261e);background:var(--bad-bg, #fbeeee);color:var(--bad, #b3261e);font-weight:600}
.og-znacznik:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.og-mail{margin:2px 0 0;font-size:var(--fs-sm)}
.og-zdjecia{display:grid;grid-template-columns:auto 1fr;gap:var(--s5);align-items:start;
  padding:var(--s4);border:1px solid var(--line-soft);border-radius:var(--radius)}
.og-kod{display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;font-size:var(--fs-xs);max-width:180px}
.og-kod img,.og-kod-pusty{width:170px;height:170px;border-radius:var(--radius-sm);background:#fff;
  border:1px solid var(--line-soft)}
.og-kod-pusty{display:grid;place-items:center;color:var(--ink-3);font-size:var(--fs-sm);padding:var(--s3)}
.og-galeria{display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.og-licznik{font-size:var(--fs-sm)}
.og-licznik.ok b{color:var(--ok-ink, #1f6b3a)}
.og-miniatury{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:8px}
.og-miniatury figure{position:relative;margin:0;aspect-ratio:1;border-radius:var(--radius-sm);overflow:hidden;
  background:var(--surface-2);animation:og-wskocz .25s ease-out}
.og-miniatury img{width:100%;height:100%;object-fit:cover;display:block}
.og-miejsce{aspect-ratio:1;border-radius:var(--radius-sm);border:1.5px dashed var(--line)}
.og-usun{position:absolute;top:4px;right:4px;width:24px;height:24px;display:grid;place-items:center;
  border-radius:50%;border:0;background:rgba(0,0,0,.55);color:#fff;cursor:pointer}
.og-usun svg{width:10px;height:10px;stroke:currentColor;stroke-width:1.8;fill:none}
.og-z-komputera{align-self:flex-start;font-size:var(--fs-sm)}
.og-okno .btn.primary.nieaktywny{opacity:.55}
@keyframes og-wskocz{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.og-miniatury figure{animation:none}}
@media (max-width:640px){
  .og-wybor{grid-template-columns:1fr}
  .og-zdjecia{grid-template-columns:1fr}
  .og-kod{max-width:none}
}
.og-okno > .og-blad{margin:0 var(--s6) var(--s3);flex:0 0 auto}
/* Opis nad polami i przypis pod stopką w kartach ustawień (Opinie Google) */
.bramka-opis{margin:0;padding:14px 18px 0}
.bramka-opis-dol{padding:12px 18px 16px}
/* STOPER NA KARCIE NAPRAWY (26.09.2026) */
.kn-stoper-start{display:inline-flex;align-items:center;gap:6px}
.kn-stoper-start svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round}
.kn-stoper.leci{display:inline-flex;align-items:center;gap:8px;padding:2px 4px 2px 10px;
  border:1px solid var(--ok-border, var(--line));border-radius:999px;background:var(--ok-bg, var(--surface-2))}
.kn-stoper-kropka{width:8px;height:8px;border-radius:50%;background:var(--ok, #2f8a4f);
  animation:kn-stoper-puls 1.6s ease-in-out infinite}
.kn-stoper-czas{font-weight:680;font-variant-numeric:tabular-nums;color:var(--ok-ink, var(--ink));min-width:4.6em}
.kn-stoper-odrzuc{background:none;border-color:transparent;color:var(--ink-3)}
.kn-stoper-odrzuc:hover{color:var(--bad)}
@keyframes kn-stoper-puls{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.kn-stoper-kropka{animation:none}}

/* =====================================================================
   KARTA NAPRAWY — NOWY UKŁAD (26.09.2026)
   Szersza (80% ekranu), zwarty pas „Najważniejsze", pasek skoków,
   bloki w kolejności pracy serwisanta.
   ===================================================================== */
.drawer.karta-naprawy{width:min(96vw,max(960px,80vw));max-width:none}
.kn-skoki{position:sticky;top:calc(-1 * var(--s5));z-index:6;display:flex;flex-wrap:wrap;gap:4px;
  margin:0 calc(-1 * var(--s6)) var(--s4);padding:8px var(--s6);
  background:color-mix(in srgb, var(--surface) 92%, transparent);backdrop-filter:blur(6px);
  border-bottom:1px solid var(--line-soft, var(--line))}
.kn-skok{border:0;background:none;padding:5px 10px;border-radius:999px;font:inherit;
  font-size:var(--fs-sm);color:var(--ink-2);cursor:pointer}
.kn-skok:hover{background:var(--surface-2);color:var(--ink)}
.kn-skok:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Strefy karty (26.09.2026): komunikacja / rozliczenie / warsztat / historia.
   Kolor strefy (--sk) idzie z tokenów semantycznych, więc działa w obu
   motywach; na blokach tylko pasek z lewej i lekko zabarwiony nagłówek. */
.kn-strefa{--sk:var(--ink-3);scroll-margin-top:56px;margin-top:var(--s5)}
.kn-strefa-komunikacja{--sk:var(--info)}
.kn-strefa-rozliczenie{--sk:var(--warn)}
.kn-strefa-warsztat{--sk:var(--ok)}
.kn-strefa-historia{--sk:var(--ink-3)}
.kn-strefa-hd{display:flex;align-items:center;gap:8px;margin:0 0 var(--s3);padding:0 0 6px 2px;
  font-size:var(--fs-sm);font-weight:720;letter-spacing:.07em;text-transform:uppercase;color:var(--sk);
  border-bottom:2px solid color-mix(in srgb, var(--sk) 30%, transparent)}
.kn-strefa-ikona{flex:none}
.kn-strefa .blok{border-left:3px solid var(--sk)}
.kn-strefa .blok .blok{border-left-width:1px;border-left-color:var(--line)}
.kn-strefa .blok > .blok-hd{background:color-mix(in srgb, var(--sk) 7%, var(--surface-2))}
.kn-strefa .blok > .blok-hd .tytul{color:var(--ink)}
.kn-skok{display:inline-flex;align-items:center;gap:6px}
.kn-skok .kn-strefa-ikona{width:14px;height:14px}
.kn-sk-komunikacja{color:var(--info)}
.kn-sk-rozliczenie{color:var(--warn)}
.kn-sk-warsztat{color:var(--ok)}
.kn-sk-historia{color:var(--ink-2)}
.kn-skok.kn-sk-komunikacja:hover,.kn-skok.kn-sk-rozliczenie:hover,.kn-skok.kn-sk-warsztat:hover{color:var(--ink)}

.kn-glowne{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  padding:var(--s4) var(--s5);margin-bottom:var(--s4)}
.kn-etyk{display:flex;align-items:center;gap:6px;font-size:var(--fs-xs);font-weight:650;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:3px}
.kn-etyk .ikonka{flex:0 0 auto;color:var(--accent-text, var(--ink-2));opacity:.85}
.kn-usterka{padding-bottom:var(--s3);margin-bottom:var(--s3);border-bottom:1px solid var(--line-soft, var(--line))}
.kn-usterka-tresc{font-size:var(--fs-md, 1rem);line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}
.kn-glowne-siatka{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--s3) var(--s5)}
.kn-fakt{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:var(--fs-sm);overflow-wrap:anywhere}
.kn-fakt > span:nth-child(2){font-size:var(--fs-base, .95rem);color:var(--ink)}
.kn-fakt-akcje{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.kn-klient{font-weight:600;font-size:inherit;padding:0}
.kn-uwagi-wew{margin-top:var(--s3);padding:8px 12px;border-radius:var(--radius-sm);
  background:var(--warn-bg, var(--surface-2));font-size:var(--fs-sm)}
.kn-uwagi-wew .kn-etyk{display:inline-flex;vertical-align:-2px;margin-right:6px}
.kn-przekazanie{margin-top:var(--s3);display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.kn-przekazanie .btn{margin-left:auto}
.kn-glowne-stopka{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:var(--s3);
  padding-top:var(--s3);border-top:1px solid var(--line-soft, var(--line))}
.kn-glowne-stopka .jak-link{padding-left:0}
/* Przycisk rozwijania i pełne dane w tym samym bloku (28.09.2026) */
.kn-glowne-stopka .btn.kn-rozwin{display:inline-flex;align-items:center;gap:6px}
.kn-rozwin .ikonka{transition:transform .15s ease}
.kn-rozwin.otwarte .ikonka{transform:rotate(180deg)}
@media (prefers-reduced-motion:reduce){ .kn-rozwin .ikonka{transition:none} }
.kn-pelne{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,3fr);gap:var(--s3) var(--s5);
  margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line-soft, var(--line))}
.kn-pelne-grupa{min-width:0}
.kn-pelne-hd{display:flex;align-items:center;gap:6px;margin:0 0 8px;font-size:var(--fs-sm);font-weight:650;color:var(--ink)}
.kn-pelne-hd .ikonka{color:var(--accent-text, var(--ink-2))}
.kn-pelne-hd .cichy{font-weight:400;margin-left:2px}
.kn-pd-siatka{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px var(--s4);margin:0}
.kn-pd{min-width:0}
.kn-pd.szeroki{grid-column:1 / -1}
.kn-pd dt{font-size:var(--fs-xs);color:var(--ink-3);margin:0 0 2px;line-height:1.3}
.kn-pd dd{margin:0;font-size:var(--fs-sm);color:var(--ink);overflow-wrap:anywhere}
.kn-pd dd.kn-punkt{display:flex;flex-wrap:wrap;gap:4px 8px;align-items:center}
.kn-przekazanie-powod{flex-basis:100%}
@media (max-width:900px){ .kn-pelne{grid-template-columns:1fr} }

/* USŁUGI I CZĘŚCI — czytelna tabela z oddechem */
.kn-pozycje td{padding:10px 0}
.kn-pozycje td + td{padding-left:var(--s4)}
.kn-pozycje .kn-poz-usun{white-space:nowrap}
.kn-pozycje .kn-poz-usun .btn + .btn{margin-left:6px}
.kn-pozycje tfoot td{padding-top:12px;padding-bottom:4px}
.kn-wycena-start{margin:0 0 var(--s3)}
@media (max-width:760px){
  .kn-skoki{margin-left:calc(-1 * var(--s4));margin-right:calc(-1 * var(--s4));padding-left:var(--s4);padding-right:var(--s4)}
  .kn-glowne{padding:var(--s3) var(--s4)}
}
@media (max-width:900px){ .drawer.karta-naprawy{width:100vw} }
.blok-bd > .pasek-akcji:first-child{margin-top:0;padding-top:0;border-top:0}
.blok-bd > .kn-zdjecia-akcje:first-child{margin-top:0;padding-top:0;border-top:0}
/* Podpowiedź „wyślij wycenę" pod pozycjami (26.09.2026) */
.kn-podpowiedz-wyceny{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;
  margin-top:var(--s3);padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--accent-soft);border:1px solid var(--accent-border);font-size:var(--fs-sm)}
.kn-podpowiedz-wyceny .cichy{margin-top:2px}
/* WZÓR BLOKADY W OKIENKU — duży, z kolejnością (26.09.2026) */
.kn-wzor-duzy{display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center}
.wzor-blokady.podglad.duzy{width:min(300px,78vw);border:1px solid var(--line);border-radius:16px;background:var(--surface)}
.wzor-blokady.podglad.duzy .wzor-linia{stroke-width:6}
.wzor-start{fill:none;stroke:var(--accent);stroke-width:3;opacity:.55}
.wzor-numer.duzy{font-size:15px;fill:var(--accent-ink)}
.kn-okno-sekret .kn-okno-kod{padding:var(--s3) 0 var(--s2)}
.kn-okno-sekret .kod-jawny{font-size:2rem;letter-spacing:.12em;padding:10px 18px}
/* STOPER — zwarta pigułka w wysokości przycisków (26.09.2026, poprawka) */
.kn-stoper.leci{box-sizing:border-box;height:34px;padding:0 3px 0 12px;gap:8px;overflow:hidden}
.kn-stoper-czas{font-size:var(--fs-sm);min-width:4.2em}
.kn-stoper-stop{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 11px;border:0;border-radius:999px;
  background:var(--ok-solid, #2f8a4f);color:var(--ok-solid-ink, #fff);font:inherit;font-size:var(--fs-sm);font-weight:650;cursor:pointer}
.kn-stoper-stop:hover{background:var(--ok-solid-hover, #26733f)}
.kn-stoper-stop svg{width:10px;height:10px;fill:currentColor}
.kn-stoper-odrzuc{display:inline-grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;
  background:transparent;color:var(--ink-3);cursor:pointer}
.kn-stoper-odrzuc:hover{background:var(--bad-bg);color:var(--bad)}
.kn-stoper-odrzuc svg{width:10px;height:10px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round}
.kn-stoper-stop:focus-visible,.kn-stoper-odrzuc:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Wiadomość do klienta w Asystencie AI — większe pola (26.09.2026) */
.ai-wiad-pola{display:flex;flex-direction:column;gap:var(--s3)}
.ai-wiad-pola .pole{width:100%;max-width:none}
.ai-wiad-pola select.input,.ai-wiad-pola textarea.input{width:100%}
.ai-wiad-pola textarea.input{min-height:76px;resize:vertical}

/* USŁUGI I CZĘŚCI — lista w siatce (26.09.2026) */
.kn-poz-lista{display:flex;flex-direction:column;border:1px solid var(--line-soft, var(--line));
  border-radius:var(--radius-sm);overflow:hidden;font-size:var(--fs-sm)}
.kn-poz{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:4px var(--s4);align-items:start;
  padding:10px 12px;border-bottom:1px solid var(--line-soft, var(--line));background:var(--surface)}
.kn-poz:hover{background:var(--surface-2)}
.kn-poz-opis{min-width:0}
.kn-poz-nazwa{font-weight:600;overflow-wrap:anywhere}
.kn-poz-ile,.kn-poz-suma{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.kn-poz-suma{min-width:7em}
.kn-poz-akcje{display:flex;gap:2px;align-self:center;min-width:60px;justify-content:flex-end}
.kn-ikona{display:inline-grid;place-items:center;width:28px;height:28px;padding:0;border:1px solid transparent;
  border-radius:var(--radius-sm);background:transparent;color:var(--ink-2);cursor:pointer}
.kn-ikona svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.kn-ikona:hover{background:var(--surface-3, var(--surface-2));border-color:var(--line)}
.kn-ikona.groznie:hover{color:var(--bad);background:var(--bad-bg);border-color:var(--bad-border)}
.kn-ikona:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.kn-ikona:disabled{opacity:.45;cursor:default}
.kn-poz-edycja{padding:12px;border-bottom:1px solid var(--line-soft, var(--line));background:var(--surface-2)}
.kn-poz-razem{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:var(--s4);align-items:baseline;
  padding:10px 12px;background:var(--surface-2);font-variant-numeric:tabular-nums}
.kn-poz-razem > span:first-child{color:var(--ink-2)}
.kn-poz-brutto{min-width:7em;text-align:right;margin-right:62px}
@media (max-width:640px){
  .kn-poz{grid-template-columns:minmax(0,1fr) auto}
  .kn-poz-ile{grid-column:1;text-align:left}
  .kn-poz-suma{grid-column:2;grid-row:1}
  .kn-poz-akcje{grid-column:2}
  .kn-poz-brutto{margin-right:0}
}
/* Asystent AI w okienku (26.09.2026) */
.okienko.ai-okno{width:min(880px,94vw);max-height:90vh}
.ai-okno .ai-narzedzia{margin:var(--s3) 0 0}
.ai-okno .ai-panel{margin-top:var(--s4)}

/* Karta naprawy: mail klienta w pasku „Najważniejsze" — jedna linia,
   długi adres ucięty wielokropkiem (pełny w dymku). */
.kn-fakt .kn-nip{color:var(--ink-2);font-size:var(--fs-sm)}
.kn-fakt .kn-mail{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;overflow-wrap:normal}

/* Dopisanie usługi / części w okienku zamiast rozwijania bloku. */
.okienko.kn-okno-pozycji{width:min(820px,94vw);max-height:90vh;overflow:auto}
.kn-okno-pozycji > .note{margin:var(--s3) 0 0}
.kn-okno-pozycji > .kartahd + *{margin-top:var(--s3)}
.okienko.kn-okno-pozycji > .kartahd .rozpychacz,
.okienko.ai-okno > .kartahd .rozpychacz{margin-left:auto}
.ai-okno .ai-panel .btn{white-space:nowrap}

/* Okienko „Wyślij wycenę do akceptacji" — pozycje w siatce, wyśrodkowane
   w pionie, kwoty wyrównane do prawej. */
.kn-wyc-lista{border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden;margin:var(--s3) 0}
.kn-wyc-wiersz{display:grid;grid-template-columns:minmax(0,1fr) auto 11ch;gap:var(--s4);align-items:center;
  padding:10px 14px;min-height:44px;border-top:1px solid var(--line-soft)}
.kn-wyc-wiersz:first-child{border-top:0}
.kn-wyc-wiersz > span:nth-child(2),.kn-wyc-wiersz > span:nth-child(3){text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.kn-wyc-nazwa{overflow-wrap:anywhere}
.kn-wyc-suma{background:var(--surface-2);border-top:1px solid var(--line)}
.kn-wyc-suma > span:first-child{color:var(--muted, var(--ink-2))}

/* Przycisk „Zamknij" w nagłówku okienek — zawsze do prawej krawędzi. */
.okienko > .kartahd > .rozpychacz{margin-left:auto}

/* Asystent AI — przykładowe pytania pod polem, klik wpisuje do pola. */
.ai-przyklady{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:var(--s2) 0}
.ai-przyklad{font:inherit;font-size:var(--fs-sm);line-height:1.3;text-align:left;cursor:pointer;
  padding:5px 10px;border:1px solid var(--line);border-radius:999px;background:var(--surface-2);color:var(--ink)}
.ai-przyklad:hover{border-color:var(--accent-border);background:var(--accent-soft)}
.ai-przyklad:focus-visible{outline:2px solid var(--accent-border);outline-offset:2px}

/* Menu: moduł z własną marką (PAKT, PULPA) — ikonka zamiast piktogramu,
   nazwa pogrubiona, pod spodem mały szary dopisek, co to jest. */
.nav .nav-marka-znak{flex:0 0 auto;width:22px;height:22px;margin:-3px -3px -3px -3px;object-fit:contain}
.nav .nav-marka{display:inline-flex;align-items:baseline;gap:7px;min-width:0}
.nav .nav-marka b{font-weight:760;letter-spacing:.06em}
.nav .nav-marka-opis{font-size:.8em;font-weight:500;opacity:.62;text-transform:lowercase;white-space:nowrap}

/* =====================================================================
   PULPA — okno przyjęcia w stylu SOK (26.09.2026)
   =====================================================================
   Łukasz: „wygląda słabo w porównaniu do reszty programu, zasugerujmy
   się wyglądem SOK-u, szczególnie paskiem postępu". Dwie kolumny:
   krok w karcie z nagłówkiem jak w SOK, obok karta przyjęcia na żywo. */
.okienko.przyjecie-okno.pz-szerokie{width:min(1180px,96vw);height:min(820px,94vh);background:var(--bg)}
.przyjecie-okno > .pz-glowa{padding:var(--s4) var(--s6) var(--s3);background:var(--surface);
  border-bottom:1px solid var(--line-soft);margin:0}
.pz-glowa .rozpychacz{margin-left:auto}
.pz-marka{display:flex;align-items:center;gap:12px;min-width:0}
.pz-marka img{width:48px;height:48px;flex:none;display:block}
.pz-marka-slowo{margin:0;font-family:'Fredoka',system-ui,sans-serif;font-weight:700;font-size:26px;
  line-height:1;letter-spacing:.02em;color:var(--ananas-slowo, var(--ink))}
.pz-marka-rozw{font-size:12.5px;line-height:1.35;color:var(--ink-2);margin-top:3px}
.pz-marka-rozw span{color:var(--ananas-litera, var(--accent));font-weight:800}
:root[data-theme="dark"] .pz-marka-slowo{color:var(--ink)}
.przyjecie-okno > .note{margin:var(--s3) var(--s6) 0}

/* Pasek postępu — ten sam rysunek co „Twoja naprawa" w SOK. */
.przyjecie-okno > .pz-postep{flex:0 0 auto;margin:0;padding:var(--s4) var(--s6) var(--s3);
  background:var(--surface);border-bottom:1px solid var(--line)}
.pz-postep ol{--kolko:26px;position:relative;display:grid;grid-template-columns:repeat(5,1fr);
  list-style:none;margin:0;padding:0}
/* Linia pod kółkami: od środka pierwszego do środka ostatniego, a na
   niej wypełnienie do bieżącego kroku. */
.pz-postep ol::before,.pz-postep ol::after{content:'';position:absolute;top:calc(var(--kolko) / 2 - 2px);
  left:10%;height:4px;border-radius:4px}
.pz-postep ol::before{right:10%;background:var(--line)}
.pz-postep ol::after{width:calc(var(--postep, 0%) * .8);background:var(--accent);transition:width .35s ease}
.pz-etap{position:relative;z-index:1;display:flex;justify-content:center}
.pz-etap button{display:flex;flex-direction:column;align-items:center;gap:7px;padding:0 4px;
  border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink-3);border-radius:var(--radius-sm)}
.pz-etap button:focus-visible{outline:none;box-shadow:var(--focus)}
.pz-etap-kolko{width:var(--kolko);height:var(--kolko);box-sizing:border-box;border-radius:50%;
  display:grid;place-items:center;background:var(--surface);border:2px solid var(--line);
  font-size:12px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--ink-3);
  transition:background .2s,border-color .2s,box-shadow .2s,color .2s}
.pz-etap-kolko svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
.pz-etap-nazwa{font-size:var(--fs-sm);font-weight:600;white-space:nowrap}
.pz-etap button:hover .pz-etap-kolko{border-color:var(--accent)}
.pz-etap button:hover .pz-etap-nazwa{color:var(--ink)}
.pz-etap.minety .pz-etap-kolko{border-color:var(--accent);color:var(--ink-2)}
.pz-etap.zrobiony .pz-etap-kolko{background:var(--ok-solid, var(--ok));border-color:var(--ok-solid, var(--ok));color:#fff}
.pz-etap.zrobiony .pz-etap-nazwa{color:var(--ink-2)}
.pz-etap.teraz .pz-etap-kolko{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);
  box-shadow:0 0 0 5px var(--accent-soft)}
.pz-etap.teraz .pz-etap-nazwa{color:var(--ink);font-weight:700}
.pz-etap.zly .pz-etap-kolko{background:var(--bad);border-color:var(--bad);color:#fff}
.pz-etap.zly .pz-etap-nazwa{color:var(--bad)}
@media (prefers-reduced-motion:reduce){.pz-postep ol::after,.pz-etap-kolko{transition:none}}

/* Dwie kolumny na tle jak strona SOK. */
.pz-uklad{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 320px;
  gap:var(--s4);padding:var(--s4) var(--s6)}
.pz-kolumna,.pz-karta{display:flex;flex-direction:column;min-height:0;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius-lg, 12px);box-shadow:var(--shadow-1);overflow:hidden}
.pz-kolumna-hd{flex:0 0 auto;display:flex;align-items:baseline;gap:8px;padding:12px 18px;
  border-bottom:1px solid var(--line-soft);background:var(--surface-2)}
.pz-kolumna-hd h3{margin:0;font-size:var(--fs-sm);font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-2)}
.pz-kolumna-nr{margin-left:auto;font-size:var(--fs-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}
.pz-kolumna > .pz-tresc{flex:1 1 auto;min-height:0;overflow:auto;padding:var(--s4) 18px var(--s5)}
.pz-krok-opis{margin:0 0 var(--s4);color:var(--ink-3);font-size:var(--fs-sm);max-width:62ch}
.pz-kolumna > .pz-tresc .podsekcja:first-child{margin-top:0}

/* Krok 1: szukajka z lupą, przełącznik osoba / firma. */
.pz-anonim{display:inline-flex;align-items:center;gap:6px;margin-bottom:var(--s3)}
.pz-szukaj{position:relative}
.pz-szukaj svg{position:absolute;left:12px;top:50%;width:18px;height:18px;transform:translateY(-50%);
  fill:none;stroke:var(--ink-3);stroke-width:1.8;stroke-linecap:round;pointer-events:none}
.pz-szukaj .input{padding-left:38px}
.pz-nowy-hd{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  margin:var(--s5) 0 var(--s3);padding-top:var(--s4);border-top:1px solid var(--line-soft)}
.pz-etykieta{font-size:var(--fs-sm);font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-2)}
.pz-przelacznik{display:inline-flex;padding:3px;gap:2px;border:1px solid var(--line);
  border-radius:var(--radius-pill, 999px);background:var(--surface-2)}
.pz-przelacznik button{font:inherit;font-size:var(--fs-sm);font-weight:600;padding:5px 14px;border:0;
  border-radius:var(--radius-pill, 999px);background:transparent;color:var(--ink-2);cursor:pointer}
.pz-przelacznik button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(13,31,60,.14)}
.pz-przelacznik button:focus-visible{outline:none;box-shadow:var(--focus)}

/* Karta przyjęcia (prawa kolumna). */
.pz-karta-tresc{flex:1 1 auto;min-height:0;overflow:auto;padding:6px}
.pz-karta-grupa{display:block;width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer;
  padding:10px 12px;border:1px solid transparent;border-radius:var(--radius-md, 10px);background:transparent}
.pz-karta-grupa + .pz-karta-grupa{margin-top:2px}
.pz-karta-grupa:hover{background:var(--surface-2)}
.pz-karta-grupa:focus-visible{outline:none;box-shadow:var(--focus)}
.pz-karta-grupa.teraz{background:var(--accent-soft);border-color:var(--accent-border)}
.pz-karta-grupa.przed{opacity:.6}
.pz-karta-tytul{display:block;margin-bottom:6px;font-size:11.5px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--ink-3)}
.pz-karta-grupa dl{display:grid;grid-template-columns:88px minmax(0,1fr);gap:4px 10px;margin:0;font-size:var(--fs-sm)}
.pz-karta-grupa dt{color:var(--ink-3)}
.pz-karta-grupa dd{margin:0;color:var(--ink);min-width:0;overflow-wrap:anywhere}
.pz-karta-skrot{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.pz-karta-brak{color:var(--ink-3)}

/* Stopka: „Dalej: Sprzęt ›". */
.przyjecie-okno .pz-stopka .btn.primary{display:inline-flex;align-items:center;gap:6px}
.pz-strzalka{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

@media (max-width:980px){
  .pz-uklad{grid-template-columns:1fr}
  .pz-karta{display:none}
}
@media (max-width:720px){
  .przyjecie-okno > .pz-glowa,.przyjecie-okno > .pz-postep{padding-left:var(--s4);padding-right:var(--s4)}
  .pz-uklad{padding:var(--s3)}
  .pz-etap-nazwa{display:none}
  .pz-etap.teraz .pz-etap-nazwa{display:block;position:absolute;top:calc(var(--kolko) + 6px)}
  .pz-marka-rozw{display:none}
}
.pz-karta-glowne{display:block;font-weight:650;color:var(--ink);overflow-wrap:anywhere}
.pz-karta-glowne.pusto{font-weight:400;color:var(--ink-3);font-style:italic}
.pz-karta-glowne + dl{margin-top:6px}

/* Przebieg: „pokaż treść" przy długiej wiadomości/notatce. */
.przebieg .pz-pokaz{margin-left:8px;font-size:var(--fs-sm);font-weight:600;white-space:nowrap}

/* Lista napraw: plakietki po prawej stoją na wysokości plakietki statusu
   (dolnej), a nie w połowie wiersza (Łukasz, 26.09.2026). */
.kol-numer.lewo .kn-uklad{align-items:flex-end}
.kol-numer.lewo .kn-boczne{justify-content:flex-end}

/* Fakturowanie — odstęp od krawędzi karty jak w „Płatnościach online"
   (26.09.2026; pełne porządki ekranów ustawień w osobnym kroku). */
.ksiegowosc-ekran{padding:4px 20px 22px}
.ksiegowosc-ekran > .sekcja{padding-left:0;padding-right:0}
.ksiegowosc-ekran .pasek-akcji .grow{flex:1 1 auto}

/* Inny adres odesłania / faktura na inne dane (migracja 304). */
.kn-inne-dane{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 var(--s3)}
.kn-inne-chip{display:inline-flex;align-items:baseline;gap:8px;flex-wrap:wrap;text-align:left;cursor:pointer;
  font:inherit;font-size:var(--fs-sm);padding:7px 12px;border-radius:var(--radius-sm);
  background:var(--warn-bg);border:1px solid var(--warn-border, var(--line));color:var(--ink);max-width:100%}
.kn-inne-chip:hover{filter:brightness(.98)}
.kn-inne-chip:focus-visible{outline:none;box-shadow:var(--focus)}
.kn-inne-etyk{font-weight:700;text-transform:uppercase;letter-spacing:.04em;font-size:11px;color:var(--ink-2)}
.kn-inne-zmien{color:var(--accent);font-weight:600}
.kn-glowne-stopka .grow{flex:1 1 auto}
.okienko.kn-okno-inne{width:min(760px,94vw)}
.kn-inne-wstep{margin:var(--s3) 0}
.kn-okno-inne .kn-tryb-wyceny{margin-bottom:var(--s3)}
.kn-inne-kartoteka{display:flex;flex-direction:column;gap:8px}
.kn-inne-wybrany{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface-2)}
.kn-inne-wybrany strong{flex:1 1 auto}
.kn-okno-inne .pasek-akcji .grow{flex:1 1 auto}
.kn-faktura-nabywca{margin:0 0 var(--s2)}

/* Wystaw fakturę — okienko z góry karty i z listy (26.09.2026). */
.okienko.kn-okno-faktura{width:min(560px,94vw)}
.kn-faktura-fakty{margin:var(--s3) 0}
.btn.kn-btn-faktura{border-color:var(--accent-border);background:var(--accent-soft)}
.kn-faktura-fakty{display:grid;grid-template-columns:90px minmax(0,1fr);gap:8px 14px}
.kn-faktura-fakty dt{color:var(--ink-3);margin:0}
.kn-faktura-fakty dd{margin:0}

/* ---------------------------------------------------------------------
   Kasa: usunięcie dnia kasowego (migracja 307)
   --------------------------------------------------------------------- */
.kasa-usun-podsumowanie{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:var(--s3);margin-bottom:var(--s4);padding:var(--s3) var(--s4);
  border:1px solid var(--line);border-radius:var(--radius)}
.kasa-usun-podsumowanie > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.kasa-usun-podsumowanie .l{font-size:var(--fs-sm);color:var(--ink-3)}
.kasa-usun-podsumowanie .v{font-weight:640;font-variant-numeric:tabular-nums}
.kasa-usun-wplaty{margin:var(--s3) 0}
.kasa-usun-wplaty .l{font-size:var(--fs-sm);color:var(--ink-2);margin-bottom:var(--s2)}
.kasa-usun-wplaty ul{list-style:none;margin:0;padding:0;max-height:180px;overflow:auto;
  border:1px solid var(--line);border-radius:var(--radius)}
.kasa-usun-wplaty li{display:flex;justify-content:space-between;gap:var(--s3);
  padding:6px var(--s3);border-bottom:1px solid var(--line)}
.kasa-usun-wplaty li:last-child{border-bottom:0}

/* ---------------------------------------------------------------------
   Karta naprawy: widoczność zdjęcia w SOK (migracja 308)
   --------------------------------------------------------------------- */
.kn-galeria:has(.kn-foto){grid-template-columns:repeat(auto-fill,minmax(112px,1fr))}
.kn-foto{margin:0;display:flex;flex-direction:column;gap:6px;min-width:0}
.kn-foto-klient{font:inherit;font-size:var(--fs-sm);line-height:1.2;padding:5px 6px;
  border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink-2);
  cursor:pointer;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kn-foto-klient:hover:not(:disabled){border-color:var(--accent);color:var(--ink)}
.kn-foto-klient:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.kn-foto-klient.widzi{background:var(--ok-bg, #e8f5ec);border-color:var(--ok-border, #b9e0c6);
  color:var(--ok, #1f7a3f);font-weight:600}
.kn-foto-klient:disabled{cursor:default;opacity:.8}
.kn-foto-zasada{margin:0 0 var(--s3);font-size:var(--fs-sm);color:var(--ink-3)}

/* ---------------------------------------------------------------------
   PULPIT NAPRAW: DZIŚ W PUNKCIE (26.09.2026)
   Rząd osób: twarz z kropką stanu, imię, stan słowami, liczba napraw.
   Stan kolorem i słowem jednocześnie — kolor sam nie niesie informacji.
   --------------------------------------------------------------------- */
.dzis-w-punkcie{margin:0}
.dzis-w-punkcie .hd{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.dzis-lista{list-style:none;margin:0;padding:var(--s3) var(--s4);display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.dzis-osoba{display:flex;align-items:center;gap:12px;min-width:0;padding:8px 10px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.dzis-osoba.ton-nie{background:var(--surface-2)}
.dzis-osoba.klik{cursor:pointer}
.dzis-osoba.klik:hover{border-color:var(--accent)}
.dzis-osoba.klik:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Otwarte sprawy osoby — okienko po kliknięciu w pasek (27.09.2026) */
.dzis-zlecenia{display:flex;flex-direction:column;gap:6px}
.dzis-zlecenie{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;width:100%;
  text-align:left;padding:10px 12px;border:1px solid var(--line);border-radius:var(--radius-sm, 8px);
  background:var(--surface);color:inherit;cursor:pointer;font:inherit}
.dzis-zlecenie:hover{border-color:var(--accent);background:var(--surface-2)}
.dzis-zl-nr{font-size:var(--fs-sm);white-space:nowrap}
.dzis-zl-opis{display:flex;flex-direction:column;min-width:0}
.dzis-zl-opis .muted{font-size:var(--fs-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dzis-zl-stan{display:flex;flex-direction:column;align-items:flex-end;gap:4px;font-size:var(--fs-sm);white-space:nowrap}
@media (max-width:640px){.dzis-zlecenie{grid-template-columns:1fr}.dzis-zl-stan{align-items:flex-start}}
.dzis-osoba.ton-nie .dzis-twarz{opacity:.6}
.dzis-twarz{position:relative;flex:0 0 44px;width:44px;height:44px;border-radius:50%;
  display:grid;place-items:center;background:var(--accent-soft, var(--surface-2));color:var(--accent);
  font-weight:700;font-size:15px;border:1px solid var(--line)}
.dzis-twarz img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.dzis-kropka{position:absolute;right:-1px;bottom:-1px;width:13px;height:13px;border-radius:50%;
  border:2px solid var(--surface);background:var(--ok, #1f7a3f)}
.ton-zajety .dzis-kropka{background:var(--warn, #b7791f)}
.ton-nie .dzis-kropka{background:var(--ink-3, #8a8f98)}
.dzis-opis{display:flex;flex-direction:column;min-width:0;line-height:1.25}
.dzis-imie{font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dzis-ja{font-weight:400;color:var(--ink-3)}
.dzis-stan{font-size:var(--fs-sm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ton-ok .dzis-stan{color:var(--ok, #1f7a3f)}
.ton-zajety .dzis-stan{color:var(--warn, #b7791f)}
.ton-nie .dzis-stan{color:var(--ink-3)}
.dzis-naprawy{font-size:var(--fs-sm);color:var(--ink-2);font-variant-numeric:tabular-nums}
.dzis-po{color:var(--bad, #c62828)}
.dzis-w-punkcie .hd .btn{margin-left:auto}

/* Przycisk „Odśwież" — karta naprawy i lista (26.09.2026). */
.btn.odswiez{display:inline-flex;align-items:center;gap:6px}
.btn.odswiez:disabled .ikona-odswiez{animation:obrot-odswiez .8s linear infinite}
@keyframes obrot-odswiez{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.btn.odswiez:disabled .ikona-odswiez{animation:none}}
.kn-glowa-przyciski{margin-left:auto;display:inline-flex;gap:6px;align-items:center}
.kn-glowa-przyciski .zamknij{margin-left:0}
@media (max-width:640px){
  .drawer-hd .kn-glowa-przyciski{grid-column:2;grid-row:1;margin-left:0;align-self:start}
}
/* Zdjęcie w kole zawsze w kole — pionowe zdjęcia wystawały pod kartę (26.09.2026, zdjęcie Kuby). */
.dzis-twarz{overflow:visible}
.dzis-twarz img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:50%}
.dzis-kropka{z-index:1}
/* Pasek poza pulpitem napraw stoi nad treścią ekranu — odstęp pod spodem. */
.dzis-w-punkcie{margin:0 0 var(--s4)}
.pulpit-napraw .dzis-w-punkcie{margin:0}

/* ---------------------------------------------------------------------
   LISTA NAPRAW: Pieniądze i Następny krok w osobnych kolumnach (26.09.2026)
   --------------------------------------------------------------------- */
.lista-napraw .kol-pieniadze{white-space:nowrap;text-align:left}
.stan-pieniedzy{display:flex;flex-direction:column;gap:2px;line-height:1.25}
.stan-pieniedzy-tekst{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);font-weight:600}
.stan-pieniedzy .kropka{width:8px;height:8px;border-radius:50%;background:currentColor;flex:0 0 8px}
.stan-pieniedzy.ton-ok .stan-pieniedzy-tekst{color:var(--ok)}
.stan-pieniedzy.ton-uwaga .stan-pieniedzy-tekst{color:var(--warn)}
.stan-pieniedzy.ton-zle .stan-pieniedzy-tekst{color:var(--bad)}
.stan-pieniedzy-kwota{font-variant-numeric:tabular-nums;color:var(--ink-2);font-size:var(--fs-sm);padding-left:14px}
.lista-napraw .kol-krok{white-space:nowrap;text-align:left}
.lista-napraw .kol-krok .akcja-wiersza{margin:0}
.lista-napraw .kol-numer .kn-glowny .pill{margin:0 0 3px}
/* Dwie nowe kolumny muszą się zmieścić bez przewijania w bok: węższy opis
   usterki i sprzętu, ciaśniejsze odstępy (26.09.2026). */
.lista-napraw td,.lista-napraw th{padding-left:10px;padding-right:10px}
.lista-napraw td.clip{max-width:200px}
.lista-napraw td[data-label="Sprzęt"] .tnij{max-width:170px}
.lista-napraw td[data-label="Serwisant"]{white-space:normal;max-width:130px}
.lista-napraw td.kol-numer{white-space:nowrap}
.lista-napraw .kol-numer .pill{max-width:230px;overflow:hidden;white-space:nowrap}
.lista-napraw .kol-pieniadze,.lista-napraw .kol-krok{width:1%}
.lista-napraw td[data-label="Klient"]{max-width:150px}

/* Szukajka u góry: stan „szukam / nic / błąd" (26.09.2026). */
.qs-stan{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:50;
  padding:10px 12px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow-2);color:var(--ink-2);font-size:var(--fs-sm);line-height:1.45}

/* Ptaszek „domyślny status" pod listą, nie obok niej (26.09.2026). */
.kn-domyslny-status{margin-top:10px}
.kn-domyslny-status .ptaszek{align-items:flex-start}
.kn-domyslny-status .ptaszek input{width:16px;height:16px;margin:calc((1lh - 16px) / 2) 0 0}

/* Plakietka statusu w kolorze z Ustawień → Statusy (26.09.2026).
   --kc daje klasa kal-c-<kolor> (ta sama paleta co kropki w ustawieniach).
   Tekst zostaje w kolorze tekstu, żeby żółty czy limonkowy był czytelny. */
:root .pill.st-kolor{background:color-mix(in srgb, var(--kc) 16%, var(--surface));
  border:1px solid color-mix(in srgb, var(--kc) 60%, transparent);color:var(--ink)}
:root .pill.st-kolor .ikonka{color:var(--kc)}
:root .pill.st-kolor.st-ostrzega .ikonka{color:var(--warn)}

/* Ustawienia → Co jeszcze trzeba ustawić (26.09.2026) */
.do-ustawienia{padding:var(--s4);display:flex;flex-direction:column;gap:var(--s4)}
.du-podsumowanie{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;padding:12px 14px;
  border-radius:var(--radius);border:1px solid var(--line);background:var(--surface-2);line-height:1.45}
.du-podsumowanie .btn{margin-left:auto}
.du-podsumowanie.zle{background:var(--bad-bg);border-color:var(--bad-border)}
.du-podsumowanie.dobrze{background:var(--ok-bg);border-color:var(--ok-border)}
.du-lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.du-poz{display:flex;align-items:center;gap:var(--s4);padding:12px 14px;background:var(--surface)}
.du-poz + .du-poz{border-top:1px solid var(--line)}
.du-poz.du-wazne{box-shadow:inset 3px 0 0 var(--bad)}
.du-poz.du-zalecane{box-shadow:inset 3px 0 0 var(--warn)}
.du-tekst{flex:1;min-width:0}
.du-tytul{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-weight:650}
.du-opis{color:var(--ink-2);font-size:var(--fs-sm);margin-top:3px;line-height:1.45}
.du-poz > .btn{flex:none}
.du-gotowe > summary{cursor:pointer;color:var(--ink-2);font-weight:600;padding:4px 0;margin-bottom:var(--s2)}

/* Pole, które zatrzymało zapis (26.09.2026) — czerwona ramka i zdanie pod nim. */
:root .input.zle, :root .input[aria-invalid="true"] { border-color: var(--bad); box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 18%, transparent); }
:root .bramka-pole small.pole-blad { color: var(--bad); font-weight: 600; }

/* Ustawienia → Punkty serwisu (26.09.2026, karty jak w Płatnościach online) */
.punkt-tytul{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.punkt-tytul h3{margin:0;font-size:var(--fs-lg)}
.punkt-skrot{font-size:var(--fs-sm);color:var(--ink-2);padding:2px 8px;border:1px solid var(--line);border-radius:6px;background:var(--surface)}
.punkt-fakty{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px 20px;padding:14px 18px}
@media (max-width:1100px){.punkt-fakty{grid-template-columns:repeat(2,minmax(0,1fr))}}
.punkt-fakty > div{display:flex;flex-direction:column;gap:3px;min-width:0;font-size:var(--fs-sm)}
.punkt-fakty > div > span{color:var(--ink-3);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;font-weight:650}
.punkt-fakty em.brak{color:var(--warn);font-style:normal}
.punkt-kod-miasto{display:grid;grid-template-columns:120px minmax(0,1fr);gap:12px}
.punkt-kod-miasto > label{display:flex;flex-direction:column;gap:6px;min-width:0}
.punkt-kod-miasto > label > span{font-weight:600;font-size:var(--fs-sm)}
.bramka-karta.wyszarzony{opacity:.7}
.punkt-fakty p{margin:0;line-height:1.45}
.akcje-karty-firmy{display:flex;align-items:center;flex-wrap:wrap;gap:8px}
/* Ogólnie: przycisk z ikoną w linii tekstu równa się środkiem, nie dołem ikony. */
.btn:has(> .ikona-sok){vertical-align:middle}

/* Okno formularza — dodawanie i edycja w okienku zamiast rozsuwania ekranu (26.09.2026). */
.okienko.okno-formularza{padding:0;display:flex;flex-direction:column;overflow:hidden;max-height:90vh}
.okno-formularza-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
  padding:16px 20px;border-bottom:1px solid var(--line-soft, var(--line));background:var(--surface-2)}
.okno-formularza-hd h3{margin:0;font-size:var(--fs-lg)}
.okno-formularza-pod{color:var(--ink-3);font-size:var(--fs-sm);margin-top:2px}
.okno-formularza-bd{overflow:auto;flex:1 1 auto}
.okno-formularza-bd > .bramka-pola{padding:18px 20px}
.okno-formularza-st{display:flex;flex-wrap:wrap;align-items:center;gap:10px 12px;padding:12px 20px;
  border-top:1px solid var(--line-soft, var(--line));background:var(--surface-2)}

/* Szukajka u góry — lista wyników szersza niż pole (26.09.2026). */
.qs-wyniki{position:fixed;z-index:80;max-height:min(70vh,640px);overflow:auto;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-2)}
.qs-wynik{display:flex;align-items:center;gap:12px;padding:9px 14px;cursor:pointer}
.qs-wynik + .qs-wynik{border-top:1px solid var(--line-soft, var(--line))}
.qs-wynik.on{background:var(--accent-soft)}
.qs-wynik-tekst{flex:1;min-width:0}
.qs-wynik-nazwa{font-weight:650;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.qs-wynik.on .qs-wynik-nazwa{color:var(--accent-text)}
.qs-wynik-pod{color:var(--ink-3);font-size:var(--fs-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:1px}
.qs-wynik .pill{flex:none}
.qs-wiecej{display:block;width:100%;border:0;border-top:1px solid var(--line);background:var(--surface-2);
  padding:9px 14px;font:inherit;font-size:var(--fs-sm);font-weight:600;color:var(--accent-text);cursor:pointer;text-align:left}
.qs-wiecej:hover{background:var(--accent-soft)}
.qs-stan{z-index:80}


/* ===================================================================
   SEKCJE USTAWIEŃ JAKO KARTY (26.09.2026, przegląd ekranów przed
   produkcją). Wzór: Płatności online — pasek z tytułem i opisem, pod
   nim pola. Jedna reguła zamiast przerabiania czterdziestu ekranów:
   każdy, kto używa <Sekcja> w ustawieniach, dostaje ten sam wygląd.
   =================================================================== */
.ust-tresc .sekcja{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  margin:16px 0 0;overflow:hidden}
.ust-tresc .sekcja:first-child{margin-top:0}
.ust-tresc .sekcja > .sekcja-hd{padding:13px 18px;background:var(--surface-2);border-bottom:1px solid var(--line-soft, var(--line))}
.ust-tresc .sekcja.zwinieta > .sekcja-hd{border-bottom:0}
.ust-tresc .sekcja > .sekcja-hd > h3{margin:0;padding:0;border:0;font-size:var(--fs-lg);font-weight:650}
.ust-tresc .sekcja > .sekcja-hd > .sekcja-opis{margin:4px 0 0;max-width:90ch}
.ust-tresc .sekcja > .sekcja-bd{padding:16px 18px}
.ust-tresc .sekcja > .sekcja-bd > .tblwrap:first-child,
.ust-tresc .sekcja > .sekcja-bd > table:first-child{margin-top:0}
.ust-tresc .sekcja .sekcja{border-radius:var(--radius-sm)}

/* Jedno wcięcie treści ustawień (26.09.2026). Ekrany miały każdy swoje:
   jedne po 16 px, drugie po 24, trzecie wcale (Stawki dotykały krawędzi).
   Teraz wcięcie daje ramka, a pudełka ekranów je zerują. */
.ust-cialo{padding:18px 20px 22px}
.ust-cialo > .bramki,.ust-cialo > .bd,.ust-cialo > .ust-blok,.ust-cialo > .st-ekran,
.ust-cialo > .do-ustawienia{padding:0}
.ust-cialo > div[style*="padding"]{padding:0 !important}
.ust-cialo > .card{border:0;box-shadow:none;background:none;padding:0}
.ust-cialo > .card > .bd{padding:0}
.ust-cialo > .ksiegowosc-ekran{padding:0}
.ust-cialo > div > .wyjasnienie:first-child{padding:0 0 14px}

/* Panel edycji w okienku — wcięcie treści i wiersz tabeli, który tylko
   trzyma okienko (bez własnej wysokości). */
.panel-edycji.w-oknie{margin:0;border:0;border-radius:0;box-shadow:none;background:none;padding:16px 20px 18px}
tr.wiersz-okna, tr.wiersz-okna > td{padding:0 !important;border:0 !important;height:0;background:none !important}
.przelacznik .podpis{font-size:var(--fs-sm);color:var(--ink-3);line-height:1.4}
.seria-edycja.w-oknie{padding:16px 20px 18px;display:flex;flex-direction:column;gap:12px;border:0;margin:0;background:none}
.seria-edycja.w-oknie .formrow{margin:0}
.pola-wlasne-edycja.w-oknie{margin:0;display:grid;gap:var(--s4)}
.sla-wybor{align-items:flex-end;gap:var(--s3)}
.sla-wybor-pole{display:flex;flex-direction:column;gap:4px;min-width:260px}
.sla-wybor-pole > span{font-size:var(--fs-sm);font-weight:600;color:var(--ink-2)}
:root .tabela-kolejnosci tbody > tr > td{text-align:left}
:root .tabela-kolejnosci tbody > tr > td:last-child{text-align:right}
:root .tabela-kolejnosci tbody > tr > td.num{text-align:right}
.zbx-wiersz{display:grid;grid-template-columns:minmax(260px,340px) 84px auto auto 1fr;align-items:center;
  gap:6px 10px;padding:10px 0;border-top:1px solid var(--line-soft, var(--line))}
.zbx-wiersz:first-of-type{margin-top:var(--s3)}
.zbx-wiersz > .input.w-min{width:84px}
.zbx-wiersz > .input.sm{width:auto}
@media (max-width:760px){.zbx-wiersz{grid-template-columns:1fr 84px auto}}
.rodzaje-pasek{margin:var(--s4) 0 var(--s3);align-items:center}
.uninet-ust{max-width:1100px}
.uninet-ust .sekcja + .sekcja,.uninet-ust .uninet-zapisz + .sekcja{margin-top:var(--s4)}
.uninet-ust .uninet-zapisz{margin:var(--s4) 0;align-items:center}
.uninet-ust .sekcja-bd > .muted:first-child{margin-top:0}
/* Treść okna formularza ma własny margines — pola wstawione wprost
   (Pole, Ptaszek, tabela) nie mogą przyklejać się do krawędzi okna. */
.okno-formularza-bd{padding:18px 20px;display:flex;flex-direction:column;gap:12px}
.okno-formularza-bd > .bramka-pola,
.okno-formularza-bd > .panel-edycji.w-oknie,
.okno-formularza-bd > .seria-edycja.w-oknie{padding:0}
.okno-formularza-bd > .pole{margin:0}
.rodzaje-pasek > select.input{width:auto;flex:0 0 auto;min-width:200px}
.rodzaje-pasek > .umowy-szukajka{flex:1 1 260px}
/* === Poczta (27.09.2026): jedna karta skrzynki zamiast pięciu sekcji === */
.poczta-ekran{display:flex;flex-direction:column;gap:var(--s4)}
.poczta-ekran > .sekcja{margin:0}
.poczta-pola{grid-template-columns:repeat(4,minmax(0,1fr));padding-bottom:6px}
.poczta-pola .pp-2{grid-column:span 2}
.poczta-blad{margin:12px 18px 0}
.poczta-bezpiecznik{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;
  margin:0 18px 16px;padding-top:14px;border-top:1px dashed var(--line)}
.poczta-omija{display:flex;flex-wrap:wrap;gap:4px 18px}
.poczta-kolejka{font-size:var(--fs-sm);color:var(--ink-2);font-variant-numeric:tabular-nums}
.poczta-kolejka .bad{color:var(--bad)}
.poczta-nieudane{padding:0 18px 14px}
.poczta-nieudane summary{cursor:pointer;font-size:var(--fs-sm);color:var(--ink-2);padding:8px 0}
.poczta-automat{padding:0 0 4px}
.poczta-skrzynki{margin-top:var(--s4)}
.poczta-skrzynki-hd{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px}
.poczta-skrzynki-hd .kolumny-tytul{margin:0}
@media (max-width:900px){.poczta-pola{grid-template-columns:repeat(2,minmax(0,1fr))}
  .poczta-bezpiecznik{grid-template-columns:1fr}}
@media (max-width:560px){.poczta-pola{grid-template-columns:1fr}.poczta-pola .pp-2{grid-column:auto}}
/* Znaczniki szablonów — zwarta siatka (27.09.2026) */
.znaczniki-siatka{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px}
.znaczniki-siatka li{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-width:0;
  padding:6px 8px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface)}
.znaczniki-siatka li.uzyty{background:var(--ok-bg);border-color:var(--ok-border)}
.znaczniki-siatka .znacznik-opis{font-size:var(--fs-xs);color:var(--ink-2);line-height:1.3;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.znaczniki-inne{display:flex;flex-wrap:wrap;gap:6px}
/* Szablony SMS — lista + edytor (27.09.2026) */
.sms-szablony-pasek{margin-bottom:var(--s3);gap:8px}
.sms-poz .sms-poz-znaki{display:flex;flex-wrap:wrap;gap:4px}
.sms-poz .pill{font-size:var(--fs-xs)}
.sms-test{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding-top:var(--s3);border-top:1px dashed var(--line)}
.szablony-lista .sms-poz{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 8px;padding:6px 10px}
.szablony-lista .sms-poz .nazwa{font-weight:550;font-size:var(--fs-sm)}
.sms-kolejnosc{margin:0 0 var(--s3)}
.sms-kolejnosc .jak-link{margin-left:6px}
.szablony-lista .sms-grupa{font-size:var(--fs-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);padding:10px 10px 4px}
.szablony-lista .sms-grupa:first-child{padding-top:4px}
.szablony-lista .sms-grupa.bad{color:var(--bad)}
.szablony-lista .sms-pusto{padding:4px 10px;font-size:var(--fs-sm)}
.szablony-lista .sms-poz.sierota .nazwa{color:var(--bad)}
.sms-poz .plakietka-modulu{font-size:10px}

/* Dziennik zdarzeń (27.09.2026): filtry w jednym rzędzie, tabela gęsta
   i wyrównana do lewej — to lista do czytania, nie do oglądania. */
.dziennik-pasek{display:grid;grid-template-columns:minmax(140px,1fr) 136px 140px 158px 150px auto auto;
  align-items:center;gap:8px;margin-bottom:var(--s3)}
.dziennik-pasek > .input{width:100%;min-width:0;font-size:var(--fs-sm)}
@media (max-width:1100px){.dziennik-pasek{grid-template-columns:1fr 1fr 1fr}
  .dziennik-pasek > input.input{grid-column:1 / -1}}
.dziennik-kasowanie{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;cursor:pointer;
  font-size:var(--fs-sm)}
:root .tabela-dziennika th{text-align:left;cursor:pointer;user-select:none;white-space:nowrap}
:root .tabela-dziennika tbody > tr > td{text-align:left;height:auto;padding-top:7px;padding-bottom:7px;
  vertical-align:middle;line-height:1.35}
.tabela-dziennika .dz-kiedy{white-space:nowrap;color:var(--muted);font-size:var(--fs-sm)}
.tabela-dziennika .dz-wiersz{cursor:pointer}
.tabela-dziennika .dz-wiersz.otwarty > td{background:var(--surface-2,rgba(127,127,127,.06))}
:root .tabela-dziennika tbody > tr > td.dz-strzalka{width:28px;color:var(--muted);text-align:center;font-size:18px;line-height:1}
.tabela-dziennika th:last-child{cursor:default}
:root .tabela-dziennika tr.dz-szczegoly > td{background:var(--surface-2,rgba(127,127,127,.06));
  padding:8px 14px 12px}
.dz-pola{display:grid;grid-template-columns:max-content 1fr;gap:3px 16px;margin:0;font-size:var(--fs-sm)}
.dz-pola dt{color:var(--muted)}
.dz-pola dd{margin:0;word-break:break-word}
.dz-id{margin-top:6px;font-size:var(--fs-xs,12px)}
.tabela-dziennika .dz-strzalka > span{display:inline-block;transition:transform .15s}
.tabela-dziennika .dz-wiersz.otwarty .dz-strzalka > span{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.tabela-dziennika .dz-strzalka > span{transition:none}}

/* Ustawienia → System (27.09.2026): Moduły, Język, Kopia danych — wiersze
   zamiast kart z nagłówkami, opisy w jednym zdaniu. */
.moduly-lista{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:var(--r-md,10px);overflow:hidden}
.modul-wiersz{display:grid;grid-template-columns:1fr auto auto;gap:6px 18px;align-items:center;padding:12px 16px}
.modul-wiersz + .modul-wiersz{border-top:1px solid var(--line)}
.modul-wiersz.wylaczony .modul-opis{opacity:.7}
.modul-nazwa{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:2px}
.modul-kiedy{white-space:nowrap;text-align:right}
.modul-akcje{display:flex;gap:6px;justify-content:flex-end}
.moduly-stopka{margin-top:10px;line-height:1.6}
.moduly-odcisk{font-size:var(--fs-sm);padding:1px 6px;border-radius:4px;background:var(--surface-2,rgba(127,127,127,.08))}
@media (max-width:760px){.modul-wiersz{grid-template-columns:1fr}.modul-kiedy{text-align:left}.modul-akcje{justify-content:flex-start}}
.jezyk-wiersz{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.jezyk-wiersz > select.input{width:260px;max-width:100%}
.kopia-wiersz{display:grid;grid-template-columns:1fr auto;gap:8px 18px;align-items:center;padding:12px 16px;
  border:1px solid var(--line);border-radius:var(--r-md,10px)}
.kopia-wiersz .mini{margin-top:2px;max-width:70ch}
.kopia-auto-glowa{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:var(--s4) 0 var(--s2)}
@media (max-width:760px){.kopia-wiersz{grid-template-columns:1fr}}
.kopie-lista{border:1px solid var(--line);border-radius:var(--r-md,10px)}
.kopia-poz{display:flex;align-items:center;justify-content:space-between;gap:8px 16px;flex-wrap:wrap;padding:10px 16px}
.kopia-poz + .kopia-poz{border-top:1px solid var(--line)}

/* Nasza firma i logo — zwarte (27.09.2026) */
.logo-wiersz{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.logo-miniatura{height:40px;min-width:120px;max-width:220px;padding:4px 10px;display:flex;align-items:center;
  justify-content:center;border:1px solid var(--line);border-radius:var(--radius-sm,6px);background:var(--surface-2)}
.logo-miniatura img{max-height:32px;max-width:200px;object-fit:contain}
.kolor-firmy{display:flex;align-items:center;gap:10px 14px;flex-wrap:wrap}
.kolor-probki{display:flex;gap:6px;flex-wrap:wrap}
.kolor-probka{width:26px;height:26px;border-radius:6px;cursor:pointer;border:1px solid var(--line);padding:0}
.kolor-probka[aria-pressed="true"]{outline:2px solid var(--ink);outline-offset:2px}
.kolor-firmy input[type=range]{flex:1 1 160px;min-width:140px;max-width:280px}
.kolor-nazwa{display:inline-flex;align-items:center;gap:6px;min-width:110px}
.kolor-kropka{width:12px;height:12px;border-radius:3px;display:inline-block}

/* Asystent AI w zakładkach (27.09.2026) */
.ai-ekran{display:flex;flex-direction:column;gap:var(--s3)}
.ai-ekran > .zakladki{margin-bottom:0}
.ai-ekran .ai-uwaga{margin:0;font-size:var(--fs-sm)}
.ai-opis-krotki{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;max-width:70ch}
.ai-uzycia .ai-uzycie{align-items:center;padding-top:8px;padding-bottom:8px}
.ai-model-pola{padding:8px 0 !important}
.ai-czat-wiersz{display:grid;grid-template-columns:1fr 1fr auto;gap:12px;align-items:end}
.ai-dane{margin-top:var(--s2)}
.ai-wynik{max-width:360px}
.ai-wynik > span{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
@media (max-width:760px){.ai-czat-wiersz{grid-template-columns:1fr}}
.bramka-gdzie{grid-column:1 / -1;font-size:var(--fs-xs,12px);line-height:1.45;margin-top:-4px}
.bramka-stopka .ptaszek{margin:0}
.bramka-adres code{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  padding:8px 10px;border:1px solid var(--line);border-radius:var(--radius-sm,6px);font-size:var(--fs-sm)}

/* Kalendarz Google (27.09.2026) */
.kal-wstep{padding:12px 18px 4px;display:flex;flex-direction:column;gap:8px}
.kal-wstep .kroki-lista{margin:0}
.kal-wiersz{display:flex;align-items:center;justify-content:space-between;gap:10px 18px;flex-wrap:wrap;padding:12px 18px}
.kal-lista{display:flex;flex-direction:column}
.kal-poz{display:flex;align-items:center;justify-content:space-between;gap:8px 16px;flex-wrap:wrap;padding:7px 18px;
  border-top:1px solid var(--line-soft,var(--line))}
.kal-poz:first-child{border-top:0}
.kal-poz.wybrany{background:var(--surface-2)}
.kal-nazwa{display:flex;align-items:center;gap:8px;cursor:pointer;min-width:0}
.kal-poz select.input{width:auto;min-width:220px}

/* Formularz na stronie w zakładkach (27.09.2026) */
.formularz-www{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s4)}
.formularz-www > .zakladki{margin-bottom:0}
.formularz-www h4:first-child{margin-top:0 !important}

/* Zasady modułu napraw — wiersze (27.09.2026) */
.zasady-ekran{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s4)}
.zasady-lista{border:1px solid var(--line);border-radius:var(--r-md,10px)}
.zasada{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 20px;align-items:center;padding:12px 16px}
.zasada + .zasada{border-top:1px solid var(--line)}
.zasada-opis .mini{margin-top:2px;max-width:72ch}
.zasada-ster{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.zasada-ster .ptaszek{margin:0;white-space:nowrap}
.zasada-ster select.input{width:auto}
.zasada-pole{display:flex;flex-direction:column;gap:2px;font-size:var(--fs-xs,12px);color:var(--ink-3)}
.zasada-pole .input{width:90px}
.zasada-pole.szersze .input{width:150px}
@media (max-width:900px){.zasada{grid-template-columns:1fr}.zasada-ster{justify-content:flex-start}}

/* Alarmy w tabeli (27.09.2026) */
.tabela-alarmow td{vertical-align:middle}
.tabela-alarmow tr.wylaczona td{opacity:.6}
.tabela-alarmow .alarm-grupa-wiersz td{background:var(--surface-2);font-size:var(--fs-xs,12px);font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;color:var(--ink-2);padding-top:5px !important;padding-bottom:5px !important}
.alarm-nazwa{display:flex;align-items:flex-start;gap:8px;cursor:pointer;min-width:240px}
.alarm-nazwa > span{display:flex;flex-direction:column;min-width:0}
.alarm-nazwa input{margin-top:3px}
.alarm-liczba{width:68px !important;display:inline-block}
.tabela-alarmow .nowrap{white-space:nowrap}
.porzadek-czysto{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 0;border-top:1px solid var(--line-soft,var(--line))}
.widgety-dodaj{display:flex;flex-wrap:wrap;gap:6px}
.tabela-alarmow select.input{min-width:118px;width:auto}
.tabela-alarmow .alarm-nazwa{min-width:280px}

/* MIKS — znak czatu zespołu (27.09.2026), jak PAKT/PULPA */
.cz-marka{display:flex;align-items:center;gap:10px;padding:12px 14px 4px}
.cz-marka img{width:40px;height:40px;display:block;flex:none}
.cz-marka-slowo{font-family:'Fredoka',system-ui,sans-serif;font-weight:700;font-size:22px;line-height:1;
  color:var(--ananas-slowo);letter-spacing:.05em}
.cz-marka-rozw{font-size:11.5px;line-height:1.3;color:var(--ink-2);margin-top:2px}
.cz-marka-rozw span{color:var(--ananas-litera);font-weight:800}
.cz-okno-miks{font-family:'Fredoka',system-ui,sans-serif;letter-spacing:.05em;color:var(--ananas-slowo)}
.cz-okno-miks span{font-family:var(--font);font-weight:500;letter-spacing:0;font-size:12px;color:var(--ink-2);margin-left:4px}

/* Godziny pracy przy koncie (migracja 317) */
.godziny-pracy { display: grid; gap: 6px; margin-top: 10px; max-width: 460px; }
.gp-wiersz { display: grid; grid-template-columns: 200px 1fr; align-items: center; gap: 12px; min-height: 36px; }
.gp-wiersz.wolne .gp-dzien { color: var(--ink-2); }
.gp-dzien { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.gp-zakres { display: inline-flex; align-items: center; gap: 8px; }
.gp-zakres .input { width: 96px; }

/* Licencja z panelu (migracja 318) */
.licencja-karta { margin-bottom: 14px; }
.licencja-karta .hd { display: flex; align-items: center; gap: 10px; }
.licencja-karta .hd .rozpychacz { margin-left: auto; }
.licencja-liczby { display: flex; gap: 40px; padding: 12px 20px 6px; font-variant-numeric: tabular-nums; }
.licencja-karta > .muted.mini { padding: 0 20px 14px; }
.licencja-liczby strong { font-size: 18px; }

/* Mapa sieci — firmy z mapą zamiast pustego ekranu (27.09.2026) */
.mapa-firmy { padding: 16px 20px 20px; }
.mapa-firmy > p { margin: 0 0 12px; }
.mapa-firmy-lista { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; }
.mapa-firma { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; text-align: left;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); cursor: pointer; }
.mapa-firma:hover { border-color: var(--accent); background: var(--surface-2); }
.mapa-firma:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mapa-firma-nazwa { font-weight: 600; }

/* Wersja pokazowa — ustawienia tylko do obejrzenia (27.09.2026) */
.demo-ustawienia { margin: var(--s3) var(--s4) 0; border-left-color: var(--accent); background: var(--surface-2); }

/* Akcje w ostatniej kolumnie listy — wyrównane do prawej (27.09.2026) */
td.akcje-wiersza { white-space: nowrap; text-align: right; width: 1%; }
td.akcje-wiersza > span { display: inline-flex; gap: 6px; justify-content: flex-end; }
/* UMOWA W OKNIE (27.09.2026) — szczegóły, co dalej, poprawka, anulowanie. */
.umowa-szczegoly{display:grid;grid-template-columns:minmax(130px,max-content) 1fr;gap:6px 18px;margin:0 0 var(--s4)}
.umowa-wiersz{display:contents}
.umowa-wiersz dt{color:var(--ink-3);font-size:var(--fs-sm);padding-top:1px}
.umowa-wiersz dd{margin:0;overflow-wrap:anywhere}
.umowa-dalej{border-top:1px solid var(--line);padding-top:var(--s3);display:flex;flex-direction:column;gap:6px}
.umowa-dalej .pasek-akcji{margin:0}
.umowa-dalej-l{min-width:80px;font-size:var(--fs-sm);color:var(--ink-3);text-transform:uppercase;letter-spacing:.04em}
.umowa-skutki{margin:0 0 var(--s3);padding-left:18px;font-size:var(--fs-sm);color:var(--ink-2)}
@media (max-width:560px){.umowa-szczegoly{grid-template-columns:1fr;gap:2px}.umowa-wiersz dd{margin-bottom:6px}}
.okienko.okno-formularza.bardzo-szerokie{width:min(1180px,96vw)}
/* Kolumna „Co" w monitoringu i wykryciach (27.09.2026) — wszystko od lewej. */
.kolumna-co{min-width:260px}
.kolumna-co .co-tytul{font-weight:560;line-height:1.35}
.kolumna-co .ai-skrot{max-width:60ch;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.kolumna-co .co-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:6px;font-size:var(--fs-xs)}
.kolumna-co .co-meta .cytat{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:40ch}
.kolumna-co .wykrycie-slad{text-align:left}
/* RAPORTY I EKSPORT (27.09.2026) — ustawienia w panelu po lewej, wynik obok. */
.raporty-uklad{display:grid;grid-template-columns:minmax(300px,380px) minmax(0,1fr);gap:var(--s4);
  padding:var(--s4);align-items:start}
.raporty-panel{display:flex;flex-direction:column;gap:var(--s4);position:sticky;top:12px;
  max-height:calc(100vh - 24px);overflow:auto;padding-right:4px}
.raporty-panel section{display:flex;flex-direction:column;gap:8px}
.raporty-panel h4{margin:0;font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);
  display:flex;align-items:baseline;gap:8px}
.raporty-panel h4 .jak-link{margin-left:auto;text-transform:none;letter-spacing:0;font-size:var(--fs-xs)}
.raporty-zestawy{display:flex;flex-direction:column;gap:6px}
.raporty-zestaw{display:flex;flex-direction:column;gap:2px;text-align:left;padding:8px 10px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);color:inherit;cursor:pointer;font:inherit}
.raporty-zestaw:hover{border-color:var(--accent)}
.raporty-zestaw.on{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}
.raporty-zestaw .nazwa{font-weight:620;font-size:var(--fs-sm)}
.raporty-zestaw .opis{font-size:var(--fs-xs);color:var(--ink-3);line-height:1.35}
.raporty-filtry{display:grid;grid-template-columns:1fr 1fr;gap:8px 10px}
.raporty-filtry .pole{min-width:0}
.raporty-chipy{display:flex;flex-wrap:wrap;gap:6px}
.raporty-chip{border:1px solid var(--line);background:var(--surface);color:var(--ink-2);border-radius:999px;
  padding:4px 10px;font:inherit;font-size:var(--fs-xs);cursor:pointer;line-height:1.3}
.raporty-chip:hover{border-color:var(--accent)}
.raporty-chip.on{background:var(--accent-soft, var(--surface-2));border-color:var(--accent);color:var(--ink);font-weight:600}
.raporty-chip:focus-visible,.raporty-zestaw:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.raporty-grupa{border-top:1px solid var(--line);padding-top:6px}
.raporty-grupa summary{cursor:pointer;font-size:var(--fs-sm);font-weight:600;padding:2px 0 6px}
.raporty-grupa summary .muted{font-weight:400;font-size:var(--fs-xs)}
.raporty-wynik{min-width:0;display:flex;flex-direction:column;gap:var(--s3)}
.raporty-wynik-hd{display:flex;align-items:center;gap:10px;flex-wrap:wrap;position:sticky;top:0;z-index:2;
  background:var(--surface);padding:6px 0;border-bottom:1px solid var(--line)}
.raporty-tytul{max-width:300px;font-weight:600}
.raporty-licznik{font-size:var(--fs-sm);white-space:nowrap}
.raporty-tabela.liczy{opacity:.55;transition:opacity .15s}
.raporty-tabela td.raporty-lp,.raporty-tabela th.raporty-lp{width:1%;white-space:nowrap}
.raporty-iframe{width:100%;height:68vh;border:1px solid var(--line);border-radius:var(--radius);background:#fff}
@media (max-width:1100px){
  .raporty-uklad{grid-template-columns:1fr}
  .raporty-panel{position:static;max-height:none}
}

/* Monitoring Zabbix — akcje w samym wierszu (27.09.2026), bez zaznaczania. */
/* 29.09.2026: jeden przycisk z następnym krokiem + „Więcej" — równa
   prawa krawędź i jedna linia w każdym wierszu (monitoring.tsx,
   AkcjeWystapienia). */
td .wiersz-akcje{display:flex;gap:6px;justify-content:flex-end;align-items:center;flex-wrap:nowrap;margin-left:auto}
td .wiersz-akcje .btn.sm{height:32px;padding:0 12px;white-space:nowrap}
td .wiersz-akcje .akcja-glowna{min-width:108px}
td .wiersz-akcje .akcja-wiecej{width:32px;padding:0;color:var(--ink-2)}
td .wiersz-akcje .akcja-wiecej[aria-expanded="true"]{border-color:var(--ink-3);background:var(--surface-2, var(--line))}
.akcje-menu{position:fixed;z-index:60;min-width:240px;padding:4px;display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 8px 28px rgba(15,23,42,.14),0 2px 6px rgba(15,23,42,.08);text-align:left}
.akcje-menu button{display:flex;flex-direction:column;align-items:flex-start;gap:1px;width:100%;
  padding:8px 10px;border:0;border-radius:calc(var(--radius) - 2px);background:transparent;
  font:inherit;color:var(--ink);cursor:pointer;text-align:left}
.akcje-menu button:hover,.akcje-menu button:focus-visible{background:var(--surface-2, rgba(15,23,42,.05));outline:none}
.akcje-menu-slowo{font-weight:600;font-size:var(--fs-sm)}
.akcje-menu-opis{font-size:var(--fs-xs);color:var(--ink-3)}
@media (prefers-reduced-motion:no-preference){
  .akcje-menu{animation:akcje-menu-wejscie .14s ease-out}
  @keyframes akcje-menu-wejscie{from{opacity:0;transform:translateY(-4px)}}
}

/* Telefon — stoper, czas pracy i zadania na karcie zlecenia (27.09.2026). */
.mob-stoper{display:flex;flex-direction:column;gap:10px}
.mob-stoper.leci{border-color:var(--ok-border, var(--line));box-shadow:inset 3px 0 0 var(--ok-solid)}
.mob-zegar{display:flex;align-items:center;gap:10px;line-height:1.1;font-variant-numeric:tabular-nums}
.mob-zegar .mono{font-size:34px;font-weight:700}
.mob-zegar .mob-maly{font-size:var(--fs-sm);font-weight:500}
.mob-zegar-kropka{width:12px;height:12px;border-radius:50%;background:var(--ok-solid);flex:none;
  animation:mob-puls 1.6s ease-in-out infinite}
@keyframes mob-puls{50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.mob-zegar-kropka{animation:none}}
.mob-rodzaje{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.mob-rodzaj{min-height:44px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  color:var(--ink);font:inherit;font-size:var(--fs-sm);cursor:pointer}
.mob-rodzaj.on{border-color:var(--ink);background:var(--ink);color:var(--surface);font-weight:600}
.mob-czasy{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm)}
.mob-czasy li{display:flex;gap:10px;align-items:baseline;padding:4px 0;border-top:1px solid var(--line-soft)}
.mob-czasy li .mono{min-width:64px;font-weight:600}
.mob-zadania{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.mob-zadanie{min-height:44px;align-items:center}
.mob-zadanie.zrobione span{text-decoration:line-through;color:var(--ink-3)}

/* Telefon — szybki serwis (27.09.2026). */
.mob-szybki{display:flex;flex-direction:column;gap:10px}
.mob-szybki-leci{flex-wrap:wrap;gap:8px}
.mob-szybki-firma{flex-basis:100%;font-size:var(--fs-sm);font-weight:500;opacity:.9}
.mob-zegar-kropka.jasna{background:currentColor;width:10px;height:10px}
.mob-szybki-wybrana{display:flex;gap:12px;align-items:baseline;min-height:44px;align-items:center}
.mob-szybki-firmy{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.mob-szybki-firma{min-height:48px;text-align:left;padding:8px 12px;background:var(--surface);border:0;
  border-top:1px solid var(--line-soft);font:inherit;color:var(--ink);cursor:pointer}
.mob-szybki-firma:first-child{border-top:0}
.mob-rodzaje.trzy{grid-template-columns:repeat(3,1fr)}

/* Telefon — czynności, sprzęt zabrany, protokół (27.09.2026). */
.mob-dopisz{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.mob-sprzet{display:flex;flex-direction:column;gap:6px;padding:8px 0;border-top:1px solid var(--line-soft)}
.mob-blok .podpis-osadzony{display:flex;flex-direction:column;gap:8px}

.btn.na-mobilny{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;margin:4px 12px 10px;white-space:nowrap}
.btn.na-mobilny svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.5}

/* Kalendarz — kto dostępny w wybranym dniu i w tygodniu (27.09.2026). */
.kal-sprawdz{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--ink-2)}
.kal-sprawdz .input{width:auto}
.kal-tydzien{margin-bottom:var(--s3)}
.kal-tydz-tab{width:100%;border-collapse:collapse;font-size:var(--fs-sm);table-layout:fixed;min-width:760px}
.kal-tydz-tab th:first-child{width:170px}
.kal-tydz-tab th{text-align:left;font-weight:600;padding:4px 6px;white-space:nowrap}
.kal-tydz-tab th .dz{text-transform:capitalize;color:var(--ink-2)}
.kal-tydz-tab th.dzis{color:var(--accent)}
.kal-tydz-tab td{padding:3px;vertical-align:top;border-top:1px solid var(--line-soft)}
.kal-tydz-tab td.kto{padding:6px;font-weight:600;overflow-wrap:anywhere}
.kal-tydz-kom{display:flex;flex-direction:column;gap:2px;width:100%;min-height:34px;text-align:left;font:inherit;
  font-size:var(--fs-xs);line-height:1.3;padding:5px 7px;border-radius:var(--radius-sm);cursor:pointer;
  border:1px solid var(--line);border-left:3px solid var(--ok);background:var(--surface);color:var(--ink)}
.kal-tydz-kom:hover{border-color:var(--ink-3)}
.kal-tydz-kom.pelno{border-left-color:var(--warn)}
.kal-tydz-kom.nie{border-left-color:var(--line);background:var(--surface-2);color:var(--ink-3)}
.kal-tydz-kom.brak{border-left-color:var(--line);color:var(--ink-3)}
.kal-tydz-kom .wn{color:var(--warn)}

/* Przyjęcie — serwisant niedostępny w dniu terminu (27.09.2026). */
.termin-konflikt{display:flex;flex-direction:column;gap:8px;margin-top:var(--s2)}
.termin-wyjscia{display:flex;flex-wrap:wrap;gap:6px}
.termin-zostawiam{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm)}

/* KASA — ciaśniej (27.09.2026). Łukasz: „kafel po lewej w połowie pusty;
   pozycje z kasy mają być widoczne na laptopie bez przewijania". */
.kasa-hd{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;padding-top:10px;padding-bottom:0}
.kasa-hd .kasa-marka{padding:0;margin-right:auto}
.kasa-hd .kasa-marka img{width:40px;height:40px}
.kasa-hd .pakt-slowo{font-size:22px}
.kasa-hd .zakladki{margin:0}
.kasa-punkt{display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-sm);color:var(--ink-2);
  margin:0 0 var(--s3)}
.kasa-punkt .input{width:auto;min-width:180px}
.kasa-gora{align-items:stretch}
.kasa-gora .kasa-baner{padding:var(--s3) var(--s4)}
.kasa-baner-v{font-size:calc(var(--fs-2xl) * 1.25)}
.kasa-baner-d{margin-top:2px}
.kasa-rachunek{margin:var(--s3) 0 0;padding-top:0;gap:4px}
.kasa-rachunek .wynik{padding-top:6px}
.kasa-utarg{padding:var(--s3) var(--s4);gap:10px}
.kasa-wykres{grid-template-rows:118px auto}
.kasa-skad{padding-top:8px;gap:4px}
/* Kafle: wartość i linia trendu obok siebie, porównanie pod spodem. */
.kasa-kpi{margin-bottom:var(--s3)}
.kpi.kasa-kafel{display:grid;grid-template-columns:auto minmax(70px,1fr);
  grid-template-areas:"l l" "v t" "o t" "d d";column-gap:16px;padding:10px 16px}
.kasa-kafel .l{grid-area:l}
.kasa-kafel .v{grid-area:v;margin-top:2px;font-size:var(--fs-xl, 22px)}
.kasa-kafel .kasa-kafel-opis{grid-area:o}
.kasa-kafel .kpi-trend{grid-area:t;align-self:center;margin:0;padding:0;height:34px}
.kasa-kafel .d{grid-area:d;margin-top:4px}
/* Trzy kolumny u góry: szuflada | kafle 2×2 | utarg. Tabela operacji
   wchodzi wtedy na pierwszy ekran laptopa. */
.kasa-gora{grid-template-columns:minmax(250px,3fr) minmax(0,4fr) minmax(0,5fr);margin-bottom:var(--s3)}
.kasa-gora .kasa-kpi{grid-template-columns:repeat(2,minmax(0,1fr));margin:0;gap:var(--s2)}
.kasa-gora .kpi.kasa-kafel{padding:8px 12px;grid-template-columns:auto minmax(40px,1fr);column-gap:10px}
.kasa-gora .kasa-kafel .l{font-size:var(--fs-xs)}
.kasa-gora .kasa-kafel .v{font-size:var(--fs-lg)}
.kasa-gora .kasa-kafel .kpi-trend{height:28px}
.kasa-gora .kasa-kafel .d{font-size:var(--fs-xs)}
.kasa-gora .kasa-wykres{grid-template-rows:100px auto}
/* Laptop: szuflada po lewej na całą wysokość, po prawej utarg, a pod nim
   kafle w jednym rzędzie — bez pustego miejsca pod rachunkiem szuflady. */
@media (max-width:1650px){
  .kasa-gora{grid-template-columns:minmax(270px,1fr) minmax(0,2.5fr);
    grid-template-areas:"b u" "b k"}
  .kasa-gora .kasa-baner{grid-area:b}
  .kasa-gora .kasa-utarg{grid-area:u}
  .kasa-gora .kasa-kpi{grid-area:k;grid-template-columns:repeat(4,minmax(0,1fr))}
  .kasa-gora .kasa-kafel .kasa-kafel-opis{display:none}
  .kasa-gora .kasa-kafel{grid-template-areas:"l l" "v t" "d d"}
  .kasa-gora .kasa-wykres{grid-template-rows:90px auto}
}
@media (max-width:1100px){
  .kasa-gora{grid-template-columns:1fr;grid-template-areas:"b" "k" "u"}
  .kasa-gora .kasa-kpi{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* „Skąd przyszły" w kafelku szuflady — węższa siatka. */
.kasa-baner .kasa-skad{margin-top:var(--s3);border-top:1px solid var(--line);padding-top:8px}
.kasa-baner .kasa-skad-w{grid-template-columns:minmax(0,1fr) 60px auto auto;gap:8px;font-size:var(--fs-xs)}
.kasa-baner .kasa-skad-w .o{min-width:0}
.kasa-rachunek dt{white-space:normal}
.kasa-hd .kasa-marka img{width:34px;height:34px}
/* Kafle na laptopie: jedna linijka etykiety i jedna linijka porównania. */
@media (max-width:1650px){
  .kasa-gora{grid-template-columns:minmax(300px,1fr) minmax(0,2.3fr)}
  .kasa-gora .kasa-kafel .l,.kasa-gora .kasa-kafel .d{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kasa-gora .kasa-kafel .v{font-size:var(--fs-md, 17px)}
  .kasa-gora .kasa-kafel .kpi-trend{height:24px}
  .kasa-gora .kasa-wykres{grid-template-rows:80px auto}
}
.kasa-gora .kasa-baner-d{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kasa-gora .kasa-utarg{justify-content:space-between}
/* Wykres wypełnia wysokość kafla — bez dziury między legendą a słupkami. */
.kasa-gora .kasa-utarg{justify-content:flex-start}
.kasa-gora .kasa-utarg .kasa-wykres{flex:1 1 auto;grid-template-rows:minmax(80px,1fr) auto}

/* Kasa — odstęp wyboru punktu od ramki (27.09.2026). */
.kasa-punkt{margin:var(--s3) var(--s4)}
/* Historia i punkty — kafle punktów jak na dniu kasowym. */
.kasa-punkty{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--s3);
  padding:var(--s3) var(--s4) 0;margin-bottom:var(--s3)}
.kasa-punkt-kafel{display:flex;flex-direction:column;gap:6px;text-align:left;font:inherit;color:var(--ink);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-1);padding:12px 16px;cursor:pointer;min-width:0}
.kasa-punkt-kafel:hover{border-color:var(--ink-3)}
.kasa-punkt-kafel.wybrany{border-color:var(--accent);box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 30%,transparent)}
.kasa-punkt-kafel.pusty{background:var(--surface-2)}
.kasa-punkt-kafel .gora{display:flex;justify-content:space-between;align-items:center;gap:8px}
.kasa-punkt-kafel .n{font-size:var(--fs-sm);font-weight:700;text-transform:uppercase;letter-spacing:.04em}
.kasa-punkt-kafel .srodek{display:grid;grid-template-columns:auto minmax(60px,1fr);align-items:center;gap:14px}
.kasa-punkt-kafel .v{font-size:var(--fs-xl);font-weight:680;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.kasa-punkt-kafel .kpi-trend{display:block;width:100%;height:30px;color:var(--seria-2)}
.kasa-punkt-kafel .dol{font-size:var(--fs-xs);color:var(--ink-3)}
.kasa-punkt-kafel .zle{color:var(--bad);font-weight:600}
.kasa-punkt-kafel .kpi-trend .krzywa{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round}
.kasa-punkt-kafel .kpi-trend .pole{fill:currentColor;opacity:.12}

/* MONITORING ZABBIX — ciaśniej (27.09.2026). */
.card > .hd.mon-zakladki{padding-top:6px;padding-bottom:0}
.mon-pasek .row{flex-wrap:wrap;gap:8px;align-items:center}
.mon-pasek .mon-szukaj{width:240px;max-width:100%}
.mon-pasek .mon-firma{max-width:260px}
.mon-pasek select.input.sm{width:auto}
.mon-ile{font-size:var(--fs-sm);white-space:nowrap}
.btn.sm.mon-info{width:30px;padding:0;justify-content:center;border-radius:50%;font-weight:700}
.rap-ust{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}
.rap-pole{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);white-space:nowrap}
.rap-godziny{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm)}
.rap-godziny .input.sm{width:96px}
.rap-maile{width:260px;max-width:100%}

/* DZIŚ W PUNKCIE — jeden rząd: tytuł z boku, ludzie obok, mniejsze kartki. */
@media (min-width:761px){
  .dzis-w-punkcie{display:flex;align-items:stretch}
  .dzis-w-punkcie > .hd{flex:0 0 auto;flex-direction:column;align-items:flex-start;justify-content:center;
    gap:4px;border-bottom:0;border-right:1px solid var(--line-soft);padding:8px 16px;min-width:170px}
  .dzis-w-punkcie > .hd h3{margin:0;font-size:var(--fs-md, 16px)}
  .dzis-w-punkcie .hd .btn{margin-left:0;margin-top:2px}
  .dzis-w-punkcie .dzis-lista{flex:1;padding:8px 12px;gap:8px;grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
}
.dzis-osoba{padding:5px 8px;gap:9px}
.dzis-twarz{flex:0 0 34px;width:34px;height:34px}
.dzis-kropka{width:11px;height:11px}
.dzis-opis{line-height:1.2}
.dzis-imie{font-size:var(--fs-sm)}
.dzis-stan,.dzis-naprawy{font-size:var(--fs-xs)}
.dzis-w-punkcie{margin:0 0 var(--s3)}
.filters.rap-ust{flex-direction:row;align-items:center}
.mon-pasek select.input{min-width:0}
.rap-godziny .input.sm{width:112px}
.mon-pasek .mon-szukaj{width:200px}
.mon-pasek .mon-firma{max-width:200px}
.rap-godziny .input.sm{width:104px}
.rap-maile{width:220px}
.rap-ust{gap:8px 12px}

/* PAKT — lista w grupach, numer z datą w jednej linijce (27.09.2026). */
.dok-lista{flex-basis:320px}
.dok-grupa{display:flex;flex-direction:column;gap:2px}
.dok-grupa + .dok-grupa{margin-top:8px}
.dok-grupa-hd{display:flex;align-items:center;gap:6px;width:100%;padding:6px 8px;border:0;border-radius:var(--radius-sm);
  background:var(--surface-2);font:inherit;font-size:var(--fs-xs);font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-2);cursor:pointer;position:sticky;top:0;z-index:1}
.dok-grupa-hd .strzalka{width:12px;color:var(--ink-3)}
.dok-grupa-hd .ile{margin-left:auto;font-weight:600;color:var(--ink-3)}
.dok-pierwsza{display:flex;align-items:baseline;gap:6px}
.dok-data{margin-left:auto;font-size:var(--fs-xs);color:var(--ink-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.dok-stan{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:0 5px;border-radius:4px}
.dok-stan.szkic{background:var(--warn-bg);color:var(--warn)}
.dok-stan.anul{background:var(--surface-2);color:var(--ink-3)}
.dok-pozycja.anulowany .dok-tytul{text-decoration:line-through;color:var(--ink-3)}

/* PAKT — lista na całą szerokość, dokument w dużym oknie (27.09.2026). */
.pakt-hd{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;padding-top:10px;padding-bottom:0}
.pakt-hd .pakt-marka{padding:0;margin-right:auto}
.pakt-hd .pakt-marka img{width:36px;height:36px}
.pakt-hd .pakt-slowo{font-size:22px}
.pakt-zakladki{margin:0}
.pakt-zakladki .ile{display:inline-block;min-width:20px;margin-left:4px;padding:0 6px;border-radius:10px;
  background:var(--surface-2);color:var(--ink-3);font-size:var(--fs-xs);font-weight:650}
.pakt-zakladki button.on .ile{background:color-mix(in srgb,var(--accent) 15%,transparent);color:var(--accent-text, var(--accent))}
.th-sort{all:unset;cursor:pointer;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit}
.th-sort:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pakt-tab tr.klik{cursor:pointer}
.pakt-tab tr.klik:hover td{background:var(--surface-2)}
.pakt-tab tr.klik:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--accent)}
.pakt-tab .pakt-tytul{font-weight:600;max-width:420px}
.pakt-tab tr.pakt-anulowany .pakt-tytul{text-decoration:line-through;color:var(--ink-3)}
.pakt-rodzaj{display:inline-block;font-size:var(--fs-xs);font-weight:650;padding:2px 8px;border-radius:10px;
  border:1px solid var(--line);white-space:nowrap}
.pakt-rodzaj.r-wycena{border-color:color-mix(in srgb,var(--seria-1) 45%,var(--line));color:var(--seria-1)}
.pakt-rodzaj.r-protokol{border-color:color-mix(in srgb,var(--seria-2) 45%,var(--line));color:var(--seria-2)}
.pakt-rodzaj.r-opinia{color:var(--ink-2)}
.okienko.dok-okno{width:min(1400px,96vw);height:92vh;max-height:92vh;padding:0;display:flex;flex-direction:column;overflow:hidden}
.dok-okno-hd{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:10px var(--s5);border-bottom:1px solid var(--line);font-size:var(--fs-sm)}
.dok-okno-bd{flex:1;overflow:auto;padding:var(--s4) var(--s5)}
:root .pakt-tab thead > tr > th,:root .pakt-tab tbody > tr > td{text-align:left;padding-top:10px;padding-bottom:10px}
:root .pakt-tab tbody > tr > td.num,:root .pakt-tab thead > tr > th.num{text-align:right}
.pakt-tab{font-size:var(--fs-sm)}
.pakt-tab .pakt-tytul{max-width:none;min-width:260px}
.pakt-tab td:nth-child(5){min-width:200px}

/* Telefon — „Nawiguj" innym kolorem niż telefon (27.09.2026). */
.btn.mob-nawiguj{background:var(--seria-1);border-color:var(--seria-1);color:#fff}
/* Kontakt na telefonie: wyśrodkowany, „Nawiguj" biały tekst na niebieskim (27.09.2026). */
.mob-kontakt .btn{justify-content:center;text-align:center}
.mob-kontakt a.btn.mob-nawiguj,.mob-kontakt a.btn.mob-nawiguj:visited,.mob-kontakt a.btn.mob-nawiguj:hover{
  background:var(--seria-1);border-color:var(--seria-1);color:#fff}
.mob-kontakt a.btn.mob-nawiguj *{color:inherit}
/* Motyw ANANAS przestawia kolor tekstu wszystkim „zwykłym" przyciskom
   (reguła z sześcioma :not() — nie do przebicia zwykłą specyficznością). */
.mob-kontakt a.btn.mob-nawiguj{color:#fff !important;background:var(--seria-1) !important;border-color:var(--seria-1) !important}
:root[data-theme="ananas"] .mob-kontakt a.btn.mob-nawiguj{background:#1f6fd1 !important;border-color:#1a63bd !important}

/* Telefon — dojazd z „Nawiguj" (27.09.2026). */
.mob-dojazd{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border-radius:var(--radius);
  background:color-mix(in srgb,var(--seria-1) 8%,var(--surface));border:1px solid color-mix(in srgb,var(--seria-1) 25%,var(--line))}
.mob-dojazd-hd{font-weight:650;font-size:var(--fs-sm)}
.mob-kontakt > .mob-maly.muted{text-align:center;margin-top:-2px}

/* =====================================================================
   TELEFON — STONOWANA KOLORYSTYKA (27.09.2026)
   Łukasz: „kolory w apce mobilnej… nawiguj, biorę, stoper… pójdźmy
   w bardziej pro kolorystykę — na stronie wygląda jak zabawka".
   Jedna barwa akcji (granat) na wszystkie główne przyciski, reszta
   obrysowana. Żółć i zieleń tylko w drobnych znakach stanu.
   !important, bo motyw ANANAS przestawia kolory przyciskom regułą
   z łańcuchem :not(), której zwykła specyficzność nie przebije.
   ===================================================================== */
.mob{--mob-akcja:#15294a;--mob-akcja-hover:#1d375f;--mob-akcja-ink:#fff;
  --mob-drugi-bg:var(--surface);--mob-drugi-ink:#15294a;--mob-drugi-line:#cdd5e0;--mob-drugi-hover:#f2f5f9;
  --mob-zle:#b3261e}
:root[data-theme="dark"] .mob{--mob-akcja:#d6e0ee;--mob-akcja-hover:#e6edf6;--mob-akcja-ink:#0f1c30;
  --mob-drugi-bg:transparent;--mob-drugi-ink:#d6e0ee;--mob-drugi-line:#3a4658;--mob-drugi-hover:#1c2533;
  --mob-zle:#f2a19b}
.mob .btn{border-radius:10px !important;box-shadow:none !important;font-weight:600 !important;
  background:var(--mob-drugi-bg) !important;color:var(--mob-drugi-ink) !important;border:1px solid var(--mob-drugi-line) !important}
.mob .btn:hover{background:var(--mob-drugi-hover) !important}
.mob .btn.primary,.mob .btn.zielony,.mob .btn.ostrzega{background:var(--mob-akcja) !important;
  color:var(--mob-akcja-ink) !important;border-color:var(--mob-akcja) !important}
.mob .btn.primary:hover,.mob .btn.zielony:hover,.mob .btn.ostrzega:hover{background:var(--mob-akcja-hover) !important}
.mob .btn.czerwony{color:var(--mob-zle) !important;border-color:color-mix(in srgb,var(--mob-zle) 45%,var(--mob-drugi-line)) !important}
.mob .btn:disabled{opacity:.45}
.mob .btn .muted{color:inherit !important;opacity:.7}
/* Kontakt: dwa równe, obrysowane przyciski z ikoną — bez kolorowych plam. */
.mob .mob-kontakt a.btn.mob-nawiguj,.mob .mob-kontakt a.btn.mob-nawiguj:visited,
:root[data-theme="ananas"] .mob .mob-kontakt a.btn.mob-nawiguj{
  background:var(--mob-drugi-bg) !important;color:var(--mob-drugi-ink) !important;border-color:var(--mob-drugi-line) !important}
.mob .mob-kontakt .btn{justify-content:flex-start;text-align:left;gap:10px;padding-left:14px;padding-right:14px}
.mob .mob-ik{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linejoin:round;opacity:.85}
.mob .mob-kontakt .btn > span{flex:1;min-width:0}
/* Wybór rodzaju pracy i rodzaju w szybkim serwisie — ta sama granatowa akcja. */
.mob .mob-rodzaj{border-radius:10px;border-color:var(--mob-drugi-line);color:var(--mob-drugi-ink)}
.mob .mob-rodzaj.on{background:var(--mob-akcja);border-color:var(--mob-akcja);color:var(--mob-akcja-ink)}
/* Stoper w biegu: zamiast zielonej belki — spokojny granatowy znacznik. */
.mob .mob-stoper.leci{box-shadow:inset 3px 0 0 var(--mob-akcja);border-color:var(--mob-drugi-line)}
.mob .mob-dojazd{background:var(--mob-drugi-hover);border-color:var(--mob-drugi-line)}
.mob .mob-blok{border-radius:12px}

/* ---------------------------------------------------------------------
   TELEFON — GÓRNY PASEK Z TECHNIKIEM I ZEGAREM (27.09.2026)
   Twarz + imię i nazwisko + data po lewej (to też przycisk konta),
   godzina po prawej. Zakładka „Moje" nazywa się teraz „Zlecenia".
   --------------------------------------------------------------------- */
.mob-gora{min-height:60px}
.mob-kto{flex:1;min-width:0;display:flex;align-items:center;gap:10px;background:none;border:0;padding:0;
  font:inherit;color:inherit;text-align:left;cursor:pointer;min-height:44px}
.mob-kto-opis{display:flex;flex-direction:column;min-width:0;line-height:1.2}
.mob-kto-opis strong{font-size:15px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mob-kto-opis span{font-size:12.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mob-kto-opis span::first-letter{text-transform:uppercase}
.mob-twarz{width:40px;height:40px;border-radius:50%;object-fit:cover;flex:0 0 auto;
  border:1px solid var(--line);background:var(--surface-2)}
.mob-twarz-inicjaly{display:inline-grid;place-items:center;font-weight:650;font-size:13px;color:var(--ink)}
.mob-zegar{flex:0 0 auto;font-size:22px;font-weight:750;letter-spacing:-.01em;font-variant-numeric:tabular-nums;
  color:var(--ink);padding:0 2px}
.mob-ja:has(.mob-twarz){padding:0;border:0;background:none;width:40px;height:40px}
.mob-ja .mob-twarz{width:36px;height:36px}
.mob-kto:focus-visible,.mob-ja:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:12px}

/* ---------------------------------------------------------------------
   POZYCJA DOKUMENTU W OKIENKU (28.09.2026) — dopisanie i poprawka
   pozycji wyceny/protokołu; opis z AI przy polu opisu.
   --------------------------------------------------------------------- */
.poz-okno{display:flex;flex-direction:column;gap:12px}
.poz-okno .pole{min-width:0}
.poz-okno-etyk{display:inline-flex;align-items:center;gap:10px}
.poz-okno-etyk .ai-link{font-size:var(--fs-sm);font-weight:600}
.poz-okno textarea.input{min-height:76px;resize:vertical}
.poz-okno-liczby{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px}
.poz-okno-liczby.bez-cen{grid-template-columns:repeat(2,minmax(0,160px))}
.poz-okno .ai-propozycja{margin:0}
@media (max-width:760px){ .poz-okno-liczby{grid-template-columns:repeat(2,minmax(0,1fr))} }

/* ---------------------------------------------------------------------
   GENERATOR HASEŁ (28.09.2026) — generator-hasel.tsx
   --------------------------------------------------------------------- */
.gen-hasel{display:flex;flex-direction:column;gap:14px}
.gen-rodzaje{align-self:flex-start}
.gen-wynik{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2);
  padding:14px 16px;text-align:center}
.gen-haslo{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:22px;
  font-weight:650;letter-spacing:.04em;overflow-wrap:anywhere;cursor:copy;color:var(--ink);background:none;padding:0}
.gen-ocena{display:flex;align-items:center;gap:10px;font-size:var(--fs-sm);color:var(--ink-2)}
.gen-pasek{flex:0 0 120px;height:6px;border-radius:3px;background:var(--surface-2);overflow:hidden;border:1px solid var(--line)}
.gen-pasek span{display:block;height:100%;background:var(--ink-3)}
.gen-ocena.ok .gen-pasek span{background:var(--ok)} .gen-ocena.ok{color:var(--ok)}
.gen-ocena.warn .gen-pasek span{background:var(--warn,#b7791f)}
.gen-ocena.bad .gen-pasek span{background:var(--bad)} .gen-ocena.bad{color:var(--bad)}
.gen-dlugosc{display:flex;flex-direction:column;gap:6px;font-size:var(--fs-sm)}
.gen-dlugosc input[type=range]{width:100%;accent-color:var(--accent)}
.gen-opcje{display:grid;grid-template-columns:1fr 1fr;gap:6px 16px}
.gen-rada{margin:0}
@media (max-width:760px){ .gen-haslo{font-size:19px} .gen-opcje{grid-template-columns:1fr} }

/* ---------------------------------------------------------------------
   OPERATOR — POŁĄCZENIA I PRZEŁĄCZNIKI (28.09.2026)
   --------------------------------------------------------------------- */
.uninet-przel{display:flex;flex-direction:column;gap:10px}
.uninet-przel-wiersz{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
  padding:10px 12px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.uninet-pol{display:flex;flex-direction:column;gap:10px}
.uninet-pol-wiersz{display:grid;grid-template-columns:minmax(180px,260px) minmax(0,1fr) auto auto;gap:8px 12px;align-items:center}
.uninet-pol-wiersz label{display:flex;flex-direction:column;gap:2px;font-weight:600;font-size:var(--fs-sm)}
.uninet-pol-zrodlo{font-weight:400}
.uninet-pol-zrodlo.brak{color:var(--warn,#b7791f)}
.uninet-pol-podp{grid-column:2 / -1;margin-top:-4px}
@media (max-width:760px){
  .uninet-pol-wiersz{grid-template-columns:1fr auto}
  .uninet-pol-wiersz label{grid-column:1 / -1}
  .uninet-przel-wiersz{grid-template-columns:1fr auto}
  .uninet-przel-wiersz > div{grid-column:1 / -1}
}

/* ---------------------------------------------------------------------
   DZIŚ W PUNKCIE — wpis z kalendarza klikalny, dłuższy (28.09.2026)
   --------------------------------------------------------------------- */
.dzis-stan-klik{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;
  overflow:hidden;text-align:left;background:none;border:0;padding:0;margin:0;font-family:inherit;font-size:var(--fs-xs);cursor:pointer;
  color:inherit;text-decoration:underline dotted;text-underline-offset:2px;line-height:1.25}
.dzis-stan-klik:hover{text-decoration-style:solid}
.dzis-stan-klik:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:3px}
.ton-ok .dzis-stan-klik{color:var(--ok, #1f7a3f)}
.ton-zajety .dzis-stan-klik{color:var(--warn, #b7791f)}
.ton-nie .dzis-stan-klik{color:var(--ink-2)}
.dzis-plan{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.dzis-plan-poz{display:grid;grid-template-columns:92px 1fr;gap:12px;padding:10px 12px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.dzis-plan-poz.trwa{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}
.dzis-plan-poz.minelo{opacity:.65}
.dzis-plan-czas{font-size:var(--fs-sm);font-weight:650;font-variant-numeric:tabular-nums;display:flex;flex-direction:column;gap:4px}
.dzis-plan-teraz{align-self:flex-start;font-size:11px;font-weight:700;padding:1px 8px;border-radius:var(--radius-pill,6px);
  background:var(--accent-soft);color:var(--accent-text, var(--accent))}
.dzis-plan-tresc{display:flex;flex-direction:column;gap:3px;min-width:0}
.dzis-plan-tresc .muted{font-size:var(--fs-sm)}
.dzis-plan-opis{margin:4px 0 0;font-size:var(--fs-sm);color:var(--ink-2);white-space:pre-wrap;overflow-wrap:anywhere}
.dzis-plan-tresc .jak-link{align-self:flex-start;margin-top:2px}
@media (max-width:640px){ .dzis-plan-poz{grid-template-columns:1fr;gap:4px} }

/* ---------------------------------------------------------------------
   LISTA NAPRAW — węższe kolumny z datą, sprzętem i klientem, więcej
   miejsca na usterkę (28.09.2026). Usterka w dwóch liniach zamiast
   jednej uciętej.
   --------------------------------------------------------------------- */
.lista-napraw td.kol-data{width:1%;white-space:nowrap;font-size:var(--fs-sm)}
.lista-napraw td[data-label="Sprzęt"]{width:175px;max-width:175px}
.lista-napraw td[data-label="Sprzęt"] .tnij{max-width:165px}
.lista-napraw td[data-label="Klient"]{width:150px;max-width:150px}
.lista-napraw td[data-label="Usterka"]{max-width:none;min-width:260px}
.lista-napraw td[data-label="Usterka"] .tnij{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  white-space:normal;overflow:hidden;text-overflow:ellipsis;max-width:none}

/* LISTA NAPRAW — wyróżnienia (28.09.2026, Łukasz): sprzęt grubszą
   czcionką, termin pogrubiony na czerwono, pełniejsza nazwa statusu. */
.lista-napraw td[data-label="Sprzęt"] .tnij{font-weight:600}
.lista-napraw .termin-listy{font-weight:700;color:var(--bad);white-space:nowrap}
.lista-napraw .termin-listy.po{background:var(--bad-bg);border:1px solid var(--bad-border);
  border-radius:4px;padding:0 5px;display:inline-block}
.lista-napraw .kol-numer .pill{max-width:360px}

/* Uwagi klienta pod usterką na karcie naprawy (28.09.2026). */
.kn-uwagi-klienta{margin-top:var(--s2)}
.kn-uwagi-klienta .kn-slowa-klienta{white-space:pre-line;color:var(--ink-2, inherit)}

/* LISTA STANOWISK — kolumna Procesor (28.09.2026); węższe Stanowisko,
   Stan i System, żeby całość zmieściła się bez przewijania. */
.lista-stanowisk td.numer-stanowiska,.lista-stanowisk th.kol-stanowisko{width:1%;white-space:nowrap}
.lista-stanowisk td.do-lewej{width:1%;white-space:nowrap}
.lista-stanowisk td.kol-cpu{max-width:190px}
.lista-stanowisk td.kol-cpu .tnij{max-width:180px}
.lista-stanowisk td.tekst-min{max-width:190px;white-space:normal;line-height:1.3}

/* Rozmiary paczek — podpowiedź z przesyłek DHL i wyrównanie „domyślny" (28.09.2026). */
.gab-z-dhl{margin:0 18px 12px;padding-top:8px;border-top:1px solid var(--line)}
.gab-z-dhl h4{margin:6px 0 4px;font-size:var(--fs-sm)}
.gab-z-dhl .gab-tabela{margin:6px 0}
.gab-domyslny input[type=radio]{margin:0;flex:none}
.gab-domyslny span{line-height:1}

/* PULPIT NAPRAW (28.09.2026) — niższe kafle, pod nimi dwa duże panele:
   ostatnie notatki i wiadomości od klientów (serwisant: „jak w NPS"). */
.pulpit-kafle .kpi.kpi2{grid-template-rows:auto auto auto auto auto;padding:8px 12px 6px}
.pulpit-kafle .kpi2 .v{height:40px;margin:6px auto 4px;font-size:24px;padding:0 14px;min-width:60px}
.pulpit-kafle .kpi2 .v.v-s{font-size:21px}
.pulpit-kafle .kpi2 .v.v-xs{font-size:18px}
.pulpit-kafle .kpi2 .v .kwota{font-size:21px}
.pulpit-kafle .kpi .kpi-trend{height:16px;margin-top:4px}
.pulpit-kafle .kpi2 .kpi-glowa{height:auto;min-height:26px}
.pulpit-listy.pulpit-listy-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.pulpit-lista.pulpit-lista-duza{height:520px}
.pulpit-lista-duza .hd{flex-wrap:wrap}
.pulpit-lista-duza .hd .hd-podtytul{color:var(--ink-3);font-size:var(--fs-sm)}
.pulpit-lista-duza .pulpit-notatka{padding:9px 6px;gap:3px}
.pulpit-lista-duza .pulpit-notatka .numer{font-weight:650}
.pulpit-lista-duza .pulpit-notatka .clip2{font-size:var(--fs-md, 15px);line-height:1.4}
.pulpit-lista-duza .pulpit-notatka.nowa{background:var(--warn-bg, #fff8e6)}
@media (max-width: 900px){ .pulpit-listy.pulpit-listy-2{grid-template-columns:1fr} }

/* LISTA NAPRAW — węższa kolumna „Numer i status" (28.09.2026, Łukasz:
   „bardzo szeroka, dajmy węższą, a rozszerzmy opis usterki"). Długa
   nazwa statusu łamie się w plakietce na dwie linie zamiast rozpychać
   kolumnę albo się ucinać. */
.lista-napraw td.kol-numer{width:1%}
.lista-napraw .kol-numer .pill{max-width:210px;white-space:normal;line-height:1.25;
  text-align:left;overflow:visible;text-overflow:clip}
.lista-napraw .kol-numer .pill svg{flex:none}
.lista-napraw td[data-label="Usterka"]{min-width:320px}

/* KARTA NAPRAWY — jak sprzęt do nas trafi + adres do wysyłki (28.09.2026). */
.kn-dostawa{display:flex;align-items:center;gap:14px;margin:0 0 var(--s3);padding:12px 16px;
  border-radius:var(--radius-lg);border:1px solid var(--line);background:var(--surface)}
.kn-dostawa.info{background:var(--info-bg, #eef4ff);border-color:var(--info-border, #c9dafb);color:var(--info, #1f4fa8)}
.kn-dostawa.ok{background:var(--ok-bg, #eaf6ef);border-color:var(--ok-border, #bfe3cc);color:var(--ok, #16753e)}
.kn-dostawa.pilne{background:var(--warn-bg);border-color:var(--warn-border);color:var(--ink)}
.kn-dostawa-tresc{display:flex;flex-direction:column;gap:2px;flex:1 1 auto;min-width:0}
.kn-dostawa-tresc strong{font-size:var(--fs-lg, 17px);color:var(--ink)}
.kn-dostawa-tresc span{color:var(--ink-2)}
.kn-dostawa-btn{font-size:var(--fs-md, 15px);padding:10px 18px}
.kn-adres{display:block;text-align:left;font-size:var(--fs-sm);color:var(--ink-2);white-space:normal}
.adres-wysylki{font-size:var(--fs-md, 15px);line-height:1.5;padding:12px 14px;border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface-2);margin-bottom:var(--s3)}
.adres-wysylki .adres-nazwa{font-weight:650}
.lista-napraw .krok-czekaj{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.lista-napraw .termin-data{font-size:var(--fs-xs)}
.lista-napraw .kol-numer .pill{padding-top:3px;padding-bottom:3px;line-height:1.3}
/* Plakietka statusu łamana w dwie linie (28.09.2026, Łukasz: „u Agi przy
   -10% w Chrome plakietki się ściskają"). `.pill` ma na sztywno 26 px
   wysokości — dwie linie tekstu wchodziły w jedną. Tu wysokość rośnie
   z treścią, a wiersz dostaje kilka pikseli oddechu. */
.lista-napraw .kol-numer .pill{height:auto;min-height:24px;padding:4px 10px;align-items:center}
.lista-napraw tbody td{padding-top:10px;padding-bottom:10px}
.lista-napraw .kol-numer .kn-glowny, .lista-napraw .kol-numer .numer{white-space:nowrap}

/* Odśwież ekran (28.09.2026). */
@keyframes s24-kreci{to{transform:rotate(360deg)}}
/* Ikona w pasku zawsze jako blok — jako zwykły tekst siadała na linii
   pisma i „odlatywała" o kilka pikseli w górę względem sąsiednich ikon. */
.ikona-w-przycisku{display:inline-flex;align-items:center;justify-content:center;line-height:0}
.kreci{display:inline-flex;animation:s24-kreci .7s ease-in-out}
@media (prefers-reduced-motion: reduce){.kreci{animation:none}}
.mob-odswiez{background:none;border:0;color:inherit;padding:6px;margin-left:auto;display:inline-flex;
  align-items:center;justify-content:center;min-width:40px;min-height:40px;border-radius:10px;cursor:pointer}
.mob-odswiez:active{background:rgba(0,0,0,.06)}

/* Szybki serwis: gdzie jesteś (Kacper, 28.09.2026) */
.szybki-gdzie{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.szybki-gdzie.mob{grid-template-columns:1fr}
.szybki-opcja{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:inherit;font:inherit;cursor:pointer}
.szybki-opcja strong{font-size:14px}
.szybki-opcja span{font-size:12px;color:var(--ink-2)}
.szybki-opcja:hover{border-color:var(--accent)}
.szybki-opcja.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);background:var(--accent-soft)}
.szybki-opcja:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.szybki-nawiguj{display:block;text-align:center;margin:var(--s3,12px) 0;white-space:normal}
@media (max-width:700px){.szybki-gdzie{grid-template-columns:1fr}}

/* Opinia / protokół / wycena: pola treści jedno pod drugim (28.09.2026).
   Krótkie pole zaczyna od dwóch linijek, długie rośnie do 22 linijek
   zamiast chować tekst za suwakiem. Tabela pozycji czytana od lewej. */
.dok-naglowek .input.rosnace{min-block-size:2.6lh;max-block-size:22lh}
table.tab-pozycji thead > tr > th,table.tab-pozycji tbody > tr > td{text-align:left;vertical-align:top}
table.tab-pozycji thead > tr > th.num,table.tab-pozycji tbody > tr > td.num,
table.tab-pozycji tbody > tr > td.kol-akcje-poz{text-align:right}
/* Dokument otwarty w okienku ma ten sam rytm bloków co na stronie. */
.dok-okno-bd > * + *{margin-top:var(--s6)}
.dok-okno-bd > .dok-naglowek{margin-bottom:0}
.dok-okno-bd > .dok-pasek-numeru + *{margin-top:var(--s4)}
.dok-pasek-numeru{flex-wrap:wrap;row-gap:var(--s2)}

/* Ślad powiadomień przy statusie w przebiegu (28.09.2026) */
.pz-slad{display:flex;flex-direction:column;gap:2px;margin-top:3px;font-size:var(--fs-sm)}
.pz-slad-poz{display:flex;align-items:baseline;gap:6px;color:var(--ink-2);overflow-wrap:anywhere}
.pz-slad-kropka{display:inline-block;flex:0 0 auto;width:7px;height:7px;border-radius:2px;
  background:var(--ink-2);transform:translateY(-1px);margin-right:4px}
.pz-slad-poz.ok .pz-slad-kropka,.pz-slad-kropka.ok{background:var(--ok)}
.pz-slad-poz.czeka .pz-slad-kropka,.pz-slad-kropka.czeka{background:var(--warn)}
.pz-slad-poz.zle,.pz-slad-poz.zle .pz-slad-kropka{color:var(--bad)}
.pz-slad-poz.zle .pz-slad-kropka,.pz-slad-kropka.zle{background:var(--bad)}
.pz-slad-poz.nic .pz-slad-kropka{background:transparent;border:1px solid var(--line)}

/* Wycena zwarta (28.09.2026): pola tekstowe obok siebie, niskie,
   nagłówek pozycji w jednym rzędzie z przyciskami — pozycje widać
   bez przewijania. */
.dok-naglowek-wycena{gap:var(--s3) var(--s4)}
.dok-naglowek .input.rosnace.zwarte{min-block-size:2.6lh;max-block-size:6lh;overflow-y:auto}
.dok-naglowek-wycena .dok-naglowek-akcje{padding-top:0;border-top:0}
.dok-okno-bd > * + *{margin-top:var(--s5)}
.dok-sekcja-hd{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s2) var(--s4)}
.dok-sekcja-hd > h3{margin:0}
.dok-sekcja-hd > .formrow{margin:0;flex:1 1 auto}
.szukaj-adresu{width:100%;margin-bottom:6px}

/* Do zrobienia: biorę / zrobione (28.09.2026) */
.zabieram-opcje{display:grid;grid-template-columns:1fr 1fr;gap:8px}
@media (max-width:560px){.zabieram-opcje{grid-template-columns:1fr}}
.notatka-dokument{display:block;margin-top:2px;font-size:var(--fs-sm)}
.zrobione-dokumenty{display:flex;flex-direction:column;gap:2px;max-height:260px;overflow:auto;
  border:1px solid var(--line);border-radius:var(--radius);padding:6px;margin:6px 0 10px;background:var(--surface)}
.zrobione-dok{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto;align-items:baseline;gap:8px;
  padding:5px 7px;border-radius:var(--radius-sm);cursor:pointer}
.zrobione-dok:hover{background:var(--surface-2)}
.zrobione-dok.on{background:var(--accent-soft)}
.zrobione-dok-tytul{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.zrobione-dok .muted{font-size:var(--fs-xs);white-space:nowrap}

/* Kafle zwarte z linią trendu w tle (Do zrobienia, 28.09.2026).
   Nazwa i podpis po lewej, liczba po prawej, linia 14 dni wypełnia
   dół kafla — ok. 90 px wysokości zamiast 150. */
.kpis.kpis-zwarte{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s3)}
.kpis-zwarte .kpi.kpi2{display:grid;grid-template-columns:minmax(0,1fr) auto;
  grid-template-rows:auto auto;column-gap:var(--s3);row-gap:2px;align-items:center;
  text-align:left;padding:var(--s3) var(--s4) 30px;min-height:0}
.kpis-zwarte .kpi2 .kpi-glowa{grid-column:1;grid-row:1;min-height:0;align-self:end}
.kpis-zwarte .kpi2 .l{font-size:var(--fs-sm);letter-spacing:.05em}
.kpis-zwarte .kpi2 .d{grid-column:1;grid-row:2;margin:0;min-height:0;align-self:start}
.kpis-zwarte .kpi2 .v{grid-column:2;grid-row:1 / span 2;margin:0;height:auto;min-width:0;
  padding:0;background:none;font-size:32px;justify-self:end}
:root[data-theme="ananas"] .kpis-zwarte .kpi2 .v{background:none}
.kpis-zwarte .kpi2 .kpi-trend{position:absolute;left:0;right:0;bottom:0;width:100%;height:28px;margin:0;
  color:var(--accent)}
.kpis-zwarte .kpi2 .kpi-trend .pole{opacity:.16}
.kpis-zwarte .kpi2.alert .kpi-trend{color:var(--bad)}

/* Nieobecności — przyciski decyzji w wierszu (28.09.2026) */
td.nieob-decyzja{vertical-align:middle;padding-top:8px;padding-bottom:8px}
td.nieob-decyzja > span{align-items:center}
/* Tryb operatora na telefonie (28.09.2026) */
.mob-tryb,.mob-kolejki{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:4px;padding:3px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius)}
.mob-tryb{margin-bottom:10px}
.mob-tryb button,.mob-kolejki button{min-height:40px;border:0;border-radius:calc(var(--radius) - 2px);background:none;
  color:var(--ink-2);font:inherit;font-size:var(--fs-sm);font-weight:600;cursor:pointer}
.mob-tryb button.on,.mob-kolejki button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.08)}
.mob-tryb button:focus-visible,.mob-kolejki button:focus-visible{outline:none;box-shadow:var(--focus)}
.mob-operator-akcje{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}
.mob-operator-akcje .btn{min-height:44px;justify-content:center}
.mob .drawer{width:100vw;max-width:100vw;inset:0}
.mob .drawer .drawer-hd{position:sticky;top:0;z-index:2;background:var(--surface)}
/* „Wróć do zgłoszenia X" nad nagłówkiem okna (28.09.2026) */
.okno-powrot{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;margin:0 0 var(--s2)}
/* Stoper operatora: dojazd / praca (migracja 331) */
.zgl-stoper-rodzaj{font-size:var(--fs-xs);font-weight:650;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3)}
.mob .zgl-stoper-rzad .btn{min-height:44px}
/* Sesje w Radiusie na wąskim ekranie — w pionie, bez przewijania w bok (28.09.2026) */
.sesje-pion{display:none}
.sesja-pion{display:flex;flex-direction:column;gap:4px;padding:10px 0;border-bottom:1px solid var(--line)}
.sesja-pion:first-child{padding-top:0}
.sesja-pion:last-child{border-bottom:0}
.sesja-pion-gora{display:flex;justify-content:space-between;align-items:center;gap:8px}
.sesja-pion-konto{overflow-wrap:anywhere}
.sesja-pion-dol{display:flex;flex-wrap:wrap;gap:2px 12px;font-size:var(--fs-sm)}
.sesja-pion-btn{margin-top:6px;min-height:44px;justify-content:center;width:100%}
@media (max-width:700px){ .sesje-pion{display:block} .sesje-tabela{display:none} }
.mob .sesje-pion{display:block}
.mob .sesje-tabela{display:none}
/* Stoper zgłoszenia — licznik nad przyciskami, praca zielona, dojazd niebieski (28.09.2026) */
.zgl-stoper{gap:8px;padding:10px 12px}
.zgl-stoper.w-drodze{border-color:var(--info-border);background:var(--info-bg)}
.zgl-stoper-licznik{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.zgl-stoper-licznik .zgl-stoper-czas{font-size:var(--fs-xl, 1.5rem);font-weight:650;font-variant-numeric:tabular-nums}
.zgl-stoper-przyciski{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px}
.zgl-stoper-przyciski .btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:40px;font-weight:600;text-decoration:none}
.zgl-btn-praca{background:var(--ok-solid);border-color:var(--ok-solid);color:var(--ok-solid-ink)}
.zgl-btn-praca:hover:not(:disabled){background:var(--ok-solid-hover);border-color:var(--ok-solid-hover);color:var(--ok-solid-ink)}
.zgl-btn-dojazd{background:var(--info-bg);border-color:var(--info-border);color:var(--info)}
.zgl-btn-dojazd:hover:not(:disabled){border-color:var(--info);color:var(--info)}
.zgl-stoper.w-drodze .zgl-btn-dojazd{background:var(--surface)}
.zgl-btn-stop.pelny{grid-column:1 / -1}
.zgl-stoper-info{display:flex;flex-wrap:wrap;gap:4px 12px;font-size:var(--fs-sm)}
.zgl-stoper-info .jak-link{padding:0;text-align:left}
/* Fakty zgłoszenia — zwarta siatka z ikonkami, opis jako cytat (28.09.2026) */
.zgl-fakty{display:flex;flex-direction:column;gap:10px;margin:var(--s3) 0}
.zgl-czego{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;font-weight:600}
.zgl-czego .ikonka,.zgl-fakt .ikonka{color:var(--accent-text, var(--ink-2));flex:0 0 auto}
.zgl-kategoria{font-weight:600;font-size:var(--fs-sm);padding:2px 8px;border-radius:var(--radius-pill);
  background:var(--warn-bg);border:1px solid var(--warn-border);color:var(--warn)}
.zgl-fakty-siatka{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 14px}
.zgl-fakt{display:flex;gap:8px;align-items:flex-start;min-width:0}
.zgl-fakt .ikonka{margin-top:2px}
.zgl-fakt > div{display:flex;flex-direction:column;min-width:0;overflow-wrap:anywhere}
.zgl-fakt.szeroki{grid-column:1 / -1}
.zgl-fakt-e{font-size:var(--fs-xs);font-weight:650;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3)}
.zgl-opis{border-left:3px solid var(--accent-border, var(--line));background:var(--surface-2);
  border-radius:var(--radius-sm);padding:8px 12px;display:flex;flex-direction:column;gap:2px}
.zgl-opis.abonent{border-left-color:var(--info-border)}
.zgl-opis-tresc{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.45}
/* Dwa kolory przycisków stopera — z !important, bo motyw ANANAS i widok
   telefonu przestawiają kolory wszystkim .btn (28.09.2026). Praca = pełny
   kolor akcji, dojazd = niebieski jasny. */
.zgl-stoper-przyciski .btn{white-space:nowrap;padding:0 10px;gap:6px}
.zgl-stoper .btn.zgl-btn-praca{background:var(--accent) !important;border-color:var(--accent) !important;color:var(--accent-ink, #fff) !important}
.zgl-stoper .btn.zgl-btn-praca:hover:not(:disabled){background:var(--accent-hover, var(--accent)) !important}
.zgl-stoper .btn.zgl-btn-dojazd{background:#e8f0fb !important;border-color:#b9cde9 !important;color:#1f5fae !important}
.zgl-stoper .btn.zgl-btn-dojazd:hover:not(:disabled){border-color:#1f5fae !important}
:root[data-theme="dark"] .zgl-stoper .btn.zgl-btn-dojazd{background:#16263b !important;border-color:#2c4666 !important;color:#9cc3f5 !important}
.mob .zgl-stoper .btn.zgl-btn-praca{background:var(--mob-akcja) !important;border-color:var(--mob-akcja) !important;color:var(--mob-akcja-ink) !important}
.zgl-stoper.w-drodze{border-color:#b9cde9;background:#f1f6fd}
:root[data-theme="dark"] .zgl-stoper.w-drodze{border-color:#2c4666;background:#111d2d}
.zgl-stoper.w-drodze .btn.zgl-btn-dojazd{background:var(--surface) !important}
.zgl-stoper-przyciski .btn.pelny{grid-column:1 / -1}
.mob .zgl-stoper-przyciski .btn{font-size:var(--fs-sm) !important;min-height:46px}
.zgl-stoper-info .jak-link{color:var(--ink-2);text-decoration:underline dotted;text-underline-offset:3px}
/* Poprawki wyglądu zgłoszenia (28.09.2026, druga runda) */
.zgl-stoper-info{justify-content:center;text-align:center;margin:4px 0 2px}
.zgl-stoper-info .jak-link{text-align:center}
.zgl-stoper{padding:12px 12px 10px}
.pomiar-lacza{gap:8px}
.pomiar-lacza .pomiar-hd{gap:10px}
.pomiar-lacza .nazwa{display:inline-flex;align-items:center;gap:8px}
.pomiar-lacza .nazwa .ikonka{color:var(--accent-text, var(--ink-2))}
.btn.pomiar-btn{background:#e8f0fb !important;border-color:#b9cde9 !important;color:#1f5fae !important;flex:0 0 auto}
:root[data-theme="dark"] .btn.pomiar-btn{background:#16263b !important;border-color:#2c4666 !important;color:#9cc3f5 !important}
.pomiar-stan{display:flex;gap:8px;align-items:flex-start;padding:8px 10px;border-radius:var(--radius-sm);
  background:var(--surface-2);font-size:var(--fs-sm);line-height:1.45;color:var(--ink-2)}
.pomiar-stan .ikonka{flex:0 0 auto;margin-top:2px;color:var(--info)}
.pomiar-stan strong{color:var(--ink)}
.pomiar-meta{display:flex;flex-wrap:wrap;gap:2px 14px;font-size:var(--fs-xs);color:var(--ink-3)}
.pomiar-meta strong{font-weight:600;color:var(--ink-2)}
.pomiar-lacza + .zgl-akcje,.pomiar-lacza ~ .zgl-akcje{margin-top:12px}
.zgl-akcje > .btn{gap:7px}
.zgl-akcje > .btn .ikonka{flex:0 0 auto;opacity:.85}
.zgl-akcje + .zgl-fakty,.zgl-fakty{margin-top:18px}
.mob .zgl-akcje > .btn{font-size:var(--fs-sm) !important;min-height:44px}
.zgl-stoper{padding:14px 14px 12px}
.zgl-stoper-info{margin:6px 0 4px;padding-top:10px;border-top:1px dashed var(--line)}
/* Ikonki w telefonie (28.09.2026) */
.mob-sekcja > .ikonka{align-self:center;flex:0 0 auto;color:var(--accent-text, var(--ink-2))}
.mob .mob-duzy{gap:8px}
.mob .mob-duzy .ikonka,.mob .mob-operator-akcje .btn .ikonka{flex:0 0 auto}
.mob .mob-operator-akcje .btn{display:inline-flex;align-items:center;gap:8px}
.mob-rodzaj{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:6px 4px;line-height:1.15}
.mob-rodzaj .ikonka{opacity:.8}
.mob-rodzaj.on .ikonka{opacity:1}

/* Rząd „Faktura" w pasku karty naprawy (28.09.2026) — stan dokumentu tuż
   pod „Pieniądze", zamiast bloku na dole strefy Rozliczenie. */
.rzad-faktura .kn-faktura{display:flex;flex-direction:column;gap:2px;min-width:0}
.rzad-faktura .kn-faktura .formrow{margin:0;gap:8px;align-items:center;flex-wrap:wrap}
.rzad-faktura .kn-faktura .formrow strong{font-variant-numeric:tabular-nums}
.rzad-faktura .wyjasnienie{margin:0;font-size:var(--fs-sm);color:var(--bad)}

/* FAKTURA NA LIŚCIE NAPRAW (28.09.2026). „Generuję fakturę…" w kolumnie
   Następny krok, dopóki agent nie odda numeru, a potem plakietka FV
   w kolumnie Pieniądze. Animacja mówi „coś się dzieje, nie klikaj". */
.krok-generuje{display:inline-flex;align-items:center;gap:8px;padding:4px 10px;
  border-radius:999px;border:1px solid var(--info-border);background:var(--info-bg);
  color:var(--info);font-size:var(--fs-sm);font-weight:600;white-space:nowrap;
  background-image:linear-gradient(100deg,transparent 30%,rgba(255,255,255,.55) 50%,transparent 70%);
  background-size:220% 100%;background-repeat:no-repeat;
  animation:krok-generuje-blysk 1.8s ease-in-out infinite}
.krok-generuje .krecik{width:12px;height:12px;border-radius:50%;flex:0 0 12px;
  border:2px solid currentColor;border-right-color:transparent;
  animation:krecik-obrot .8s linear infinite}
@keyframes krecik-obrot{to{transform:rotate(360deg)}}
@keyframes krok-generuje-blysk{0%{background-position:120% 0}100%{background-position:-120% 0}}

.plakietka-faktura{display:inline-flex;align-items:center;gap:4px;margin-top:4px;
  padding:1px 8px;border-radius:999px;border:1px solid var(--ok-border);
  background:var(--ok-bg);color:var(--ok);font-size:var(--fs-xs);font-weight:600;
  white-space:nowrap;font-variant-numeric:tabular-nums;
  animation:plakietka-wskakuje .35s ease-out}
@keyframes plakietka-wskakuje{from{opacity:0;transform:translateY(3px) scale(.96)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion: reduce){
  .krok-generuje,.plakietka-faktura{animation:none}
  .krok-generuje .krecik{animation-duration:2.4s}
}

/* UMOWA OBSŁUGI IT W PAKCIE (migracja 333, 29.09.2026). */
.umowa-karta{display:flex;flex-direction:column;gap:var(--s4)}
.umowa-karta > .note{margin:0}
.umowa-pola{border:0;margin:0;padding:0;min-width:0;display:flex;flex-direction:column;gap:var(--s4)}
.umowa-blok{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s4);
  border:1px solid var(--line);border-radius:var(--radius, 8px);background:var(--surface)}
.umowa-blok > h3,.umowa-blok .dok-sekcja-hd h3{margin:0;font-size:var(--fs-md, 1rem)}
.umowa-blok .pola{margin:0}
.umowa-strona{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) minmax(0,1fr);gap:var(--s3);align-items:start}
.umowa-strona > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.umowa-etyk{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}
.umowa-powierzenie{display:flex;gap:8px;align-items:center;font-size:var(--fs-sm)}
.umowa-zakladki{margin:0}
.umowa-tresc-uklad{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--s3);align-items:start}
.input.umowa-tresc{width:100%;height:auto;min-height:560px;padding:var(--s3);resize:vertical;font-size:13px;line-height:1.55;
  font-family:var(--font-body, inherit);white-space:pre-wrap;tab-size:2}
.umowa-wstawki{position:sticky;top:0;max-height:620px;overflow:auto;border:1px solid var(--line);
  border-radius:var(--radius, 8px);padding:var(--s2) var(--s3);background:var(--surface-2)}
.umowa-wstawki p{margin:0 0 var(--s2)}
.umowa-wstawki ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.umowa-wstawki li{display:flex;flex-direction:column;gap:1px;min-width:0}
.umowa-wstawka{align-self:flex-start;font-family:var(--font-mono, monospace);font-size:var(--fs-xs);
  padding:1px 6px;border:1px solid var(--line);border-radius:4px;background:var(--surface);
  color:var(--ink);cursor:pointer}
.umowa-wstawka:hover:not(:disabled){border-color:var(--accent)}
.umowa-wstawka:disabled{cursor:default;opacity:.7}
.umowa-wartosc{font-size:var(--fs-xs);color:var(--ink-2);overflow-wrap:anywhere}
.umowa-skladnia{margin:0}
.umowa-stopka{margin:0}
@media (max-width: 900px){
  .umowa-strona,.umowa-tresc-uklad{grid-template-columns:minmax(0,1fr)}
  .umowa-wstawki{position:static;max-height:260px}
}

/* Magazyn → Stany: przełącznik „z wygaszonymi" w pasku filtrów (29.09.2026). */
.mag-wygaszone{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-size:var(--fs-sm);color:var(--ink-2);cursor:pointer}
.mag-wygaszone input{margin:0}

/* Wykaz przetwarzania i dalsze podmioty w umowie (migracja 334). */
.umowa-wykaz{width:100%;table-layout:fixed}
.umowa-wykaz th{font-size:var(--fs-xs);text-align:left}
.umowa-wykaz td{vertical-align:top;padding:4px}
.umowa-wykaz td.srodek{text-align:center;padding-top:12px}
.umowa-wykaz th:nth-last-child(1),.umowa-wykaz td:nth-last-child(1){width:52px}
.umowa-wykaz textarea.input{width:100%;height:auto;min-height:52px;padding:6px 8px;
  font-size:var(--fs-xs);line-height:1.35;resize:vertical}
.umowa-wykaz th[title]{width:52px}

/* Umowy i ochrona danych na karcie firmy (migracja 336) */
.ochrona-danych{display:flex;flex-direction:column;gap:var(--s3);margin-top:var(--s3)}
.ochrona-pasek{align-items:center;gap:var(--s3)}
.ochrona-umowy td{vertical-align:middle}
.ochrona-umowy tr.klikalny{cursor:pointer}
.ochrona-umowy tr.klikalny:focus-visible td{background:var(--wiersz-hover)}
.input.umowa-lista{height:auto;min-height:120px;font-family:inherit;line-height:1.45}

/* =====================================================================
   PRZEJŚCIA (29.09.2026) — Łukasz: „żeby przejścia, przekliki nie były
   takie natychmiastowe, tylko żeby lekka animacja była. Subtelna".
   Krótko (120–220 ms), bez sprężynek. Tabele i listy się nie ruszają —
   przy dużych danych ruch przeszkadza. Kto ma w systemie „ogranicz ruch",
   dostaje wszystko od razu (blok na końcu).
   ===================================================================== */
/* Zmiana ekranu (przejscia.ts): treść przenika i podnosi się o kilka
   pikseli; pasek boczny i górny stoją, bo przed i po wyglądają tak samo. */
html.przejscie-ekranu .tresc-ekranu{view-transition-name:tresc}
::view-transition-old(root),::view-transition-new(root){animation-duration:.22s}
::view-transition-group(tresc){animation-duration:0s}
::view-transition-old(tresc){animation:s24-ekran-znika .14s ease-out both}
::view-transition-new(tresc){animation:s24-ekran-wchodzi .3s cubic-bezier(.2,0,0,1) .04s both}
@keyframes s24-ekran-znika{to{opacity:0}}
@keyframes s24-ekran-wchodzi{from{opacity:0;translate:0 12px}}

/* Okna, szuflady, zasłona pod nimi — wejście. Wyjście zostaje natychmiastowe:
   zamknięcie ma „odpowiadać od razu", nie czekać na animację. */
.scrim{animation:s24-zaslona .2s ease-out}
.okienko{animation:s24-okno .24s cubic-bezier(.2,0,0,1)}
.drawer{animation:s24-szuflada .3s cubic-bezier(.2,0,0,1)}
/* Poranna przypominajka stoi na środku jak okno, nie wjeżdża z boku. */
.drawer.briefing{animation:s24-okno .24s cubic-bezier(.2,0,0,1)}
@keyframes s24-zaslona{from{opacity:0}}
@keyframes s24-okno{from{opacity:0;scale:.96;translate:0 10px}}
@keyframes s24-szuflada{from{opacity:.3;translate:48px 0}}

/* Przyciski, zakładki, menu, wiersze — płynna zmiana koloru zamiast skoku
   i lekkie „wciśnięcie" przycisku. */
.btn{transition:background-color .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease,scale .08s ease}
.btn:active:not(:disabled){scale:.98}
.zakladki button{transition:color .15s ease,border-color .15s ease,background-color .15s ease}
.side button.nav{transition:background-color .14s ease,color .14s ease,border-color .14s ease}
.side button.nav.ma-podmenu .strzalka{transition:transform .18s ease}
tbody tr{transition:background-color .12s ease}
.jak-link{transition:color .14s ease}

@media (prefers-reduced-motion:reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none !important}
  .scrim,.okienko,.drawer,.drawer.briefing{animation:none}
  .btn:active:not(:disabled){scale:none}
}

/* Klucze bezpieczeństwa w oknie „Logowanie dwuetapowe" (migracja 339) */
.oddziel-2fa{border:0;border-top:1px solid var(--line);margin:var(--s5) 0 var(--s4)}
.klucze-sekcja{display:flex;flex-direction:column;gap:var(--s3)}
.klucze-sekcja h3{margin:0}
.klucze-sekcja .wyjasnienie{margin:0}
.klucze-tab{width:100%}
.klucze-dodaj{align-items:flex-end;gap:var(--s3)}

/* AI w protokołach i opiniach (migracja 340) */
.ai-tresc-start{flex-wrap:wrap}
.ai-tresc-pole{display:flex;flex-direction:column;gap:4px}
.ai-tresc-hd{display:flex;align-items:center;justify-content:space-between;gap:8px}

/* Doliczanie pozycji (migracja 341, 29.09.2026) — stawka informacyjna,
   pozycja wspólna dla wybranych wariantów. */
.poz-doliczanie{font-size:var(--fs-xs);color:var(--ink-2);font-style:italic;margin-top:2px}
.poz-warianty-wybor{display:flex;flex-wrap:wrap;gap:6px 16px;padding:2px 0 4px}

/* PDF faktury (migracja 342): okno wysyłki leży w DOM wewnątrz rzędu
   „Faktura", gdzie .wyjasnienie jest czerwone (błąd wystawienia).
   W oknie i przy informacji o wysyłce to zwykły opis, nie błąd. */
.rzad-faktura .okno-formularza .wyjasnienie,
.rzad-faktura .wyjasnienie.info{color:var(--ink-2)}

/* Lista napraw (29.09.2026): godzina przyjęcia pod datą — kolumna „Przyjęto"
   węższa, a status przy numerze RMA dostaje więcej miejsca. */
.lista-napraw td.kol-data{line-height:1.35}
.lista-napraw td.kol-data .kol-data-godz{font-size:var(--fs-xs)}
.lista-napraw .kol-numer .pill{max-width:250px}

/* =====================================================================
   ROZLICZENIE — „FINAŁ" NAPRAWY (29.09.2026)
   Pieniądze + faktura + PDF w jednej karcie, w stylu karty dostawy.
   ===================================================================== */
.kn-rozliczenie{margin:0 0 var(--s3);padding:14px 18px;border:1px solid var(--line);border-radius:var(--radius-lg);
  background:var(--surface);display:flex;flex-direction:column;gap:12px}
.kn-rozliczenie.info{background:var(--info-bg, #eef4ff);border-color:var(--info-border, #c9dafb)}
.kn-rozliczenie.ok{background:var(--ok-bg, #eaf6ef);border-color:var(--ok-border, #bfe3cc)}
.kn-rozl-glowa{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.kn-rozl-etykieta{font-size:var(--fs-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2);
  min-width:92px}
.kn-rozl-kwota{display:flex;align-items:baseline;gap:6px 12px;flex-wrap:wrap;flex:1 1 auto;min-width:0}
.kn-rozl-kwota strong{font-size:var(--fs-lg, 17px);color:var(--ink)}
.kn-rozl-suma{font-size:22px;font-weight:800;color:var(--ink)}
.kn-rozliczenie.ok .kn-rozl-suma{color:var(--ok, #16753e)}
.kn-rozl-pod{color:var(--ink-2);font-size:var(--fs-sm)}
.kn-rozl-faktura{border-top:1px solid color-mix(in srgb, var(--line) 70%, transparent);padding-top:12px}
.kn-rozl-faktura.zle{border-top-color:var(--bad-border)}
.kn-rozl-faktura .kn-faktura{display:flex;flex-direction:column;gap:6px}
.kn-rozl-dok{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.kn-rozl-dok > .ikonka{color:var(--ink-2);flex:none}
.kn-rozl-dok-opis{display:flex;flex-direction:column;gap:2px;flex:1 1 220px;min-width:0}
.kn-rozl-dok-numer{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.kn-rozl-dok-numer strong{font-size:var(--fs-md, 15px)}
.kn-rozl-akcje{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.kn-rozl-drobne{display:flex;gap:4px 16px;flex-wrap:wrap;padding-left:30px}
.kn-rozl-drobne:empty{display:none}
.btn-link{background:none;border:0;padding:2px 0;font:inherit;font-size:var(--fs-sm);color:var(--ink-2);
  text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.btn-link:hover{color:var(--ink)}
.btn-link:focus-visible{outline:2px solid var(--accent, #2b6cb0);outline-offset:2px;border-radius:3px}
.btn-link.groznie{color:var(--bad)}
.btn-link:disabled{opacity:.5;cursor:default}
.kn-rozl-faktura .wyjasnienie{margin:0;padding:0;border:0;font-size:var(--fs-sm);color:var(--bad)}
.kn-rozl-faktura .wyjasnienie.info,.kn-rozl-faktura .okno-formularza .wyjasnienie{color:var(--ink-2)}
.kn-rozl-faktura .okno-formularza .wyjasnienie{padding:var(--s3) var(--pad-card);border-bottom:1px solid var(--line-soft);font-size:var(--fs-sm)}

/* FAKTURY ZA ABONAMENT IT (migracja 345) — sekcja nad „Do fakturowania". */
.abonamenty .hd{flex-wrap:wrap;gap:var(--s2) var(--s3)}
.abonamenty .abo-miesiac{display:inline-flex;align-items:center;gap:6px}
.abonamenty .abo-miesiac strong{min-width:9.5em;text-align:center;font-variant-numeric:tabular-nums}
.abonamenty .abo-odbiorca{font-size:var(--fs-sm)}
.abonamenty .abo-blad{color:var(--bad);font-size:var(--fs-sm);margin-top:4px;max-width:36ch;white-space:normal}
.abonamenty tr.abo-pominiety td{color:var(--ink-3)}
.abonamenty td.num .formrow{flex-wrap:nowrap}

/* NABYWCA NA FAKTURZE — dane do faktury przy kliencie. */
.nabywca-faktury{border:1px solid var(--line-soft);border-radius:var(--radius);padding:var(--s3);margin:var(--s3) 0;display:grid;gap:var(--s2)}
.nabywca-faktury .nabywca-glowa{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--s3);flex-wrap:wrap}
.nabywca-faktury .nabywca-etykieta{font-size:var(--fs-xs, 12px);text-transform:uppercase;letter-spacing:.04em;color:var(--ink-3);margin-bottom:2px}
.nabywca-faktury .nabywca-szukaj{display:grid;gap:6px;justify-items:start}
.nabywca-faktury .nabywca-szukaj .input{width:100%;max-width:420px}
.nabywca-faktury .nabywca-lista{list-style:none;margin:0;padding:0;display:grid;gap:4px}
.abonamenty .abo-tabela td,.abonamenty .abo-tabela th{white-space:nowrap}
.abonamenty .abo-tabela td.clip{max-width:27ch;white-space:normal;text-align:left}
.abonamenty .abo-tabela td.clip > div:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kn-rozliczenie .kn-rozl-wystaw{margin-left:auto}

/* KARTA NAPRAWY — pasek akcji pogrupowany (29.09.2026): „Praca" (przydział,
   stoper, wydanie), „Dokumenty" (wydruki, panel klienta, Więcej ▾), „Status". */
.pasek-zlecenia .rzad-dokumenty{padding-top:10px;border-top:1px solid var(--line)}
.pasek-zlecenia .kn-rzad-prawa{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.kn-wiecej{position:relative;display:inline-flex}
.kn-wiecej-lista{position:absolute;right:0;top:calc(100% + 4px);z-index:30;min-width:260px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 8px 24px rgb(0 0 0 / .12);padding:4px;display:grid;gap:2px}
.kn-wiecej-poz{all:unset;box-sizing:border-box;cursor:pointer;display:grid;gap:2px;padding:8px 10px;
  border-radius:var(--radius-sm);font-weight:600;color:var(--ink)}
.kn-wiecej-poz small{font-weight:400;color:var(--ink-3);font-size:var(--fs-xs)}
.kn-wiecej-poz:hover,.kn-wiecej-poz:focus-visible{background:var(--line-soft)}
.kn-wiecej-poz:focus-visible{outline:2px solid var(--accent-border);outline-offset:-2px}
.kn-wiecej-poz.groznie{color:var(--bad)}
@media (max-width:700px){.pasek-zlecenia .kn-rzad-prawa{margin-left:0}}
