/* ============================================================================
   12-kartoteki.css — Materiały, Bloki, Klienci, Dostawcy i pozostałe katalogi
   ----------------------------------------------------------------------------
   Wszystkie kartoteki mają ten sam szkielet:
     .section-header    — tytuł + akcje
     .catalog-toolbar   — szukajka + filtry
     .table-wrap        — przewijalna ramka na tabelę
       table.catalog-table
         thead > tr[data-catalog-headrow] > th.cat-th (sortowalne)
         tr.catalog-filter-row (filtry per kolumna, zwijane)
     .catalog-pager     — stronicowanie
   Konwencja liczb: wartości i ilości do prawej, cyfry tabelaryczne.
   ============================================================================ */
/* --- Nagłówek sekcji --- */
.section-header { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); }
.section-header h1, .section-header h2 { font-size: var(--t-lg); font-weight: var(--w-bold); line-height: var(--lh-tight); }
.section-header .inline-actions { margin-left: auto; }
/* --- Pasek narzędzi kartoteki: to KARTA, nie goły rząd -----------------------
   W v8 (monolit 4066 + 24562) pasek ma własne białe tło, ramkę, promień,
   wyściółkę 12/14, cień i rozsuwa zawartość na boki (`space-between`).
   U nas był samym flexem bez tła i wyściółki — stąd wrażenie bałaganu
   w nagłówku KAŻDEJ kartoteki z tabelą. Guziki w pasku mają 40 px (27807). */
/* Wygląd paska jest WSPÓLNY dla całej aplikacji (arkusz 06) — tu tylko to,
   co odróżnia kartotekę: filtry po lewej, licznik i akcje po prawej. */
.catalog-toolbar { justify-content: space-between; }
.catalog-search-field { flex: 1 1 260px; max-width: 420px; }
/* --- KONIEC PODWÓJNEGO PASKA PRZEWIJANIA -----------------------------------
   Przewijać ma się WYŁĄCZNIE tabela. Wcześniej przewijała się i tabela, i cała
   treść strony (`.content` miał `overflow: auto` i nadmiar 9 px) — użytkownik
   widział dwa paski obok siebie. Lekarstwo to łańcuch flex od `.workspace`
   w dół: każde ogniwo `overflow: hidden` + `min-height: 0`, a dopiero
   `.table-wrap` dostaje `overflow: auto` i `flex: 1`, czyli wypełnia resztę
   panelu. `min-height: 0` jest obowiązkowe — bez niego element flex nie może
   zmaleć poniżej swojej treści i cały łańcuch przestaje działać.
   v8 ma to samo, ale przypięte do dwóch tabel (monolit 4209); u nas działa dla
   KAŻDEJ kartoteki z tabelą, żeby wszystkie zachowywały się tak samo. */
.workspace:has(> #content > .panel > .table-wrap) { display: flex; flex-direction: column; height: calc(100vh / var(--skala-ui)); min-height: 0; overflow: hidden; }
#content:has(> .panel > .table-wrap) { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; }
#content > .panel:has(> .table-wrap) { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; }
#content > .panel > .table-wrap { flex: 1; min-height: 0; max-height: none; }
/* --- Ramka tabeli: TYLKO scroll ---------------------------------------------
   Monolit ma tu dosłownie `overflow: auto` i nic więcej. Moja wersja dokładała
   tło, ramkę i promień 12 px — a ponieważ kontener przycina zawartość, ten
   promień zaokrąglał KOŃCE paska nagłówka tabeli. Miało być proste odcięcie.
   Kartę rysuje `.panel` na zewnątrz; tabela leży w niej płasko. */
.table-wrap { overflow: auto; }
/* --- Tabela kartoteki --- */
.catalog-table { font-size: var(--t-sm); }
.catalog-table thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-2); border-bottom: 1px solid var(--line-strong); padding: var(--s-2) var(--s-3); text-align: left; font-size: var(--t-xs); font-weight: var(--w-bold); color: var(--text-muted); white-space: nowrap; }
/* Ujednolicenie 11.08.2026 — hover BYŁ, ale zmiana koloru skakała natychmiast.
   Nagłówek sortowania jest `<th data-action>` w kartotekach i `<button>`
   w Projektach — fokus klawiaturą rysuje globalna reguła 01-reset.css:19. */
.cat-th.is-sortable { cursor: pointer; transition: color var(--szybko); }
.cat-th.is-sortable:hover { color: var(--text); }
.cat-sort-ind { margin-left: var(--s-1); opacity: .45; font-size: var(--t-xs); }
/* Aktywna strzałka. Celujemy w klasę `.is-active`, którą RZECZYWIŚCIE nadaje
   JS — wcześniej było `.cat-th[aria-sort]`, a tego atrybutu żaden renderer
   nie wypisywał, więc podświetlenie kierunku sortowania nigdy nie działało
   ani w kartotekach, ani w Projektach. */
.cat-sort-ind.is-active { opacity: 1; color: var(--accent-strong); }
/* `overflow: hidden` — tabela ma `table-layout: fixed`, więc kolumna ma stałą
   szerokość, ale treść dłuższa niż komórka WYLEWA SIĘ na sąsiednią zamiast się
   uciąć. W Materiałach nazwa dostawcy („KRAIBURG Relastec GmbH & Co.KG")
   nachodziła na Kategorię, a cena na Stan — tekst na tekście, nie do czytania.
   Wyjątek to kolumna z menu ⋮: tam przycięcie schowałoby rozwijaną listę. */
.catalog-table tbody td { padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); vertical-align: middle; }
/* Nagłówek sortowania — ta sama reguła (23.09.2026). Bez niej przy 1440 px „Zamówić" pokazywało
   się jako „Zamów" bez żadnego znaku, że to ucięte. Pełna nazwa i tak jest w dymku `title`. */
