/*
 * Tablica Kanban.
 *
 * Układ: poziomy pas kolumn przewijany w bok, każda kolumna przewijana
 * niezależnie w pionie. Kolumny mają stałą szerokość — kolumny elastyczne
 * zmieniałyby szerokość przy dodaniu następnej, przez co karty
 * przeformatowałyby się w całej tablicy przy operacji, która ich nie dotyczy.
 */

.board {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

/* --- Pasek nad tablicą ---------------------------------------------------- */

.board__bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-shrink: 0;

    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}

.board__members {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 1;
    /* Przy wąskim oknie pasek zawija się zamiast wypychać przycisk ustawień
       poza widok. */
    flex-wrap: wrap;
}

/* Odsuwa przycisk ustawień do prawej krawędzi paska. */
.board__bar-spacer {
    flex: 1;
}

/* --- Pasek filtrów -------------------------------------------------------- */

/*
 * Drugi pas pod paskiem zespołu, nie ta sama linia.
 *
 * Skład zespołu i ustawienia projektu opisują TABLICĘ; filtry opisują to, co
 * użytkownik akurat na niej robi. Wrzucone w jeden rząd tworzyły siedem
 * przycisków bez hierarchii, w którym trzeba szukać oczami. Osobny pas jest
 * przy tym miejscem, w którym da się położyć podsumowanie („widoczne 7 z 42")
 * bez odsuwania czegokolwiek na bok.
 */
.board__bar--filtry {
    /* Delikatniejszy od paska zespołu — jest narzędziem, nie nagłówkiem. */
    background: var(--surface-sunken);
    padding-block: var(--space-2);
    flex-wrap: wrap;
}

.filtry__szukaj {
    /* Szersze niż reszta, bo to pole jest tu czynnością główną, a wpisywana
       treść bywa długa („numer faktury z zeszłego tygodnia"). */
    flex: 0 1 18rem;
    min-width: 9rem;
}

/* Liczba zaznaczonych wartości przy nazwie kryterium. */
.filtry__licznik {
    display: inline-grid;
    place-items: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 3px;
    margin-left: var(--space-1);

    border-radius: var(--radius-full);
    background: var(--accent);
    color: var(--text-inverse);
    font-size: 10px;
    font-weight: 600;
}

.filtry__podsumowanie {
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* Brak wyników nie jest błędem, ale musi być widoczny — inaczej pusta tablica
   wygląda jak utrata danych. */
.filtry__podsumowanie--pusto {
    color: var(--warning);
}

/* Panel wyboru terminu jest szerszy — mieści dwa pola dat obok podpisów. */
.filtr-picker {
    width: 19rem;
}

.picker__separator {
    height: 1px;
    background: var(--border);
    margin-block: var(--space-1);
}

.picker__empty {
    font-size: var(--text-xs);
    color: var(--text-muted);
    padding: var(--space-2);
}

.filtr-termin {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.filtr-termin__skroty {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.filtr-termin__zakres {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--space-2) var(--space-3);
}

/* --- Pas kolumn ----------------------------------------------------------- */

.board__columns {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    flex: 1;
    min-height: 0;

    padding: var(--space-4);
    overflow-x: auto;
    overflow-y: hidden;
}

/* --- Kolumna -------------------------------------------------------------- */

.column {
    display: flex;
    flex-direction: column;
    flex-shrink: 0; /* bez tego kolumny ściskałyby się zamiast przewijać */

    width: 17rem;
    max-height: 100%;

    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}

.column__header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    padding: var(--space-3) var(--space-3) var(--space-2);
}

.column__name {
    font-size: var(--text-sm);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Licznik zadań — informacja o obciążeniu kolumny, przydatna np. do
   zauważenia, że „W trakcie" spuchło. */
.column__count {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}

.column__actions {
    margin-left: auto;
    display: flex;
    gap: var(--space-1);
    /* Akcje kolumny pojawiają się na najechaniu — w spoczynku nagłówek
       pozostaje czysty. Na urządzeniach dotykowych, gdzie najechanie nie
       istnieje, są widoczne stale (reguła @media poniżej). */
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease-out);
}

.column:hover .column__actions,
.column:focus-within .column__actions {
    opacity: 1;
}

@media (hover: none) {
    .column__actions {
        opacity: 1;
    }
}

/* Lista kart — jedyny obszar przewijany w kolumnie. */
.column__cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    flex: 1;
    min-height: 2rem;

    padding: 0 var(--space-2) var(--space-2);
    overflow-y: auto;
    overflow-x: hidden;
}

.column__footer {
    flex-shrink: 0;
    padding: var(--space-1) var(--space-2) var(--space-2);
}

/* Podświetlenie kolumny, nad którą trwa przeciąganie. Bez tego przy kilku
   kolumnach nie widać, do której trafi karta. */
