/* ============================================================================
   19-modale-tresc.css — ZAWARTOŚĆ okien dialogowych.
   Rama okna (tło, nagłówek, stopka, przewijanie) jest w 05-komponenty.css.
   Tutaj jest to, co siedzi w środku.

   ODKRYCIE, na którym stoi cały plik: okna projektu, materiału, bloku,
   konstrukcji, dostawcy, usługi, ekipy i planowania mają IDENTYCZNY szkielet —
   kolumna boczna + kolumna główna, a w nich sekcje („panele") z nagłówkiem
   i siatką pól. W monolicie każde okno miało własny komplet reguł (~1500 linii
   powtórzeń). Tutaj jest JEDEN wzorzec i kilka wariantów; nazwy klas z JS-a
   podpinamy do niego listą selektorów, zamiast pisać je od nowa.
   ============================================================================ */
/* Szerokość okna niesie --okno-w z 05-komponenty — o rozmiarze decyduje treść.
   Wartości 1:1 z monolitem (zmierzone), nie „na oko". */
.project-modal, .construction-modal { --okno-w: 1600px; }
.crew-modal, .transport-modal, .material-modal { --okno-w: 1400px; }
/* Okno Bloków w v8 NIE MA ograniczenia szerokości (monolit 7995:
   `.modal.block-modal.full-height { max-width: 100% }`) — wypełnia ekran.
   Zakucie go na 1400 px odbierało 380 px i ściskało cały środek: panele
   komponentów 909 zamiast 1296 px, kolumny 463 zamiast 655 px. */
/* Okno Bloków wykorzystuje szeroki monitor i ROŚNIE Z EKRANEM także w pionie
   (monolit 27570): sufit 1880×1040, a nie kartotekowe 760 px wysokości.
   Przy niższym suficie kolumna boczna przewijała się o 40 px więcej. */
.modal.block-modal { --okno-w: 1880px; }
.modal.catalog-modal.block-modal.full-height { width: min(1880px, 100%); }
/* Okno Design zajmuje CAŁĄ szerokość ekranu (monolit: `width: 100vw`).
   Na domyślnych 1120 px podgląd osi czasu dostawał 357 px i harmonogram
   trzeba było przewijać na kilka ekranów. */
.design-modal { --okno-w: calc(100vw / var(--skala-ui)); }
/* Konstrukcja OTWARTA Z DESIGNU to ma być TO SAMO okno co Design — zmienia się
   tylko prawa strona. Bez tego okno przeskakiwało z 1880 na 1600 px i przesuwało
   się o 140 px w prawo (zmierzone przy ekranie 1920), więc wyglądało jak drugie,
   węższe okno. Konstrukcja otwarta poza Designem (bez bocznego menu) zostaje 1600 px. */
.modal.construction-modal.construction-in-design { --okno-w: calc(100vw / var(--skala-ui)); }
/* === 0. SKÓRKA OKNA — JEDNA na komputerze i telefonie (W1, 27.09.2026) =======
   Właściciel 26.09: „okna popup mają wyglądać i mieć takie same kolory” na PC i na telefonie. Wzorcem jest
   skórka telefonu zatwierdzona 13.09: szare tło okna (--okno-tlo, 05-komponenty), na nim BIAŁE GRUPY bez ramek
   (promień --grupa-r), sekcje bez kreski pod nagłówkiem, zwykła pisownia (bez wersalików z rozstrzeleniem).
   Reguły przeniesione z 9-telefon/2-okna.css §1 (tam zostało tylko to, co wymusza wąski ekran: bez wcięć
   kolumn) i z listy grup 9-telefon/1-podstawa.css §7 (klasy, które występują w oknach). `#modal-root` daje
   wagę ponad reguły wyglądu poszczególnych okien, tak jak wcześniej na telefonie. Kolory tylko z tokenów. */
/* Powłoki edytorów miały własne szare tło, a kolumny boczne były białe z kreską — w oknie tło daje samo okno. */
#modal-root :is(.block-editor-form, .material-editor-form, .supplier-editor-form, .work-service-editor-form, .transport-editor-form, .installation-crew-editor-form, .project-editor-shell, .design-workspace, .construction-editor-grid, .offer-builder, .offer-search-layout, .project-card-form) { background: transparent; }
#modal-root :is(.block-editor-side, .material-editor-side, .supplier-editor-side, .work-service-editor-side, .transport-editor-side, .crew-editor-side, .block-editor-main, .material-editor-main, .supplier-editor-main, .work-service-editor-main, .transport-editor-main, .crew-editor-main, .design-construction-sidebar, .offer-section, .offer-selected-panel, .offer-results-panel) { border: 0; background: transparent; }
/* Grupa = biała powierzchnia bez ramki i bez cienia; karta w grupie traci ramkę i tło (bez „karty w karcie”). */
#modal-root :is(.panel, .form-panel, .material-editor-panel, .work-service-editor-panel, .transport-editor-panel, .block-editor-panel, .supplier-editor-panel, .crew-editor-panel, .project-card-stack, .calculation-command-panel, .design-core-panel, .design-description-panel, .design-attachment-panel, .construction-bom-panel, .construction-presentation-panel, .construction-dimensions-panel, .todo-tree, .work-service-side-card, .crew-side-card, .block-side-section, .material-side-section, .supplier-side-section, .offer-filter-panel, .offer-row) { border-color: transparent; border-radius: var(--grupa-r); background: var(--surface); box-shadow: none; }
#modal-root :is(.panel, .form-panel, .material-editor-panel, .work-service-editor-panel, .transport-editor-panel, .block-editor-panel) :is(.material-metric-card, .project-field-card, .form-panel, .panel, .card) { border-color: transparent; background: transparent; box-shadow: none; }
#modal-root :is(.block-panel-head, .material-panel-head, .form-panel-head, .project-panel-head, .panel > header) { border-bottom: 0; padding-bottom: 0; }
/* Prosty formularz bez paneli („Nowy materiał”, kategorie, „Zapisz wersję”, Zamów): siatka pól = jedna biała grupa
   (dawniej tylko na telefonie, 9-telefon/2-okna.css §1). */
#modal-root .modal > form > .form-grid,
#modal-root .modal > form.compact-catalog-form > .form-grid { padding: 14px; border-radius: var(--grupa-r); background: var(--surface); }
/* Podpisy grup w edytorach (bok Bloku, zestawienie, BOM konstrukcji, transport): szare, waga 600 na obu ekranach. */
#modal-root :is(.block-side-title, .calc-command-label, .design-sidebar-head, .transport-group-label) { color: var(--text-muted); font-weight: var(--w-bold); }
/* M6 (18.10.2026): odczyty BOM konstrukcji (kwota materiału, pojemność) i atrakcje — `.kst-odcz`, `.kst-atr` w 25c-konstrukcja-okno.css. */
/* Zwykła pisownia w oknie — wersaliki z rozstrzeleniem („KONSTRUKCJE”, „PROFIL KOSZTÓW”) były tylko na komputerze.
   `inherit`, nie `normal`: zwykły tekst zostaje z odstępem liter ekranu (komputer: lekko ściśnięty krój). */
#modal-root * { text-transform: none; letter-spacing: inherit; }
/* === 1. POWŁOKA EDYTORA — dwie kolumny na całą wysokość okna ===============
   Okno jest flexem w pionie, więc powłoka musi jawnie dostać resztę wysokości
   i min-height:0, inaczej wewnętrzne przewijanie nie zadziała.
   --bok = szerokość kolumny bocznej; wariant zmienia ją jedną linijką. */
/* NAPRAWA 11.08.2026 — SZCZELINA MIEDZY KOLUMNAMI.
   Zmierzone w oknie Gwarancji: `gap: normal`, czyli ZERO. Lewa kolumna konczyla
   sie na x=914 i prawa zaczynala sie na x=914 — stykaly sie bez odstepu
   i bez kreski (`border: 0 none` po obu stronach). Jedyne, co je rozdzielalo,
   to biala karta w srodku lewej, wiec podzial wygladal na przypadek. */
.block-editor-form, .material-editor-form, .supplier-editor-form, .work-service-editor-form, .transport-editor-form, .installation-crew-editor-form, .project-editor-shell { --bok: 300px; display: grid; grid-template-columns: var(--bok) minmax(0, 1fr); gap: var(--s-3); flex: 1 1 auto; min-height: 0; height: 100%; overflow: hidden; background: var(--surface-2); }
/* Okno Bloków ma kolumnę boczną ZMIENNĄ, nie stałą: monolit 16585 daje
   `clamp(360px, 25vw, 440px)`. Przy oknie 1587 px to 396,8 px — nasze sztywne
   320 px odbierało jej 77 px i ściskało wszystko w środku (wybieraki
   komponentów 150/220 zamiast 220/330, pola 262 zamiast 345 px). */