.catalog-table tbody td:not(.material-menu-cell):not(.catalog-col-tools), .catalog-table thead .cat-th { overflow: hidden; text-overflow: ellipsis; }
/* PRÓG SZEROKOŚCI zamiast ściskania (23.09.2026) — ten sam wzór co `.compact-data-table`
   (arkusz 27) i `.bom-preview-table` (arkusz 24): poniżej progu tabela przewija się w bok
   w `.table-wrap`, zamiast ściskać kolumny. Zmierzone przy oknie 1024 px: tabela miała 741 px,
   komórki łamały się na 4–6 linii, gwiazdka priorytetu i pola stanu („szt", „dni") były ucięte
   w prawie każdym wierszu; w Użytkownikach listy wyboru dostawały po 90 px przy treści 128–145 px.
   Progi z pomiaru, nie z głowy: Materiały i Bloki mają procenty kolumn dobrane pod ~1155 px
   (okno 1440) — sama kolumna gwiazdki (3,5%) potrzebuje tabeli ≥1143 px, stąd 1150. Użytkownikom
   wystarcza 980 (listy po 166 px ≥ 148 px treści). Na telefonie te tabele są kartami. */
:root:not([data-ui="mobile"]) .materials-stock-table { min-width: max(1150px, 100%); }
/* POPR-n31: Bloki mają kolumny do wyboru — najmniejsza szerokość tabeli rośnie z liczbą widocznych kolumn (--min-tabeli z JS). */
:root:not([data-ui="mobile"]) .block-catalog-table { min-width: max(var(--min-tabeli, 1150px), 100%); }
:root:not([data-ui="mobile"]) .rg-tabela { min-width: max(980px, 100%); }
/* ERG6-06: na tablecie 1024 taka tabela przewija się w bok — cień przy krawędzi mówi, że dalej są kolumny
   (bez niego wyglądała na uciętą). Nakładki „local" jadą z treścią i gaszą cień, gdy dojdzie się do końca. */
:root:not([data-ui="mobile"]) [data-catalog-table-wrap] { background: linear-gradient(to right, var(--surface) 40%, transparent) left / 32px 100% no-repeat local, linear-gradient(to left, var(--surface) 40%, transparent) right / 32px 100% no-repeat local, radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--text) 24%, transparent), transparent) left / 14px 100% no-repeat scroll, radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--text) 24%, transparent), transparent) right / 14px 100% no-repeat scroll; }
/* POPR-n13 (audyt 28.09.2026): PRZYPIĘTA 1. KOLUMNA. Na tablecie poziomo (1024 px) Materiały i Bloki przewijają się w bok,
   a przy tym uciekała nazwa — po przesunięciu do „Rezerwy/Dostępne” nie było wiadomo, czyj to wiersz. Nazwa zostaje
   przyklejona z lewej (Materiały: gwiazdka + nazwa, Bloki: kod z zestawienia), reszta jedzie pod nią, a kreska z cieniem
   oddziela przyklejoną część. Tylko tam, gdzie tabela (1150 px) na pewno jest szersza niż ramka: tablet (dotyk) i okno do
   1180 px — szeroki komputer bez zmian. Tabela ma wtedy dokładnie 1150 px, stąd lewa krawędź nazwy materiału liczona od tej
   szerokości (3,5 % z 1150 px = kolumna gwiazdki). */
@media (max-width: 1180px) {
  :root:not([data-ui="mobile"]) .materials-stock-table :is(th, td):is(:nth-child(1), :nth-child(2)),
  :root:not([data-ui="mobile"]) .block-catalog-table :is(th, td):first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); }
  :root:not([data-ui="mobile"]) .materials-stock-table :is(th, td):nth-child(2) { left: calc(1150px * .035); }
  :root:not([data-ui="mobile"]) :is(.materials-stock-table :is(th, td):nth-child(2), .block-catalog-table :is(th, td):first-child) { box-shadow: inset -1px 0 0 var(--line-strong), 10px 0 12px -6px color-mix(in srgb, var(--text) 28%, transparent); }
  :root:not([data-ui="mobile"]) :is(.materials-stock-table, .block-catalog-table) thead th:is(:nth-child(1), :nth-child(2)) { z-index: 3; background: var(--surface-2); }
  :root:not([data-ui="mobile"]) :is(.materials-stock-table, .block-catalog-table) tbody tr:hover > td:is(:nth-child(1), :nth-child(2)) { background: var(--surface-2); }
  :root:not([data-ui="mobile"]) .materials-stock-table tbody td:nth-child(n+6):nth-child(-n+11) { padding-inline: var(--s-1); }
  :root:not([data-ui="mobile"]) .materials-stock-table .delivery-cell .stock-unit { display: none; }
}
:root[data-ui="tablet"] .materials-stock-table :is(th, td):is(:nth-child(1), :nth-child(2)),
:root[data-ui="tablet"] .block-catalog-table :is(th, td):first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); }
:root[data-ui="tablet"] .materials-stock-table :is(th, td):nth-child(2) { left: calc(1150px * .035); }
:root[data-ui="tablet"] :is(.materials-stock-table :is(th, td):nth-child(2), .block-catalog-table :is(th, td):first-child) { box-shadow: inset -1px 0 0 var(--line-strong), 10px 0 12px -6px color-mix(in srgb, var(--text) 28%, transparent); }
:root[data-ui="tablet"] :is(.materials-stock-table, .block-catalog-table) thead th:is(:nth-child(1), :nth-child(2)) { z-index: 3; background: var(--surface-2); }
:root[data-ui="tablet"] :is(.materials-stock-table, .block-catalog-table) tbody tr:hover > td:is(:nth-child(1), :nth-child(2)) { background: var(--surface-2); }
/* Liczby bez wielokropka („−61 0…”): kolumny liczbowe (Stan … Zamówić) z węższą wyściółką, a „dni” przy każdym wierszu
   znika — nagłówek kolumny i tak mówi „Dni”. */