.column--drop-target {
    background: var(--accent-subtle);
    border-color: var(--accent-border);
}

/* --- Kolejność kolumn (ustawienia projektu) -------------------------------- */

.column-order {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.column-order__row {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);

    /* Wiersz jest chwytany w całości, nie tylko za uchwyt — uchwyt zapowiada
       możliwość przeciągania, ale celowanie w niego byłoby uprzykrzaniem. */
    cursor: grab;
    /* Bez tego przeglądarka na ekranie dotykowym zacznie przewijać stronę
       zaraz po ruchu palcem i przejmie zdarzenia wskaźnika. */
    touch-action: none;
}

.column-order__grip {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    color: var(--text-subtle);
}

/*
 * Przeciągany wiersz.
 *
 * Uniesienie sygnalizuje cień — jedna z dwóch sytuacji, w których ten projekt
 * dopuszcza cień (druga to okno modalne). Lekka przezroczystość pozwala
 * dostrzec, między które wiersze element właśnie wchodzi.
 */
.sortable__item--dragging {
    cursor: grabbing;
    opacity: 0.9;
    border-color: var(--accent);
    box-shadow: var(--shadow-drag);
}

/* W trakcie gestu kursor „łapki" obowiązuje nad całą listą, także w przerwach
   między wierszami — inaczej migotałby przy każdym przejściu nad szczeliną. */
.sortable--active,
.sortable--active .column-order__row {
    cursor: grabbing;
}

.column-order__name {
    flex: 1;
    min-width: 0;

    font-size: var(--text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Karta zadania -------------------------------------------------------- */

.task-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);

    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);

    text-align: left;
    width: 100%;

    /*
     * Karta otwiera okno zadania, więc musi to zapowiadać kursorem.
     *
     * Reguła `button { cursor: pointer }` z `base.css` jej nie obejmuje —
     * karta jest elementem `div` z `role="button"` (przyciskiem być nie może,
     * bo zawiera własne elementy interaktywne i podlega przeciąganiu).
     * Rola sama w sobie nie zmienia kursora, więc trzeba go ustawić wprost.
     */
    cursor: pointer;

    /*
     * Wyłączenie domyślnych gestów przeglądarki na karcie.
     *
     * Bez tego na ekranie dotykowym przeglądarka rozpocznie przewijanie
     * zaraz po ruchu palcem i przejmie zdarzenia wskaźnika — przeciąganie
     * przestaje działać. Utrata przewijania kolumny palcem po karcie jest
     * kompensowana aktywacją przeciągania dopiero po przytrzymaniu
     * (patrz komentarz w views/board.js).
     */
    touch-action: none;
    user-select: none;

    transition: border-color var(--duration-fast) var(--ease-out),
                background-color var(--duration-fast) var(--ease-out);
}

.task-card:hover {
    border-color: var(--border-strong);
}

/*
 * Karta odfiltrowana znika z układu, a nie staje się przezroczysta.
 *
 * Przygaszenie („opacity") zostawiłoby ją w kolumnie i kazało przeglądać
 * wzrokiem to samo, co przed filtrowaniem — czyli nie zrobiłoby tego, po co
 * sięga się po filtr. Karta zostaje przy tym w DOKUMENCIE, więc zdarzenia
 * czasu rzeczywistego trafiają w nią normalnie (patrz komentarz w board.js).
 *
 * Reguła musi stać PO `.task-card`. Oba selektory mają tę samą swoistość, więc
 * o wyniku decyduje kolejność — postawiona wcześniej przegrywała z `display:
 * flex` i filtr liczył karty poprawnie, ale żadnej nie ukrywał.
 */
.task-card--odfiltrowana {
    display: none;
}

/*
 * Okładka karty — pierwszy dołączony obraz.
 *
 * Stała proporcja 16:9 z przycięciem (`object-fit: cover`). Bez niej wysokość
 * karty zależałaby od proporcji przesłanego pliku: zrzut ekranu telefonu
 * zająłby pół kolumny, a panorama byłaby paskiem kilku pikseli. Jednakowa
 * wysokość utrzymuje rytm kolumny i pozwala porównywać karty wzrokiem.
 */
.task-card__cover {
    margin: calc(var(--space-3) * -1) calc(var(--space-3) * -1) 0;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    overflow: hidden;
    background: var(--surface-sunken);
}

.task-card__cover img {
    width: 100%;
    aspect-ratio: 16 / 6;
    object-fit: cover;
}

.task-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
}