.block-editor-form { --bok: clamp(360px, 25vw / var(--skala-ui), 440px); }
.installation-crew-editor-form { --bok: 270px; }
/* Materiał ma bok po PRAWEJ (w HTML <main> jest przed <aside>). */
.material-editor-form { grid-template-columns: minmax(0, 1fr) 318px; }
/* Okno projektu: formularz + czat obok. Bez czatu zostaje jedna kolumna. */
/* NAPRAWA UKŁADU 11.08.2026 — okno Gwarancji (jedyne okno, które używa tej
   siatki z czatem: public/js/okna/).
   ZMIERZONE PRZED: okno 1600 × 942 px na ekranie 2187 px. Siatka wychodziła
   `620px 966px`, bo druga kolumna brała `1fr`, czyli CAŁĄ resztę ekranu.
   Skutek: formularz o SZEŚCIU polach (Status, Data, Konstrukcja, Osoby, Opis,
   Załączniki — łącznie 530 px treści) dostawał 620 px szerokości i 820 px
   wysokości, a rozmowa przy nim 966 px. Okno rosło razem z monitorem, więc
   im szerszy ekran, tym bardziej puste wyglądało.
   Dwie przyczyny, obie usunięte:
     1. `1fr` bez sufitu — kolumna czatu rosła w nieskończoność. Teraz ma sufit;
        powyżej ~640 px wiersz rozmowy i tak robi się za długi, żeby go czytać.
     2. Formularz miał sufit 620 px dobrany pod TAMTO okno. 520 px wystarcza
        tym polom z zapasem, a różnicę oddajemy rozmowie.
   Wymiar samego okna ustawiony niżej (`.modal.project-modal.full-height`). */
/* KOREKTA po pomiarze: kolumna formularza 520 px była ZA WĄSKA. Pasek narzędzi
   edytora „Opis gwarancji" ma 13 kontrolek i potrzebuje 511 px, a przy kolumnie
   520 dostawał 454 — brakowało 57 px, więc pole opisu dostawało własny poziomy
   pasek przewijania (zgłoszone przez użytkownika). Kolumna 580 daje kartę 516 px
   i pasek mieści się w jednym rzędzie. */
.project-editor-shell { grid-template-columns: minmax(480px, 580px) minmax(360px, 1fr); }
.project-editor-shell-no-chat { grid-template-columns: minmax(0, 1fr); }
/* Okno Gwarancji dostaje wymiar z tej samej rodziny co okno czatu (1180 px) —
   oba są „formularz + rozmowa", więc mają wyglądać na to samo okno, a nie na
   dwa różne. Wysokość 820, nie pełne 942: treść formularza to 530 px, a lista
   wiadomości i tak przewija się w środku. */
.modal.project-modal.full-height { width: min(1280px, 100%); }
/* --- CZAT PROJEKTU JAKO OSOBNE OKNO ----------------------------------------
   Po wyprowadzeniu czatu z edytora projektu rozmowa ma własne okno. Wymiary
   biorą się z tego, ile miejsca czat zajmował wcześniej jako druga kolumna
   okna 1600 px (czyli ok. 980 px) — z zapasem na szynę wątków. Wysokość
   pełna, bo lista wiadomości ma się przewijać wewnątrz, a nie rozpychać okno. */
.modal.project-chat-modal { --okno-w: 1180px; }
.modal.project-chat-modal.full-height { width: min(1180px, 100%); }
.project-chat-shell { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); flex: 1 1 auto; min-height: 0; overflow: hidden; background: var(--surface-2); }
/* Formularz okna Z POWŁOKĄ oddaje jej całą przestrzeń — padding i grid
   z `.modal > form` (05-komponenty) tylko by ją zdublowały. Wyliczamy okna
   po nazwie: proste kartoteki (kategorie, użytkownicy) powłoki nie mają
   i muszą zachować normalny padding formularza. */
.modal.block-modal > form, .modal.material-modal > form, .modal.supplier-modal > form, .modal.work-service-modal > form, .modal.crew-modal > form, .modal.transport-modal > form, .modal.construction-modal > form { display: block; padding: 0; overflow: hidden; }
/* Planowanie i konstrukcja mają JESZCZE jedno opakowanie między oknem a powłoką — musi
   przepuścić wysokość, inaczej treść nie wypełni okna. Rail designu staje OBOK edytora. */
/* `.modal > .planning-shell` WYJĘTE z tej listy (skan 13.09.2026): waga (0,2,0) biła `.planning-shell`
   z 25-design-plany (flex: formularz | czat) i robiła z powłoki siatkę JEDNOKOLUMNOWĄ — formularz
   planów dostawał wiersz 0 px, czat całe okno, a „Zapisz plany" zapisywało coś, czego nie widać.
   Układ powłoki planowania należy w całości do 25-design-plany.css §6. */
.construction-workspace { display: grid; grid-template-rows: minmax(0, 1fr); flex: 1 1 auto; min-height: 0; height: 100%; overflow: hidden; }
/* Boczne menu konstrukcji ma TĘ SAMĄ szerokość co w oknie Designu (284 px z
   .design-workspace). Było `auto`, czyli szerokość treści — zmierzone 145 px,
   więc przy wejściu w konstrukcję menu kurczyło się o połowę i całe okno „skakało". */
.construction-workspace:not(.no-sidebar) { grid-template-columns: var(--bok-design) minmax(0, 1fr); }
/* Proste kartoteki (kategorie, transport osobowy) powłoki nie mają — stos sekcji. */
.compact-catalog-form { display: grid; align-content: start; gap: var(--s-3); }
/* Bok: własne przewijanie i kreska oddzielająca. Główna kolumna: lista sekcji. */
.block-editor-side, .material-editor-side, .supplier-editor-side, .work-service-editor-side, .transport-editor-side, .crew-editor-side { display: grid; align-content: start; gap: var(--s-2); min-width: 0; overflow-x: hidden; overflow-y: auto; padding: var(--s-2) var(--s-3); border-right: 1px solid var(--line); background: var(--surface); }
.block-editor-main, .material-editor-main, .supplier-editor-main, .work-service-editor-main, .transport-editor-main, .crew-editor-main { display: grid; align-content: start; gap: var(--s-2); min-width: 0; min-height: 0; overflow: auto; padding: var(--s-2) var(--s-3); }
/* Materiał: bok jest po prawej, więc kreska też musi się przenieść. */
.material-editor-side { border-right: 0; border-left: 1px solid var(--line); }
/* Sekcja („panel") — pudełko z nagłówkiem i polami. Jedno dla wszystkich okien. */
.block-editor-panel, .material-editor-panel, .supplier-editor-panel, .work-service-editor-panel, .transport-editor-panel, .crew-editor-panel, .form-panel { display: grid; gap: var(--s-2); min-width: 0; padding: var(--s-2) var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); }
/* Nagłówek sekcji: tytuł z lewej, podpis „co tu wpisać" z prawej. */
.block-panel-head, .material-panel-head, .form-panel-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); }
.block-panel-head h3, .material-panel-head h3, .form-panel-head h3 { font-size: var(--t-base); font-weight: var(--w-bold); }
.block-panel-head span, .material-panel-head > span, .form-panel-head span { color: var(--text-muted); font-size: var(--t-xs); }
/* Grupa w kolumnie bocznej — biała grupa bez ramki (skórka okna §0, W1). Było: kreska pod każdą grupą,
   a na telefonie biała grupa BEZ wcięcia — pola dotykały jej krawędzi. */
.block-side-section, .material-side-section, .supplier-side-section { display: grid; gap: var(--s-2); min-width: 0; padding: var(--s-2) var(--s-3); }
.block-side-title { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
/* Kafelek podsumowania w boku (podgląd karty dostawcy, ekipy, usługi). */
.work-service-side-card, .crew-side-card, .supplier-card-preview, .crew-card-preview, .work-service-supplier-preview { display: grid; gap: var(--s-1); min-width: 0; padding: var(--s-2) var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface-2); }
.work-service-side-card > strong, .crew-side-card > strong, .supplier-card-preview strong { overflow: hidden; font-weight: var(--w-bold); text-overflow: ellipsis; white-space: nowrap; }
.work-service-side-card > span, .crew-side-card > span, .supplier-card-preview span { color: var(--text-muted); font-size: var(--t-xs); }
/* === 2. SIATKA PÓL — dwie kolumny, `.full` na całą szerokość ===============
   Jedna reguła obsługuje siatki wszystkich okien; różnią się tylko nazwą. */
.form-grid, .material-basic-grid, .material-billing-grid, .supplier-data-grid, .supplier-phone-grid, .crew-data-grid, .work-service-form-grid, .construction-context-grid, .construction-dimensions-grid, .block-two-field-grid, .block-margin-grid, .block-installation-grid, .block-capacity-grid, .block-editor-panel-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); align-items: end; }
.form-grid > .full, .material-basic-grid > .full, .work-service-form-grid > .full, .supplier-data-grid > .full, .crew-data-grid > .full { grid-column: 1 / -1; }
/* ERG6-05: wymiary konstrukcji mieszczą się w swojej karcie także na tablecie 1024 (pole „Długość m” wystawało poza ramkę). */
.construction-dimensions-grid > .field { min-width: 0; }
.construction-dimensions-grid > .field > input { width: 100%; min-width: 0; }
/* W1: pola w dwóch kolumnach boku Bloku („Typ marży | Marża własna %”) nie wystają poza grupę — pole „Marża własna”
   miało szerokość własną (169 px) większą niż kolumna (152 px) i wychodziło 5 px poza białą grupę. */
