/* =====================================================================
   SIMTU WWW Client — components.css
   ---------------------------------------------------------------------
   WLASCICIEL: agent "tokeny". Komponenty wielokrotnego uzytku, wspolne
   dla wszystkich ekranow. Reguly specyficzne dla jednego ekranu naleza
   do screen-*.css; powloka (rail, titlebar, tabbar) do layout.css.

   Wymaga wczesniejszego zaladowania theme.css.
   ZASADA: zero wartosci hex — wylacznie var(--token) z theme.css.

   Wymiary pochodza z Figmy 5EhOBm4rUvbayzFZkwnQpT, strona 232:159
   "App - Komponenty" (numery node przy komponentach). Paleta z Qt6.

   SPIS TRESCI
     01. Efekt "glazed dark"
     02. Ikony (.ic, ikony wyeksportowane z Figmy)
     03. Panele, karty, moduly
     04. Naglowki stron, toolbary, siatki
     05. Przyciski
     06. Pola formularzy
     07. Search bar + Filters
     08. Chipy filtrow statusow
     09. Status dot, pigulki (priorytet, status, projekt)
     10. Progress
     11. Avatary
     12. Odznaki (badge, badge-notify)
     13. Tabele
     14. Dropdown / menu
     15. Modale
     16. Toasty
     17. Empty state, spinner, skeleton
   ===================================================================== */


/* =====================================================================
   01. EFEKT "GLAZED DARK"
   ---------------------------------------------------------------------
   Figma: styl "SIMTU_App_transparent 2" — trzy warstwy na tym samym
   promieniu (potwierdzone w get_design_context dla Search by keyword,
   Filters, Quick View, Explore, Bottom Dropdown Menu):
       1) rgba(29,29,29,0.10)  mix-blend-mode: color-burn
       2) #050208              mix-blend-mode: plus-lighter
       3) rgba(29,29,29,0.50)
   Realizacja: tlo elementu = warstwa 3 (wizualnie dominujaca),
   ::before = warstwa 1, ::after = warstwa 2. Pseudoelementy dostaja
   z-index:-1, wiec maluja sie NAD tlem elementu, a POD jego trescia —
   dokladnie tam, gdzie w Figmie. Kolejnosc warstw 1/2 wzgledem 3 jest
   odwrocona wzgledem Figmy; przy alfach 0.10 i #050208 roznica jest
   niedostrzegalna, a uklad miesci sie w dwoch pseudoelementach.
   ===================================================================== */

.glazed {
    position: relative;
    background-color: var(--glaze-3);
    border-radius: var(--radius-md);
}

.glazed::before,
.glazed::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}

.glazed::before {
    background: var(--glaze-1);
    mix-blend-mode: color-burn;
}

.glazed::after {
    background: var(--glaze-2);
    mix-blend-mode: plus-lighter;
}

/* Warianty promienia — Figma uzywa 4px dla przyciskow karty, 6px dla
   kart i kontrolek, 8px dla okna i menu. */
.glazed-sm { border-radius: var(--radius-sm); }
.glazed-lg { border-radius: var(--radius-lg); }

/* Wariant awaryjny dla przegladarek bez mix-blend-mode. */
@supports not (mix-blend-mode: color-burn) {
    .glazed {
        background-color: var(--glaze-flat);
        box-shadow: inset 0 0 0 1px var(--glaze-edge);
    }
    .glazed::before,
    .glazed::after { display: none; }
}

/* Glowne okno aplikacji — glazed + rozmycie i cien z Figmy. */
.glazed-window {
    -webkit-backdrop-filter: blur(var(--glaze-blur-window));
    backdrop-filter: blur(var(--glaze-blur-window));
    box-shadow: var(--shadow-window);
}


/* =====================================================================
   02. IKONY
   ---------------------------------------------------------------------
   Dwa zrodla, dwa mechanizmy:
     .ic      — wrapper dla inline SVG z ui.js icon() (Lucide-like, 24x24
                viewBox, stroke: currentColor).
     .ic-fig  — ikony WYEKSPORTOWANE Z FIGMY, pobrane do assets/icons/.
                Renderowane jako maska + background-color: currentColor,
                zeby kolor szedl z tokenu, a geometria pozostala oryginalna.
   Kazda ikona ma wlasne wymiary — NIE skalujemy wszystkiego jedna regula.
   ===================================================================== */

.ic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: inherit;
}
.ic svg {
    width: var(--ic-md);
    height: var(--ic-md);
    stroke: currentColor;
    fill: none;
    stroke-width: 1.8;
}

.ic-sm svg    { width: var(--ic-sm);      height: var(--ic-sm); }
.ic-lg svg    { width: var(--ic-lg);      height: var(--ic-lg); }
.ic-rail svg  { width: var(--ic-rail);    height: var(--ic-rail); }
.ic-file svg  { width: var(--ic-file);    height: var(--ic-file); }
.ic-chev svg  { width: var(--ic-chevron); height: var(--ic-chevron); }

/* Alias zgodnosciowy — czesc widokow uzywa jeszcze .icon. */
.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.icon svg { width: var(--ic-md); height: var(--ic-md); stroke: currentColor; fill: none; stroke-width: 1.5; }
.icon.sm svg { width: var(--ic-sm); height: var(--ic-sm); }
.icon.lg svg { width: var(--ic-lg); height: var(--ic-lg); }

/* --- Ikony z Figmy (assets/icons/*.svg) ----------------------------- */

.ic-fig {
    display: inline-block;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}