.task-card__title {
    /* Tytuł jest treścią karty, więc dostaje największą wagę w jej obrębie —
       przy przeglądaniu tablicy to on decyduje, czy karta jest tą szukaną. */
    font-size: var(--text-md);
    line-height: var(--leading-tight);
    font-weight: 600;

    /*
     * Najwyżej trzy wiersze tytułu. Zadanie z opisem wklejonym w tytuł nie
     * może rozciągnąć karty na całą kolumnę — reszta tablicy przestałaby być
     * widoczna. Pełny tytuł jest w oknie szczegółów.
     */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.task-card__labels {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
}

.task-card__meta {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;

    font-size: var(--text-xs);
    color: var(--text-muted);
}

/*
 * Termin i liczniki bez tła — sam tekst z ikoną.
 *
 * Plakietki z wypełnieniem sprawdzają się, gdy jest ich jedna lub dwie; przy
 * czterech karta zamieniała się w zbiór kolorowych prostokątów, w którym
 * tytuł przestawał być pierwszym, co widać.
 */
.task-card__due,
.task-card__count {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}

/* Termin bliski lub przekroczony — jedyne miejsce na karcie, gdzie kolor
   sygnalizuje pilność. Data pozostaje widoczna, więc informacja nie zależy
   od rozróżniania barw. */
.task-card__due--urgent {
    color: var(--danger);
    font-weight: 600;
}

/* Odsuwa awatar na prawą krawędź karty, niezależnie od liczby etykiet. */
.task-card__spacer {
    flex: 1;
}

/*
 * Karta w trakcie przeciągania — element unoszący się pod palcem.
 * Pozycjonowanie stałe względem okna, bo karta musi móc opuścić granice
 * kolumny, w której się zaczęła.
 */
.task-card--dragging {
    position: fixed;
    z-index: var(--z-drag);
    pointer-events: none; /* nie może przechwytywać zdarzeń pod sobą */

    /* W trakcie przeciągania kursor mówi „trzymam", a nie „kliknę". */
    cursor: grabbing;

    box-shadow: var(--shadow-drag);
    border-color: var(--accent);
    /* Lekkie przechylenie sygnalizuje „element oderwany od siatki". */
    transform: rotate(1.5deg);
    opacity: 0.95;
}

/*
 * Miejsce, w którym karta wyląduje.
 *
 * Wersja przerywana zamiast przesuwania sąsiednich kart: przesuwanie
 * wymagałoby animowania wielu elementów przy każdym ruchu wskaźnika,
 * a przy szybkim ruchu daje efekt drgania.
 */
.drop-placeholder {
    height: 3.5rem;
    flex-shrink: 0;

    border: 1px dashed var(--accent-border);
    border-radius: var(--radius-md);
    background: var(--accent-subtle);
}

/* Karta w liście podczas przeciągania jej kopii — pozostawiona, aby lista
   nie zmieniała długości, ale wygaszona. */
.task-card--source {
    opacity: 0.35;
}

/* --- Panel szczegółów zadania --------------------------------------------- */

.task-detail {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.task-detail__row {
    display: grid;
    grid-template-columns: 7rem 1fr;
    align-items: center;
    gap: var(--space-3);
}

@media (max-width: 30rem) {
    .task-detail__row {
        grid-template-columns: 1fr;
        gap: var(--space-2);
    }
}

/* Wiersz, którego prawa kolumna sama się rozwija (kalendarz) — etykieta
   zostaje przy górnej krawędzi, w linii z polem, a nie na środku wysokości. */
.task-detail__row--top {
    align-items: start;
}

.task-detail__row--top .task-detail__label {
    /* Wyrównanie do tekstu w polu: pole ma własne dopełnienie i obramowanie. */
    padding-top: calc(var(--space-2) + 1px);
}

.task-detail__label {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-muted);
}

.task-detail__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);

    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* Pole terminu z przyciskiem czyszczenia — pole zajmuje resztę wiersza. */
.task-detail__due {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.task-detail__due .input {
    flex: 1;
    min-width: 0;
}

/* =========================================================================
 * Okno szczegółów zadania — układ dwukolumnowy
 * ========================================================================= */

.task-panel {
    display: grid;
    /*
     * Treść zadania szersza niż rozmowa: opis i załączniki potrzebują miejsca,
     * a komentarze są krótkie. `minmax(0, …)` jest konieczne — bez niego
     * kolumna siatki nie kurczy się poniżej swojej zawartości i długa nazwa
     * pliku rozpycha całe okno.
     */
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);

    /*
     * Wiersz siatki musi dać się ścisnąć.
     *
     * Domyślny wiersz `auto` przyjmuje wysokość najwyższej kolumny, więc
     * `max-height` na pojemniku tylko PRZYCINAŁO zawartość: kolumna miała
     * 1242 px przy oknie wysokim na 665 px i nie przewijała się, przez co
     * załączników na dole nie dało się w ogóle zobaczyć. `minmax(0, 1fr)`
     * ogranicza wiersz do wysokości pojemnika i dopiero wtedy `overflow-y`
     * w kolumnach ma czym zarządzać.
     */
    grid-template-rows: minmax(0, 1fr);

    min-height: 26rem;
    max-height: 70vh;
    /* Zawartość kolumn nie może wyjść poza zaokrąglone rogi okna. */
    overflow: hidden;
}

