/* ============================================================================
   15-zadania.css — zadania, podzadania, wykonawcy, notatki-tematy
   ----------------------------------------------------------------------------
   Trzy miejsca dzielą te same klocki: kartoteka „Zadania i notatki" (widok
   pełnoekranowy, `.zn-page`), panel zadań w oknie projektu (`.todo-panel`)
   i kartoteka „Notatki" (`.zn-notes`). Wszędzie układ jest ten sam:
   DRZEWO po lewej — SZCZEGÓŁY albo FORMULARZ po prawej.

   Zadanie ma wielu wykonawców i każdy odhacza SWOJĄ część, dlatego stan bywa
   cząstkowy: kropka `.todo-dot.part` i procent na pasku `.todo-bar`.
   Wcięcia podzadań liczy JS (`padding-left` inline rośnie z głębokością) —
   arkusz nie zna poziomów drzewa i nie próbuje ich odtwarzać.
   ============================================================================ */
/* Szerokości kolumn tego widoku — brak dla nich tokenu, bo nigdzie indziej nie
   występują. Trzymamy je razem, żeby zmienić proporcje w jednym miejscu. */
.zn-page, .todo-panel { --zn-drzewo: 390px; --zn-lista: 300px; }
/* === 1. KARTOTEKA PEŁNOEKRANOWA =========================================== */
/* Kartoteka wypełnia ekran BEZ przewijania strony — przewijają się dopiero
   drzewo i szczegóły. Ten sam wzorzec co okno projektu. */
.content:has(.zn-page) { display: grid; grid-template-rows: minmax(0, 1fr); height: calc(100dvh / var(--skala-ui) - var(--topbar-h) - var(--s-5)); min-height: 0; overflow: hidden; }
.zn-page, .zn-body { display: flex; flex-direction: column; min-height: 0; }
.zn-page { height: 100%; gap: var(--s-3); }
.zn-body { flex: 1; }
/* Przełącznik widoku (Moje / Zlecone / Gotowe) — pigułki na wspólnym tle. */
.zn-sub { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
/* Ten sam przełącznik w Harmonogramie (Timeline · Gantt · Kalendarz · Obciążenie — tor A) i na stronie „Zadania” (v15 b7;
   także „Tydzień | Miesiąc” kalendarza — wzór zh2: wybrane białe na szarym, jak widoki; v15 b10: „Wiersze | Karty” w Klientach). */
/* v15 b19: wymiary ze wzoru (ui-seg) — ramka 3 px, promień 12, tło --surface-3; przycisk na wysokość kontrolki, 13 px / 600. */
.zn-sub .views, .hg-przelacznik .views, .zh-r1 .views, .zt-kal-pasek .views, .kl-pasek .views { display: flex; gap: 3px; padding: 3px; border-radius: var(--r); background: var(--surface-3); }
.zn-sub .view, .hg-przelacznik .view, .zh-r1 .view, .zt-kal-pasek .view, .kl-pasek .view { min-height: var(--h-control); padding: 0 var(--s-3); border-radius: var(--r-sm); color: var(--text-muted); font-size: var(--t-sm); font-weight: var(--w-bold); cursor: pointer; }
.zn-sub .view.on, .hg-przelacznik .view.on, .zh-r1 .view.on, .zt-kal-pasek .view.on, .kl-pasek .view.on { background: var(--surface); color: var(--text); box-shadow: var(--cien-1); }
/* Dwie kolumny: lista trzyma stałą szerokość, szczegóły biorą resztę. */
.zn-two { display: grid; grid-template-columns: minmax(0, var(--zn-drzewo)) minmax(0, 1fr); gap: var(--s-3); flex: 1; min-height: 0; }
/* === 2. DRZEWO ZADAŃ (lewa kolumna) ======================================= */
/* Ujednolicenie 11.08.2026 — cień kontenera --cien-1 (jak .zn-notes-left wyżej). */
.zn-tree, .todo-tree { display: flex; flex-direction: column; min-width: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--cien-1); }
.zn-tree-top { display: flex; flex-direction: column; gap: var(--s-2); flex: none; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
.zn-tree-top-row { display: flex; align-items: center; gap: var(--s-2); }
.zn-sort-select { max-width: 60%; margin-left: auto; }
/* Szukajka: ramkę rysuje kontener, pole zostaje gołe (inaczej widać dwie ramki). */
.tree-search { display: flex; align-items: center; gap: var(--s-2); height: var(--h-control); padding: 0 var(--s-2); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); }
/* `:not(...)` = podbicie szczegółowości do (0,3,1), inaczej bazowa reguła pól
   (0,2,1) zostawia polu WŁASNĄ ramkę w środku ramki `.tree-search` i widać dwie.
   Monolit v8 robi dokładnie to samo i podpisuje: „koniec podwójnej ramki" (27422). */