/* "Filters" — Figma 438:3379, leaf 12x8 */
.ic-filters {
    width: 12px;
    height: 8px;
    -webkit-mask-image: url("../icons/filters.svg");
            mask-image: url("../icons/filters.svg");
}

/* Chevron sortowania w naglowku kolumny — Figma 553:3829.
   Leaf 5x9 obrocony o -90deg -> pole 9x5. Wrapper trzyma pole 9x5,
   pseudoelement niesie leaf w oryginalnych wymiarach. */
.ic-sort {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 9px;
    height: 5px;
    flex-shrink: 0;
    color: inherit;
}
.ic-sort::before {
    content: "";
    width: 5px;
    height: 9px;
    background-color: currentColor;
    transform: rotate(-90deg) scaleY(-1);
    -webkit-mask: url("../icons/column-sort.svg") no-repeat center / contain;
            mask: url("../icons/column-sort.svg") no-repeat center / contain;
}
.ic-sort.asc::before  { transform: rotate(90deg) scaleY(-1); }

/* Trojkat rozwijania listy — Figma 492:7171.
   Jeden asset 9x12 (obie warianty w Figmie to ten sam leaf; "Variant2"
   12x9 to obrot o 90deg). */
.ic-list-toggle {
    width: 9px;
    height: 12px;
    -webkit-mask-image: url("../icons/list-toggle.svg");
            mask-image: url("../icons/list-toggle.svg");
    transition: transform var(--t-base) var(--ease);
}
.ic-list-toggle.open,
[aria-expanded="true"] > .ic-list-toggle { transform: rotate(90deg); }

/* Licznik zadan na chipie filtru — Figma 548:4083, leaf 8.084x10 */
.ic-subtasks {
    width: 8.084px;
    height: 10px;
    -webkit-mask-image: url("../icons/chip-count.svg");
            mask-image: url("../icons/chip-count.svg");
}

/* Chevrony menu rozwijanego — Figma 475:4040, leaf 4x2 */
.ic-caret-up,
.ic-caret-down {
    width: 4px;
    height: 2px;
}
.ic-caret-up {
    -webkit-mask-image: url("../icons/caret-up.svg");
            mask-image: url("../icons/caret-up.svg");
}
.ic-caret-down {
    -webkit-mask-image: url("../icons/caret-down.svg");
            mask-image: url("../icons/caret-down.svg");
}


/* =====================================================================
   03. PANELE, KARTY, MODULY
   ===================================================================== */

.card,
.module {
    position: relative;
    background-color: var(--glaze-3);
    border-radius: var(--radius-md);
}
.card::before,
.card::after,
.module::before,
.module::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.card::before,
.module::before { background: var(--glaze-1); mix-blend-mode: color-burn; }
.card::after,
.module::after  { background: var(--glaze-2); mix-blend-mode: plus-lighter; }

.panel {
    position: relative;
    background-color: var(--glaze-3);
    border-radius: var(--radius-lg);
    -webkit-backdrop-filter: blur(var(--glaze-blur));
            backdrop-filter: blur(var(--glaze-blur));
}
.panel::before,
.panel::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.panel::before { background: var(--glaze-1); mix-blend-mode: color-burn; }
.panel::after  { background: var(--glaze-2); mix-blend-mode: plus-lighter; }

@supports not (mix-blend-mode: color-burn) {
    .card,
    .module,
    .panel {
        background-color: var(--glaze-flat);
        box-shadow: inset 0 0 0 1px var(--glaze-edge);
    }
    .card::before,  .card::after,
    .module::before,.module::after,
    .panel::before, .panel::after { display: none; }
}

.card-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--submenu-h);
    padding: 0 var(--panel-pad);
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-primary);
    flex-shrink: 0;
}
.card-title { font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font); color: var(--text-primary); flex: 1; min-width: 0; }
.card-sub   { font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font); color: var(--text-secondary); }
.card-body  { padding: var(--panel-pad); }
.card-foot  {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--panel-pad);
    border-top: 1px solid var(--border-subtle);
}


/* =====================================================================
   04. NAGLOWKI STRON, TOOLBARY, SIATKI
   ===================================================================== */

.page-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--panel-pad);
    flex-shrink: 0;
}
.page-title   { font: var(--fw-bold) var(--fs-title) / var(--lh-title) var(--font); color: var(--text-primary); }
.page-sub     { font: var(--fw-medium) var(--fs-sm) / var(--lh-sm) var(--font); color: var(--text-secondary); margin-top: 2px; }
.page-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }

.section-title {
    font: var(--fw-semi) var(--fs-sm) / 1 var(--font);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: var(--space-5) 0 var(--space-3);
}
.section-title:first-child { margin-top: 0; }

.divider { height: 1px; background: var(--border-subtle); margin: var(--space-3) 0; }

.toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--panel-pad);
    flex-wrap: wrap;
    flex-shrink: 0;
}

/* Siatki modulow — odstep 4px (ZASADA NADRZEDNA z CLAUDE.md 5). */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--module-gap); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--module-gap); }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--module-gap); }

/* Lista klucz-wartosc (podglad rekordu). */
.kv    { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: var(--space-2) var(--space-4); }
.kv dt { font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; align-self: center; }
.kv dd { font: var(--fw-medium) var(--fs-md) / var(--lh-md) var(--font); color: var(--text-primary); word-break: break-word; }