.task-panel__main {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);

    padding: var(--space-5);
    overflow-y: auto;

    /*
     * BEZ TEGO KOLUMNA SIĘ NIE PRZEWIJA.
     *
     * Element siatki ma domyślnie `min-height: auto`, czyli „nie kurcz się
     * poniżej swojej zawartości". Wysoka zawartość — na przykład rozwinięty
     * kalendarz — rozpychała więc kolumnę mimo `overflow-y: auto`, a razem
     * z nią całe okno: panel wychodził poza stopkę z przyciskami.
     * `min-height: 0` przywraca ograniczeniu wysokości moc sprawczą.
     */
    min-height: 0;
}

/* Pasek nad tytułem: termin po lewej, osoby i priorytet po prawej. */
.task-panel__head {
    display: flex;
    flex-wrap: wrap;
    /* Do góry, nie do środka: rozwinięty kalendarz jest wysoki, a osoby
       i priorytet mają zostać w linii z polem terminu, a nie zjechać
       na środek jego wysokości. */
    align-items: flex-start;
    gap: var(--space-3);
}

.task-panel__head-spacer {
    flex: 1;
}

/* Termin w pasku nagłówka nie rozciąga się na całą szerokość — obok stoją
   jeszcze osoby i priorytet. */
.task-panel__head .dtp {
    flex: 0 1 auto;
    max-width: 20rem;
}

/*
 * Termin w nagłówku bez obramowania.
 *
 * W pasku nad tytułem jest to przede wszystkim INFORMACJA („na kiedy to
 * jest"), a dopiero potem pole do zmiany. Ramka robiła z niego formularz
 * i konkurowała z tytułem tuż pod spodem. Obramowanie pojawia się przy
 * najechaniu i przy otwartym kalendarzu — czyli wtedy, gdy pole faktycznie
 * zachowuje się jak pole.
 */
.task-panel__head .dtp__trigger {
    border-color: transparent;
    background: transparent;

    /* Dopełnienie zostaje niezmienne, a ujemny margines wyrównuje tekst
       do tytułu poniżej. Zmiana dopełnienia przy najechaniu przesuwałaby
       napis o kilka pikseli — to widać jako drganie. */
    margin-left: calc(var(--space-3) * -1);
}

.task-panel__head .dtp__trigger:hover {
    border-color: var(--border);
    background: var(--surface);
}

.task-panel__prop {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-muted);
}

/* Priorytet jako pole zwarte — w pasku nagłówka nie potrzebuje pełnej
   szerokości, którą pola formularza biorą domyślnie. */
.task-panel__prop .select {
    width: auto;
    min-width: 7rem;
}

.task-panel__labels {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

/*
 * Tytuł i opis w postaci treści, nie pól formularza.
 *
 * Etykieta pola zostaje w dokumencie dla czytnika ekranu, ale znika z widoku:
 * napis „Tytuł" nad wierszem złożonym pismem 24 px nie niesie informacji.
 * Ramka pojawia się dopiero przy najechaniu i przy pisaniu — dzięki temu
 * widać, że tekst jest edytowalny, a spokój czytania zostaje zachowany.
 */
.field--headline .field__label,
.field--body .field__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.field--headline .input,
.field--body .textarea {
    border-color: transparent;
    background: transparent;
    padding-inline: var(--space-2);
}

.field--headline .input:hover,
.field--body .textarea:hover {
    border-color: var(--border);
}

.field--headline .input:focus,
.field--body .textarea:focus {
    background: var(--surface);
}

.field--headline .input {
    font-size: var(--text-lg);
    font-weight: 600;
    line-height: var(--leading-tight);
}

.field--body .textarea {
    min-height: 6rem;
    line-height: var(--leading-normal);
}

/* Na wąskim ekranie kolumny stają jedna pod drugą — dwie kolumny po ok. 20 rem
   nie mieszczą się na telefonie, a rozmowa jest wtedy dalszym ciągiem treści. */
@media (max-width: 52rem) {
    .task-panel {
        grid-template-columns: 1fr;
        max-height: none;
    }
}

/* --- Komentarze ----------------------------------------------------------- */

.comments {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-left: 1px solid var(--border);
    background: var(--surface-sunken);
}

@media (max-width: 52rem) {
    .comments {
        border-left: none;
        border-top: 1px solid var(--border);
    }
}

.comments__header {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-4) var(--space-4) var(--space-3);
    border-bottom: 1px solid var(--border);

    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
}

.comments__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);

    flex: 1;
    min-height: 0;
    padding: var(--space-4);
    overflow-y: auto;
}