:root[data-ui="tablet"] .materials-stock-table tbody td:nth-child(n+6):nth-child(-n+11) { padding-inline: var(--s-1); }
:root[data-ui="tablet"] .materials-stock-table .delivery-cell .stock-unit { display: none; }
/* Wybór widocznych kolumn (widoki/kolumny-kartotek.js): Materiały z ukrytymi kolumnami zajmują szerokość ramki (bez przewijania
   w bok), więc przypięta kolumna nie jest potrzebna — przyklejenie wyłączone, żeby nazwa nie nachodziła na sąsiada.
   Bloki NIE: ich najmniejsza szerokość (--min-tabeli) maleje z liczbą widocznych kolumn (JS), a gdy nadal jest szersza
   od ramki, tabela przewija się w bok z przypiętym kodem bloku — zamiast ucinać liczby wielokropkiem. */
:root:not([data-ui="mobile"]) .materials-stock-table.ma-ukryte-kolumny { min-width: 100%; }
:root:not([data-ui="mobile"]) .materials-stock-table.ma-ukryte-kolumny :is(th, td) { position: static; box-shadow: none; }
:root[data-ui="tablet"] .catalog-table .row-menu > summary { width: 44px; height: 44px; }   /* menu ⋮ wiersza — cel dotyku 44 px */
/* Komórka menu ⋮ z wąską wyściółką — przycisk mieści się w swojej kolumnie (resztę pilnuje poszerzKolumneMenu w JS). */
.catalog-table :is(th, td).material-menu-cell { padding-inline: var(--s-1); }
.catalog-table :is(th, td).kolumna-schowana { width: 0; max-width: 0; padding: 0; overflow: hidden; border-left-width: 0; border-right-width: 0; font-size: 0; visibility: hidden; }
.kolumny-panel { position: fixed; z-index: var(--z-menu-nad-trescia); display: grid; gap: 2px; overflow: auto; padding: var(--s-2); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.kolumny-panel-tytul { margin: 0 0 var(--s-1); padding: 0 var(--s-2); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.kolumny-panel-wiersz { display: flex; align-items: center; gap: var(--s-2); min-height: var(--h-control); padding: 0 var(--s-2); border-radius: var(--r-sm); cursor: pointer; }
.kolumny-panel-wiersz:hover { background: var(--surface-2); }
/* v15 b10 (wzór Klienci): dwa równe przyciski na całą szerokość listy — w każdej kartotece tak samo. */
.kolumny-panel-stopka > .button { flex: 1; justify-content: center; }
.kolumny-panel-stopka { display: flex; justify-content: space-between; gap: var(--s-2); margin-top: var(--s-1); padding-top: var(--s-2); border-top: 1px solid var(--line); }
/* Ujednolicenie 11.08.2026 — podświetlenie wiersza wskakiwało bez przejścia. */
.catalog-table tbody tr { transition: background var(--szybko); }
.catalog-table tbody tr:hover { background: var(--surface-2); }
.catalog-table tbody tr:last-child td { border-bottom: 0; }
/* Liczby: prawa strona, jednakowa szerokość cyfr */
.price-cell, .stock-cell, .prio-cell, .delivery-cell { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Cena to WYJĄTEK od `nowrap`: mieści dwie informacje („10,00 EUR / 1 szt"
   plus waga), a kolumna ma 98 px. Z zakazem łamania treść wystawała o 8 px
   i po przycięciu komórki ginęła jednostka — na ekranie zostawało
   „10,00 EUR /". Zawijanie nic nie gubi. */
.price-cell { white-space: normal; }
/* Nazwa materiału: główna linia + opis pod spodem */
.material-name-line { font-weight: var(--w-medium); color: var(--text); }
.material-meta-line { font-size: var(--t-xs); color: var(--text-muted); }
/* --- Stany magazynowe: kolor niesie znaczenie, nie ozdobę --- */
.stock-negative { color: var(--danger); font-weight: var(--w-bold); }
/* ERG6-07: stan poniżej zera także w polu do wpisania — czerwony jak w kolumnie „Dostępne”. */
.stock-inline-input.stock-negative { color: var(--danger); -webkit-text-fill-color: var(--danger); }
/* ERG6-07: „Na stanie: X” pod nazwą materiału tylko na telefonie (na komputerze stan ma własną kolumnę). */
:root[data-ui="mobile"] .catalog-table td .tiny.material-stan-karta { display: block; }
/* ERG6-07: nagłówki Materiałów bez ucinania — strzałka sortowania może zejść pod nazwę (inline-block daje miejsce
   złamania), a trzy wąskie kolumny liczbowe (Rezerwy, Dostępne, Zamówić) mają mniejszą wyściółkę boczną. */
.materials-stock-table thead .cat-th { white-space: normal; vertical-align: top; } /* E3: nazwy kolumn w jednej linii u góry, także gdy strzałka zeszła niżej (dawniej „Minimum”, „Rezerwy” stały wyżej niż „Materiał”). */
.materials-stock-table thead .cat-th .cat-sort-ind { display: inline-block; }
.materials-stock-table thead .cat-th:nth-child(n+9):nth-child(-n+11) { padding-inline: var(--s-1); }
.stock-below-min { color: var(--warn-strong); font-weight: var(--w-medium); }
.stock-to-order { color: var(--accent-strong); }
.stock-zero { color: var(--text-faint); }
/* Pole edycji stanu bezpośrednio w tabeli */
/* NAPRAWA 11.08.2026 — opakowanie stanu robi się KONTENEREM, który się mieści.
   W komórce siedzi pole liczby ORAZ jednostka: `<span class="stock-edit">
   <input><span class="stock-unit">szt</span></span>`. Razem 75 px (60 + 15)
   w komórce dającej 60 px na treść — a komórka ma `text-overflow: ellipsis`,
   więc obok KAŻDEJ liczby w trzech kolumnach rysował się wielokropek. To, co
   wyglądało jak „0 …", było po prostu ucinaną jednostką.
   Dawne `width: 72px` nigdy nie działało: `<span>` jest elementem LINIOWYM,
   a na takim `width` się ignoruje — stąd 75 px, czyli sama szerokość treści.
   `inline-flex` sprawia, że wymiar zaczyna obowiązywać, jednostka ma pierwszeństwo
   (nie skurczy się), a pole oddaje jej miejsce. Sufit 72 px zostaje dla widoków,
   gdzie miejsca jest więcej (Zamówienia). */
.stock-edit { display: inline-flex; align-items: center; justify-content: flex-end; gap: 2px; width: 100%; max-width: 72px; height: var(--h-control-sm); text-align: right; font-variant-numeric: tabular-nums; }
/* Skan 13.09.2026: przy sufitcie 72 px jednostka „para" / „dni" zostawiała polu ~24 px — „14" czytało się
   jak „1", a „0" jak „C". Pole ma PODŁOGĘ na 4 cyfry (tabular-nums: 1ch = szerokość cyfry) i nie oddaje jej
   jednostce; komórka rośnie o te kilka pikseli zamiast ucinać liczbę. */
.stock-edit > .stock-inline-input { flex: 1 0 auto; min-width: calc(3ch + var(--s-2)); padding-inline: var(--s-1); }
.stock-edit:has(> .stock-unit) { max-width: none; width: auto; }
.stock-edit > .stock-unit { flex: none; }
/* Kolumna „Dni" (Materiały, komputer): pole liczby dni jest dwucyfrowe — przy szerokości pola stanu jednostka „dni" ucinała się do „dni…" (skan 14.09.2026). */
.materials-stock-table .delivery-cell .stock-edit > .delivery-inline-input { flex: none; width: calc(2ch + var(--s-4)); min-width: 0; }
/* --- Filtry per kolumna (wiersz pod nagłówkiem, zwijany) ---
   Komórki tego wiersza to `<th>`, nie `<td>` (public/js/widoki/
   → renderCatalogFilterCells). Reguła na `td` NIGDY nie działała.
   `position: static` jest konieczne: wiersz siedzi w <thead>, więc bez tego
   dziedziczy przyklejenie po nagłówku i dwa sticky wiersze na siebie nachodzą. */
/* `overflow: hidden` na komórce filtra jest KONIECZNE — patrz reguła
   `.catalog-col-filter` niżej: bez tego pole rozwijane wylewa się na sąsiednie
   kolumny i wiersz filtrów wygląda jak rozsypany. */
/* Monolit (4074): `flex: 1 1 auto` + gap 8 px + `min-width: 0`. Bez `flex`
   grupa nie zajmowała przydzielonego miejsca w pasku filtrów — zmierzony
   rozjazd 1101 px. */
.catalog-filter-group { display: flex; flex: 1 1 auto; align-items: center; gap: var(--s-2); min-width: 0; }
/* --- WIZYTÓWKI: Klienci i Dostawcy -----------------------------------------
   Te dwie kartoteki nie mają danych do porównywania w kolumnach — mają karty
   kontaktowe. W tabeli sześć z siedmiu kolumn pokazywało „-", a lista
   dodatkowych kontaktów (`contacts[]`) nie była widoczna wcale.
   Siatka `auto-fill` układa tyle kart w rzędzie, ile się mieści; przy wąskim
   oknie schodzi do jednej kolumny bez żadnego progu w media query. */
/* Tło spisu jest o ton ciemniejsze od karty. Bez tego biała karta leżała na
   białym panelu i granicę rysowała wyłącznie linia w kolorze --line — karty
   zlewały się z tłem. Teraz białe wizytówki odcinają się jak kartki w segregatorze. */
.party-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--s-3); align-content: start; padding: var(--s-3) 14px; background: var(--surface-2); }
/* Litera spisu zajmuje CAŁY wiersz siatki (1 / -1), więc karty po niej zaczynają
   się od nowej linii — jak sekcje w książce telefonicznej. Kreska za literą to
   ::after, dzięki czemu w treści strony zostaje sama litera. */
.party-litera { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--s-2); color: var(--text-muted); font-size: var(--t-sm); font-weight: var(--w-bold); }
.party-litera::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--line); }
/* Wizytówka (Klienci, Dostawcy): cienka ramka jak każda karta, znakiem firmy jest kółko z inicjałami.
   E3 (27.09.2026, zgłoszenie W2): był gruby kolorowy pasek po lewej („grzbiet segregatora”) — ten sam
   szablonowy „side-stripe”, który W2 zdjął z kafli Pulpitu (02ea1ff). Pod kursorem karta dalej „podnosi się”
   cieniem, a kółko z inicjałami bierze pełny akcent. */