/* =====================================================================
   05. PRZYCISKI
   ===================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: 30px;
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-default);
    background: var(--overlay-hover);
    color: var(--text-primary);
    font: var(--fw-medium) var(--fs-md) / 1 var(--font);
    white-space: nowrap;
    transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.btn:hover:not(:disabled) { background: var(--overlay-active); border-color: var(--border-strong); }
.btn:disabled { opacity: 0.45; }
.btn svg { width: var(--ic-sm); height: var(--ic-sm); stroke: currentColor; fill: none; stroke-width: 1.5; }

.btn-primary,
.btn-accent {
    background: var(--accent-primary);
    border-color: transparent;
    color: var(--text-on-accent);
    font-weight: var(--fw-semi);
}
.btn-primary:hover:not(:disabled),
.btn-accent:hover:not(:disabled) { background: var(--accent-hover); border-color: transparent; }
.btn-primary:active,
.btn-accent:active { background: var(--accent-active); }

.btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--text-secondary);
}
.btn-ghost:hover:not(:disabled) { background: var(--overlay-hover); color: var(--text-primary); border-color: transparent; }

.btn-danger {
    background: var(--status-danger-bg);
    border-color: var(--status-danger-bd);
    color: var(--status-danger-fg);
}
.btn-danger:hover:not(:disabled) { background: var(--status-danger-bg); border-color: var(--status-danger); }

/* Przycisk nawigacyjny / ikonowy w paskach narzedzi. */
.btn-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    transition: background var(--t-fast), color var(--t-fast);
}
.btn-nav:hover { color: var(--text-primary); background: var(--overlay-hover); }

.btn-sm    { height: 24px; padding: 0 9px; font-size: var(--fs-list); }
.btn-lg    { height: 36px; padding: 0 var(--space-5); }
.btn-block { width: 100%; }
.btn-icon  { width: 30px; padding: 0; }
.btn-icon.btn-sm { width: 24px; }

/* --- Akcje w naglowkach list (Qt-exact 93x26) ----------------------- */

.btn-add,
.btn-edit,
.btn-delete {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    height: 26px;
    min-width: 93px;
    padding: 0 var(--space-3);
    border-radius: 5px;
    border: 1px solid transparent;
    white-space: nowrap;
    transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.btn-add {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    font: var(--fw-bold) var(--fs-list) / 1 var(--font);
}
.btn-add:hover:not(:disabled) { background: var(--accent-hover); }
.btn-add:active { background: var(--accent-active); }

.btn-edit {
    background: var(--overlay-hover);
    color: var(--text-primary);
    border-color: var(--border-default);
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
}
.btn-edit:hover:not(:disabled) { background: var(--overlay-strong); border-color: var(--border-strong); }

.btn-delete {
    background: var(--status-danger-bg);
    color: var(--status-danger-fg);
    border-color: var(--status-danger-bd);
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
}
.btn-delete:hover:not(:disabled) { background: var(--status-danger-bg); border-color: var(--status-danger); }

.btn-add:disabled,
.btn-edit:disabled,
.btn-delete:disabled { opacity: 0.45; }

/* --- Quick View / Explore (Figma 677:6208 / 677:6212) ---------------
   110px szerokosci, radius 4px, padding 6px, Inter Regular 10/14, biale.
   Podstawowy = glazed; hover = SIMTU accent 3 -> --status-info;
   selected = SIMTU accent 1 -> --accent-primary.
   Wysokosc: 16px (tak wystepuje w karcie brandu, CLAUDE.md 5.1/5.2).
   Samodzielny komponent w Figmie ma 21px — uzyj .btn-quickview.tall.  */

.btn-quickview,
.btn-explore {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--card-btn-w);
    height: var(--card-btn-h);
    padding: 0 6px;
    border-radius: var(--radius-sm);
    background-color: var(--glaze-3);
    color: var(--text-on-accent);
    font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font);
    text-align: center;
    transition: background-color var(--t-fast);
}
.btn-quickview::before, .btn-quickview::after,
.btn-explore::before,   .btn-explore::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.btn-quickview::before, .btn-explore::before { background: var(--glaze-1); mix-blend-mode: color-burn; }
.btn-quickview::after,  .btn-explore::after  { background: var(--glaze-2); mix-blend-mode: plus-lighter; }

.btn-quickview:hover, .btn-explore:hover { background-color: var(--status-info); }
.btn-quickview.selected, .btn-explore.selected,
.btn-quickview[aria-pressed="true"], .btn-explore[aria-pressed="true"] { background-color: var(--accent-primary); }

.btn-quickview.tall,
.btn-explore.tall { height: 21px; }

@supports not (mix-blend-mode: color-burn) {
    .btn-quickview,
    .btn-explore { background-color: var(--glaze-flat); box-shadow: inset 0 0 0 1px var(--glaze-edge); }
    .btn-quickview::before, .btn-quickview::after,
    .btn-explore::before,   .btn-explore::after { display: none; }
}

/* --- Przelacznik widoku (CLAUDE.md 5.7: osobne przyciski, gap 4px) --- */

.view-toggle { display: inline-flex; align-items: center; gap: var(--space-1); }
.view-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 24px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--text-secondary);
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.view-toggle-btn:hover { background: var(--overlay-hover); color: var(--text-primary); }
.view-toggle-btn.active {
    background: var(--accent-glow);
    color: var(--accent-primary);
    border-color: var(--accent-border);
}


/* =====================================================================
   06. POLA FORMULARZY
   ===================================================================== */

.field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }

.field > label,
.field-label {
    font: var(--fw-bold) var(--fs-micro) / 1 var(--font);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.field-hint  { font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font); color: var(--text-tertiary); }