/*
 * Komunikat o stanie rozmowy (wczytywanie, brak komentarzy).
 *
 * Zajmuje cały wolny obszar i jest w nim wyśrodkowany. Przyklejony do górnej
 * krawędzi wyglądał jak pierwszy wiersz treści, która się nie doczytała —
 * a nie jak informacja, że rozmowy jeszcze nie ma.
 */
.comments__status {
    /* Marginesy automatyczne w obu osiach środkują element w pojemniku
       elastycznym — także wtedy, gdy jest w nim jedyny. */
    margin: auto;
    padding: var(--space-4);

    font-size: var(--text-sm);
    color: var(--text-subtle);
    text-align: center;
}

.comment {
    display: flex;
    gap: var(--space-3);
}

.comment__body {
    min-width: 0;
    flex: 1;
}

.comment__head {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
}

.comment__author {
    font-size: var(--text-sm);
    font-weight: 600;
}

.comment__time {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* Przycisk usunięcia pojawia się dopiero po najechaniu na wpis — stale
   widoczny przy każdej wypowiedzi robiłby z rozmowy listę przycisków. */
.comment__delete {
    margin-left: auto;
    opacity: 0;
}

.comment:hover .comment__delete,
.comment__delete:focus-visible {
    opacity: 1;
}

.comment__text {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    /* Zachowuje łamanie wierszy wpisane przez autora. */
    white-space: pre-wrap;
}

/* --- Wątki ---------------------------------------------------------------- */

.thread {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/*
 * Odpowiedzi wcięte i połączone pionową linią z wypowiedzią nadrzędną.
 * Samo wcięcie bywa niejednoznaczne przy dłuższej rozmowie — linia mówi
 * wprost, dokąd sięga wątek.
 */
.thread__replies {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);

    margin-left: var(--space-4);
    padding-left: var(--space-3);
    border-left: 2px solid var(--border);
}

.comment--reply .comment__author {
    font-weight: 600;
}

.comment__actions {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin-left: auto;
    opacity: 0;
}

.comment:hover .comment__actions,
.comment__actions:focus-within {
    opacity: 1;
}

/* Oznaczenie osoby w treści — wyróżnione własną barwą, bez tła, żeby
   nie rozbijało rytmu czytania zdania.
   Barwa jest osobnym tokenem, nie akcentem: oznaczenie to element TREŚCI,
   a akcent należy do elementów sterujących. Wspólny token wiązał ze sobą
   dwie rzeczy, których nic nie łączy poza chwilową zgodnością koloru. */
.mention {
    color: var(--mention);
    font-weight: 600;
}

/*
 * Oznaczenie osoby czytającej.
 *
 * Tło jest tu dopuszczone wbrew regule powyżej i właśnie dlatego działa:
 * skoro pozostałe oznaczenia rytmu czytania nie rozbijają, to jedno, które
 * go rozbija, zwraca uwagę samo — bez powiększania, migania czy ikony.
 * Wyróżnienie musi być widoczne „kątem oka", zanim zdanie zostanie
 * przeczytane, bo po to istnieje.
 *
 * Element `<mark>` ma własne tło z arkusza przeglądarki (żółte) i własną
 * barwę tekstu — oba trzeba nadpisać, inaczej wyróżnienie wypadłoby
 * z palety aplikacji i było nieczytelne w motywie ciemnym.
 */
.mention--me {
    padding: 0 var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--mention-subtle);
    box-shadow: inset 0 0 0 1px var(--mention-border);
    color: var(--mention);
}

/*
 * Odnośnik w treści jako kafelek z ikoną serwisu i tytułem strony.
 *
 * Element liniowy, nie blokowy: odnośnik bywa wpleciony w zdanie („zerknij na
 * <kafelek>, tam jest opis"), więc przeniesienie go do osobnego wiersza
 * rozbijałoby wypowiedź. Szerokość ograniczona, a tytuł skracany — długa
 * nazwa strony nie może rozepchnąć kolumny komentarzy.
 */
.link-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    vertical-align: baseline;
    max-width: 100%;

    margin: 1px 2px;
    padding: 2px var(--space-2) 2px 4px;
    border: 1px solid var(--border);
    border-radius: var(--radius-full);
    background: var(--surface);

    font-size: var(--text-xs);
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--duration-fast) var(--ease-out),
                background-color var(--duration-fast) var(--ease-out);
}

.link-chip:hover {
    border-color: var(--accent);
    background: var(--accent-subtle);
}

.link-chip__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;

    width: 16px;
    height: 16px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    color: var(--text-subtle);
}

.link-chip__icon img {
    width: 16px;
    height: 16px;
    object-fit: contain;
}

.link-chip__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Dłuższy tytuł skracamy, ale kafelek ma pozostać rozpoznawalny —
       kilkanaście znaków wystarcza, by wiedzieć, dokąd prowadzi. */
    max-width: 16rem;
}