.tree-search input:not([type="checkbox"]):not([type="radio"]) { flex: 1; min-width: 0; height: 100%; min-height: 0; padding: 0; border: 0; border-radius: 0; background: transparent; }
.zn-tree-body, .todo-tree-body { flex: 1; overflow: auto; padding: var(--s-1) 0; }
.todo-tree-head { display: flex; flex-direction: column; gap: var(--s-2); position: sticky; top: 0; z-index: 1; padding: var(--s-3); border-bottom: 1px solid var(--line); background: var(--surface); color: var(--text-muted); font-weight: var(--w-medium); }
.todo-tree-head-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
/* Nagłówek grupy (projekt / bez projektu) — zwijany, z licznikiem do zrobienia. */
.zn-group { display: flex; align-items: center; gap: var(--s-2); width: 100%; padding: var(--s-2) var(--s-3); border-top: 1px solid var(--line); color: var(--text-muted); font-size: var(--t-sm); font-weight: var(--w-bold); text-align: left; cursor: pointer; }
.zn-tree-body > .zn-group:first-child { border-top: 0; }
.zn-group:hover { background: var(--surface-2); }
.zn-group-caret { flex: none; width: var(--s-3); font-size: var(--t-xs); text-align: center; }
.zn-group-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zn-group-badge { margin-left: var(--s-1); }
/* Panel zadań w oknie projektu: to samo drzewo, tylko dwie kolumny obok siebie.
   Lista zadań dostaje szerokość STAŁĄ (`--zn-lista`, 300 px), a formularz
   edycji całą resztę. Poprzedni podział .9fr/1.1fr dzielił okno prawie po
   połowie: lista z krótkimi nazwami miała ~560 px pustki, a formularz
   z trzema polami w rzędzie i edytorem opisu dusił się na tej samej szerokości. */
.todo-panel { display: grid; grid-template-columns: minmax(260px, var(--zn-lista)) minmax(0, 1fr); height: 100%; }
.todo-tree { border: 0; border-right: 1px solid var(--line); border-radius: 0; }
.todo-detail-col { display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: auto; padding: var(--s-4); }
/* === 3. WĘZEŁ DRZEWA ====================================================== */
/* Wcięcie podzadania nadaje JS (padding-left rośnie z głębokością) — tu tylko wygląd. */
.todo-node { display: flex; align-items: center; gap: var(--s-2); margin: 0 var(--s-2); padding: var(--s-2) var(--s-3); border-radius: var(--r-sm); cursor: pointer; }
.todo-node:hover { background: var(--surface-2); }
/* Ujednolicenie 11.08.2026 — pasek akcentu --s-1, jeden na całą aplikację. */
.todo-node.is-sel { background: var(--accent-soft); }   /* POPR-n45: zaznaczenie = tło, bez paska z lewej */
/* STRZAŁKA ROZWIJANIA — cel do kliknięcia, nie ozdobnik.
   Miała 16 px szerokości i stopień 11 px; przy 8-pikselowej kropce statusu
   obok wyglądała jak przecinek i nie było widać, że w ogóle coś rozwija.
   Teraz kwadrat 22 px z wyraźnym trójkątem, obracany zamiast podmienianego
   znaku — ruch sam mówi, co się dzieje. Węzeł bez podzadań ma to pole PUSTE,
   ale zajęte, żeby tytuły wszystkich wierszy stały w jednej osi. */
.todo-caret { display: inline-grid; place-items: center; flex: none; width: 22px; height: 22px; border-radius: var(--r-sm); color: var(--text-muted); font-size: var(--t-2xs); line-height: 1; transition: background var(--szybko), color var(--szybko), transform var(--szybko); }
.todo-caret.has { cursor: pointer; }
.todo-caret.has:hover { background: var(--surface-3); color: var(--accent-strong); }
/* Licznik podzadań przy tytule — od razu widać, że zadanie coś w sobie ma. */
.todo-node-kids { flex: none; min-width: 18px; padding: 1px var(--s-1); border-radius: var(--r-pill); background: var(--surface-3); color: var(--text-muted); font-size: var(--t-2xs); font-weight: var(--w-bold); text-align: center; }
/* --- PODZADANIA: pudełko z kreską prowadzącą (jak w ClickUp) ---------------
   Wcześniej podzadanie było zwykłym wierszem odsuniętym inline'owym
   `padding-left` — z boku wyglądało jak zadanie główne, tylko wcięte.
   Teraz dzieci siedzą we własnym pudełku z pionową kreską i wcięciem,
   więc widać przynależność, a nie samo wcięcie. */
.todo-kids { position: relative; margin-left: 22px; padding-left: var(--s-3); }
.todo-kids::before { content: ""; position: absolute; left: 0; top: 2px; bottom: 6px; width: 2px; border-radius: var(--r-pill); background: var(--line-strong); }
/* Sam wiersz podzadania: mniejszy stopień i poziomy łącznik do kreski. */
.todo-node.is-sub { position: relative; }
.todo-node.is-sub .todo-node-title { font-size: var(--t-base); font-weight: var(--w-regular); }
/* Łącznik MUSI sięgać do pionowej kreski, a wiersz ma własny margines boczny
   (`.todo-node { margin: 0 var(--s-2) }`). Bez doliczenia tych 8 px kreska
   kończyła się w powietrzu i zostawała widoczna przerwa — z boku wyglądało
   to jak połamana litera L, a nie jak połączenie z zadaniem nadrzędnym. */