.block-two-field-grid > .field > input { width: 100%; min-width: 0; }
/* Etykieta pola w oknie: drobna i przygaszona — treść ma być ważniejsza. */
.modal .field > label { color: var(--text-muted); font-size: var(--t-2xs); font-weight: var(--w-medium); }   /* POPR2-x04: podpis pola 12 px — w oknie --t-xs to już tekst treści (13 px) */
/* W1: każdy podpis w oknie (także pola wyboru, „Licz po parametrach”, podpisy w kartach) — szary, waga 500, jak na
   telefonie. Etykiety-przyciski (wgraj plik, obraz w edytorze) mają kolor przycisku. */
.modal label:not(.upload-button, .rich-image-button, .button) { color: var(--text-muted); font-weight: var(--w-medium); }
/* === 3. OKNO PROJEKTU =====================================================
   Formularz to jedna kolumna kart na przygaszonym tle — czytelna pionowa
   ścieżka „od góry do dołu", a nie tabela pól. */
/* NAPRAWA 11.08.2026 — 162 px MARTWEJ SZAREJ PUSTKI pod biala karta.
   Zmierzone w oknie Gwarancji: karta konczyla sie na y=727, a jej kontener
   na y=905.  sciskal wiersze do gory, wiec karta brala
   tylko tyle, ile miala tresci, a reszta kolumny zostawala pusta.
   Prawa kolumna czatu rozciagala sie na pelne 820 px, wiec lewa i prawa
   strona okna konczyly sie w innym miejscu.
    kaze karcie wypelnic kolumne — obie strony konczy sie rowno. */
.project-card-form { display: grid; grid-template-rows: minmax(0, 1fr); gap: var(--s-3); height: 100%; min-height: 0; overflow: auto; padding: var(--s-4); background: var(--surface-2); }
/* Karta wypelnia kolumne (min-height:0 + overflow), a tresc w srodku dalej
   klei sie do gory przez align-content na wewnetrznej siatce. */
.project-card-stack { display: grid; align-content: start; gap: var(--s-3); min-height: 0; overflow: auto; padding: var(--s-4); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-1); }
/* --- „NOWY PROJEKT" PRZED WYBOREM RODZAJU (klasa `project-form-only`) --------
   Dopóki nie wybierzesz Projekt / Projekt serwisowy, okno pokazuje DWA guziki
   i zdanie podpowiedzi — i w v8 jest wtedy MAŁE: 740×275 px (monolit 21617).
   Nie mieliśmy na tę klasę ANI JEDNEJ reguły, więc okno brało pełny ekran
   (1600×1230) i rozlewało się pustym błękitem. Wysokość musi iść z treści
   (`height: auto` + kolumna flex), a nie z `full-height`. */
/* SUFIT WYSOKOŚCI = tyle, ile daje ekran, a nie sztywne 900 px.
   Sztywne `min(900px, 100%)` ucinało formularz na 900 px i włączało w nim
   pasek przewijania, mimo że pod oknem zostawało jeszcze ~330 px wolnego
   miejsca (ekran 1270). Teraz okno rośnie z treścią aż do krawędzi ekranu
   i przewija się dopiero wtedy, gdy naprawdę się nie mieści. */
.modal.project-modal.project-form-only { display: flex; flex-direction: column; width: min(740px, calc(100vw / var(--skala-ui) - 24px)); height: auto; max-height: calc(100dvh / var(--skala-ui) - var(--h-row)); }
.modal.project-modal.project-form-only > header, .modal.project-modal.project-form-only > footer { flex: 0 0 auto; }
.modal.project-modal.project-form-only .project-editor-shell-no-chat { display: grid; grid-template-rows: minmax(0, 1fr); flex: 1 1 auto; min-height: 0; overflow: hidden; }
/* Jedna biała powierzchnia zamiast karty w karcie — stąd brak tła i ramki na
   stosie pól, a wyściółka siedzi na samym formularzu. */
.modal.project-modal.project-form-only .project-card-form { height: auto; min-height: 0; max-height: none; overflow: auto; padding: var(--s-3) var(--s-5) var(--s-5); grid-template-rows: max-content; align-content: start; }
.modal.project-modal.project-form-only .project-card-stack { grid-auto-rows: max-content; align-content: start; }
/* W1 (27.09.2026): „Nowy / Edytuj projekt” — stos pól to BIAŁA GRUPA na szarym tle okna, na komputerze i telefonie
   (wcześniej: jedna biała powierzchnia bez grupy na komputerze, pola wprost na szarym tle na telefonie). Wyściółka
   grupy (--s-4 z reguły wyżej) mieści też obwódkę fokusu pola — naprawa z 11.08 (ucinana poświata) zostaje spełniona. */
.project-panel-head { display: flex; align-items: center; grid-column: 1 / -1; padding-bottom: var(--s-2); border-bottom: 1px solid var(--line); }
.project-panel-head strong { overflow: hidden; font-weight: var(--w-bold); text-overflow: ellipsis; white-space: nowrap; }
/* Pole = etykieta + kontrolka, BEZ ramki wokół pary (ramkę ma sama kontrolka). */
.project-field-card { display: grid; gap: var(--s-1); min-width: 0; }
.project-field-card > span, .project-card-title-row > span { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-medium); }
/* Znacznik przy etykiecie pola — mówi, DO CZEGO ta wartość służy dalej.
   Pierwszy użytek: adres instalacji („z niego liczy się transport"), żeby nikt
   nie brał go za adres klienta z kartoteki. Kursywa bez koloru alarmowego:
   to podpowiedź, nie ostrzeżenie. */
.project-field-card > span .field-tag { color: var(--accent); font-style: normal; font-weight: var(--w-medium); }
.project-card-title-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.project-card-title-row small { color: var(--text-muted); font-size: var(--t-xs); }
/* Numer nadawany automatycznie — wygląda na pole, ale jest odczytem. */
.project-number-field input { color: var(--pole-napis-zablokowane); }   /* tło i ramka: pole tylko do odczytu (03-kontrolki, POPR3-pola) */
/* Wiersze „pole + przycisk" (klient, adres): pole rośnie, przycisk zostaje. */
.project-client-row, .project-address-row { display: flex; align-items: stretch; gap: var(--s-2); }
.project-client-row > .combo, .project-client-row input, .project-client-row select, .project-address-row input { flex: 1 1 auto; min-width: 0; }
/* `height: auto` puszcza w ruch `align-items: stretch` z wiersza wyżej: przycisk
   dorasta do pola obok. Bez tego `.button.mini` trzyma sztywne 27 px przy polu
   wysokim na 32 px i guzik siedzi niżej niż okno, do którego należy. */
.project-client-row .button, .project-address-row .button { white-space: nowrap; height: auto; }
.project-address-status { min-height: var(--s-4); color: var(--text-muted); font-size: var(--t-xs); }
/* Potwierdzenie adresu MUSI byc widac. Program od dawna dokladal tu klasy
   `is-valid` / `is-error`, ale NIC ich nie malowalo — napis „Zweryfikowano…"
   i „Adres nie jest jeszcze zweryfikowany" wychodzil taka sama szarala jak reszta
   podpowiedzi, wiec nikt nie zauwazal roznicy. Dopisane 13.08.2026.
   Kolory z wariantow tekstowych (--ok-strong / --danger), nie z tonow tla. */
.project-address-status.is-valid { color: var(--ok-strong); font-weight: var(--w-medium); }
.project-address-status.is-error { color: var(--danger); font-weight: var(--w-medium); }
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
/* === 4. OKNO MATERIAŁU ====================================================
   Kafle liczbowe w boku: etykieta na górze, wartość pod spodem. */
.material-metric-card { display: grid; gap: var(--s-2); padding: var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2); }
.material-metric-card.primary { border-color: var(--accent-strong); background: var(--accent-soft); }
.material-metric-head { display: grid; gap: var(--s-1); }
.material-metric-head span { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.material-metric-head strong { font-size: var(--t-base); font-weight: var(--w-bold); line-height: var(--lh-tight); }
/* Pasek podsumowań w nagłówku sekcji (cena, masa) — pigułki wyrównane do prawej. */
.material-summary-strip { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-1); }
.material-summary-strip span { display: inline-flex; align-items: center; min-height: var(--h-control-sm); padding: 0 var(--s-2); border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--surface-2); color: var(--text-muted); font-size: var(--t-xs); }
.material-summary-strip strong { margin-left: var(--s-1); color: var(--text); font-weight: var(--w-bold); }
/* Przełącznik „ten materiał ma kolory / to pozycja priorytetowa". */
/* UWAGA: `.material-priority-row` to <tr> W TABELI — nie wolno mu nadawać
   `display: flex`, bo komórki przestają się trzymać kolumn tabeli
   (zmierzony rozjazd: 1533 px). Monolit stylizuje tam WYŁĄCZNIE tło komórek
   (linia 24060). Flex należy się tylko przełącznikowi. */