.party-card { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--cien-1); transition: border-color var(--szybko), box-shadow var(--szybko); }
.party-card:hover { border-color: var(--line-strong); box-shadow: var(--cien-2); }
.party-card:hover .party-avatar { background: var(--accent-hover); color: var(--surface); }
.party-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s-2); }
.party-avatar { background: var(--accent-soft); color: var(--accent-strong); font-size: min(var(--t-sm), calc(var(--avatar-d) * .38)); font-weight: var(--w-heavy); }
.party-title { min-width: 0; }
/* Nazwa firmy w DWÓCH liniach zamiast wielokropka (skan 13.09.2026: 48 nazw uciętych, choć karta miała
   ~180 px wolnego — niewidoczne do najechania „Edytuj / Usuń" i tak rezerwują miejsce w nagłówku). */
.party-title > strong { display: -webkit-box; overflow: hidden; font-size: var(--t-md); font-weight: var(--w-bold); line-height: var(--lh-tight); overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.party-person { display: block; overflow: hidden; color: var(--text-muted); font-size: var(--t-xs); text-overflow: ellipsis; white-space: nowrap; }
/* Akcje wiersza pokazują się dopiero pod kursorem — karta ma być czytelna,
   a nie zastawiona guzikami. Na dotyku (brak hovera) zostają widoczne. */
.party-act { opacity: 0; transition: opacity var(--szybko); }
.party-card:hover .party-act, .party-card:focus-within .party-act { opacity: 1; }
@media (hover: none) { .party-act { opacity: 1; } }
/* Ujednolicenie 11.08.2026 — gap 3px → --s-1 (4 px). Stos wierszy „etykieta:
   wartość" w wizytówce to ta sama rola co `.project-person-lines` (29) —
   obie miały 3 px spoza skali. */
.party-body { display: grid; gap: var(--s-1); }
/* Etykieta stałej szerokości — wartości układają się w jednej osi we
   wszystkich kartach, więc oko czyta je jak kolumnę, bez tabeli. */
.party-line { display: grid; grid-template-columns: 74px minmax(0, 1fr); gap: var(--s-2); align-items: start; font-size: var(--t-base); }
.party-lbl { color: var(--text-faint); font-size: var(--t-xs); font-weight: var(--w-bold); line-height: 1.5; }
.party-val { min-width: 0; overflow-wrap: anywhere; }
.party-notes .party-val { color: var(--text-muted); font-size: var(--t-xs); }
.party-empty { color: var(--text-faint); font-size: var(--t-xs); font-style: italic; }
/* POPR-n42 → v15 b10: reguły kartoteki Klienci (wiersze, pole logo, wizytówki, pasek) — 4-widoki/12c-klienci.css. */
:root[data-ui="tablet"] .party-card .party-val > a, :root[data-ui="tablet"] .party-contact > a.party-val { display: inline-flex; align-items: center; min-height: 44px; }
/* Pusty stan to jedno zdanie na całą szerokość — w siatce etykieta|wartość wpadał do kolumny 74 px (4 linie). */
.party-line.party-empty { display: block; }
/* Ujednolicenie 11.08.2026 — dodane `transition`: hover był, ale bez przejścia. */
.party-more { display: flex; align-items: center; gap: var(--s-2); width: 100%; padding: var(--s-1) 0; border: 0; border-top: 1px solid var(--line); background: none; color: var(--accent-strong); font-size: var(--t-xs); font-weight: var(--w-bold); text-align: left; cursor: pointer; transition: color var(--szybko); }
.party-more:hover { color: var(--accent-strong); }
.party-more-chevron { width: 14px; height: 14px; transition: transform var(--szybko); }
.party-more[aria-expanded="true"] .party-more-chevron { transform: rotate(90deg); }
/* Dodatkowe kontakty otwierają się jako OSOBNE OKIENKO nad spisem — karta nie
   rośnie i nie rozpycha sąsiadów w siatce. Musi być `fixed`, bo `.panel` ma
   `overflow: hidden` i `absolute` zostałby obcięty; współrzędne wylicza skrypt
   i wpisuje stylem inline — dokładnie tak jak `.combo-panel` (03-kontrolki). */
.party-contacts { position: fixed; z-index: var(--z-lista); display: grid; gap: var(--s-2); width: 300px; max-width: calc(100vw / var(--skala-ui) - var(--s-4)); max-height: calc(60vh / var(--skala-ui)); overflow-y: auto; padding: var(--s-2); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.party-contacts[hidden] { display: none; }
.party-contact { display: grid; gap: 1px; padding: var(--s-2); border-radius: var(--r-sm); background: var(--surface-2); font-size: var(--t-xs); }
.party-contact > strong { font-size: var(--t-base); }
.party-role { color: var(--text-muted); }
/* --- PANEL FILTRÓW (rozwijany pod paskiem narzędzi) -------------------------
   Zastąpił wiersz filtrów wciśnięty pod nagłówek tabeli. Powód był
   arytmetyczny: 12-13 kolumn na 1660 px daje 130 px na kolumnę, a zmierzone
   pola miały 27-142 px — sześć z dziesięciu nie mieściło własnej podpowiedzi,
   a rozwijana lista brała szerokość pola i ucinała nazwy.
   Tu każde pole ma minimum 220 px i etykietę nad sobą. */
/* SZUFLADA po lewej — wchodzi na miejsce menu, chowa się tym samym przyciskiem.
   Dlaczego nie poziomy panel: przy 10 filtrach pola dzieliły szerokość okna
   i znów robiły się za wąskie, czyli wracał ten sam problem co w wierszu
   tabeli. W pionie każde pole ma pełne ~270 px — widać etykietę I wartość.
   Szuflada zasłania menu boczne (szerokość 320 px kontra 238 px menu),
   więc nie zabiera miejsca tabeli i nie przesuwa układu. */
.catalog-filter-drawer { position: fixed; left: 0; top: 0; bottom: 0; z-index: var(--z-szuflada); display: flex; flex-direction: column; gap: var(--s-3); width: min(320px, 88vw / var(--skala-ui)); padding: var(--s-3); overflow-y: auto; border-right: 1px solid var(--line-strong); background: var(--surface); box-shadow: var(--cien-3); }
.catalog-filter-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); padding-bottom: var(--s-2); border-bottom: 1px solid var(--line); }
.catalog-filter-drawer-head > strong { font-size: var(--t-md); font-weight: var(--w-bold); }
/* Pola JEDNO POD DRUGIM — to jest cały sens szuflady. */
.catalog-filter-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-3); align-content: start; }
/* Plakietki na dole szuflady, oddzielone kreską — widać, co jest ustawione,
   nie przewijając pól z powrotem w górę. */