.todo-node.is-sub::before { content: ""; position: absolute; left: calc((var(--s-3) + var(--s-2)) * -1); top: 50%; width: calc(var(--s-3) + var(--s-2)); height: 2px; border-radius: var(--r-pill); background: var(--line-strong); }
.todo-node.is-root > .todo-node-title { font-weight: var(--w-bold); }
.todo-node-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--w-medium); }
.todo-node.is-done .todo-node-title { color: var(--text-faint); font-weight: var(--w-regular); text-decoration: line-through; }
/* Licznik „odhaczone / wszyscy" albo procent — cyfry o równej szerokości. */
.todo-node-nm { flex: none; color: var(--text-muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
/* B1c: skąd jest zadanie spoza „Zadań” (Etap, Design, Gwarancja, Plany) — spokojna plakietka w miejscu licznika. */
.todo-node-rodzaj { flex: none; padding: 0 var(--s-2); border-radius: var(--r-pill); background: var(--surface-2); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-medium); line-height: 1.6; }
/* Pudełko reszty wiersza i termin (tura 4): na komputerze pudełko „znika" (dzieci stoją w wierszu jak dotąd),
   a termin jest tylko na telefonie — tam wiersz ma drugą linię (31-telefon-wzorzec.css). */
.todo-node-meta { display: contents; }
.todo-node-termin { display: none; }
/* Akcja „dodaj podzadanie" wychodzi spod kursora — drzewo zostaje spokojne. */
.todo-node-act { flex: none; opacity: 0; }
.todo-node:hover .todo-node-act { opacity: 1; }
/* Kropka stanu — te same tony co statusy w reszcie apki, więc „w toku" znaczy
   wszędzie to samo: open = do zrobienia · part = w toku · done = wykonane · over = po terminie. */
.todo-dot, .task-status-dot { --ton: var(--status-oczekuje); flex: none; width: var(--s-2); height: var(--s-2); border-radius: var(--r-pill); background: var(--ton); }
:is(.zl-w, .zt-kolumna-glowa) > .todo-dot.open { box-sizing: border-box; border: 2px solid var(--line-strong); background: transparent; }
.todo-dot.part, .task-status-dot.part { --ton: var(--status-wtoku); }
.todo-dot.done, .task-status-dot.done { --ton: var(--status-gotowy); }
.todo-dot.over, .task-status-dot.over { --ton: var(--danger); }
/* Awatary wykonawców nachodzą na siebie; obrys = ta osoba już odhaczyła swoje. */
.todo-avas { display: inline-flex; flex: none; }
.todo-avas .todo-ava:first-child { margin-left: 0; }
/* NAPRAWA 11.08.2026 — kolor inicjałów dobierany do tła (kolor działu bywa
   jasny, a białe inicjały dawały wtedy 3,3:1 przy 9 px). Liczy to
   `kolorNapisuNa()` w public/js/rdzen/dane-projektu.js; szczegóły przy `.avatar` w 06-elementy. */
/* POPR2-awatar: inicjały 12 px (było 11 px — poniżej progu czytelności); ten sam rozmiar w awatarach pola „Dla kogo” (.asel-av). */
/* v15 b19 (wzór .zd-av): 26 px, tło = 24 % koloru osoby na powierzchni, inicjały w kolorze osoby przyciemnionym tuszem
   (czytelne także przy bardzo jasnym albo bardzo ciemnym kolorze działu i w ciemnym motywie); zrobione = zielona obwódka. */
.todo-ava { --avatar-d: 26px; --avatar-ramka: 2px; display: inline-grid; place-items: center; box-sizing: border-box; width: var(--avatar-d); height: var(--avatar-d); margin-left: 2px; border: 2px solid var(--surface); border-radius: var(--r-pill); background: color-mix(in srgb, var(--ava, var(--accent)) 24%, var(--surface)); color: color-mix(in srgb, var(--ava, var(--accent)) 70%, var(--text)); font-size: min(var(--t-xs), calc((var(--avatar-d) - 2 * var(--avatar-ramka)) * .44)); font-weight: var(--w-strong); line-height: 1; white-space: nowrap; }
.todo-ava-wiecej { --ava: var(--text-faint); }   /* „+N” — więcej niż 3 wykonawców */
/* Ciemny motyw: ciemny kolor działu (np. grafit) ginął na ciemnym tle (kontrast 2,5 : 1) — inicjały bliżej koloru tekstu. */
:root[data-theme="dark"] :is(.todo-ava, .zk-av) { background: color-mix(in srgb, var(--ava, var(--accent)) 24%, var(--line-strong)); color: color-mix(in srgb, var(--ava, var(--accent)) 35%, var(--text)); }   /* ciemny motyw: kółko na jaśniejszym tle — awatar osoby z ciemnym kolorem nie znika w wierszu */
.todo-ava.is-done { box-shadow: 0 0 0 2px var(--ok); }
/* === 4. SZCZEGÓŁY ZADANIA ================================================= */
/* `flex: 1` jest TU KONIECZNE — to ogniwo urywało łańcuch wysokości.
   Edytor opisu (`.rich-editor`) rośnie prawidłowo (`flex: 1 1 0%`), ale
   rósł tylko do wysokości TEGO pudełka, a ono miało `flex: 0 1 auto`, czyli
   kurczyło się do treści. Efekt: pole na opis miało 140 px minimum, a pod
   spodem zostawała pusta biel na całą resztę okna. Zadanie może zawierać
   tekst I RYSUNKI, więc pole musi brać całą dostępną wysokość. */
.todo-detail { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.todo-empty { padding: var(--s-7) var(--s-5); color: var(--text-faint); line-height: var(--lh-base); text-align: center; }
.todo-d-head { display: flex; align-items: flex-start; gap: var(--s-3); margin-bottom: var(--s-3); }
.todo-d-title { flex: 1; font-size: var(--t-lg); font-weight: var(--w-bold); line-height: var(--lh-tight); }
.todo-d-title.is-done { color: var(--text-faint); text-decoration: line-through; }
/* Pigułka stanu — ten sam ton co kropka w drzewie. */
.todo-pill { --ton: var(--status-oczekuje); flex: none; padding: 0 var(--s-3); border-radius: var(--r-pill); background: color-mix(in srgb, var(--ton) 16%, var(--surface)); color: var(--ton); font-size: var(--t-sm); font-weight: var(--w-bold); }
.todo-pill.done { --ton: var(--status-gotowy); }
.todo-pill.over { --ton: var(--danger); }
.todo-pill.part { --ton: var(--status-wtoku); }
.todo-d-meta { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); margin-bottom: var(--s-4); padding-bottom: var(--s-3); border-bottom: 1px solid var(--line); color: var(--text-muted); }
.todo-d-meta b { color: var(--text); font-weight: var(--w-medium); }
.todo-d-meta b.is-over, .todo-due-over { color: var(--danger); font-weight: var(--w-bold); }
/* Kropka rozdzielająca fragmenty metryki — czytelniejsza niż kreska. */
.todo-mnames { color: var(--text); font-weight: var(--w-medium); }
.todo-mdiv { flex: none; width: 3px; height: 3px; border-radius: var(--r-pill); background: var(--line-strong); }
.todo-remind { display: inline-flex; align-items: center; gap: var(--s-1); color: var(--warn-strong); }
.todo-d-tools { display: inline-flex; align-items: center; gap: var(--s-1); margin-left: auto; }
.todo-block { display: flex; flex-direction: column; flex: 1; min-height: 0; margin-bottom: var(--s-4); }
.todo-block-lbl, .task-detail-label { margin-bottom: var(--s-2); color: var(--text-faint); font-size: var(--t-xs); font-weight: var(--w-bold); }.task-desc { flex: 1; min-height: 0; overflow: auto; white-space: pre-wrap; word-break: break-word; }
/* Opis + stopka to jeden formularz — edytor ma rosnąć, stopka zostaje na dole. */
.todo-desc-form { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.zn-form .rich-editor, .todo-detail .rich-editor { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.task-rich-notes { --edytor-h: 140px; }
/* Opis zadania (formularz i szczegóły) nie schodzi poniżej paska narzędzi + 140 px pola. Na tablecie (1024 px) wąska
   kolumna szczegółów zawijała pasek narzędzi w 3 rzędy, a `min-height: 0` wyżej ścinało samo pole opisu do zera — nie było
   gdzie pisać ani czego przeczytać. Najmniejsza wysokość = pasek + 140 px: pole ma `contain: size`, więc długość opisu jej
   nie powiększa — długi opis dalej przewija się w polu, a przyciski pod nim zostają na miejscu. Telefon ma własny układ
   (formularz na całą stronę, pole rośnie z treścią) i tej reguły nie dostaje (przegląd E1, 27.09). */
:root:not([data-ui="mobile"]) :is(.zn-form, .todo-detail) .task-rich-notes,
:root:not([data-ui="mobile"]) :is(.todo-detail, .todo-detail .todo-block-main, .todo-detail .todo-desc-form) { min-height: min-content; }
:root:not([data-ui="mobile"]) :is(.zn-form, .todo-detail) .task-rich-notes > .rich-editable { contain: size; }
.task-rich-notes .rich-editable { flex: 1; min-height: var(--edytor-h); max-height: none; }
/* Odhaczanie per-osoba: pole zostaje PUSTE do kliknięcia (ptaszek przezroczysty). */
.task-check { display: grid; place-items: center; flex: none; width: var(--s-5); height: var(--s-5); border: 2px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: transparent; cursor: pointer; }
.task-check:hover { border-color: var(--status-gotowy); }
.task-check:disabled { cursor: default; opacity: .6; }
.task-check.checked { border-color: var(--status-gotowy); background: var(--status-gotowy); color: var(--text-invert); }
/* Postęp = ilu wykonawców odhaczyło. Pasek czyta się szybciej niż „2/5". */
.todo-prog { display: flex; align-items: center; gap: var(--s-2); }
.todo-prog b { color: var(--ok-strong); font-variant-numeric: tabular-nums; }
.todo-bar { flex: 1; height: var(--s-2); overflow: hidden; border-radius: var(--r-pill); background: var(--surface-3); }
.todo-bar span { display: block; height: 100%; background: var(--ok); }
/* Stopka zostaje na dole panelu — akcje nie uciekają pod scroll. */
.todo-foot { display: flex; align-items: center; justify-content: space-between; flex: none; flex-wrap: wrap; gap: var(--s-2) var(--s-4); margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); color: var(--text-muted); }
.todo-foot-status { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-4); min-width: 0; }
.todo-foot-acts { display: flex; align-items: center; gap: var(--s-2); flex: none; margin-left: auto; }
.todo-foot-person { display: inline-flex; align-items: center; gap: var(--s-2); color: var(--text); font-weight: var(--w-medium); }
.todo-foot-hint { color: var(--text-faint); font-size: var(--t-sm); }
.todo-foot .todo-bar { flex: none; width: 130px; }
.todo-col-tag { margin-left: auto; color: var(--text-muted); font-size: var(--t-xs); }
.todo-col-tag.done { color: var(--ok-strong); font-weight: var(--w-medium); }
.todo-dz { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); color: var(--text-faint); font-size: var(--t-sm); }
/* === 5. FORMULARZ ZADANIA ================================================= */
/* Ujednolicenie 11.08.2026 — cień kontenera --cien-1 (jak drzewo obok). */
.zn-detail { display: flex; flex-direction: column; min-height: 0; overflow: auto; padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--cien-1); }
/* `.todo-detail-col >` DOPISANE — ta reguła rozciągała formularz tylko
   w widoku Zadania (`.zn-detail`), a w oknie zadań otwieranym z projektu
   rodzicem jest `.todo-detail-col`. Bez tego formularz DODAWANIA zadania
   nie rósł i pole opisu zostawało na swoim minimum 140 px, mimo że okno
   ma ponad 1200 px wysokości. Ten sam defekt co wcześniej w `.todo-detail`. */