.material-priority-toggle { display: flex; align-items: center; gap: var(--s-2); margin: var(--s-2) 0 var(--s-1); font-size: var(--t-base); cursor: pointer; }
.material-priority-row td { background: color-mix(in srgb, var(--warn) 7%, transparent); }
.material-priority-toggle span { line-height: var(--lh-base); }
/* Podgląd zdjęcia (materiał, blok): bez wymiaru w CSS <img> wchodzi w PEŁNEJ
   rozdzielczości i rozsadza kolumnę — ta sama pułapka co awatary. */
.material-photo-frame, .block-image-preview, .block-image-frame { display: grid; place-items: center; overflow: hidden; aspect-ratio: 4 / 3; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface-2); }
.material-photo-frame img, .block-image-preview img, .block-image-frame img { max-width: 100%; max-height: 100%; object-fit: contain; }
.material-photo-placeholder, .block-image-source, .supplier-logo-placeholder, .supplier-price-empty { color: var(--text-faint); font-size: var(--t-xs); text-align: center; }
/* Stan magazynowy PER KOLOR: tabela bez ramek, pola wtopione w komórki —
   to arkusz do szybkiego wpisywania, nie raport. */
.color-stock-table { width: 100%; border-collapse: collapse; }
.color-stock-table th { padding: 0 var(--s-2) var(--s-1); border-bottom: 1px solid var(--line); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); text-align: left; }
.color-stock-table th:nth-child(2), .color-stock-table th:nth-child(3) { width: 92px; text-align: right; }
.color-stock-table th:last-child { width: 42px; }
.color-stock-table td { padding: 0; border-bottom: 1px solid var(--line); vertical-align: middle; }
.color-stock-table tr:last-child td { border-bottom: 0; }
/* Jednostka w nagłówku ma zostać małą literą („m²", nie „M2"). */
.color-stock-table .th-unit { color: var(--text-faint); font-weight: var(--w-regular); text-transform: none; }
.color-stock-table input[type="number"] { appearance: textfield; text-align: right; font-variant-numeric: tabular-nums; }
.material-color-subrow > td { background: var(--surface-2); }
.material-color-subname { padding-left: var(--s-5); color: var(--text-muted); }
.material-color-warn > td { background: var(--warn-soft); }
/* Certyfikaty materiału: lista plików z ikoną typu i akcjami. */
.material-cert-list { display: grid; gap: var(--s-2); align-content: start; }
.material-cert-item { display: flex; align-items: center; gap: var(--s-2); min-width: 0; padding: var(--s-1) var(--s-2); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
.material-cert-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.material-cert-tag, .material-cert-badge { padding: 0 var(--s-2); border-radius: var(--r-pill); background: var(--accent-soft); color: var(--accent-strong); font-size: var(--t-xs); font-weight: var(--w-bold); }
.material-cert-tools { margin-left: auto; display: inline-flex; gap: var(--s-1); }
.material-cert-empty, .material-cert-hint { color: var(--text-muted); font-size: var(--t-xs); }
/* === 5. OKNO BLOKU — receptura komponentów + linie wymiarów ===============
   Tabela komponentów jest edytowalna, więc komórki są ciasne, a kontrolki
   wypełniają je w całości: liczy się liczba widocznych wierszy. */
.component-table-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); min-height: var(--h-control-sm); }
/* `:not([type="checkbox"])` (skan 13.09.2026): kratka „Blok" dostawała szerokość 100 % kolumny (38 × 38 px pusty
   kwadrat), a jej podpis „Blok" wypadał poza kolumnę i był niewidoczny. */
.component-table select, .component-table input:not([type="checkbox"]) { width: 100%; height: var(--h-control-sm); padding: 0 var(--s-2); }
.component-table th:nth-child(2), .component-table td:nth-child(2) { width: 80px; text-align: center; }
.component-table th:nth-child(3), .component-table td:nth-child(3), .component-table th:nth-child(4), .component-table td:nth-child(4) { width: 118px; }
.component-table th:last-child, .component-table td:last-child { width: 36px; text-align: center; }
.component-table tfoot td { background: var(--surface-2); font-weight: var(--w-bold); }
.component-picker { display: grid; grid-template-columns: minmax(150px, 0.34fr) minmax(220px, 0.66fr); gap: var(--s-1); align-items: center; }
.component-picker-with-mode { grid-template-columns: 58px minmax(150px, 0.34fr) minmax(220px, 0.66fr); }
.component-mode-toggle { display: inline-flex; align-items: center; gap: var(--s-1); color: var(--text-muted); font-size: var(--t-xs); white-space: nowrap; } :root[data-ui="tablet"] :is(.measure-line .measure-auto, .component-mode-toggle) { min-height: var(--h-control); margin-block: calc((var(--h-control) - 1em * var(--lh-base)) / -2); }   /* tablet: pole dotyku 44 px */
/* ERG6-02: PODGLĄD karty (klik w blok) — formularz w <fieldset disabled>. Obudowa nie zmienia układu okna,
   a wyłączone pola czyta się jak zwykły tekst (bazowe :disabled ma przygaszony kolor). */
fieldset.catalog-podglad { display: contents; }
fieldset.catalog-podglad :is(input, select, textarea):disabled { color: var(--text); -webkit-text-fill-color: var(--text); cursor: not-allowed; }   /* POPR3-pola: pole zablokowane = kursor not-allowed (także w podglądzie karty) */
/* Linia wymiaru: etykieta | przelicznik | pole liczbowe | jednostka.
   MUSI być SIATKĄ CZTERECH KOLUMN `118px 56px 1fr 96px` (monolit 27646), nie
   flexem — inaczej każdy wiersz układa się po swojemu i etykiety, pola oraz
   jednostki nie stoją w jednej linii w pionie. Kolumny są przypisane jawnie,
   bo elementy pośrednie mają `display: contents`. */
/* Skan 13.09.2026: boczna kolumna okna Bloki ma ~300 px, więc na pole liczbowe zostawało ~30 px —
   „30" wyglądało jak „3", „900" jak „9", a „0,027 m3 =" wchodziło na pole. Nadal jedna siatka dla
   wszystkich wierszy (pola i jednostki w jednej linii w pionie), ale w DWÓCH RZĘDACH:
   góra = etykieta (+ AUTO) i przelicznik nad polem, dół = pole | jednostka. */
.measure-line { display: grid; grid-template-columns: minmax(0, 1fr) auto 96px; grid-template-rows: auto auto; align-items: center; column-gap: 6px; row-gap: 2px; min-width: 0; padding: 2px 0; }
.measure-line-top, .measure-line-ctl { display: contents; }
.measure-line-label { grid-column: 1; grid-row: 1; justify-self: start; font-size: var(--t-xs); font-weight: var(--w-medium); white-space: nowrap; }
.measure-line .measure-auto { grid-column: 2; grid-row: 1; justify-self: end; display: inline-flex; align-items: center; gap: var(--s-1); cursor: pointer; }
.measure-line-cur { grid-column: 3; grid-row: 1; justify-self: end; }
.measure-line-cur, .measure-line .measure-auto { color: var(--text-muted); font-size: var(--t-xs); font-style: normal; white-space: nowrap; font-variant-numeric: tabular-nums; }
.measure-line-ctl > input { grid-column: 1 / span 2; grid-row: 2; min-width: 0; text-align: right; }
.measure-line-ctl select { grid-column: 3; grid-row: 2; }
.measure-line-ctl input, .measure-line-ctl select { height: var(--h-control-sm); }
/* Okno Materiały podmienia WSZYSTKIE selecty na combo (upgradeSelectsToCombo) — combo musi
   przejąć szerokość selecta, inaczej rozpycha wiersz. Lista zostaje absolutna (03-kontrolki). */
.modal .combo-input { width: 100%; }
.measure-line .combo { grid-column: 3; grid-row: 2; }
/* === 6. DOSTAWCA, KLIENT, EKIPA ==========================================
   Kontakt = cztery pola w wierszu; przy wąskim oknie schodzą pod siebie (§9). */
/* Zasięg pierścieni ROI pod polem adresu. Suwak stoi tu, a nie w Ustawieniach,
   bo zasięg dobiera się do konkretnego miasta — mała miejscowość i aglomeracja
   mają inny obszar ciążenia. */