/* --- Pole pisania --------------------------------------------------------- */

/*
 * Obszar pisania jest wyraźnie oddzielony od reszty okna: własny nagłówek,
 * jaśniejsze tło i przycisk z nazwą czynności. Wcześniej sąsiadował
 * bezpośrednio z przyciskiem „Zapisz" okna zadania i jedno brało się za
 * drugie — użytkownik zapisywał zadanie, tracąc napisany komentarz.
 */
.comments__composer {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);

    padding: var(--space-3) var(--space-4) var(--space-4);
    border-top: 2px solid var(--border);
    background: var(--surface);
}

.composer__title {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
}

.composer__reply {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--accent-subtle);

    font-size: var(--text-xs);
    color: var(--text);
}

.composer__reply button {
    margin-left: auto;
}

/*
 * Wszystkie trzy elementy wiersza mają JEDNĄ, wspólną wysokość.
 *
 * Pole rozciągalne w pionie i przycisk o własnej wysokości dawały wiersz,
 * w którym nic nie stało w jednej linii, a wysokość zmieniała się przy
 * pisaniu. Teraz wysokość jest ustalona (`--composer-h`), pole ma wyłączone
 * rozciąganie, a dłuższa wypowiedź przewija się wewnątrz pola.
 */
.composer__row {
    --composer-h: 2.5rem;

    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Kotwica dla listy podpowiedzi oznaczeń. */
.composer__field {
    position: relative;
    flex: 1;
    min-width: 0;
}

/*
 * Pole pisania: jedna wysokość, pasek przewijania tylko gdy naprawdę trzeba.
 *
 * Poprzednio dopełnienie liczone z `1.4em` dawało sumę o kilka pikseli
 * większą niż wysokość pola, więc pusty obszar tekstowy już był „przewijany"
 * i przeglądarka rysowała pasek, zanim cokolwiek napisano. Teraz wysokość
 * wiersza i dopełnienie są podane w tej samej jednostce i mieszczą się
 * w zadanej wysokości z zapasem.
 */
.composer__input {
    height: var(--composer-h);
    min-height: var(--composer-h);
    resize: none;

    line-height: 1.25rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;

    /* `auto` pokazuje pasek dopiero po przekroczeniu wysokości — a przy
       jednym wierszu tekstu do przekroczenia nie dochodzi. */
    overflow-y: auto;
}

.composer__send {
    width: var(--composer-h);
    height: var(--composer-h);
    min-width: var(--composer-h);
    padding: 0;
    flex-shrink: 0;
}

/* --- Podpowiedzi oznaczeń ------------------------------------------------- */

.composer__mentions {
    position: absolute;
    bottom: calc(100% + var(--space-1));
    left: 0;
    right: 0;
    z-index: var(--z-dropdown);

    display: flex;
    flex-direction: column;
    gap: 1px;
    max-height: 12rem;
    overflow-y: auto;

    padding: var(--space-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);
    box-shadow: var(--shadow-overlay);
}

.composer__mention {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);

    font-size: var(--text-sm);
    text-align: left;
}

.composer__mention:hover,
.composer__mention--on {
    background: var(--surface-hover);
}

/* --- Załączniki ----------------------------------------------------------- */

/*
 * Kafelki w siatce zamiast listy jednokolumnowej. Załączniki są zwykle
 * plikami o krótkich nazwach; lista marnowała całą szerokość okna na jeden
 * wiersz, a przy kilkunastu plikach wypychała komentarze poza ekran.
 */
.attachments {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: var(--space-2);
}

.attachment {
    position: relative;

    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);
}

.attachment:hover {
    border-color: var(--border-strong);
}

.attachment__link {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    padding: var(--space-2);
    text-decoration: none;
    color: inherit;
}

/* Przyciski leżą NAD kafelkiem, a nie w jego wierszu — inaczej zabierałyby
   miejsce nazwie pliku, której i tak jest mało w kolumnie tej szerokości. */
.attachment__actions {
    position: absolute;
    top: 2px;
    right: 2px;

    display: flex;
    gap: 1px;
    padding: 1px;
    border-radius: var(--radius-sm);
    background: var(--surface);

    opacity: 0;
}

.attachment:hover .attachment__actions,
.attachment__actions:focus-within {
    opacity: 1;
}

/*
 * Miniatura o stałych wymiarach z przycięciem zawartości. Bez `object-fit`
 * obraz panoramiczny rozciągnąłby wiersz listy, przez co pozycje przestałyby
 * być równej wysokości.
 */
.attachment__thumb {
    width: 2.5rem;
    height: 2.5rem;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--surface-sunken);
    flex-shrink: 0;
}