.zn-detail > .zn-form, .zn-detail > .todo-detail,
.todo-detail-col > .zn-form, .todo-detail-col > .todo-detail { display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* Ujednolicenie 11.08.2026 — wersaliki .03em → kanon .04em. Dotyczy czterech
   podpisów tej samej roli w tym arkuszu (.zn-form-sub, .zn-flbl, .notes2-lbl,
   .note-editor2-sub); w całej aplikacji było .02/.03/.04/.05/.08, a .04em ma
   19 miejsc — to jest wartość kanoniczna, reszta była rozjazdem. */
.zn-form-sub { margin-bottom: var(--s-1); color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
.zn-form-sub b { color: var(--accent-strong); }
/* Tytuł wpisuje się wprost w nagłówek — bez ramki, żeby wyglądał jak nagłówek. */
.zn-head { display: flex; align-items: flex-start; gap: var(--s-3); padding-bottom: var(--s-2); border-bottom: 1px solid var(--line); }
.zn-h-title { flex: 1; width: 100%; height: auto; padding: var(--s-1) 0; border: 0; background: none; font-size: var(--t-lg); font-weight: var(--w-bold); }
.zn-h-title:focus { box-shadow: none; }
/* Pola same dobierają liczbę kolumn — bez osobnych progów @media dla formularza. */
.zn-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--s-3); margin: var(--s-3) 0; }
.zn-field { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }.zn-flbl { color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); }
/* `.zn-isel` bywa <select>, bywa <button> (wybór daty) — obie formy mają wyglądać tak samo. */
/* W1: w oknie wygląda jak pole okna (zmienne --okno-pole-*, 05-komponenty §3). */
.zn-isel { width: 100%; min-height: var(--h-control); padding: 0 var(--s-3); border: 1px solid var(--okno-pole-ramka, var(--pole-ramka)); border-radius: var(--okno-pole-r, var(--r)); background: var(--okno-pole-tlo, var(--pole-tlo)); box-shadow: var(--okno-pole-obrys, none); color: var(--text); }
.zn-date-trigger { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); text-align: left; cursor: pointer; }
.zn-date-trigger .zn-date-ph { color: var(--text-faint); }
/* `min-width: 0` MUSI tu być: `.asel` ma własne dno 260 px, a tor siatki
   `.zn-fields` przy czterech polach schodzi do ~218 px. `min-width` bije `width`,
   więc bez tego widget wystaje 42 px na sąsiednie pole „Etap" i je zasłania. */