.project-population-rings { display: grid; gap: var(--s-1); margin-top: var(--s-2); }
.project-population-rings label { color: var(--text-muted); font-size: var(--t-sm); }
.project-population-rings small { color: var(--text-muted); font-size: var(--t-sm); }
/* J1: przełącznik „Okręgi (km)” / „Czas dojazdu” i panel suwaka wybranego trybu (drugi ukryty). */
.project-population-tryb { justify-self: start; }
.project-population-tryb-panel { display: grid; gap: var(--s-1); }
.project-population-tryb-panel[hidden] { display: none; }
/* Podpisy krańców skali. Suwak zawsze zostawia margines na kciuk, więc bez nich
   położenie na maksimum wygląda jak niedosunięte do końca. */
.project-population-rings-scale { display: flex; justify-content: space-between; margin-top: calc(var(--s-1) * -1); }
/* NAPRAWA 11.08.2026 — SUWAK DOJEŻDŻA DO OBU KOŃCÓW.
   Zgłoszenie: „kółko suwaka nie dojeżdża do końca ani początku, tylko ma jakąś
   przestrzeń zostawioną". To zachowanie NATYWNEGO suwaka: przeglądarka trzyma
   gałkę w całości nad torem, więc na obu krańcach zostaje pusto po pół gałki.
   Przy podpisach „1 km" i „5 km" stojących pod krańcami wyglądało to tak,
   jakby maksimum nie było maksimum — komentarz wyżej opisuje ten sam objaw
   i próbował go obejść samymi podpisami.
   Rysujemy tor i gałkę sami (`appearance: none`) i cofamy gałkę o połowę
   różnicy wysokości, żeby jej ŚRODEK trafiał dokładnie w koniec toru.
   `accent-color` przestaje działać przy własnym wyglądzie, więc kolor idzie
   wprost z tokenów.
   Chrome i Firefox mają OSOBNE nazwy pseudoelementów i nie wolno ich łączyć
   przecinkiem — jeden nieznany selektor unieważnia całą regułę. Stąd pięć
   osobnych bloków zamiast dwóch. */
/* `min-height: 0` jest KONIECZNE: bazowa reguła pól (03-kontrolki) daje każdemu
   `input` minimum 32 px, a minimum BIJE zwykłą wysokość — bez tego suwak
   zostawał 32 px wysoki, gałka pływała w środku i tor nie stał tam, gdzie
   podpisy „1 km" / „5 km". */
.project-population-rings input[type="range"] { width: 100%; height: var(--s-4); min-height: 0; margin: 0; padding: 0; border: 0; background: transparent; appearance: none; -webkit-appearance: none; cursor: pointer; }
.project-population-rings input[type="range"]::-webkit-slider-runnable-track { height: var(--s-1); border-radius: var(--r-pill); background: var(--line-strong); }
.project-population-rings input[type="range"]::-moz-range-track { height: var(--s-1); border-radius: var(--r-pill); background: var(--line-strong); }
.project-population-rings input[type="range"]::-moz-range-progress { height: var(--s-1); border-radius: var(--r-pill); background: var(--accent-strong); }
.project-population-rings input[type="range"]::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: var(--s-4); height: var(--s-4); margin-top: calc((var(--s-4) - var(--s-1)) / -2); border: 0; border-radius: var(--r-pill); background: var(--accent-strong); }
.project-population-rings input[type="range"]::-moz-range-thumb { width: var(--s-4); height: var(--s-4); border: 0; border-radius: var(--r-pill); background: var(--accent-strong); } :root[data-ui="tablet"] .modal .project-population-rings input[type="range"]:not([type="checkbox"]):not([type="radio"]) { height: var(--h-control); }   /* tablet: suwak 44 px (był 12) */
.supplier-contact-list { display: grid; gap: var(--s-2); }
/* Minimum kolumny to 170 px — tyle ma naturalna szerokość pola formularza,
   które celowo nie kurczy się niżej (`.field` w 03-kontrolki). Węższa kolumna
   nie ściska kontrolki, tylko wypuszcza ją na sąsiednią. Telefon dostaje 280 px,
   bo mieści DWIE kontrolki: kierunkowy z flagą i nazwą kraju (~160 px) oraz sam
   numer (~110 px). Na te 854 px minimum okno jest poszerzone w 05-komponenty. */
.supplier-contact-row { display: grid; grid-template-columns: minmax(170px, 1fr) minmax(170px, .85fr) minmax(170px, 1fr) minmax(280px, 1.35fr) auto; align-items: end; gap: var(--s-2); min-width: 0; padding: var(--s-2); border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface-2); }
.supplier-logo-preview, .crew-logo-preview { display: grid; place-items: center; overflow: hidden; aspect-ratio: 16 / 7; border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); }
.supplier-logo-preview img, .crew-logo-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* E3: w węższej wizytówce (ekipa 94 px, dostawca na tablecie 91 px) inicjał pod „Dodaj logo” wychodził poza ramkę — mniejsze odstępy w pustej ramce. */
:is(.supplier-logo-preview, .crew-logo-preview) .logo-preview-click.is-empty { gap: var(--s-1); }
/* Stawki ekipy: stała siatka kolumn, żeby pola nie skakały przy wpisywaniu. */
.crew-rates-table { table-layout: fixed; width: 100%; }
.crew-rates-table input, .crew-rates-table select { height: var(--h-control-sm); }
.crew-rates-table td:nth-child(4) input { text-align: right; }
.crew-rates-table th:last-child, .crew-rates-table td:last-child { width: 38px; text-align: center; }
/* === 7. KONSTRUKCJA I PLANOWANIE ========================================== */
/* Zakładki kontekstu (Design / konstrukcje / materiały prezentacyjne):
   aktywna „wjeżdża" na tło panelu i dostaje kreskę u góry, jak w teczce. */
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
.context-tab { display: inline-flex; align-items: center; gap: var(--s-2); min-height: var(--h-row); max-width: 220px; padding: 0 var(--s-3); border: 1px solid transparent; border-bottom: 0; border-radius: var(--r-sm) var(--r-sm) 0 0; color: var(--text-muted); font-weight: var(--w-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.context-tab:hover { background: var(--surface-2); }
.context-tab.active { border-color: var(--line); background: var(--surface-2); color: var(--accent-strong); box-shadow: inset 0 3px 0 var(--accent); }
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
/* Konstrukcja: dane po lewej, BOM/podsumowanie po prawej. */
/* UKŁAD EDYTORA KONSTRUKCJI — 12.08.2026, ostateczna decyzja użytkownika:
   „kolumna nr 1 wymiary i pod nią BOM, a obok panel do prezentacji".
   (Wcześniejszy wariant 2×2 z BOM-em przez całą szerokość został odrzucony —
   „BOM w sumie miał miejsce".) Ten sam układ w pełnym oknie i w dymku. */
.construction-editor-grid { display: grid; grid-template-columns: minmax(var(--kolumna-formularza-min), var(--kolumna-formularza)) minmax(0, 1fr); gap: var(--s-3); height: 100%; min-height: 0; overflow: hidden; padding: var(--s-3); }
.construction-main-stack, .construction-side-stack, .construction-bom-panel { display: grid; align-content: start; gap: var(--s-2); min-width: 0; min-height: 0; }
/* Lewa kolumna przewija się w sobie: wymiary + BOM ze sprawdzeniem bywają dłuższe niż okno. */
.construction-main-stack { overflow: auto; }
/* Galeria wypełnia swoją kolumnę i też przewija się w środku, a nie rozpycha okna. */
.construction-side-stack { align-content: stretch; grid-template-rows: minmax(0, 1fr); }
.construction-side-stack > .construction-presentation-panel { grid-template-rows: auto auto minmax(0, 1fr); min-height: 0; }

/* === DYMEK KONSTRUKCJI W OKNIE DESIGN (12.08.2026) =========================
   Karta doklejona NAD oknem Design, nie drugie okno. Okno Design zostaje pod spodem
   widoczne i szerokie — tam planuje się resztę projektu. Dymek wisi obok bocznego menu
   konstrukcji (284 px), więc kafelek, w który kliknąłeś, jest cały czas widoczny.
   Doklejany do `.modal`, NIE do środka formularza Designu — formularz w formularzu
   jest niedozwolony i przeglądarka wycinała formularz konstrukcji. */
.modal.design-editor-modal { position: relative; }
.construction-bubble { position: absolute; z-index: var(--z-menu-lokalne); top: var(--s-3); bottom: var(--s-3); left: calc(var(--bok-design) + var(--s-4)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; width: min(var(--dymek-w), calc(100% - var(--bok-design) - var(--s-7))); overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-3); }
/* MAŁE OKNO KONSTRUKCJI (12.08.2026) — kliknięcie konstrukcji w drzewie projektu.
   Ten sam środek co dymek, tylko jako samodzielne okno: szerokość z tokenu dymka,
   wysokość dobierana do treści z sufitem, żeby nie zajmowało całego ekranu. */
.modal.construction-popup { --okno-w: var(--dymek-w); }
.modal.construction-popup .construction-editor-grid { overflow: auto; }
/* B2: okno „Przenieś do…” (Tablica zadań) — trzy przyciski, wąskie okno. */
.modal.zt-przenies-okno { --okno-w: 440px; }

/* Gospodarz bez bocznego menu konstrukcji (kalkulator kosztów) — dymek nie ma się
   do czego przykleić z lewej, więc staje na środku okna. */
.modal { position: relative; }
.construction-bubble.bez-menu { left: 50%; width: min(var(--dymek-w), calc(100% - var(--s-7))); transform: translateX(-50%); }
.construction-bubble-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); background: var(--surface-2); }
.construction-bubble-title { display: grid; gap: 2px; min-width: 0; }
.construction-bubble-title strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.construction-bubble-title small { color: var(--text-muted); font-size: var(--t-xs); }
.construction-bubble > form { display: grid; grid-template-rows: minmax(0, 1fr); min-height: 0; overflow: hidden; }
.construction-bubble-footer { display: flex; justify-content: flex-end; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-top: 1px solid var(--line); background: var(--surface-2); }
/* W dymku jest ciaśniej niż w pełnym oknie — miniatury renderów o jeden rozmiar mniejsze. */
.construction-bubble .construction-presentation-list { grid-template-columns: repeat(auto-fill, minmax(var(--miniatura-w-dymek), 1fr)); }
.construction-bubble .construction-presentation-thumb { height: var(--miniatura-h-dymek); }
/* Miniatury materiałów prezentacyjnych: szachownica pod spodem pokazuje, że
   plik ma przezroczystość (rendery PNG bez tła). */