.field-error { font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font); color: var(--status-danger-fg); }
.field-caption { font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font); color: var(--text-secondary); }
.field-spacer  { height: var(--space-2); }
.field-row   { display: flex; gap: var(--space-3); align-items: flex-end; flex-wrap: wrap; }
.form-grid   { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.form-grid .field.span-2 { grid-column: 1 / -1; }

.field.invalid .input,
.field.invalid .textarea,
.field.invalid .select { border-color: var(--status-danger); }

.input,
.select,
.textarea,
.dialog-input,
.dialog-select,
.dialog-textarea {
    width: 100%;
    height: 28px;
    padding: 0 var(--space-2);
    background: var(--bg-input);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
    outline: none;
    transition: border-color var(--t-fast);
}
.textarea,
.dialog-textarea { height: auto; min-height: 76px; padding: var(--space-2); line-height: 1.5; }
.select,
.dialog-select { cursor: pointer; }

.input:focus, .select:focus, .textarea:focus,
.dialog-input:focus, .dialog-select:focus, .dialog-textarea:focus { border-color: var(--border-accent); }

.input::placeholder, .textarea::placeholder,
.dialog-input::placeholder, .dialog-textarea::placeholder { color: var(--text-tertiary); }

.input:disabled, .select:disabled, .textarea:disabled,
.dialog-input:disabled {
    color: var(--text-tertiary);
    border-color: var(--border-hairline);
    cursor: not-allowed;
}
.dialog-input.invalid { border-color: var(--status-danger); }

.checkbox,
.radio,
.dialog-check {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
    color: var(--text-primary);
    cursor: pointer;
    user-select: none;
}
.checkbox input,
.radio input,
.dialog-check input[type="checkbox"] {
    width: 14px;
    height: 14px;
    accent-color: var(--accent-primary);
    cursor: pointer;
    flex-shrink: 0;
}

/* Przelacznik on/off. */
.switch {
    position: relative;
    display: inline-flex;
    width: 34px;
    height: 18px;
    border-radius: var(--radius-full);
    background: var(--overlay-strong);
    border: 1px solid var(--border-default);
    cursor: pointer;
    transition: background var(--t-base), border-color var(--t-base);
    flex-shrink: 0;
}
.switch::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    border-radius: var(--radius-full);
    background: var(--text-secondary);
    transition: transform var(--t-base) var(--ease), background var(--t-base);
}
.switch.on {
    background: var(--accent-glow);
    border-color: var(--accent-border);
}
.switch.on::after {
    transform: translateX(16px);
    background: var(--accent-primary);
}


/* =====================================================================
   07. SEARCH BAR + FILTERS
   ---------------------------------------------------------------------
   Figma 438:3366 (Search by keyword, 212x16) i 438:3379 (Filters).
   Oba: radius 6px, padding 0 9px, tlo glazed, Inter Medium 10/14,
   kolor placeholdera SIMTU light grey -> --text-secondary.
   Gap search -> filters: 12px (CLAUDE.md 5.5).
   ===================================================================== */

.searchbar,
.search-bar {
    position: relative;
    width: var(--search-w);
    height: var(--control-h);
    padding: 0 9px;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    background-color: var(--glaze-3);
    color: var(--text-primary);
    font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font);
    outline: none;
    transition: border-color var(--t-fast);
}
.searchbar::placeholder,
.search-bar::placeholder { color: var(--text-secondary); }
.searchbar:focus,
.search-bar:focus { border-color: var(--border-accent); }
.searchbar::selection,
.search-bar::selection { background: var(--accent-primary); color: var(--text-on-accent); }
/* <input> nie moze niesc pseudoelementow, wiec warstwy blendu zastepuje
   wariant plaski — wizualnie warstwa 3 dominuje i tak. */

.filters-btn,
.btn-filters {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    height: var(--control-h);
    padding: 0 9px;
    border-radius: var(--radius-md);
    background-color: var(--glaze-3);
    color: var(--text-secondary);
    font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font);
    white-space: nowrap;
    transition: color var(--t-fast);
}
.filters-btn::before, .filters-btn::after,
.btn-filters::before, .btn-filters::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.filters-btn::before, .btn-filters::before { background: var(--glaze-1); mix-blend-mode: color-burn; }
.filters-btn::after,  .btn-filters::after  { background: var(--glaze-2); mix-blend-mode: plus-lighter; }
.filters-btn:hover,
.btn-filters:hover { color: var(--text-primary); }
.filters-btn.active,
.btn-filters.active { color: var(--accent-primary); }

@supports not (mix-blend-mode: color-burn) {
    .filters-btn,
    .btn-filters { background-color: var(--glaze-flat); box-shadow: inset 0 0 0 1px var(--glaze-edge); }
    .filters-btn::before, .filters-btn::after,
    .btn-filters::before, .btn-filters::after { display: none; }
}

/* Pasek: search + filters, odstep 12px, padding 12px od krawedzi. */
.searchrow {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--panel-pad);
    flex-shrink: 0;
}


/* =====================================================================
   08. CHIPY FILTROW STATUSOW
   ---------------------------------------------------------------------
   Figma 548:4083 "Filters" — 120x16, radius 6px, padding 0 9px,
   Inter Medium 10/14, solidne tlo w kolorze statusu, po prawej ikona
   (8.084x10) + licznik, gap 2px. Kolory ze statusow Qt6:
       All Tasks   -> --status-neutral
       Not Started -> --status-info      (Figma SIMTU accent 3)
       In Progress -> --status-warning
       Overdue     -> --status-danger
       Completed   -> --status-success
   Nieaktywny chip jest przygaszony — to nasz stan wyboru filtru
   (Figma nie definiuje wariantu "inactive").
   ===================================================================== */