.zn-fields .asel { width: 100%; min-width: 0; max-width: none; }
.zn-date-trigger.is-open { border-color: var(--accent-strong); box-shadow: 0 0 0 var(--s-1) color-mix(in srgb, var(--accent) 18%, transparent); }
/* POLSKIE POLE DATY (tura 4, 26.09.2026; public/js/zadania/terminy-i-przypomnienia.js `ulepszPolaDat`): systemowe pole daty zostaje w formularzu
   pod przyciskiem (niewidoczne, bez kliknięć — dymek „wymagane" i przewinięcie trafiają w to samo miejsce),
   a przycisk wygląda jak termin zadania w Zadaniach. */
.pl-data { position: relative; display: block; min-width: 0; }
.pl-data > input.pl-data-natywne { position: absolute; inset: 0; width: 100%; height: 100%; min-height: 0; opacity: 0; pointer-events: none; }
.pl-data-pole { font: inherit; font-variant-numeric: tabular-nums; }
/* W oknach pola mają wyściółkę 10 px i wagę 500 (03-kontrolki.css) — przycisk daty tak samo, żeby stał równo z nimi. */
.modal .pl-data-pole { padding-inline: 10px; font-weight: var(--w-medium); }
/* W1 / POPR3-pola: wyłączony przycisk daty jak wyłączone pole (03-kontrolki) — tło i ramka pola zablokowanego, bez obrysu. */
.pl-data-pole:disabled { --okno-pole-obrys: none; border-color: var(--pole-ramka-zablokowane); background: var(--pole-tlo-zablokowane); color: var(--pole-napis-zablokowane); cursor: not-allowed; }
.pl-data-pole.is-tylko-odczyt:disabled { color: var(--text); }
.zn-form-actions { display: flex; justify-content: flex-end; gap: var(--s-2); margin-top: var(--s-3); }
/* Kalendarz terminu wisi nad wszystkim — JS pozycjonuje go przy przycisku. */
/* Ujednolicenie 11.08.2026 — jeden wzorzec panelu pływającego: --r + --cien-2
   (--cien-3 to głębia okna modalnego, kalendarz nie ma być cięższy od okna). */