/* GALERIA RENDERÓW — 12.08.2026. Była lista wierszy (miniatura 96×62 + nazwa + kosz),
   czyli katalog plików. Teraz kafelki: duży podgląd na górze, nazwa pod nim, kosz w rogu.
   Liczba kolumn dobiera się sama do szerokości — bez breakpointów. */
.construction-presentation-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--miniatura-w), 1fr)); align-content: start; gap: var(--s-2); min-height: 0; overflow: auto; }
.construction-presentation-item { position: relative; display: grid; grid-template-rows: auto auto; align-items: start; gap: var(--s-1); padding: var(--s-1); border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); }
.construction-presentation-preview { display: block; min-width: 0; }
.construction-presentation-thumb { display: grid; place-items: center; overflow: hidden; width: 100%; height: var(--miniatura-h); border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface-2); color: var(--text-muted); }
.construction-presentation-meta { min-width: 0; padding: 0 var(--s-1) var(--s-1); }
.construction-presentation-meta strong { display: block; overflow: hidden; font-size: var(--t-xs); text-overflow: ellipsis; white-space: nowrap; }
.construction-presentation-meta small { color: var(--text-muted); font-size: var(--t-xs); }
/* Kosz siedzi NA miniaturze, żeby kafelek został wąski i równy. */
.construction-presentation-item > .icon-button.danger { position: absolute; top: var(--s-2); right: var(--s-2); }
/* NAPRAWA 11.08.2026 — JS renderuje <img class="construction-presentation-thumb">,
   czyli klasa jest NA obrazku, a nie na opakowaniu. Selektor potomka nigdy go nie
   lapal, wiec obraz dostawal sztywne 96x62 bez object-fit → domyslne 
   → ZDJECIE ROZCIAGNIETE. Wariant PDF dzialal, bo canvas jest dzieckiem. */
img.construction-presentation-thumb { object-fit: contain; }
.construction-presentation-thumb img, .construction-presentation-canvas { max-width: 100%; max-height: 100%; object-fit: contain; }
.construction-presentation-meta { display: grid; gap: var(--s-1); min-width: 0; }
.construction-presentation-meta strong, .construction-presentation-meta small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.construction-presentation-meta small { color: var(--text-muted); font-size: var(--t-xs); }
.construction-presentation-empty { color: var(--text-faint); font-size: var(--t-xs); }
/* Cała sekcja jest strefą upuszczania plików — sygnał na akcencie. */
.construction-presentation-panel.is-dragover { border-color: var(--accent-strong); background: var(--accent-soft); }
/* Planowanie: lista konstrukcji z lewej, arkusz i czat z prawej. */
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
.planning-notes-area { min-height: calc(var(--h-control) * 3); }.attachment-list { display: grid; gap: var(--s-2); }
.attachment-item, .supplier-attachment-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s-3); padding: var(--s-2); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
/* Ikona = skrót rozszerzenia (PDF, DWG…) — czytelniejszy niż uniwersalna kartka. */
.attachment-icon { display: grid; place-items: center; width: var(--s-7); height: var(--h-control); border-radius: var(--r-sm); background: var(--surface-2); color: var(--accent-strong); font-size: var(--t-xs); font-weight: var(--w-bold); }.attachment-item a, .attachment-item strong { display: block; overflow: hidden; font-weight: var(--w-medium); text-overflow: ellipsis; white-space: nowrap; }
.attachment-item small, .attachment-empty, .supplier-attachment-item small { color: var(--text-muted); font-size: var(--t-xs); }
/* Wyciete 11.08.2026 — martwe reguly, zero wystapien w public/js. Szczegoly: AUDYT-CSS-2026-08-11.md B9. */
/* === 8. OKNO „ZADANIA" PROJEKTU ============================================ (z dawnego 26, K15)
   OKNO BIERZE PEŁNĄ WYSOKOŚĆ — i tak ma być. Zadanie mieści opis z tekstem
   I RYSUNKAMI, więc pole na opis musi mieć gdzie się rozwinąć; drzewo zadań
   też ma sens dopiero, gdy widać naraz kilkanaście wierszy.
   Wcześniejszy problem NIE polegał na tym, że okno jest za wysokie, tylko że
   pole opisu nie rosło do jego wysokości: łańcuch flexa urywał się na
   `.todo-detail` (arkusz 15), które miało `flex: 0 1 auto` i kurczyło się do
   treści. Pole zostawało na swoim minimum 140 px, a pod spodem była pustka.
   Dlatego wysokość zostaje pełna, a naprawione jest to jedno ogniwo.
   `.modal.task-modal` to dwie klasy na jednym elemencie — wygrywa z bazowym
   `.modal` (05-komponenty) bez żadnego `!important`. */
.modal.task-modal { --okno-w: 1240px; }
/* Ciało okna nie jest `.modal-body`, więc nie łapie bazowego paddingu ani
   scrolla — i dobrze: przewijać ma się drzewo i szczegóły W ŚRODKU panelu,
   a nie całe okno. `min-height: 0` odblokowuje to zagnieżdżone przewijanie. */
.task-modal-body { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; padding: 0; }
/* Edytor opisu w tym oknie dostaje wysokość z układu, nie z własnego minimum. */
.modal.task-modal .task-rich-notes { min-height: 0; }
/* ============================================================================
   9. RESPONSYWNOŚĆ — progi 1180 / 980 / telefon
   ============================================================================ */