.catalog-filter-drawer .catalog-filter-chips { margin-top: auto; padding-top: var(--s-3); border-top: 1px solid var(--line); }
.catalog-filter-field > label { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
/* Pole w panelu ma pełną szerokość swojej komórki siatki — inaczej wracamy
   do tego samego problemu co w kolumnach tabeli. */
.catalog-filter-drawer .catalog-col-filter, .catalog-filter-drawer .combo, .catalog-filter-drawer .combo-input { width: 100%; min-width: 0; height: var(--h-control); }
.catalog-filter-drawer .catalog-col-range { grid-template-columns: 1fr 1fr; }
.catalog-filter-drawer .catalog-col-range:has(.catalog-col-unit) { grid-template-columns: 1fr 1fr auto; }
/* Plakietki: co jest ustawione, widoczne po wybraniu — tego brakowało
   najbardziej, bo w polu szerokim na 27 px nie było widać nic. */
.catalog-filter-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.catalog-filter-chip { display: inline-flex; align-items: center; gap: var(--s-1); padding: 3px var(--s-2); border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent-strong); font-size: var(--t-xs); font-weight: var(--w-medium); }
.catalog-filter-chip strong { font-weight: var(--w-bold); }
/* Ujednolicenie 11.08.2026 — dodane `transition`: krzyżyk zmieniał kolor skokiem. */
.catalog-filter-chip-x { padding: 0 2px; border: 0; background: none; color: inherit; font-size: var(--t-md); line-height: 1; cursor: pointer; transition: color var(--szybko); }
.catalog-filter-chip-x:hover { color: var(--danger); }
.catalog-filter-empty { color: var(--text-faint); font-size: var(--t-xs); }
/* Zakres „od-do": dwa pola obok siebie. Gdy kolumna ma JEDNOSTKĘ („kg" przy
   Transporcie), dochodzi TRZECIE dziecko — bez własnej kolumny w siatce
   trafiało do drugiego rzędu i rozpychało cały wiersz filtrów.
   `auto` daje jednostce dokładnie tyle, ile zajmuje jej napis. */