/* Wysokość najwyżej ekran minus margines, reszta przewija się w środku: telefon poziomo (390 px wysokości) nie mieści
   całego miesiąca z przyciskami dotykowymi, a „Ustaw” uciekało pod dolną krawędź (przegląd E1, 27.09). */
.zn-date-pop { position: fixed; z-index: var(--z-dymek); max-width: calc(92vw / var(--skala-ui)); max-height: calc(100vh / var(--skala-ui) - var(--s-4)); overflow-y: auto; overscroll-behavior: contain; padding: var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.zn-date-pop-foot { display: flex; justify-content: flex-end; gap: var(--s-2); margin-top: var(--s-2); }
/* === 6. WYBÓR WYKONAWCÓW (.asel) ========================================== */
/* Zwijany dropdown: w polu widać awatary wybranych, po kliknięciu lista z filtrem.
   Checkbox jest ukryty — stan niesie `:has(input:checked)`, więc klika się cały wiersz. */
.asel { --asel-w: 320px; position: relative; display: inline-block; min-width: 260px; }
/* W1: w oknie wygląda jak pole okna (zmienne --okno-pole-*, 05-komponenty §3). */
.asel-trigger { display: flex; align-items: center; gap: var(--s-2); width: 100%; min-height: var(--h-control); padding: 0 var(--s-3); border: 1px solid var(--okno-pole-ramka, var(--pole-ramka)); border-radius: var(--okno-pole-r, var(--r)); background: var(--okno-pole-tlo, var(--pole-tlo)); box-shadow: var(--okno-pole-obrys, none); text-align: left; cursor: pointer; }
.asel-trigger:hover { border-color: var(--accent-strong); }
.asel-summary { display: flex; align-items: center; gap: var(--s-2); flex: 0 1 auto; min-width: 0; max-width: 62%; }
.asel-summary:empty { display: none; }
.asel-ph, .asel-chev { flex: none; color: var(--text-faint); }
.asel-cnt { color: var(--text); font-weight: var(--w-medium); white-space: nowrap; }
.asel-avs { display: inline-flex; flex: none; }
.asel-avs .asel-av:not(:first-child) { margin-left: calc(var(--s-2) * -1); }
/* Kolor inicjałów dobierany do tła — jak `.todo-ava` wyżej. */
.asel-av { --avatar-d: var(--s-5); --avatar-ramka: 2px; display: inline-grid; place-items: center; flex: none; width: var(--avatar-d); height: var(--avatar-d); border: var(--avatar-ramka) solid var(--surface); border-radius: var(--r-pill); background: var(--ava, var(--accent)); color: var(--ava-tekst, var(--text-invert)); font-size: min(var(--t-xs), calc((var(--avatar-d) - 2 * var(--avatar-ramka)) * .44)); font-weight: var(--w-bold); letter-spacing: -.02em; line-height: 1; white-space: nowrap; }
/* Awatary WYBRANYCH osób w polu „Dla kogo” (klasa także `.xs`) mają 12 px — tak było zawsze: ogólna klasa `.xs`
   stała w arkuszu ładowanym później (27) i wygrywała kolejnością; po K16 (27 przed widokami) spadły do 11 px. */
.asel-av.xs { font-size: min(var(--t-xs), calc((var(--avatar-d) - 2 * var(--avatar-ramka)) * .44)); }
/* Pole „Dla kogo" siedzi WEWNĄTRZ przycisku z ramką — musi być bez własnej.
   `input.asel-input` + `:not(...)` daje (0,3,1) i bije regułę bazową (0,2,1). */
input.asel-input:not([type="checkbox"]):not([type="radio"]) { flex: 1 1 auto; min-width: 44px; height: 100%; min-height: 0; padding: 0; border: 0; border-radius: 0; background: transparent; }
.asel-pop { position: absolute; z-index: var(--z-menu-nad-trescia); top: calc(100% + var(--s-1)); left: 0; width: var(--asel-w); max-width: calc(86vw / var(--skala-ui)); overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); box-shadow: var(--cien-2); }
.asel-pop[hidden], .asel-hidden { display: none; }
.asel-search { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
.asel-list { max-height: calc(var(--h-row) * 7); overflow-y: auto; padding: var(--s-1); }
.asel-row { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2); border-radius: var(--r-sm); cursor: pointer; }
.asel-row:hover { background: var(--surface-2); }
.asel-row > input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.asel-nm { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: var(--lh-tight); }
.asel-nm b { font-weight: var(--w-medium); }
.asel-nm small { color: var(--text-faint); font-size: var(--t-xs); }
/* Ptaszek pokazuje się dopiero po zaznaczeniu — lista zostaje czysta. */
.asel-tick { flex: none; color: var(--accent-strong); opacity: 0; }
.asel-row:has(input:checked) { background: var(--accent-soft); }
.asel-row:has(input:checked) .asel-tick { opacity: 1; }
.asel-none { padding: var(--s-3); color: var(--text-faint); text-align: center; }
/* === 7. NOTATKI-TEMATY — w 15b-notatki.css (v15-b5); tu zostają klocki wspólne z Zadaniami ======== */
/* „Nowe zadanie" NAD listą zadań (ergonomia 26.09, E1) — w pasku nad drzewem (widok Zadania: obok sortowania,
   okno zadań projektu: obok napisu „Zadania projektu"). Dawniej pod listą, dociśnięte do dołu kolumny. */