.attachment__icon {
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-sm);
    background: var(--surface-sunken);
    flex-shrink: 0;
}

.attachment__info {
    display: flex;
    flex-direction: column;
    /* `min-width: 0` jest konieczne, by długa nazwa dała się skrócić —
       element elastyczny domyślnie nie kurczy się poniżej swojej treści. */
    min-width: 0;
    flex: 1;
}

.attachment__name {
    font-size: var(--text-sm);
    color: var(--text);

    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.attachment__link:hover .attachment__name {
    color: var(--accent);
}

.attachment__meta {
    display: block;
}

.attachment__meta {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* --- Obszar wyboru i upuszczania plików ----------------------------------- */

.dropzone {
    display: grid;
    place-items: center;

    padding: var(--space-4);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);

    font-size: var(--text-sm);
    color: var(--text-muted);
    cursor: pointer;
    transition:
        border-color var(--duration-fast) var(--ease-out),
        background var(--duration-fast) var(--ease-out);
}

.dropzone:hover,
.dropzone--over {
    border-color: var(--accent);
    background: var(--accent-subtle);
    color: var(--accent);
}

/* Etykieta z polem wyboru — pole i tekst w jednej linii bazowej. */
.checkbox {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    font-size: var(--text-sm);
    color: var(--text);
    cursor: pointer;
}

.checkbox input {
    width: 1rem;
    height: 1rem;
    accent-color: var(--accent);
    cursor: pointer;
}

/* --- Dodawanie ------------------------------------------------------------ */

/* Pole dopisywane na końcu kolumny — bez obramowania w spoczynku, żeby nie
   dokładać linii do i tak gęstego układu. */
.add-card {
    display: flex;
    align-items: center;
    gap: var(--space-2);

    width: 100%;
    padding: var(--space-2) var(--space-3);

    border: 1px dashed transparent;
    border-radius: var(--radius-md);

    font-size: var(--text-sm);
    color: var(--text-muted);
    text-align: left;
}

.add-card:hover {
    background: var(--surface-hover);
    border-color: var(--border);
    color: var(--text);
}

/* Kolumna „dodaj nową" na końcu pasa. */
.column-add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);

    flex-shrink: 0;
    width: 17rem;
    padding: var(--space-3);

    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-lg);

    font-size: var(--text-sm);
    color: var(--text-muted);
    text-align: center;
}

.column-add:hover {
    background: var(--surface-hover);
    color: var(--text);
}

/* --- Lista członków w oknie zarządzania ----------------------------------- */

.member-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
}

/*
 * Awatar z nazwą prowadzą do profilu, reszta wiersza (plakietka roli,
 * przycisk usunięcia) nie. Odnośnik obejmuje więc dokładnie tę część,
 * która przedstawia OSOBĘ — gdyby obejmował cały wiersz, kliknięcie obok
 * przycisku „Usuń" wyprowadzałoby z okna zarządzania zespołem.
 */
.member-row__link {
    display: flex;
    align-items: center;
    gap: var(--space-3);

    color: inherit;
    text-decoration: none;
    border-radius: var(--radius-sm);
    padding: var(--space-1) var(--space-2);
    margin-inline-start: calc(-1 * var(--space-2));

    transition: background-color var(--duration-fast) var(--ease-out);
}

.member-row__link:hover {
    background: var(--surface-hover);
}

.member-row__name {
    font-size: var(--text-sm);
}