.chip,
.filter-chip {
    display: inline-flex;
    align-items: center;
    /* Figma: etykieta 64px + grupa licznika 38px = 102px = 120 - 2*9 paddingu.
       Zadnego gapu miedzy nimi — inaczej etykieta traci miejsce. */
    gap: 0;
    width: var(--chip-w);
    height: var(--control-h);
    padding: 0 9px;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    background: var(--status-neutral);
    color: var(--text-on-accent);
    font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font);
    white-space: nowrap;
    user-select: none;
    transition: opacity var(--t-fast);
}
/* .filter-chip pelni role przelacznika filtru — nieaktywny jest przygaszony.
   .chip bez tej roli (etykieta w wierszu) zostaje w pelnej sile. */
.filter-chip { cursor: pointer; opacity: 0.55; }
.filter-chip:hover { opacity: 0.8; }
.filter-chip.active { opacity: 1; }

.chip-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.chip-count {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 2px;
    flex-shrink: 0;
    min-width: 38px;
}

.chip-all,         .chip-neutral     { background: var(--status-neutral); }
.chip-not-started, .chip-info        { background: var(--status-info); }
.chip-in-progress, .chip-warning     { background: var(--status-warning); color: var(--text-inverse); }
.chip-overdue,     .chip-danger      { background: var(--status-danger); }
.chip-completed,   .chip-success     { background: var(--status-success); }

/* Wariant do zamykania (chip tagu, nie filtru). */
.chip-x { color: inherit; opacity: 0.7; font-size: var(--fs-md); line-height: 1; cursor: pointer; }
.chip-x:hover { opacity: 1; }


/* =====================================================================
   09. STATUS DOT + PIGULKI
   ===================================================================== */

/* --- Status Dot (Figma 438:3556, 10x10, 5 wariantow) ----------------
   W Figmie to wyeksportowany SVG, ale jego jedyna trescia jest kolor
   wypelnienia — a kolory bierzemy z palety Qt6 (decyzja usera), nie
   z Figmy. Dlatego kropka jest rysowana tokenem, a nie plikiem. */

.status-dot {
    display: inline-block;
    width: var(--dot-size);
    height: var(--dot-size);
    border-radius: var(--radius-full);
    background: var(--status-neutral);
    flex-shrink: 0;
}
.sd-all,         .status-dot.s-all         { background: var(--status-neutral); }
.sd-not-started, .status-dot.s-not-started { background: var(--status-info); }
.sd-in-progress, .status-dot.s-in-progress { background: var(--status-warning); }
.sd-overdue,     .status-dot.s-overdue     { background: var(--status-danger); }
.sd-completed,   .status-dot.s-completed   { background: var(--status-success); }

/* Mala kropka ogolnego przeznaczenia (kolor projektu w listach). */
.dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: var(--project-gray);
    flex-shrink: 0;
}
.dot.lg { width: 11px; height: 11px; }

/* --- Priorytet (Figma 496:4242, 100x16, radius 6, Inter 10/14) ------
   Kolory Figmy zmapowane na palete Qt6:
       Urgent  #ff3b30 -> --status-danger
       High    #ffa100 -> --status-warning (tekst ciemny, CLAUDE.md 5.3)
       Normal  #00adee -> --status-info
       Low     #9c9c9c -> --status-neutral
       Not set  obrys  -> obrys --text-secondary
   Klasy .p-medium (istniejacy model danych High/Medium/Low) traktujemy
   jak "Normal".                                                        */

.pill-priority,
.priority-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--priority-w);
    max-width: 100%;
    height: var(--control-h);
    padding: 0 var(--space-2);
    border-radius: var(--radius-md);
    /* Domyslnie (brak klasy wariantu) = "Not set": sam obrys. */
    border: 1px solid var(--text-secondary);
    background: transparent;
    color: var(--text-secondary);
    font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font);
    white-space: nowrap;
    text-align: center;
}

.p-urgent { background: var(--status-danger);  color: var(--text-on-accent); border-color: transparent; }
.p-high   { background: var(--status-warning); color: var(--text-inverse);   border-color: transparent; }
.p-normal,
.p-medium { background: var(--status-info);    color: var(--text-on-accent); border-color: transparent; }
.p-low    { background: var(--status-neutral); color: var(--text-on-accent); border-color: transparent; }
.p-none,
.p-not-set { background: transparent; color: var(--text-secondary); border-color: var(--text-secondary); }

/* --- Pigulka statusu (CLAUDE.md 5.3: tinted, 12% tla / 30% obrysu) -- */

.status-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 18px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    border: 1px solid var(--status-neutral-bd);
    background: var(--status-neutral-bg);
    color: var(--status-neutral-fg);
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    white-space: nowrap;
}
.status-pill.s-not-started { background: var(--status-info-bg);    border-color: var(--status-info-bd);    color: var(--status-info-fg); }
.status-pill.s-in-progress { background: var(--status-warning-bg); border-color: var(--status-warning-bd); color: var(--status-warning-fg); }
.status-pill.s-overdue     { background: var(--status-danger-bg);  border-color: var(--status-danger-bd);  color: var(--status-danger-fg); }
.status-pill.s-completed   { background: var(--status-success-bg); border-color: var(--status-success-bd); color: var(--status-success-fg); }

/* --- Tag projektu — obrys w kolorze projektu ------------------------
   Kolor podaje widok przez `style="--pill-color: var(--project-teal)"`
   albo przez klase .pc-*.                                              */