.zn-tree-add { display: flex; flex: none; }
.reminders-section { color: var(--text-muted); font-size: var(--t-sm); font-weight: var(--w-bold); }
.reminders-empty { padding: var(--s-5) var(--s-2); color: var(--text-faint); text-align: center; }
/* === 8. KALENDARZ TERMINU I PRZYPOMNIENIA ================================= */
.reminder-picker, .rcal, .rtime, .reminders-list, .reminder-alarm-body { display: flex; flex-direction: column; gap: var(--s-2); }
/* Wybór przypomnienia w OKNIE (klasa także `.modal-form`) ma układ formularza okna — siatka, odstęp 12 px — jak zawsze
   (dawniej dawała go reguła `.modal-form` z arkusza 27, ładowanego później). Wybór w dymku (`.zn-date-pop`) — flex jak wyżej. */
.modal-form.reminder-picker { display: grid; gap: var(--s-3); }
.rcal-head { display: flex; align-items: center; justify-content: space-between; }
.rcal-title { font-weight: var(--w-bold); text-transform: capitalize; }
.rcal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.rcal-wd { padding: var(--s-1) 0; color: var(--text-muted); font-size: var(--t-xs); font-weight: var(--w-bold); text-align: center; }
.rcal-cell { display: flex; align-items: center; justify-content: center; height: var(--h-control); }
/* Dzień ma wysokość komórki (`.rcal-cell`, --h-control), a nie `height: 100%`: procent w wierszu siatki o wysokości „auto”
   nie działał — pierwszy tydzień (z pustą komórką) miał 32 px, pozostałe po 19 px, więc tygodnie stały w nierównych
   odstępach, a dni były za małe do stuknięcia palcem (przegląd E1, 27.09). */
.rcal-day { width: 100%; border: 1px solid transparent; border-radius: var(--r-sm); cursor: pointer; }
.rcal-day:hover { background: var(--surface-2); }
/* Dziś tylko obramowane, wybrany dzień pełnym akcentem — nie mylą się ze sobą. */
.rcal-day.is-today { border-color: var(--line-strong); font-weight: var(--w-bold); }
.rcal-day.is-past { color: var(--text-faint); }
.rcal-day.is-sel { border-color: var(--accent-strong); background: var(--accent); color: var(--text-invert); font-weight: var(--w-bold); }
.rtime-row { display: flex; align-items: center; gap: var(--s-2); }
.rtime-row select { min-width: 64px; font-weight: var(--w-medium); }
.rtime-sep { color: var(--text-muted); font-size: var(--t-lg); font-weight: var(--w-bold); }
.rquick { display: flex; flex-wrap: wrap; gap: var(--s-2); }
/* Lista ustawionych przypomnień + alarm, gdy termin właśnie minął. */
.reminder-row { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); }
/* Zaległe = ramka i tło ostrzegawcze (POPR-n45: bez paska z lewej); sama zmiana ramki ginie w długiej liście. */
.reminder-row.is-due { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); background: var(--warn-soft); }
.reminder-row-dot { flex: none; width: var(--s-2); height: var(--s-2); border-radius: var(--r-pill); background: var(--text-faint); }
.reminder-row.is-due .reminder-row-dot { background: var(--warn); }
.reminder-row-main { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.reminder-row-title { font-weight: var(--w-medium); word-break: break-word; }
.reminder-row-time { color: var(--text-muted); font-size: var(--t-xs); }
.reminder-row.is-due .reminder-row-time { color: var(--warn-strong); font-weight: var(--w-bold); }
.reminder-row-actions, .reminder-snooze-row, .reminder-alarm-snooze { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }
.reminder-alarm-h { display: inline-flex; align-items: center; gap: var(--s-2); }
.reminder-alarm-h .icon { color: var(--warn-strong); }
.reminder-alarm-task { font-size: var(--t-md); font-weight: var(--w-bold); line-height: var(--lh-tight); }
.reminder-alarm-meta, .reminder-alarm-snooze-label { color: var(--text-muted); font-size: var(--t-sm); }
/* Ujednolicenie 11.08.2026 — gap 5px → --s-1 (4px). */
.task-reply-edit { display: inline-flex; align-items: center; gap: var(--s-1); align-self: flex-start; }
/* === 9. TABLET I TELEFON ================================================== */
/* Poniżej 980 px dwie kolumny obok siebie robią się za wąskie — drzewo idzie
   nad szczegóły i dostaje ograniczoną wysokość, żeby nie zajęło całego ekranu. */
@media (max-width: 980px) {
  /* `minmax(0, 1fr)`, nie `1fr` (skan 13.09.2026): tor `1fr` rośnie do min-content treści — pasek edytora
     opisu w jednym rzędzie rozpychał kolumnę do 747 px i szczegóły zadania wychodziły za ekran telefonu. */
  .zn-two, .todo-panel { grid-template-columns: minmax(0, 1fr); }
  .zn-detail { min-width: 0; }
  .zn-tree, .todo-tree { max-height: 320px; }
  .todo-tree { border-right: 0; border-bottom: 1px solid var(--line); }
}
/* #59, 13.09.2026 (test ścieżek na telefonie): `height:auto; overflow:visible` NIE dawało przewijania
   strony — `.content` i tak dostawał wysokość ekranu (flex:1), a `#app` ucina resztę. Szczegóły
   zadania siedziały w pudełku ~350 px pod drzewem; formularz „Nowe zadanie" z otwartą listą „Dla
   kogo" wychodził poza nie, a „Zleć zadanie" lądował przy dolnym pasku zakładek. Teraz przewija się
   cała strona (jak inne widoki), szczegóły rosną z treścią, drzewo zostaje ograniczone. */
:where(:root[data-ui="mobile"]) .content:has(.zn-page) { display: block; height: auto; overflow-y: auto; }
:where(:root[data-ui="mobile"]) .zn-page { height: auto; }
:where(:root[data-ui="mobile"]) .zn-two, :where(:root[data-ui="mobile"]) .zn-body { flex: none; }
:where(:root[data-ui="mobile"]) .zn-detail { height: auto; overflow: visible; }
:where(:root[data-ui="mobile"]) .zn-tree-top-row { flex-wrap: wrap; }
:where(:root[data-ui="mobile"]) .zn-sort-select { max-width: none; margin-left: 0; }
:where(:root[data-ui="mobile"]) .asel, :where(:root[data-ui="mobile"]) .asel-pop { width: 100%; min-width: 0; }
/* === 10. ODHACZANIE (checklisty, priorytet) =============================== (z dawnego 27, K16)
   Własne pudełko, bo natywnego checkboxa nie da się powiększyć ani wpiąć
   w wiersz z przekreślanym tekstem. Odhaczone = przekreślone i wyszarzone. */
.rt-check { display: flex; align-items: center; gap: var(--s-2); margin: var(--s-1) 0; }
.rt-check-box { position: relative; flex: 0 0 auto; display: inline-block; width: var(--s-4); height: var(--s-4); border: 2px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); cursor: pointer; user-select: none; }
.rt-check-box::after { content: ""; position: absolute; left: var(--s-1); top: 0; width: 5px; height: 10px; border: solid var(--text-invert); border-width: 0 2px 2px 0; opacity: 0; transform: rotate(45deg); }
.rt-check[data-checked="true"] .rt-check-box { border-color: var(--ok-strong); background: var(--ok); }
.rt-check[data-checked="true"] .rt-check-box::after { opacity: 1; }
.rt-check-text { flex: 1; min-width: 0; }
.rt-check[data-checked="true"] .rt-check-text { color: var(--text-muted); text-decoration: line-through; }
/* Gwiazdka priorytetu — natywny input schowany, klikalna jest gwiazdka. */
.prio-check { display: inline-flex; align-items: center; cursor: pointer; }
.prio-check input { position: absolute; width: 0; height: 0; opacity: 0; }
/* NAPRAWA 11.08.2026 — kolor pustej gwiazdki --line-strong → --text-faint.
   `--line-strong` to kolor KRESKI, nie znaku: dawał kontrast 1,39:1 na białym,
   czyli gwiazdka priorytetu była praktycznie niewidoczna, choć jest klikalna.
   Teraz 4,86:1. Stan „zaznaczona" niesie BARWA (bursztyn), nie sama jasność,
   więc oba stany nadal łatwo od siebie odróżnić. */