@media (max-width: 1180px) {
  /* Bok robi się za ciasny na sensowne pola — oddajemy mu mniej miejsca. */
  .block-editor-form, .material-editor-form, .supplier-editor-form, .work-service-editor-form, .transport-editor-form, .installation-crew-editor-form { --bok: 260px; }
  /* Wąski ekran: kolumna z wymiarami i BOM-em zwęża się, kolejność kolumn zostaje
     (formularz z lewej, prezentacja z prawej). Wartość z tokenu, nie z palca. */
  .construction-editor-grid { grid-template-columns: minmax(0, var(--kolumna-formularza-min)) minmax(0, 1fr); }
  /* E2 (27.09): bez okien BEZ czatu (Nowy projekt, nowa Gwarancja) — reguła wygrywała z `.project-editor-shell-no-chat`
     (ta sama waga, później w pliku) i na tablecie 1024 formularz miał pół okna, a druga połowa stała pusta. */
  .project-editor-shell:not(.project-editor-shell-no-chat) { grid-template-columns: minmax(380px, 1fr) minmax(300px, .8fr); }
  /* Pięć kolumn kontaktu potrzebuje 854 px; przy tej szerokości okna zostaje
     ~815 px, więc zamiast wypychać kontrolki na sąsiednie kolumny wiersz
     schodzi na dwie linie — czytelnie i bez nakładania. */
  .supplier-contact-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 980px) {
  /* Poniżej tej szerokości dwie kolumny się nie mieszczą: bok schodzi pod
     treść, a przewijanie przejmuje całe okno (kolumny nie mają już własnego). */
  .block-editor-form, .material-editor-form, .supplier-editor-form, .work-service-editor-form, .transport-editor-form, .installation-crew-editor-form, .project-editor-shell, .construction-editor-grid { grid-template-columns: minmax(0, 1fr); overflow: auto; }
  .block-editor-side, .material-editor-side, .supplier-editor-side, .work-service-editor-side, .transport-editor-side, .crew-editor-side { overflow: visible; border-right: 0; border-left: 0; border-bottom: 1px solid var(--line); }
  /* `min-height: auto` (skan 13.09.2026): bazowe `min-height: 0` pozwalało siatce o wysokości 100 %
     ŚCISNĄĆ kolumnę główną poniżej treści, a kolumna boczna (następny wiersz) rysowała się NA jej polach —
     w Materiałach „Zdjęcie" i „Karta materiału" przykrywały Cenę, Masę i Stan, a listy wyboru (position:
     relative) wystawały nad nimi. Wiersz ma teraz co najmniej wysokość treści, przewija się całe okno. */
  .block-editor-main, .material-editor-main, .supplier-editor-main, .work-service-editor-main, .transport-editor-main, .crew-editor-main { overflow: visible; min-height: auto; }  .supplier-contact-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* DYMEK KONSTRUKCJI NA WĄSKIM EKRANIE (12.08.2026).
     Poniżej 980 px boczne menu Designu schodzi POD treść (25-design-plany.css), więc nie ma
     obok czego przypinać dymka — przypięty do 284 px robił się paskiem szerokości 2 px
     (zmierzone na 375 px). Tutaj dymek zajmuje całe okno jak arkusz. */
  .construction-bubble { top: var(--s-2); right: var(--s-2); bottom: var(--s-2); left: var(--s-2); width: auto; }
  /* OKNO KONSTRUKCJI NA WĄSKIM EKRANIE (skan 13.09.2026). `.construction-workspace:not(.no-sidebar)` ma wagę
     (0,2,0) i trzymało DWIE kolumny (bok 284 px, w 70 % pusty) mimo reguły 1 kolumny z 25-design-plany,
     a stosy z `min-height: 0` ściskały kartę „BOM konstrukcji" (ucięty rząd „Wgraj"). Jedna kolumna,
     wysokość = treść, przewija się całe okno. */
  .construction-workspace:not(.no-sidebar) { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; align-content: start; overflow: auto; }
  .construction-editor-grid { height: auto; overflow: visible; }
  .construction-main-stack, .construction-side-stack, .construction-bom-panel { min-height: auto; overflow: visible; }
  .construction-side-stack, .construction-side-stack > .construction-presentation-panel { grid-template-rows: auto; }
}
/* Telefon: wszystko w jednej kolumnie, siatki pól też. */
:where(:root[data-ui="mobile"]) .form-grid, :where(:root[data-ui="mobile"]) .material-basic-grid, :where(:root[data-ui="mobile"]) .material-billing-grid, :where(:root[data-ui="mobile"]) .supplier-data-grid, :where(:root[data-ui="mobile"]) .supplier-phone-grid, :where(:root[data-ui="mobile"]) .crew-data-grid, :where(:root[data-ui="mobile"]) .work-service-form-grid, :where(:root[data-ui="mobile"]) .construction-context-grid, :where(:root[data-ui="mobile"]) .construction-dimensions-grid, :where(:root[data-ui="mobile"]) .supplier-contact-row, :where(:root[data-ui="mobile"]) .component-picker, :where(:root[data-ui="mobile"]) .component-picker-with-mode, :where(:root[data-ui="mobile"]) .block-two-field-grid, :where(:root[data-ui="mobile"]) .block-margin-grid, :where(:root[data-ui="mobile"]) .block-installation-grid, :where(:root[data-ui="mobile"]) .block-capacity-grid, :where(:root[data-ui="mobile"]) .block-editor-panel-row { grid-template-columns: minmax(0, 1fr); }
:where(:root[data-ui="mobile"]) .project-card-form, :where(:root[data-ui="mobile"]) .project-card-stack { padding: var(--s-3); }
:where(:root[data-ui="mobile"]) .project-client-row, :where(:root[data-ui="mobile"]) .project-address-row { flex-wrap: wrap; }
/* Telefon: galeria renderów na jedną kolumnę — także w dymku. Reguła dymka jest
   bardziej szczegółowa (dwa człony), więc bez tego wiersza wygrywałaby ona i kafelki
   150 px wystawałyby poza ekran. */
:where(:root[data-ui="mobile"]) .construction-presentation-list, :where(:root[data-ui="mobile"]) .construction-bubble .construction-presentation-list { grid-template-columns: minmax(0, 1fr); }
:where(:root[data-ui="mobile"]) .construction-presentation-thumb, :where(:root[data-ui="mobile"]) .construction-bubble .construction-presentation-thumb { height: 120px; }

/* === OKNO KONSTRUKCJI W ODMIANIE POPUP (otwierane z Designu) =================
   Zgłoszenie 13.08.2026: „dlaczego nie mogę przewijać BOM w tym oknie".
   Ta odmiana NIE dostaje klasy `full-height` (patrz public/js/okna/,
   `constructionModalClassName` dla trybu kompaktowego), więc okno nie miało
   OKREŚLONEJ wysokości. A bez określonej wysokości `height: 100%` w środku
   rozwiązuje się do „auto": nic nie jest przewijalne, a lista BOM (85 pozycji)
   zostaje po prostu UCIĘTA przez `overflow: hidden` okna.
   Dajemy tej odmianie własną wysokość — wtedy `overflow: auto` na siatce edytora
   (reguła wyżej) ma się względem czego liczyć i przewijanie wraca.
   TA SAMA LEKCJA co przy oknie klienta: `height: auto`/`fit-content` NIE działa,
   bo po przycięciu przez `max-height` wysokość znów przestaje być określona. */
.modal.construction-modal.construction-popup { display: flex; flex-direction: column; overflow: hidden; }
.modal.construction-modal.construction-popup > form { flex: 1 1 auto; min-height: 0; }

/* === OKNO „KOMENTARZ BOM" ====================================================
   Zgłoszenie 13.08.2026: „okno komentarza BOM jest dziwne i nieforemne, ma się
   od razu otwierać tak jak na rozmiarze full screen".
   Powód: okno dostawało tylko klasy `bom-comment-modal compact-catalog-modal`,
   a ŻADNA z nich nie miała w arkuszach reguły — czyli edytor tekstu lądował
   w domyślnym, wąskim oknie. Nadajemy mu wymiary POWIĘKSZONEGO edytora
   (te same co `.rich-expand-panel` w 17-czat.css: 1160 px / 86vh), żeby otwierał
   się od razu duży, bez klikania „powiększ". */
.modal.bom-comment-modal { display: flex; flex-direction: column; width: min(1160px, calc(100vw / var(--skala-ui) - 32px)); height: min(86vh / var(--skala-ui), 900px); max-height: calc(100dvh / var(--skala-ui) - var(--h-control)); overflow: hidden; }
.modal.bom-comment-modal > form { flex: 1 1 auto; display: grid; grid-template-rows: minmax(0, 1fr); min-height: 0; padding: var(--s-3); }
.modal.bom-comment-modal .form-grid, .modal.bom-comment-modal .field.full { display: grid; grid-template-rows: minmax(0, 1fr); min-height: 0; }
.modal.bom-comment-modal .field.full { grid-template-rows: auto minmax(0, 1fr); }
.modal.bom-comment-modal .rich-editor { min-height: 0; }
.modal.bom-comment-modal .rich-editable { max-height: none; }
/* Pole tekstu ma WYPEŁNIĆ to okno, nie stać w nim jako pasek na 80 px: siatka
   formularza rozciąga się na całą wysokość, ale samo pole domyślnie zostaje przy
   swojej treści — stąd `align-self: stretch` i `height: 100%` w dół łańcucha. */
.modal.bom-comment-modal .form-grid > .field.full { align-self: stretch; height: 100%; }
.modal.bom-comment-modal .field.full > .rich-editor { height: 100%; min-height: 0; }

/* MOJA WPADKA Z 13.08.2026 — do zapamiętania. Dokładając „Upuść pliki tutaj" do panelu
   obrazków dołożyłem CZWARTY element, a szablon wierszy niżej wymieniał trzy
   (`auto auto minmax(0, 1fr)`). Lista miniatur przestała być wierszem elastycznym,
   więc przy większej liczbie obrazków panel nie dawał się przewijać.
   Zmiana liczby dzieci panelu = obowiązkowa zmiana szablonu wierszy. */
.construction-side-stack > .construction-presentation-panel { grid-template-rows: auto auto auto minmax(0, 1fr); }

/* OKNO KALKULACJI (sprawdzenie BOM) — 13.08.2026: „dlaczego to okno BOM też się nie da
   przewinąć". Treść okna nosi klasę `.modal-form` (to <div>, nie <form>), więc NIE łapie
   jej reguła dla formularzy okien pełnowysokościowych: nie dostawała ani `flex: 1 1 auto`,
   ani `overflow`. Tabela 83 pozycji wychodziła poza okno i była ucinana.
   Ten sam zabieg co w oknie oferty (21-oferta.css). */