.catalog-col-range { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-1); min-width: 0; align-items: center; }
.catalog-col-range:has(.catalog-col-unit) { grid-template-columns: 1fr 1fr auto; }
/* `min-width: 0` — TO JEST PRZYCZYNA ROZSYPANEGO WIERSZA FILTRÓW.
   Pole rozwijane bierze domyślnie szerokość NAJDŁUŻSZEJ OPCJI i `width: 100%`
   samo tego nie cofa. Zmierzone w Materiałach: kolumna „Prio." ma 64 px,
   a jej filtr rozpychał się do 166 px; „Kategoria" 117 kontra 166 — pola
   nachodziły na sąsiednie kolumny i stąd wrażenie bałaganu.
   `text-overflow` ucina długą nazwę kategorii zamiast rozpychać kolumnę. */
.catalog-col-filter { width: 100%; min-width: 0; max-width: 100%; height: var(--h-control-sm); overflow: hidden; text-overflow: ellipsis; }
/* Pola wyboru w wierszu filtrów są PODMIENIANE NA COMBO (upgradeSelectsToCombo):
   natywny `<select>` znika pod `.combo-native`, a widoczne jest `.combo-input`.
   Dlatego reguła na `.catalog-col-filter` sama nie wystarczała — trafiała
   w schowany element. To combo trzeba zwęzić do szerokości kolumny. */
/* --- Menu wiersza (trzy kropki) --- */
/* `width: 1%` to sztuczka dla KOMÓRKI TABELI (kolumna zwęża się do treści).
   Klasa `.catalog-col-tools` siedzi jednak w DWÓCH miejscach: na komórce
   tabeli i na kontenerze przycisku „Filtry kolumn" w pasku narzędzi.
   Bez zawężenia do `th`/`td` reguła zgniatała ten kontener w pasku do 1%
   szerokości i przycisk nachodził na „Dostawca". */
th.material-menu-cell, td.material-menu-cell,
th.catalog-col-tools, td.catalog-col-tools { width: 1%; text-align: center; }
/* W pasku narzędzi to zwykła grupa przycisków — ma zajmować tyle, ile treść.
   Ujednolicenie 11.08.2026 — gap 7px → --s-2, jak `.toolbar` w którym ta grupa
   siedzi (06-elementy) i jak `.top-actions` (04-uklad). */
.catalog-toolbar .catalog-col-tools { display: inline-flex; align-items: center; gap: var(--s-2); }
/* NAPRAWA 11.08.2026 — MENU ⋮ ODLATYWALO DO ROGU CALEJ STRONY.
   `.row-menu-panel` (niżej w tym pliku) jest `position: absolute`,
   ale ZADEN arkusz nie ustawial `position` na jego kotwicy. Caly lancuch
   przodkow (td → tr → table → .table-wrap → .panel → .content → .app-shell)
   tez jej nie mial, wiec blokiem zawierajacym stawal sie initial containing
   block: menu ladowalo w prawym GORNYM rogu okna, 34 px od gory, nad paskiem
   gornym (--z-dymek 10000 > --z-topbar 20). Jedna linia to naprawia. */
.row-menu { position: relative; }
/* Ujednolicenie 11.08.2026 — dodane `transition`: tło menu ⋮ wskakiwało skokiem. */
.row-menu > summary { list-style: none; display: grid; place-items: center; width: var(--h-control-sm); height: var(--h-control-sm); border-radius: var(--r-sm); cursor: pointer; color: var(--text-muted); transition: background var(--szybko), color var(--szybko); }
.row-menu > summary::-webkit-details-marker { display: none; }
.row-menu[open] > summary, .row-menu > summary:hover { background: var(--surface-3); color: var(--text); }
/* --- Kolumna audytu (kto / kiedy) --- */
/* NAPRAWA 11.08.2026 — WIELOKROPEK dla drugiej linijki w komórce tabeli.
   `.tiny` to podpis pod treścią komórki (wymiary bloku, nazwa dostawcy).
   Miał `white-space: nowrap` i `overflow: visible`, a komórka `overflow: hidden`
   — czyli tekst był ucinany przez RODZICA, w połowie znaku i bez wielokropka.
   Zmierzone w kartotece Bloków: 209 wystąpień, np. „30 x 30 x 30 cm" w 84 px
   komórki przy 90 px treści (widać było „30 x 30 x 30 c").
   Zawężone do `.catalog-table td`, bo `.tiny` w tabeli walidacji BOM ma inną
   rolę — jest tam dopiskiem w LINII (24-bom-katalogi.css:54) i nic mu nie brakuje. */