.prio-star { color: var(--text-faint); font-size: var(--t-lg); line-height: 1; transition: color var(--szybko) ease; }
.prio-check input:checked + .prio-star, .prio-check:hover .prio-star { color: var(--warn-strong); }

/* POPR-n28: kółko do odhaczenia w wierszu listy (wygląd .mp-odhacz z Mojego pulpitu); zrobiona część — pełne zielone. */
.todo-node .todo-odhacz { width: 24px; height: 24px; }
.todo-odhacz.is-done { border-color: var(--ok); background: var(--ok); color: var(--text-invert); }
:root[data-ui="tablet"] .todo-node .todo-odhacz { width: 44px; height: 44px; }   /* dotyk: cel ≥ 44 px (telefon: 9-telefon/8-moj-pulpit.css) */
/* POPR2-n28: tablet — tytuł zadania i nazwa grupy w dwóch liniach zamiast wielokropka (dymka z pełnym tytułem na dotyku nie ma;
   „Sprawdzić odbiór techniczny” było widać jako „Sprawdzić…”). Telefon ma to samo w 9-telefon/4-projekty-zadania-czat.css. */
:root[data-ui="tablet"] .todo-node-title, :root[data-ui="tablet"] .zn-group-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; white-space: normal; overflow-wrap: anywhere; }
/* POPR-n28 (raport: „pusty opis zajmuje 330 px i spycha komentarze”): w SZCZEGÓŁACH zadania opis jest zwinięty do ok.
   3 linii i nie rozpycha kolumny — czas pracy i komentarze wchodzą wyżej. Kliknięcie w opis (pisanie) rozwija pole do 200 px;
   dłuższy opis przewija się w polu. Formularz „Nowe zadanie” (.zn-form) bez zmian. */
:root:not([data-ui="mobile"]) .todo-detail .todo-block-main { flex: 0 0 auto; }
:root:not([data-ui="mobile"]) .todo-detail .task-rich-notes { --edytor-h: 72px; }
:root:not([data-ui="mobile"]) .todo-detail .task-rich-notes:focus-within { --edytor-h: 200px; }