.member-row__email {
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.invite-link {
    display: flex;
    gap: var(--space-2);
    align-items: center;
}

.invite-link__input {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

/* -------------------------------------------------------------------------
 * Dziennik zmian
 *
 * Dwa miejsca, jeden wygląd: panel podręczny z historią JEDNEGO zadania
 * (spod trzech kropek w oknie zadania) i okno z dziennikiem CAŁEJ tablicy.
 * Wspólne klasy zamiast dwóch zestawów — wpis wygląda tak samo, zmienia się
 * wyłącznie to, co go otacza, i to, czy nad zdaniem stoi tytuł zadania.
 * ---------------------------------------------------------------------- */

.historia {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/*
 * Panel historii zadania jest szerszy od pozostałych paneli podręcznych
 * (`.picker` ma 17rem). Tamte mieszczą listę krótkich nazw, a tu każdy wpis
 * jest zdaniem — przy tamtej szerokości łamałoby się po dwa słowa w wierszu
 * i lista zdarzeń zrobiłaby się dwa razy wyższa, niż musi być.
 */
.picker--historia {
    width: 26rem;
}

/* Panel bierze fokus na siebie, żeby obsłużyć Escape i przewijanie klawiszami
   (uzasadnienie przy `tabindex` w `openHistoryPicker`). Nie jest to jednak
   element, z którym się wchodzi w interakcję, więc nie rysuje pierścienia —
   ta sama zasada, co przy oknie modalnym w `components.css`. */
.picker--historia:focus {
    outline: none;
}

.historia__lista {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/*
 * Lista przewija się WEWNĄTRZ swojego pojemnika, w obu zastosowaniach.
 * W oknie: bez tego rosłoby ono poza ekran, a przycisk „Pokaż starsze"
 * uciekałby poza dolną krawędź razem z zamknięciem. W panelu: panel podręczny
 * jest ustawiany względem okna przeglądarki i nie ma dokąd rosnąć — zadanie
 * z długą historią wyszłoby dołem poza widok.
 *
 * Odstęp z prawej to miejsce na pasek przewijania, żeby nie kładł się on
 * na ramce wpisu.
 */
.historia__lista--pelna,
.historia__lista--panel {
    overflow-y: auto;
    padding-right: var(--space-2);
}

.historia__lista--pelna {
    max-height: 60vh;
}

.historia__lista--panel {
    max-height: 20rem;
}

.historia__stopka {
    display: flex;
    justify-content: center;
}

/*
 * Wpis jest PUDEŁKIEM, a nie kolejnym akapitem.
 *
 * Wiersze dziennika mają nieregularną długość: jedno zdarzenie mieści się
 * w pół wiersza („usunął opis"), następne zajmuje trzy („przesunął termin
 * z … na …") i ma nad sobą jeszcze tytuł zadania. Sam odstęp między nimi
 * nie wystarcza — oko nie widzi, gdzie kończy się jeden wpis, a zaczyna
 * kolejny, i lista czyta się jak jeden zlepiony blok tekstu. Ramka i wspólne
 * tło robią z każdego zdarzenia jeden przedmiot, który daje się objąć
 * wzrokiem bez czytania.
 *
 * Tło wgłębione, a nie białe: pod spodem jest już powierzchnia okna albo
 * panelu (`--surface`), więc pudełko w tym samym kolorze odcinałaby wyłącznie
 * ramka. Wgłębienie mówi zarazem, czym ta lista jest — zapisem do odczytu,
 * a nie zbiorem kart do klikania.
 */
.wpis {
    display: flex;
    gap: var(--space-3);
    align-items: flex-start;

    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);

    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

/*
 * Ikona zdarzenia w krążku.
 *
 * Niesie znaczenie drugorzędne — pozwala przebiec listę wzrokiem, szukając
 * przeniesień wśród komentarzy — więc jest przygaszona i mniejsza od tekstu;
 * w pełnej sile koloru rozbijałaby kolumnę zdań na rząd znaczków. Krążek daje
 * jej za to stałą szerokość: bez niego ikony o różnym rysunku (wąska kropka
 * kalendarza obok szerokiej strzałki) zaczynałyby każde zdanie w nieco innym
 * miejscu, a przy kilkunastu wpisach pod sobą widać to od razu.
 */
.wpis__ikona {
    display: grid;
    place-items: center;
    flex-shrink: 0;

    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-full);
    background: var(--surface);
    color: var(--text-muted);
}

.wpis__ikona svg {
    width: 14px;
    height: 14px;
}

.wpis__tresc {
    min-width: 0;
    flex: 1;

    display: flex;
    flex-direction: column;
    gap: 2px;
}

/*
 * Tytuł zadania — wyłącznie w dzienniku całej tablicy.
 *
 * Mniejszy od zdania pod nim, choć stoi wyżej: jest podpisem mówiącym,
 * CZEGO wpis dotyczy, a nie nagłówkiem sekcji. Pełną siłę niesie barwą
 * tekstu i grubością, nie rozmiarem.
 */
.wpis__zadanie {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text);

    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * Nazwa pliku bywa długim ciągiem bez spacji („raport_2026_v3_ostateczny.pdf"),
 * a wpis o załączniku wpisuje ją w zdanie. Bez łamania w dowolnym miejscu
 * jeden taki wyraz rozpycha pudełko poza szerokość listy.
 */
.wpis__zdanie {
    min-width: 0;
    overflow-wrap: anywhere;
}

.wpis__autor {
    font-weight: 600;
    color: var(--text);
    text-decoration: none;
}

.wpis__autor:hover {
    text-decoration: underline;
}

.wpis__autor--brak {
    font-style: italic;
    font-weight: 500;
    color: var(--text-subtle);
}

/*
 * Wartość wewnątrz zdania (nazwa kolumny, priorytet, plik).
 *
 * Wyróżniona samą grubością i barwą tekstu, bez tła i bez cudzysłowów.
 * Wpis jest zdaniem, a nie tabelą — pigułka przy każdej wartości dawałaby
 * wiersz złożony z klocków, w którym gubi się czasownik, czyli to, co się
 * właściwie stało.
 */
.wpis__wartosc {
    font-weight: 600;
    color: var(--text);
}

.wpis__czas {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