.modal.calculation-modal.full-height > .modal-form { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* POMOC W KAŻDYM OKNIE — znak zapytania obok krzyżyka (12.08.2026, polecenie
   użytkownika). Przycisk dokłada JS przy otwieraniu okna (`dodajPrzyciskPomocy`).

   ⛔ WYGLĄD PRZENIESIONY 18.08.2026 do `03-kontrolki.css` (reguła `.help-button`).
   Ten sam przycisk miał wtedy PIĘĆ różnych wyglądów w pięciu arkuszach; właściciel:
   *„weź to ogarnij jako token przycisku pomocy globalnie"*. Tutaj zostaje WYŁĄCZNIE
   to, co dotyczy POŁOŻENIA w nagłówku okna. Nie dopisywać tu wyglądu z powrotem. */
/* ZNAK ZAPYTANIA MA STAC PRZY KRZYZYKU (13.08.2026, zgloszenie uzytkownika: „dlaczego
   w tym i wielu innych oknach ta ikona nie jest obok krzyzyka jak w kalkulatorze").
   Naglowki okien uzywaja `justify-content: space-between`, wiec przy trzech dzieciach
   (tytul, znak zapytania, krzyzyk) znak ladowal POSRODKU. `margin-left: auto` dosuwa
   go do prawej — krzyzyk idzie zaraz za nim i para trzyma sie razem. */
.modal-help-btn { margin-left: auto; }
/* Krzyzyk ma iSC TUZ ZA znakiem zapytania. Naglowki okien odsuwaja go wlasnym
   `margin-left: auto`; gdy oba maja auto, wolne miejsce dzieli sie miedzy nie
   i miedzy przyciskami robi sie kilkaset pikseli dziury. */
/* Regula musi byc MOCNIEJSZA niz ta z 05-komponenty.css, ktora daje krzyzykowi wlasny
   odstep auto — inaczej miedzy nim a znakiem zapytania robi sie kilkaset pikseli dziury. */
.modal > header > .modal-help-btn + .icon-button:last-child { margin-left: 0; }
/* --- Okna: licznik opisu konstrukcji, zdjęcie, BOM, projekt, plan produkcji, pomoc (z dawnego 28, K17) --- */
[data-construction-description-counter].is-limit { color: var(--danger); }
.user-photo-card { display: grid; justify-items: center; gap: var(--s-2); min-width: 0; padding: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); }
.user-photo-preview { display: grid; place-items: center; width: 78px; height: 78px; overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--surface-2); }
.user-photo-preview img { width: 100%; height: 100%; object-fit: cover; }
.user-photo-preview .small-avatar { width: 100%; height: 100%; border: 0; font-size: var(--t-lg); }
.client-avatar-preview { padding: 2px 0 var(--s-3); border: 0; background: transparent; aspect-ratio: auto; }
.client-avatar-placeholder { gap: var(--s-2); padding: 0; }
/* Kolumny wiersza kontaktu ustawia 19 — tu tylko ochrona przed rozpychaniem. */
.supplier-contact-role, .supplier-contact-email, .contact-phone-field { min-width: 0; }
.professional-material-form { width: 100%; }
.contact-list { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
.contact-list span { padding: 3px var(--s-2); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.client-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: var(--s-3); padding: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); }
.image-popup-body { display: flex; align-items: center; justify-content: center; padding: var(--s-3); overflow: hidden; }
.image-popup-body img { max-width: 100%; max-height: min(660px, calc(92vh / var(--skala-ui) - 100px)); object-fit: contain; border-radius: var(--r-sm); }
.construction-presentation-thumb.is-file { background: var(--surface-2); }
.project-user-search { position: relative; display: grid; align-items: center; min-width: 0; }
.project-user-search .icon { position: absolute; left: var(--s-2); color: var(--text-muted); pointer-events: none; }
.project-selected-empty { padding: 3px var(--s-1); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.project-type-picker { display: flex; gap: var(--s-2); margin-bottom: var(--s-2); }
.project-type-picker .button { flex: 1; min-height: var(--h-row); font-size: var(--t-base); font-weight: var(--w-bold); }
/* Wybrany rodzaj musi być widać (skan 13.09.2026: po wyborze „Projekt" oba przyciski wyglądały tak samo). */
.project-type-picker .button.is-active { border-color: var(--accent-strong); background: var(--accent-soft); color: var(--accent-strong); box-shadow: inset 0 0 0 1px var(--accent-strong); }
.project-type-hint { margin-top: var(--s-1); padding: var(--s-4) var(--s-3); border: 1px dashed color-mix(in srgb, var(--accent) 40%, var(--line)); border-radius: var(--r-sm); background: var(--accent-soft); color: var(--text-muted); font-size: var(--t-base); line-height: var(--lh-base); text-align: center; }
.project-address-field { gap: var(--s-2); }
.help-modal-body { padding: var(--s-5) var(--s-5) var(--s-6); text-align: center; }
/* Formularze okien konstrukcji / planu / oferty / prezentacji. */
.construction-editor-form .form-panel { gap: var(--s-3); }

/* ============================ SZUKAJ WSZĘDZIE (G2, 27.09.2026) ============= */
/* Okno szukania (public/js/ui/szukaj-wszedzie.js): skórka W1 — szare tło okna, pole wypełnione, wyniki w białych grupach.
   Okno stoi w górnej części ekranu (jak szukanie w programach biurowych), żeby lista wyników rosła w dół, a nie skakała. */
.modal-backdrop:has(> .modal.szukaj-wszedzie-modal) { place-items: start center; padding-top: calc(10vh / var(--skala-ui)); }
.modal.szukaj-wszedzie-modal { --okno-w: 640px; max-height: min(640px, 80vh / var(--skala-ui)); }
.szukaj-wszedzie { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: var(--s-3); min-height: 0; padding: var(--s-1) var(--s-5) var(--s-4); overflow: hidden; }
.szukaj-wszedzie-wyniki { display: grid; align-content: start; gap: var(--s-3); min-height: 0; overflow: auto; }
.szukaj-wszedzie-grupa { display: grid; gap: 2px; padding: var(--s-2); border-radius: var(--grupa-r); background: var(--surface); }
.szukaj-wszedzie-grupa h3 { padding: var(--s-1) var(--s-2); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.szukaj-wszedzie-wynik { display: grid; gap: 2px; min-height: var(--h-control); padding: var(--s-2); border: 0; border-radius: var(--pole-r); background: transparent; color: var(--text); text-align: left; cursor: pointer; }
.szukaj-wszedzie-wynik strong { overflow: hidden; font-weight: var(--w-medium); text-overflow: ellipsis; white-space: nowrap; }
.szukaj-wszedzie-wynik small { overflow: hidden; color: var(--text-muted); font-size: var(--t-xs); text-overflow: ellipsis; white-space: nowrap; }
.szukaj-wszedzie-wynik:hover, .szukaj-wszedzie-wynik[aria-selected="true"] { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.szukaj-wszedzie-wynik:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.szukaj-wszedzie-pusto { padding: var(--s-4) var(--s-2); text-align: center; }
.szukaj-wszedzie-klawisze { font-size: var(--t-xs); }
.szukaj-wszedzie-klawisze kbd { padding: 1px var(--s-1); border: 1px solid var(--line-strong); border-radius: 4px; background: var(--surface); color: var(--text); font-family: inherit; font-size: var(--t-2xs); font-weight: var(--w-bold); }
/* Telefon: okno na cały ekran (jak każde okno), bez podpowiedzi klawiszy — nie ma klawiatury ze strzałkami. */
:root[data-ui="mobile"] .modal-backdrop:has(> .modal.szukaj-wszedzie-modal) { padding-top: 0; }
:root:is([data-ui="mobile"], [data-ui="tablet"]) .szukaj-wszedzie-klawisze { display: none; }
:root[data-ui="mobile"] .szukaj-wszedzie { padding: var(--s-1) var(--s-4) var(--s-4); }
.szukaj-wszedzie-klawisze { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4); }
/* SKRÓTY KLAWISZOWE (G6): lista pod „?” — klawisze w kolumnie po lewej, opis obok, w jednej białej grupie. */
.skroty-klawiszowe { display: grid; gap: var(--s-3); padding: 0 var(--s-5) var(--s-5); }
.skroty-klawiszowe dl { display: grid; gap: 2px; padding: var(--s-2); border-radius: var(--grupa-r); background: var(--surface); }
.skroty-klawiszowe dl > div { display: grid; grid-template-columns: 120px minmax(0, 1fr); align-items: center; gap: var(--s-3); min-height: var(--h-control); padding: 0 var(--s-2); }
.skroty-klawiszowe dd { margin: 0; }
.skroty-klawiszowe kbd { padding: 1px var(--s-2); border: 1px solid var(--line-strong); border-radius: 4px; background: var(--surface-2); color: var(--text); font-family: inherit; font-size: var(--t-xs); font-weight: var(--w-bold); }
/* ZAPISY BEZ INTERNETU (G4): okno kolejki — wiersze jak na stronie projektu (.mgrupa/.mwiersz), błąd serwera na czerwono. */
.kolejka-offline-okno { display: grid; gap: var(--s-3); padding: 0 var(--s-5) var(--s-4); overflow: auto; }
.kolejka-offline-okno .mwiersz { flex-wrap: wrap; }
.kolejka-offline-okno .kolejka-offline-blad { color: var(--danger); }