.pill-project,
.project-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 18px;
    max-width: 100%;
    padding: 0 var(--space-2);
    border-radius: var(--radius-sm);
    border: 1px solid var(--pill-color, var(--project-gray));
    background: transparent;
    color: var(--pill-color, var(--text-secondary));
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.pc-green  { --pill-color: var(--project-green); }
.pc-purple { --pill-color: var(--project-purple); }
.pc-pink   { --pill-color: var(--project-pink); }
.pc-teal   { --pill-color: var(--project-teal); }
.pc-amber  { --pill-color: var(--project-amber); }
.pc-blue   { --pill-color: var(--project-blue); }
.pc-gray   { --pill-color: var(--project-gray); }


/* =====================================================================
   10. PROGRESS
   ---------------------------------------------------------------------
   .progress          — pasek z obrysem i procentem w srodku (nowy wzorzec)
   .progress-wrap     — uklad zastany w JS: track + osobny procent obok
   ===================================================================== */

.progress {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-width: 60px;
    height: var(--control-h);
    border-radius: var(--radius-full);
    border: 1px solid var(--border-default);
    background: transparent;
    overflow: hidden;
}
.progress-bar-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--progress, 0%);
    background: var(--progress-color, var(--accent-primary));
    opacity: 0.35;
    transition: width var(--t-slow) var(--ease);
}
.progress-value {
    position: relative;
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.progress-wrap,
.progress-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 18px;
}
.progress-track {
    flex: 1;
    min-width: 32px;
    height: 4px;
    background: var(--border-subtle);
    border-radius: var(--radius-full);
    overflow: hidden;
}
.progress-fill {
    height: 100%;
    border-radius: var(--radius-full);
    background: var(--accent-primary);
    transition: width var(--t-slow) var(--ease);
}
.progress-pct {
    flex-shrink: 0;
    min-width: 28px;
    text-align: right;
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}


/* =====================================================================
   11. AVATARY
   ---------------------------------------------------------------------
   Figma 445:3965 "Member Avatar": 32x32, radius 6px, inicjaly
   Inter Regular 13/18, biale, wysrodkowane. Kwadrat z zaokragleniem —
   NIE kolo (zmiana wzgledem CLAUDE.md 5.4, ktory mowil o kole).
   ===================================================================== */

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-md);
    border: 2px solid var(--bg-primary);
    background: var(--avatar-6);
    color: var(--text-on-accent);
    font: var(--fw-regular) var(--fs-micro) / 1 var(--font);
    flex-shrink: 0;
    overflow: hidden;
    user-select: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }

.avatar.xs { width: 20px; height: 20px; border-radius: var(--radius-sm); font-size: var(--fs-badge); border-width: 1px; }
.avatar.sm { width: 22px; height: 22px; border-radius: var(--radius-sm); font-size: var(--fs-micro); }
.avatar.md { width: var(--avatar-size); height: var(--avatar-size); font: var(--fw-regular) var(--fs-body) / var(--lh-body) var(--font); }
.avatar.lg { width: 36px; height: 36px; font-size: var(--fs-sm); }
.avatar.xl { width: 56px; height: 56px; border-radius: var(--radius-lg); font-size: var(--fs-title); border-width: 0; }
.avatar.xxl{ width: 72px; height: 72px; border-radius: var(--radius-lg); font-size: var(--fs-kpi); border-width: 0; }
.avatar.plain  { border: none; }
.avatar.circle { border-radius: var(--radius-full); }

.avatar.av-sb, .avatar.av-1 { background: var(--avatar-1); }
.avatar.av-ec, .avatar.av-2 { background: var(--avatar-2); }
.avatar.av-db, .avatar.av-3 { background: var(--avatar-3); }
.avatar.av-mt, .avatar.av-4 { background: var(--avatar-4); }
.avatar.av-md, .avatar.av-5 { background: var(--avatar-5); }
.avatar.av-default, .avatar.av-6 { background: var(--avatar-6); }

/* Nakladajace sie avatary przypisanych osob. */
.avatar-stack { display: inline-flex; align-items: center; }
.avatar-stack > .avatar { border: 2px solid var(--bg-primary); }
.avatar-stack > .avatar + .avatar { margin-left: -6px; }

.avatar-more,
.assignee-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 22px;
    padding: 0 6px;
    margin-left: -6px;
    border-radius: var(--radius-sm);
    background: var(--overlay-strong);
    color: var(--text-secondary);
    font: var(--fw-medium) var(--fs-micro) / 1 var(--font);
    flex-shrink: 0;
}

.avatar-wrap { position: relative; flex-shrink: 0; display: inline-flex; }
.online-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: var(--text-tertiary);
    border: 2px solid var(--bg-primary);
    box-sizing: content-box;
}
.online-dot.on { background: var(--status-success); }


/* =====================================================================
   12. ODZNAKI
   ===================================================================== */

/* Notification Badge (Figma 445:3975): radius 4px, padding 0 2px,
   Inter Regular 7/14, wysokosc pola tekstu 13px, tlo SIMTU accent 3. */
.badge-notify {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 13px;
    height: 13px;
    padding: 0 2px;
    border-radius: var(--radius-sm);
    background: var(--status-info);
    color: var(--text-on-accent);
    font: var(--fw-regular) var(--fs-badge) / var(--lh-badge) var(--font);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
    overflow: hidden;
}
.badge-notify.accent  { background: var(--accent-primary); }
.badge-notify.danger  { background: var(--status-danger); }
.badge-notify.success { background: var(--status-success); }