.catalog-table td .tiny { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.catalog-table td .tiny.material-stan-karta { display: none; }   /* ERG6-07: tylko na telefonie (niżej) */
/* NAPRAWA 11.08.2026 — dopisany WIELOKROPEK.
   Obie linijki miały `white-space: nowrap` (dziedziczone z `.audit-cell`), ale
   nie miały `overflow` ani `text-overflow`, więc komórka po prostu UCINAŁA je
   w połowie znaku. Zmierzone w kartotece Materiałów: „Bartek Kusztal/Bar" —
   92 px miejsca przy 146 px treści, bez żadnego znaku, że tekst jest niepełny.
   To sam czubek: w kartotece Bloków ten sam defekt policzyłem 205 razy.
   Wielokropek niczego nie ukrywa — mówi prawdę o tym, że treść jest skrócona. */
.audit-cell { font-size: var(--t-xs); color: var(--text-muted); white-space: nowrap; }
.audit-dates, .audit-users { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.audit-users { color: var(--text-faint); }
/* --- Stronicowanie — STOPKA ramki, symetryczna do paska nagłówka -------------
   Wyściółka boczna 14 px, dokładnie ta sama co w pasku narzędzi (arkusz 06).
   Wcześniej było `padding: 12px 0` — zero po bokach, więc „Poprzednia strona"
   i „Następna strona" dotykały krawędzi karty, tak samo jak wcześniej pola
   w nagłówku. Góra i dół ramki mają wyglądać tak samo. */
.catalog-pager { justify-content: center; }
/* E3: pusty wynik prostej kartoteki (Klienci, Wynajem, Użytkownicy…) jak pusty wiersz tabeli Materiałów — z odstępem, na środku (dawniej przyklejony do lewej krawędzi ramki). */
.catalog-empty { padding: var(--s-5); color: var(--text-muted); text-align: center; }
/* ============================================================================
   RESPONSYWNOŚĆ
   ============================================================================ */
@media (max-width: 1180px) {
  .table-wrap { max-height: calc(100vh / var(--skala-ui) - 190px); }
  /* Audyt schodzi pierwszy — najmniej istotny: komórki i nagłówek tej samej kolumny (Materiały, Bloki).
     E3 (27.09.2026): nagłówek po WŁASNEJ klasie `.audit-head`. Dawniej `th:nth-last-child(2)` każdej kartoteki
     — w prostych tabelach (Dziennik zmian, Profile marż, Atrakcje, Transport…) chował nagłówek Notatki/Status/
     Metoda, a jego komórki zostawały, więc „Akcje” stało nad notatkami, a przyciski bez nagłówka. */
  .audit-cell, .audit-head { display: none; }
}
/* Na telefonie tabela nie ma sensu — wiersz staje się kartą.
   JS stempluje komórki atrybutem data-label, stąd ::before z etykietą. */
:where(:root[data-ui="mobile"]) .catalog-table thead { display: none; }
:where(:root[data-ui="mobile"]) .catalog-table, :where(:root[data-ui="mobile"]) .catalog-table tbody, :where(:root[data-ui="mobile"]) .catalog-table tr, :where(:root[data-ui="mobile"]) .catalog-table td { display: block; }
:where(:root[data-ui="mobile"]) .catalog-table tr { margin-bottom: var(--s-2); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); padding: var(--s-2); }
:where(:root[data-ui="mobile"]) .catalog-table td { display: grid; grid-template-columns: minmax(90px, 40%) 1fr; gap: var(--s-2); border: 0; padding: var(--s-1) 0; text-align: left; }
:where(:root[data-ui="mobile"]) .catalog-table td::before { content: attr(data-label); font-size: var(--t-xs); font-weight: var(--w-bold); color: var(--text-muted); }
:where(:root[data-ui="mobile"]) .price-cell, :where(:root[data-ui="mobile"]) .stock-cell, :where(:root[data-ui="mobile"]) .prio-cell, :where(:root[data-ui="mobile"]) .delivery-cell { text-align: left; }
:where(:root[data-ui="mobile"]) .catalog-toolbar { flex-direction: column; align-items: stretch; }
/* --- Znak zapytania w pasku zakładek (z dawnego 28, K17) --- */
/* Znak zapytania w pasku zakładek. Stoi PO zakładkach, odsunięty `margin-left`,
   żeby nie wyglądał na trzecią zakładkę.
   ⛔ WYGLĄD PRZENIESIONY 18.08.2026 do `03-kontrolki.css` (`.help-button`) — tu
   zostaje sam odstęp. Wcześniej ten przycisk był SZARY I PRZEZROCZYSTY, podczas
   gdy ten sam przycisk w oknach był niebieskim kółkiem. Właściciel zobaczył oba
   obok siebie: „ta niebieska ikona to jest przycisk pomocy!!!". */
.help-button { margin-left: var(--s-3); }
/* NAPRAWA 11.08.2026 — trzy rzeczy naraz (kotwica siedzi w 12-kartoteki.css):
   `top: 34px` — surowa i nietrafiona liczba: przycisk ma --h-control-sm (27 px),
     wiec menu wisialo 7 px za nisko. Konwencja calej aplikacji (22:104, 24:246,
     27:99) to `calc(100% + var(--s-1))` i tak teraz jest.
   `--r-lg` (12) -> `--r` (9): kanon mowi okna 12, MENU 9. Byl jedynym menu
     w projekcie z promieniem okna.
   `max-width` dodany — panel nie mial zadnego ograniczenia, wiec dluga nazwa
     pozycji mogla go rozciagnac poza ekran. */
.row-menu-panel { position: absolute; top: calc(100% + var(--s-1)); right: 0; z-index: var(--z-dymek); max-width: min(240px, calc(100vw / var(--skala-ui) - var(--s-4))); padding: var(--s-2); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.row-menu-panel .inline-actions { flex-direction: column; gap: var(--s-1); }
.row-menu-panel .button { width: 100%; justify-content: center; }
/* === KONTA KLIENTÓW — okno „Konta klientów” z karty klienta (F8c, v14, 27.09.2026) ==========================
   Dom klas `.konta-klienta-*` / `.konto-klienta-*` (public/js/okna/kartoteki-konta-klientow.js). Grupy = `.panel`
   (skórka okna W1 robi z nich białe grupy), status = `.status-pill` z tonem. Wiersz konta: osoba + stan w górnym
   rzędzie, zakres + przyciski w dolnym — mieści się w oknie 760 px bez poziomego przewijania. Telefon: 9-telefon/5. */
.modal.konta-klienta-modal { --okno-w: 780px; }
.konta-klienta-lista { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
.konto-klienta-wiersz { display: grid; grid-template-areas: "osoba stan" "zakres akcje"; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-1) var(--s-3); align-items: center; padding: var(--s-3) 0; }
.konto-klienta-wiersz + .konto-klienta-wiersz { border-top: 1px solid var(--kreska-wlos); }
.konto-klienta-osoba { grid-area: osoba; display: grid; min-width: 0; }
.konto-klienta-osoba strong, .konto-klienta-osoba small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.konto-klienta-osoba small { color: var(--text-muted); font-size: var(--t-sm); }
.konto-klienta-stan { grid-area: stan; justify-self: end; }
.konto-klienta-zakres { grid-area: zakres; min-width: 0; color: var(--text-muted); font-size: var(--t-sm); }
.konto-klienta-akcje { grid-area: akcje; flex-wrap: wrap; }
.konta-klienta-formularz { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
.konta-klienta-formularz :is(.full, .field:has([data-konto-kontakt])) { grid-column: 1 / -1; }
.konta-klienta-formularz > .field-hint { margin: 0; }
.konta-klienta-projekty { display: grid; gap: var(--s-1); max-height: 220px; overflow: auto; }
.konta-klienta-link p { margin: 0 0 var(--s-3); line-height: 1.45; }
.konta-klienta-link-pole { display: flex; gap: var(--s-2); }
.konta-klienta-link-pole input { flex: 1 1 auto; min-width: 0; font-family: var(--font-mono); font-size: var(--t-sm); }
/* === PRZEKAŻ KLIENTÓW — okno z paska kartoteki Klienci (F8d, v14, 27.09.2026; public/js/okna/klienci-przekazanie.js) === */
.modal.przekazanie-klientow-modal { --okno-w: 720px; }
.przekazanie-osoby { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
.przekazanie-osoby .field, .przekazanie-osoby select { min-width: 0; max-width: 100%; }
.przekazanie-podsumowanie { margin: 0 0 var(--s-3); line-height: 1.45; }
.przekazanie-lista { display: grid; gap: 0; margin: 0 0 var(--s-2); padding: 0; list-style: none; }
.przekazanie-klient { display: grid; gap: 2px; padding: var(--s-2) 0; }
.przekazanie-klient + .przekazanie-klient { border-top: 1px solid var(--kreska-wlos); }
.przekazanie-klient small { padding-left: 26px; color: var(--text-muted); font-size: var(--t-sm); }
/* AN1 (v15 b16): ostrzeżenie o cenach przed przekazaniem — ile niesprzedanych projektów zmieni cenę („było → będzie”). */
.przekazanie-ceny { display: grid; gap: var(--s-1); margin: 0 0 var(--s-3); padding: var(--s-2) var(--s-3); border-radius: var(--r); background: var(--warn-soft); color: var(--text); font-size: var(--t-sm); line-height: 1.45; }
.przekazanie-ceny p { margin: 0; }
.przekazanie-ceny-lista { margin: 0; padding-left: var(--s-4); font-variant-numeric: tabular-nums; }
/* F9d: „Co widzi klient” — przełączniki w dwóch kolumnach (telefon: jedna, 9-telefon/5). */
.konta-klienta-widocznosc { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-4); }
.konta-klienta-widocznosc .checkbox-line { align-items: flex-start; min-height: 44px; }
.konta-klienta-widocznosc .checkbox-line input { margin-top: 3px; }
.konta-klienta-widocznosc .checkbox-line span { display: grid; }
.konta-klienta-widocznosc small { color: var(--text-muted); font-size: var(--t-sm); }
/* === DZIENNIK ZMIAN (POPR-n34, 28.09.2026) — filtry nad tabelą, „Gdzie w programie” jako link ===
   Markup: public/js/widoki/kartoteki-dziennik.js. */
.dziennik-filtry { display: flex; flex-wrap: wrap; align-items: end; gap: var(--s-2) var(--s-3); padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
.dziennik-filtr { display: grid; gap: var(--s-1); flex: 0 1 200px; min-width: 150px; margin: 0; }
.dziennik-filtr > span { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.dziennik-tabela td { vertical-align: top; }
.dziennik-tabela :is(th, td):first-child { width: 150px; white-space: nowrap; }
.dziennik-tabela :is(th, td):nth-child(2) { width: 22%; }
.dziennik-tabela :is(th, td):last-child { width: 22%; }
.dziennik-tabela .dziennik-co strong { font-weight: var(--w-medium); }
.dziennik-kiedy .tiny { display: inline; color: var(--text-muted); }   /* godzina w tej samej linii co data */
.dziennik-link { padding: 0; border: 0; background: none; color: var(--accent-strong); font: inherit; text-align: left; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.dziennik-link:hover { color: var(--accent); }
:where(:root[data-ui="mobile"], :root[data-ui="tablet"]) .dziennik-link { min-height: var(--h-control); }
:where(:root[data-ui="mobile"]) .dziennik-filtry { padding: 0 0 var(--s-3); border-bottom: 0; }
:where(:root[data-ui="mobile"]) .dziennik-filtr { flex: 1 1 140px; }

/* DEC-18 (28.09.2026): panel „Import z Excela” nad tabelą kartoteki (widoki/kartoteki-import-eksport.js) — treść jak zakładka
   importu w Raportach (klasy dash-*, raporty-pasek z 27-raporty.css), tu tylko ramka i nagłówek. */
.kartoteka-import { display: grid; gap: var(--s-3); margin: 0 14px var(--s-3); padding: var(--s-3) var(--s-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-2); }
.kartoteka-import-naglowek { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.kartoteka-import-naglowek h3 { margin: 0; font-size: var(--t-md); font-weight: var(--w-strong); }