/* Odznaka tekstowa — ui.js statusBadge() sklada klase `badge badge-<tone>`. */
.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 18px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    border: 1px solid var(--status-neutral-bd);
    background: var(--status-neutral-bg);
    color: var(--status-neutral-fg);
    font: var(--fw-medium) var(--fs-list) / 1 var(--font);
    white-space: nowrap;
}
.badge-green,  .badge-success { background: var(--status-success-bg); color: var(--status-success-fg); border-color: var(--status-success-bd); }
.badge-orange, .badge-warning { background: var(--status-warning-bg); color: var(--status-warning-fg); border-color: var(--status-warning-bd); }
.badge-red,    .badge-danger  { background: var(--status-danger-bg);  color: var(--status-danger-fg);  border-color: var(--status-danger-bd); }
.badge-blue,   .badge-info    { background: var(--status-info-bg);    color: var(--status-info-fg);    border-color: var(--status-info-bd); }
.badge-violet { background: var(--project-purple-bg); color: var(--project-purple-fg); border-color: var(--project-purple-bd); }
.badge-cyan   { background: var(--project-teal-bg);   color: var(--project-teal-fg);   border-color: var(--project-teal-bd); }
.badge-gray   { background: var(--status-neutral-bg); color: var(--status-neutral-fg); border-color: var(--status-neutral-bd); }
.badge-high   { background: var(--status-warning); color: var(--text-inverse); border-color: transparent; }
.badge-solid  { border-color: transparent; }


/* =====================================================================
   13. TABELE
   ---------------------------------------------------------------------
   Naglowek kolumny wg Figma 553:3829 "Column Name": Inter Regular 10/14,
   kolor SIMTU white -> --text-primary, gap 4px do chevronu 9x5.
   Wiersz: 36px, hover, zaznaczenie z lewym paskiem accentu (CLAUDE.md 5.6).
   ===================================================================== */

.table-wrap {
    width: 100%;
    overflow: auto;
    border-radius: var(--radius-md);
    background: var(--glaze-3);
}
.table {
    width: 100%;
    min-width: 560px;
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
    color: var(--text-primary);
}

.table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    height: 28px;
    padding: 0 var(--space-3);
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-subtle);
    font: var(--fw-regular) var(--fs-list) / var(--lh-list) var(--font);
    color: var(--text-primary);
    text-align: left;
    white-space: nowrap;
    user-select: none;
}
.table thead th.sortable { cursor: pointer; }
.table thead th.sortable:hover .ic-sort { color: var(--accent-primary); }
/* Naglowek z chevronem — .th-inner trzyma gap 4px z Figmy. */
.th-inner {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

.table tbody td {
    height: var(--row-h);
    padding: 0 var(--space-3);
    border-bottom: 1px solid var(--border-hairline);
    vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover td { background: var(--overlay-hover); }
.table.zebra tbody tr:nth-child(even) td { background: var(--overlay-zebra); }
.table.zebra tbody tr:nth-child(even):hover td { background: var(--overlay-hover); }
.table tbody tr.selected td {
    background: var(--accent-soft);
}
.table tbody tr.selected td:first-child { box-shadow: inset 2px 0 0 var(--accent-primary); }
.table tbody tr.clickable { cursor: pointer; }
.table .num   { text-align: right; font-variant-numeric: tabular-nums; }
.table .tight { width: 1%; white-space: nowrap; }

/* Wiersze zagniezdzone — wciecie + trojkat rozwijania. */
.table tbody tr.nested td:first-child { padding-left: var(--space-6); }
.table tbody tr.nested-2 td:first-child { padding-left: calc(var(--space-6) + var(--space-4)); }

.row-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-4);
    height: var(--space-4);
    margin-right: var(--space-1);
    color: var(--text-secondary);
    cursor: pointer;
    flex-shrink: 0;
    transition: color var(--t-fast);
}
.row-toggle:hover { color: var(--text-primary); }

.table-empty {
    padding: var(--space-7) var(--space-4);
    text-align: center;
    color: var(--text-tertiary);
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
}


/* =====================================================================
   14. DROPDOWN / MENU
   ---------------------------------------------------------------------
   Figma 475:4040 "Bottom Dropdown Menu": 244x40, radius 8px, glazed,
   badge 12x12 po lewej (left 12px), tekst Inter Regular 13/18 od 32px,
   przelacznik 12x12 z obrysem po prawej (left 221px).
   ===================================================================== */

.dropdown { position: relative; display: inline-flex; }

.dropdown-toggle {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: var(--dropdown-w);
    max-width: 100%;
    height: var(--dropdown-h);
    padding: 0 var(--space-3);
    border-radius: var(--radius-lg);
    background-color: var(--glaze-3);
    color: var(--text-primary);
    font: var(--fw-regular) var(--fs-body) / var(--lh-body) var(--font);
    text-align: left;
}
.dropdown-toggle::before,
.dropdown-toggle::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}
.dropdown-toggle::before { background: var(--glaze-1); mix-blend-mode: color-burn; }
.dropdown-toggle::after  { background: var(--glaze-2); mix-blend-mode: plus-lighter; }
.dropdown-toggle .badge-notify { margin-right: var(--space-1); }
.dropdown-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Przelacznik 12x12 z obrysem (Figma: border 1px SIMTU white, radius 6). */
.dropdown-caret {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;
    height: 12px;
    border: 1px solid var(--text-primary);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    flex-shrink: 0;
}

@supports not (mix-blend-mode: color-burn) {
    .dropdown-toggle { background-color: var(--glaze-flat); box-shadow: inset 0 0 0 1px var(--glaze-edge); }
    .dropdown-toggle::before, .dropdown-toggle::after { display: none; }
}

.menu {
    position: absolute;
    z-index: var(--z-menu);
    min-width: 180px;
    padding: var(--space-1);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-default);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-menu);
}
.menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    height: 26px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
    text-align: left;
    white-space: nowrap;
    transition: background var(--t-fast), color var(--t-fast);
}
.menu-item:hover { background: var(--overlay-hover); color: var(--text-primary); }
.menu-item.active { background: var(--accent-glow); color: var(--accent-primary); }
.menu-item.danger { color: var(--status-danger-fg); }
.menu-sep { height: 1px; margin: var(--space-1) 0; background: var(--border-subtle); }
.menu-label {
    padding: var(--space-1) var(--space-2);
    font: var(--fw-bold) var(--fs-micro) / 1 var(--font);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}


/* =====================================================================
   15. MODALE
   ===================================================================== */

.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-backdrop);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    background: var(--scrim);
    -webkit-backdrop-filter: blur(2px);
            backdrop-filter: blur(2px);
}

.modal-dialog {
    display: flex;
    flex-direction: column;
    width: 540px;
    max-width: 100%;
    max-height: 100%;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-default);
    background: var(--bg-dialog);
    box-shadow: var(--shadow-dialog);
    overflow: hidden;
}
.modal-dialog.w-sm { width: 360px; }
.modal-dialog.w-md { width: 540px; }
.modal-dialog.w-lg { width: 720px; }
.modal-dialog.w-xl { width: 940px; }
.modal-dialog.edit-mode { width: 540px; height: 620px; }

.modal-header,
.task-dialog-header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--submenu-h);
    padding: 0 var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
    font: var(--fw-medium) var(--fs-body) / var(--lh-body) var(--font);
    color: var(--text-primary);
    flex-shrink: 0;
}
.modal-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    flex-shrink: 0;
}
.modal-close:hover { color: var(--text-primary); background: var(--overlay-active); }

.modal-body,
.task-dialog-body {
    padding: var(--space-4);
    overflow-y: auto;
    min-height: 0;
    flex: 1;
}
.modal-footer,
.task-dialog-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--border-subtle);
    flex-shrink: 0;
}
.modal-footer .spread,
.task-dialog-footer .spread { margin-right: auto; }
.modal-text { font: var(--fw-regular) var(--fs-body) / 1.55 var(--font); color: var(--text-primary); }
.task-dialog-separator { height: 1px; background: var(--border-subtle); margin: var(--space-3) 0; }

/* Blok komentarzy w dialogu edycji zadania (parts/task_comments.js montuje
   sie w .task-dialog-comments). Naglowek to etykieta sekcji — ta sama
   typografia co .card-title, zeby dialog mowil jezykiem kart. */
.task-dialog-comments-header {
    margin-bottom: var(--space-2);
    color: var(--text-secondary);
    font: var(--fw-medium) var(--fs-list) / var(--lh-list) var(--font);
}
.task-dialog-comments {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* Blokada przewijania tla, gdy modal jest otwarty (ui.js, task_dialog.js,
   event_dialog.js dodaja te klase na <body>). Powloka i tak trzyma
   100vh, ale dialog moze urosnac ponad ekran i wtedy body by sie przewijalo. */
body.modal-open { overflow: hidden; }


/* =====================================================================
   16. TOASTY
   ===================================================================== */

.toasts {
    position: fixed;
    right: var(--space-4);
    bottom: var(--space-4);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 240px;
    max-width: 380px;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-default);
    border-left: 2px solid var(--status-info);
    background: var(--bg-elevated);
    color: var(--text-primary);
    font: var(--fw-regular) var(--fs-md) / var(--lh-md) var(--font);
    box-shadow: var(--shadow-toast);
    pointer-events: auto;
    animation: toast-in 0.18s var(--ease);
}
.toast-info    { border-left-color: var(--status-info); }
.toast-success { border-left-color: var(--status-success); }
.toast-error   { border-left-color: var(--status-danger); }
.toast-warning { border-left-color: var(--status-warning); }
.toast-msg     { flex: 1; min-width: 0; }
.toast-close {
    color: var(--text-secondary);
    flex-shrink: 0;
    line-height: 1;
}
.toast-close:hover { color: var(--text-primary); }
.toast.hiding { animation: toast-out 0.16s var(--ease) forwards; }

@keyframes toast-in  { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(6px); } }


/* =====================================================================
   17. EMPTY STATE, SPINNER, SKELETON
   ===================================================================== */

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-8) var(--space-6);
    text-align: center;
}
.empty-state-icon { color: var(--text-tertiary); }
.empty-state-icon svg { width: 48px; height: 48px; stroke: currentColor; fill: none; stroke-width: 1.25; }
.empty-state-title { font: var(--fw-semi) var(--fs-section) / var(--lh-section) var(--font); color: var(--text-primary); }
.empty-state-text  { font: var(--fw-regular) var(--fs-md) / 1.55 var(--font); color: var(--text-secondary); max-width: 420px; }
.empty-state-actions { margin-top: var(--space-3); display: flex; gap: var(--space-2); }

.spinner {
    width: 16px;
    height: 16px;
    border: 2px solid var(--border-default);
    border-top-color: var(--accent-primary);
    border-radius: var(--radius-full);
    animation: spin 0.7s linear infinite;
    flex-shrink: 0;
}
.spinner.lg { width: 28px; height: 28px; border-width: 3px; }
.spinner-block {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-8) var(--space-6);
    color: var(--text-secondary);
    font: var(--fw-medium) var(--fs-md) / var(--lh-md) var(--font);
}

@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg, var(--overlay-hover), var(--overlay-strong), var(--overlay-hover));
    background-size: 200% 100%;
    animation: shimmer 1.2s linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }
