/* =========================================================
   TOKENY STYLI — jedno miejsce, z którego czerpią kolory/odstępy
   powtarzające się w wielu miejscach pliku. Poza wygodą (zmiana w jednym
   miejscu zamiast szukania po całym CSS) to też przygotowanie pod
   przyszły przełącznik jasny/ciemny motyw: cały motyw ciemny (obecny,
   jedyny na razie) jest zdefiniowany tu, w :root. Jasny motyw, kiedy
   powstanie, nadpisze te same nazwy zmiennych w jednym dodatkowym bloku
   (np. `html[data-theme="light"] { --bg-1: #fff; ... }`) zamiast wymagać
   przepisywania reguł w całym pliku.
   ========================================================= */
:root {
    --accent: #d97b2e;
    --accent-light: #f0994a;
    --accent-dark: #b8631f;

    /* Tło strony (radialny gradient pod całą stroną) i najciemniejszy
       odcień, w który wtapia się dół baneru działu — musi być NIEMAL
       identyczny z kolorem tła w tym miejscu, inaczej widać szew. */
    --bg-1: #161616;
    --bg-2: #0a0a0a;
    --bg-3: #050505;
    --bg-deep: #060504;

    /* Baner-nagłówek działu (Pulpit/Trasy/Ogłoszenia/Wydarzenia/Galeria/Czat).
       --banner-gradient to CAŁA nakładka na zdjęciu jako jedna zmienna (nie
       tylko kolor końcowy) — ważne, bo w ciemnym motywie ma sens dociemniać
       AŻ do koloru tła strony (--bg-deep) i dać treści na nią "nachodzić"
       (--banner-overlap), a w jasnym motywie próba zrobienia tego samego
       (ciemna od razu na zdjęciu -> jasne tło strony) dawała brzydki,
       mętny "szew" — dwa bardzo różne kolory nie da się ładnie przenikać
       na krótkim dystansie. W jasnym motywie baner więc kończy się zwykłym,
       czystym cięciem (umiarkowany ciemny winieta na zdjęciu, bez próby
       dopasowania do koloru tła) i BEZ nachodzenia — patrz override niżej. */
    --banner-gradient: linear-gradient(180deg, rgba(6,5,4,0.34) 0%, rgba(6,5,4,0.4) 30%, rgba(6,5,4,0.6) 55%, rgba(6,5,4,0.86) 76%, var(--bg-deep) 92%, var(--bg-deep) 100%);
    --banner-min-height: 260px;
    --banner-min-height-mobile: 190px;
    --banner-overlap: 46px;
    --banner-overlap-mobile: 30px;
    --banner-gap-after: 0px;

    /* --- "Chrome" strony — topbar, stopka, powitanie na pulpicie i inne
       elementy leżące BEZPOŚREDNIO na tle strony (nie w .card/.chat-layout/
       modalu — te są już jasne i niezależne od motywu, więc nie są tu
       tokenizowane). To jest właściwa "podstawa pod przełącznik": jasny
       motyw (niżej, html[data-theme="light"]) nadpisuje te same nazwy. */
    --text-hero: #fff;
    --text-hero-muted: #999;
    --text-chrome: #eee;
    --text-chrome-muted: #999;
    --text-chrome-faint: #666;
    --text-chrome-dim: #888;

    --chrome-fill: rgba(255,255,255,0.06);
    --chrome-fill-hover: rgba(255,255,255,0.11);
    --chrome-fill-strong: rgba(255,255,255,0.13);
    --chrome-border: rgba(255,255,255,0.08);
    --chrome-border-strong: rgba(255,255,255,0.12);

    --panel-bg: #151515;
    --panel-border: rgba(255,255,255,0.08);
    --panel-hover: rgba(255,255,255,0.07);
    --panel-shadow: 0 2px 12px rgba(0,0,0,0.3);
    --panel-ring: #1a1a1a;

    --nav-pill-bg: rgba(255,255,255,0.05);
    --nav-pill-hover: rgba(255,255,255,0.07);

    /* Karty/czat/auth-card są już jasne niezależnie od motywu (patrz
       komentarz przy html[data-theme="light"] niżej) — ta jedna zmienna to
       jedyna rzecz, którą dostają inną: odrobinę mocniejszą ramkę w jasnym
       motywie, żeby nie "znikały" na też-już-jasnym tle strony. */
    --card-border: rgba(0,0,0,0.05);
}

/* --- Jasny motyw — nadpisuje WYŁĄCZNIE nazwy zmiennych z bloku :root
   powyżej. Zdjęcie w banerze zostaje wizualnie takie samo w obu motywach
   (ciemna nakładka na zdjęciu + biały tekst zawsze dobrze się czyta,
   niezależnie od tła strony wokół) — zmienia się tylko tło strony, topbar,
   stopka i elementy leżące bezpośrednio na tle. Karty/czat/modale są już
   jasne i teoretycznie niezależne od motywu, więc nie są tu ruszane —
   dostają jedynie odrobinę innej ramki (patrz .card niżej), żeby nie
   "zlewać się" wizualnie z też-już-jasnym tłem strony. */
html[data-theme="light"] {
    --bg-1: #f3f0e9;
    --bg-2: #ebe6da;
    --bg-3: #e3ddce;
    --bg-deep: #e3ddce;

    --text-hero: #17140f;
    --text-hero-muted: #6b6560;
    --text-chrome: #17140f;
    --text-chrome-muted: #6b6560;
    --text-chrome-faint: #8a847d;
    --text-chrome-dim: #8a847d;

    --chrome-fill: rgba(23,20,15,0.05);
    --chrome-fill-hover: rgba(23,20,15,0.09);
    --chrome-fill-strong: rgba(23,20,15,0.12);
    --chrome-border: rgba(23,20,15,0.1);
    --chrome-border-strong: rgba(23,20,15,0.16);

    --panel-bg: #ffffff;
    --panel-border: rgba(23,20,15,0.08);
    --panel-hover: rgba(23,20,15,0.05);
    --panel-shadow: 0 2px 12px rgba(23,20,15,0.14);
    --panel-ring: #f3f0e9;

    --nav-pill-bg: rgba(23,20,15,0.05);
    --nav-pill-hover: rgba(23,20,15,0.07);

    --card-border: rgba(23,20,15,0.13);

    /* Baner w jasnym motywie: zwykła, umiarkowana ciemna winieta na zdjęciu,
       która kończy się SAMA W SOBIE (nie próbuje dojechać do jasnego tła
       strony — stąd brak var(--bg-deep) w tym gradiencie, w przeciwieństwie
       do wersji ciemnej). Bez nachodzenia treści (overlap=0, gap zamiast
       tego daje odrobinę oddechu pod spodem) — czyste, płaskie przejście. */
    --banner-gradient: linear-gradient(180deg, rgba(6,5,4,0.22) 0%, rgba(6,5,4,0.3) 40%, rgba(6,5,4,0.48) 70%, rgba(6,5,4,0.68) 100%);
    --banner-overlap: 0px;
    --banner-overlap-mobile: 0px;
    --banner-gap-after: 20px;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    min-height: 100vh;
    overflow-x: hidden;
    background: radial-gradient(ellipse at top, var(--bg-1) 0%, var(--bg-2) 55%, var(--bg-3) 100%);
    background-attachment: fixed;
    color: var(--text-chrome);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* --- Baner-nagłówek działu: pełna szerokość okna, wtapia się dołem w tło
   strony (--bg-deep), a treść pod nim (.card / .chat-layout / .welcome-hero)
   nachodzi na ten wtapiający się fragment tak, żeby nie było widać żadnej
   przerwy ani szwu. Oba elementy dostają position:relative + z-index, bo
   inaczej pozycjonowany .section-banner (position:relative, potrzebne dla
   sztuczki z pełną szerokością) potrafi malować się NAD zwykłymi,
   niepozycjonowanymi elementami mimo że jest wcześniej w DOM — to właśnie
   ten błąd z nakładaniem się grafiki na treść. --- */
.section-banner {
    position: relative;
    z-index: 0;
    left: 50%;
    right: 50%;
    width: 100vw;
    margin-left: -50vw;
    margin-right: -50vw;
    margin-top: 0;
    margin-bottom: calc(-1 * var(--banner-overlap));
    padding-bottom: var(--banner-overlap);
    min-height: var(--banner-min-height);
    background-size: cover;
    background-position: center;
    background-color: #1a1712;
    display: flex;
    align-items: flex-end;
}
.section-banner-inner {
    max-width: 1180px;
    margin: 0 auto;
    width: 100%;
    padding: 24px 16px 58px;
}
.section-banner-inner h1 {
    color: #fff;
    font-size: 22px;
    margin: 0 0 4px;
    text-shadow: 0 1px 6px rgba(0,0,0,0.5);
}
.section-banner-inner p {
    color: #f0ece4;
    font-size: 13px;
    margin: 0;
    max-width: 640px;
    text-shadow: 0 1px 6px rgba(0,0,0,0.5);
}
/* Cokolwiek jest zaraz po banerze (.card, .chat-layout, .welcome-hero...)
   musi wygrywać nad nim w kolejności malowania — patrz komentarz wyżej. */
.section-banner + * {
    position: relative;
    z-index: 1;
    margin-top: var(--banner-gap-after);
}

/* Powitanie na pulpicie (.welcome-hero) nie ma własnego tła (w
   przeciwieństwie do .card, które zawsze jest jasne niezależnie od motywu)
   — więc "nachodzenie" na baner (--banner-overlap), które w reszcie
   serwisu chowa się bez śladu pod tłem kart, tutaj w motywie ciemnym
   wystawało na widok wprost na zdjęcie baneru. Efekt: zawsze czyste
   odsunięcie od baneru, tak jak w jasnym motywie, niezależnie od tego,
   czy w danym motywie baner ma nachodzenie włączone. */
.section-banner + .welcome-hero {
    margin-top: calc(var(--banner-overlap) + 20px);
}

@media (max-width: 720px) {
    .section-banner {
        min-height: var(--banner-min-height-mobile);
        margin-top: -14px;
        margin-bottom: calc(-1 * var(--banner-overlap-mobile));
        padding-bottom: var(--banner-overlap-mobile);
    }
    .section-banner-inner { padding: 16px 12px 38px; }
    .section-banner-inner h1 { font-size: 18px; }

    .section-banner + .welcome-hero {
        margin-top: calc(var(--banner-overlap-mobile) + 16px);
    }
}

a { color: inherit; }

.icon { display: inline-block; vertical-align: -3px; flex-shrink: 0; }

.wrap {
    max-width: 1180px;
    margin: 0 auto;
    padding: 20px 16px 60px;
}

/* --- Górny pasek nawigacji (dwuwierszowy: logo/szukaj/użytkownik + osobny rząd menu) --- */
.topbar {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px 4px 18px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--chrome-border);
}
.topbar-row1 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.topbar .brand {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    font-size: 15px;
    letter-spacing: .01em;
    text-decoration: none;
    flex-shrink: 0;
}
.topbar .brand img { height: 54px; width: auto; display: block; }
/* Jedyny plik logo, jaki mamy, jest biały (na ciemne tło) — w jasnym
   motywie zamieniamy go na czarny filtrem zamiast trzymać drugi plik. */
html[data-theme="light"] .topbar .brand img { filter: brightness(0); }

/* Przycisk "hamburger" i wrapper reszty paska — na desktopie oba są
   niewidoczne/przezroczyste dla layoutu (display:contents na wrapperze
   sprawia, że jego dzieci — szukajka/dzwonek/użytkownik — zachowują się
   dokładnie tak, jakby nie było wokół nich żadnego diva), więc desktop
   wygląda identycznie jak wcześniej. Realną rolę oba elementy zaczynają
   grać dopiero w mobilnej media query niżej. */
.topbar-menu-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 8px;
    border: none;
    background: var(--chrome-fill);
    color: var(--text-chrome);
    cursor: pointer;
    flex-shrink: 0;
}
.topbar-menu-toggle:hover { background: var(--chrome-fill-hover); }
.topbar-row1-extras { display: contents; }

.topbar-nav-row {
    display: flex;
    align-items: center;
    gap: 2px;
    background: var(--nav-pill-bg);
    border-radius: 7px;
    padding: 4px;
    flex-wrap: wrap;
}
.topbar-nav-row a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-chrome-muted);
    text-decoration: none;
    transition: background .15s, color .15s;
    white-space: nowrap;
}
.topbar-nav-row a:hover { color: var(--text-chrome); background: var(--nav-pill-hover); }
.topbar-nav-row a.active { background: var(--accent); color: #fff; font-weight: 600; }

.topbar-search {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--chrome-fill);
    border: 1px solid var(--chrome-border-strong);
    border-radius: 20px;
    padding: 8px 14px;
    color: var(--text-chrome-muted);
    flex: 1;
    max-width: 360px;
}
.topbar-search:focus-within { border-color: var(--accent); color: var(--accent-light); }
.topbar-search input[type=text] {
    background: transparent;
    border: none;
    color: var(--text-chrome);
    width: 100%;
    padding: 0;
    font-size: 16px; /* patrz komentarz przy .chat-composer-row input[type=text] — ten sam powód (blokada auto-zoomu iOS) */
    /* Reset wspólnej reguły "input[type=text] { height:44px }" (dodanej przy
       ujednolicaniu wysokości pól formularzy) — tutaj to pole żyje wewnątrz
       własnej "pigułki" (.topbar-search) z własnym paddingiem, więc
       wymuszona wysokość 44px rozdymała cały pasek wyszukiwania w górnym
       menu do groteskowych rozmiarów. Wysokość ma dawać padding rodzica, nie
       samo pole. */
    height: auto;
}
@media (min-width: 769px) {
    .topbar-search input[type=text] { font-size: 13px; }
}
.topbar-search input[type=text]:focus { outline: none; box-shadow: none; }

.avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 600;
    object-fit: cover;
    vertical-align: middle;
    flex-shrink: 0;
}

/* Kropka "online teraz" (users.last_seen_at, patrz is_user_online() w
   helpers.php) — doklejana jako mały, pozycjonowany element w prawym-dolnym
   rogu awatara. Wrapper (.avatar-wrap) jest potrzebny tam, gdzie awatar nie
   ma już własnego position:relative z innego powodu (np. .chat-bubble-avatar
   ma je już nadane bezpośrednio, więc kropkę można dokleić bez dodatkowego
   wrappera — patrz includes/chat_render.php). Stały rozmiar kropki (nie
   skalowany razem z awatarem) — przy większych awatarach (profil) wygląda
   odrobinę mniej "dopasowana", ale zostaje czytelna wszędzie bez dodatkowych
   wariantów rozmiaru. */
.avatar-wrap { position: relative; display: inline-flex; flex-shrink: 0; vertical-align: middle; }
.online-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #3fb950;
    border: 2px solid #fff;
    box-sizing: content-box;
}

.topbar .user-menu-wrap { position: relative; flex-shrink: 0; }
.topbar .user-menu-trigger {
    display: flex;
    align-items: center;
    gap: 7px;
    background: var(--chrome-fill);
    border: none;
    border-radius: 20px;
    padding: 4px 12px 4px 4px;
    cursor: pointer;
    color: var(--text-chrome);
    font-size: 12px;
    font-family: inherit;
    font-weight: 400;
    box-shadow: none;
    transition: background .15s;
    white-space: nowrap;
}
.topbar .user-menu-trigger:hover { background: var(--chrome-fill-hover); opacity: 1; transform: none; box-shadow: none; }
.topbar .user-menu-trigger .badge { background: rgba(217,123,46,0.22); color: var(--accent-light); }
.topbar .user-menu-trigger .chevron { color: var(--text-chrome-dim); transition: transform .15s; }
.topbar .user-menu-trigger.open .chevron { transform: rotate(180deg); }

.user-menu-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 6px;
    padding: 6px;
    min-width: 170px;
    display: none;
    flex-direction: column;
    z-index: 50;
    box-shadow: var(--panel-shadow);
}
.user-menu-dropdown.open { display: flex; }
.user-menu-dropdown a {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border-radius: 5px;
    color: var(--text-chrome);
    text-decoration: none;
    font-size: 12px;
}
.user-menu-dropdown a:hover { background: var(--panel-hover); }

.notif-wrap { position: relative; flex-shrink: 0; }
.notif-trigger {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    min-width: 34px;
    padding: 0;
    flex-shrink: 0;
    background: var(--chrome-fill);
    border: none;
    border-radius: 50%;
    cursor: pointer;
    color: var(--text-chrome);
    transition: background .15s;
}
.notif-trigger:hover { background: var(--chrome-fill-hover); opacity: 1; transform: none; box-shadow: none; }
.notif-trigger.open { background: var(--chrome-fill-strong); }
.notif-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 15px;
    height: 15px;
    padding: 0 3px;
    border-radius: 8px;
    background: var(--accent-light, #d97b2e);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--panel-ring);
}
.notif-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 320px;
    max-width: calc(100vw - 24px);
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 10px;
    display: none;
    flex-direction: column;
    z-index: 60;
    box-shadow: var(--panel-shadow);
    overflow: hidden;
}
.notif-panel.open { display: flex; }
.notif-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--panel-border);
    color: var(--text-chrome);
    font-size: 13px;
    font-weight: 600;
}
.notif-mark-all {
    background: none;
    border: none;
    color: var(--text-chrome-muted);
    font-size: 11px;
    font-family: inherit;
    cursor: pointer;
    padding: 0;
    box-shadow: none;
    text-align: right;
}
.notif-mark-all:hover { color: var(--accent-light, #d97b2e); opacity: 1; transform: none; box-shadow: none; }
.notif-list { max-height: 360px; overflow-y: auto; }
.notif-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--panel-border);
    color: var(--text-chrome);
    text-decoration: none;
    font-size: 12.5px;
    line-height: 1.4;
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--panel-hover); }
.notif-item.unread { background: rgba(217,123,46,0.08); }
.notif-item-icon {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    margin-top: 1px;
    border-radius: 50%;
    background: var(--chrome-fill);
    color: var(--text-chrome-muted);
    display: flex;
    align-items: center;
    justify-content: center;
}
.notif-item.unread .notif-item-icon { background: rgba(217,123,46,0.2); color: var(--accent-light, #d97b2e); }
.notif-item-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.notif-item-time { color: var(--text-chrome-dim); font-size: 11px; }
/* Krzyżyk do odrzucenia pojedynczego powiadomienia bez wchodzenia pod link
   — dzięki temu można "wyczyścić" dzwoneczek, nie zamieniając go w historię
   (patrz komentarz w notifications_api.php). */
.notif-item-dismiss {
    flex-shrink: 0;
    align-self: flex-start;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--text-chrome-dim);
    font-size: 15px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: .5;
}
.notif-item-dismiss:hover { opacity: 1; background: rgba(0,0,0,0.12); color: #c0392b; }

/* Wizualnie ukryty input pliku dla szybkiej zmiany awatara (profile.php) —
   trigger to <label> (avatar + plakietka z aparatem), sam input pozostaje
   dostępny dla czytników ekranu, tylko niewidoczny. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}
.avatar-edit-trigger {
    position: relative;
    display: inline-block;
    cursor: pointer;
    border-radius: 50%;
}
.avatar-edit-badge {
    position: absolute;
    right: -2px;
    bottom: -2px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #f6f3ef;
}

.btn-logout {
    background: #e5e5e5;
    color: #111;
    padding: 6px 12px;
    border-radius: 4px;
    text-decoration: none;
    font-weight: 500;
    font-size: 12px;
}

/* --- Karty --- */
.card {
    background: #f6f3ef;
    color: #171512;
    border-radius: 8px;
    padding: 20px;
    margin-bottom: 16px;
    border: 1px solid var(--card-border);
}
.card h2 {
    font-size: 15px;
    font-weight: 700;
    color: #17140f;
    margin: 0 0 14px;
    letter-spacing: .01em;
    display: flex;
    align-items: center;
    gap: 8px;
}
.card p.muted { color: #6b6560; font-size: 13px; }

/* --- Zwijane karty "Dodaj..." (ogłoszenie/trasa/wydarzenie/zdjęcia) —
   domyślnie zwinięte, żeby formularz nie straszył kogoś, kto wchodzi tylko
   przejrzeć listę. <details>/<summary>
   zamiast <div>/<h2>, ten sam wzorzec wizualny co .year-archive/
   .rsvp-details niżej (strzałka obracana o 90°), ale w rozmiarze/kolorze
   nagłówka karty (.card h2), żeby wyglądało jak zwykła karta z klikalnym
   tytułem, a nie jak osobny mniejszy element. --- */
.card.collapsible-card { padding: 0; }
.card.collapsible-card summary {
    cursor: pointer;
    padding: 20px;
    font-size: 15px;
    font-weight: 700;
    color: #17140f;
    letter-spacing: .01em;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 8px;
}
.card.collapsible-card summary::-webkit-details-marker { display: none; }
.card.collapsible-card summary::before {
    content: '';
    width: 0; height: 0;
    border-left: 6px solid #8a847d;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    transition: transform .12s;
    flex-shrink: 0;
}
.card.collapsible-card[open] summary::before { transform: rotate(90deg); }
.card.collapsible-card .collapsible-body { padding: 0 20px 20px; }

/* --- Ekran logowania / rejestracji --- */
.auth-shell {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 16px 170px;
    position: relative;
    overflow: hidden;
    background-size: cover;
    background-position: center;
    /* background-attachment:fixed — bez tego "cover" liczy się względem
       WYSOKOŚCI SAMEGO ELEMENTU .auth-shell, nie okna przeglądarki. Formularz
       rejestracji ma więcej pól niż logowanie, więc jest wyższy niż jeden
       ekran (min-height:100vh go nie ogranicza, tylko ustawia minimum) —
       przez to to samo tło jest inaczej "docinane"/skalowane na rejestracji
       niż na logowaniu, mimo identycznego markupu i CSS. Przypięcie tła do
       viewportu (fixed) usuwa tę zależność od wysokości treści. */
    background-attachment: fixed;
}
.auth-shell.has-bg::before, .auth-shell.has-bg::after { display: none; }
.auth-shell-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(8,6,4,0.6), rgba(8,6,4,0.8));
    pointer-events: none;
}
.auth-shell::before {
    content: '';
    position: absolute;
    top: -280px;
    left: 50%;
    transform: translateX(-50%);
    width: 900px;
    height: 900px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(217,123,46,0.18) 0%, rgba(217,123,46,0) 62%);
    pointer-events: none;
}
.auth-shell::after {
    content: '';
    position: absolute;
    bottom: -320px;
    right: -120px;
    width: 640px;
    height: 640px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(217,123,46,0.10) 0%, rgba(217,123,46,0) 65%);
    pointer-events: none;
}
.auth-shell-inner { position: relative; z-index: 1; width: 100%; max-width: 400px; }
.auth-logo { text-align: center; margin-bottom: 18px; }
.auth-logo img { height: 172px; width: auto; }
.auth-card {
    background: #f6f3ef;
    color: #171512;
    border-radius: 10px;
    padding: 32px 28px 28px;
    border: 1px solid var(--card-border);
    position: relative;
    overflow: hidden;
}
.auth-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 4px;
    background: linear-gradient(90deg, var(--accent-light), var(--accent), var(--accent-dark));
}
.auth-card h2 { text-align: center; margin: 4px 0 3px; font-size: 19px; color: #17140f; }
.auth-card .auth-sub { text-align: center; color: #8a847d; font-size: 12.5px; margin: 0 0 18px; }
.auth-field { position: relative; }
.auth-field .auth-field-icon {
    position: absolute;
    left: 12px;
    bottom: 11px;
    color: #a8a29a;
    pointer-events: none;
    display: flex;
}
.auth-field input { padding-left: 34px !important; }
.auth-submit {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 8px;
}
.auth-footer-link { text-align: center; margin-top: 18px; margin-bottom: 0; font-size: 12.5px; color: #8a847d; }
.auth-footer-link a { color: var(--accent-dark); font-weight: 600; text-decoration: none; }
.auth-footer-link a:hover { text-decoration: underline; }
.auth-check { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0 4px; font-size: 12px; color: #6b6560; }
.auth-check input { margin-top: 2px; }
.auth-honeypot { position: absolute; left: -9999px; top: -9999px; opacity: 0; height: 0; width: 0; }
@media (max-width: 480px) {
    .auth-shell { padding: 14px 16px 64px; }
    .auth-card { padding: 26px 20px 22px; }
    .auth-logo img { height: 138px; }
}

.empty-state {
    text-align: center;
    padding: 28px 10px;
    color: #8a847d;
}
.empty-state .icon-lg { opacity: .4; margin-bottom: 10px; }
.empty-state p { margin: 0; font-size: 13px; }
.empty-state a { color: var(--accent-dark); font-weight: 600; text-decoration: none; }
.empty-state a:hover { text-decoration: underline; }

.list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid rgba(0,0,0,0.06);
    border-radius: 6px;
    margin-bottom: 8px;
    text-decoration: none;
    color: #171512;
    transition: transform .12s, box-shadow .12s, border-color .12s;
}
a.list-item:hover { border-color: rgba(217,123,46,0.35); }
.list-item .title { font-size: 13px; font-weight: 600; margin: 0; }

/* Klikalne linki do publicznego profilu członka (member_profile.php) —
   wtopione w tekst, bez domyślnego niebieskiego podkreślenia przeglądarki,
   z podkreśleniem tylko po najechaniu. */
.title a[href^="member_profile.php"],
.who a[href^="member_profile.php"],
.meta a[href^="member_profile.php"],
p.muted a[href^="member_profile.php"],
.materials-post-meta a[href^="member_profile.php"] {
    color: inherit;
    text-decoration: none;
}
.title a[href^="member_profile.php"]:hover,
.who a[href^="member_profile.php"]:hover,
.meta a[href^="member_profile.php"]:hover,
p.muted a[href^="member_profile.php"]:hover,
.materials-post-meta a[href^="member_profile.php"]:hover {
    text-decoration: underline;
}
.list-item .meta { font-size: 11px; color: #7a746e; margin: 2px 0 0; }
.list-item .badge { font-size: 12px; color: #555; white-space: nowrap; background: #eee; padding: 2px 8px; border-radius: 20px; }
.badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--accent-dark); white-space: nowrap; background: rgba(217,123,46,0.15); padding: 3px 9px; border-radius: 20px; font-weight: 500; }

/* Plakietka "szuka towarzystwa" TAM, gdzie zwykły .badge ginie na szarym tle
   listy (np. .list-item .badge wyżej dostaje stonowane, szare tło) — ma być
   widoczna kolorem na pulpicie. Osobna,
   nadrzędna klasa zamiast modyfikacji .list-item .badge, bo tamten szary
   styl jest współdzielony z innymi plakietkami (licznik komentarzy, "prywatna"
   itd.), którym ma zostać bez zmian. Ten sam pomarańcz co .route-card-badge
   na kafelkach tras (spójny kolor wszędzie, gdzie oznaczamy to samo). */
.badge-companions { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600; color: #fff; white-space: nowrap; background: #d97b2e; padding: 3px 9px; border-radius: 20px; }

.list-item-thumb {
    width: 40px;
    height: 40px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
}
.list-item-thumb-icon {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 700;
}

/* --- Materiały: gotowe posty na Facebooka (siatka kart o stałej,
   ograniczonej szerokości — żeby pojedynczy post nie rozciągał się na
   całą szerokość karty, a kilka postów wyglądało jednolicie). --- */
.materials-post-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 220px));
    justify-content: start;
    gap: 12px;
}
.materials-post-card {
    background: #fff;
    border: 1px solid rgba(0,0,0,0.06);
    border-radius: 8px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.materials-post-card img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
    background: #ece7de;
}
.materials-post-body {
    padding: 10px;
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 7px;
}
/* Karta promująca sklep SOG na samej górze materials.php — baner na CAŁĄ
   szerokość strony jak inne banery sekcji (render_section_banner()), ale
   celowo dużo NIŻSZY (nie "kinowy" hero na wiele setek px), a opis + link do
   sklepu idą POD zdjęciem, nie obok niego z boku. Tło to ten sam ciepły,
   lekko podbity gradient co .leaderboard-compact na pulpicie — spójnie
   z już przyjętym stylem, zamiast płaskiego kremowego tła zwykłej .card. */
/* .card.materials-shop-card (obie klasy w selektorze) celowo, NIE samo
   .materials-shop-card — inaczej na telefonie (@media max-width:720px niżej
   w tym pliku) przegrywało z mobilnym padding:14px zwykłej .card, bo obie
   reguły mają tę samą specyficzność i o wyniku decydowała kolejność w
   pliku. Efekt na telefonie: gradientowe tło "prześwitywało" jako rama
   wokół zdjęcia zamiast zdjęcie sięgało od krawędzi do krawędzi. */
.card.materials-shop-card {
    overflow: hidden;
    padding: 0;
    background: linear-gradient(160deg, #fbe0c2, #f9ead9 55%, #f6f3ef 100%);
    border: 1px solid rgba(217,123,46,.3);
}
.materials-shop-card img { width: 100%; display: block; max-height: 220px; object-fit: cover; background: #ece7de; }
.materials-shop-body { padding: 16px 18px; }
.materials-shop-body .muted { color: #5a4632; }
@media (max-width: 640px) {
    .materials-shop-card img { max-height: 150px; }
}

/* Graficzny baner + opis nad "Plikami do pobrania", scalony w JEDNĄ kartę
   z listą plików poniżej (nie osobna karta) — obrazek "wychodzi" poza
   padding .card (ujemny margines), żeby
   sięgał od krawędzi do krawędzi z zaokrąglonymi tylko górnymi rogami, tak
   jak w bannerze sklepu, mimo że jest teraz wewnątrz zwykłej .card. */
.materials-files-banner-wrap {
    margin: -20px -20px 14px;
    overflow: hidden;
    border-radius: 8px 8px 0 0;
}
.materials-files-banner-wrap img { width: 100%; display: block; max-height: 200px; object-fit: cover; background: #ece7de; }
.materials-files-banner-desc { margin: 0 0 14px; }
.materials-files-sep { border: none; border-top: 1px solid rgba(0,0,0,0.08); margin: 0 0 16px; }
@media (max-width: 720px) {
    /* .card ma tu mniejszy padding (14px zamiast 20px) — ujemny margines
       banera musi się z nim zgadzać, inaczej zostanie szpara albo obrazek
       wyjdzie za daleko poza kartę. */
    .materials-files-banner-wrap { margin: -14px -14px 12px; border-radius: 6px 6px 0 0; }
}
@media (max-width: 640px) {
    .materials-files-banner-wrap img { max-height: 140px; }
}
.materials-post-grow { flex: 1; }
.materials-post-card .title { font-size: 12.5px; }
.materials-post-text {
    font-size: 11.5px;
    line-height: 1.45;
    color: #45403a;
    white-space: pre-line;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.materials-post-meta {
    font-size: 11px;
    color: #7a746e;
    margin: 0;
}
.material-edit-form {
    display: none;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(0,0,0,0.08);
}
.material-edit-form.open { display: block; }

label { display: block; font-size: 12px; font-weight: 500; color: #6b6560; margin: 12px 0 5px; }
input[type=text], input[type=email], input[type=url], input[type=password],
input[type=tel], input[type=number], input[type=date], input[type=datetime-local], input[type=file], textarea, select {
    width: 100%;
    min-width: 0; /* bez tego Mobile Safari ignorował width:100% na
                     input[type=date] i pole wystawało poza kartę — pole
                     formularza domyślnie nie kurczy się poniżej rozmiaru
                     własnej treści (kalendarzyk/spinner), trzeba to
                     jawnie zezwolić */
    padding: 10px 12px;
    border-radius: 6px;
    border: 1px solid #d8d3cc;
    background: #fff;
    color: #171512;
    font-size: 15px;
    font-family: inherit;
    line-height: 1.4;
    box-sizing: border-box;
    transition: border-color .12s, box-shadow .12s;
}
/* Jednolita wysokość pól jednoliniowych — bez tego input[type=date] (czasem
   też select) renderował się z inną wysokością wewnętrznego kontrolera
   przeglądarki niż zwykłe pola tekstowe, przez co formularz "skakał" w
   wysokości między polami (widoczne zwłaszcza na telefonie, np. przy dacie
   urodzenia w profilu). Textarea i file celowo pominięte — mają inną, własną
   logikę wysokości (textarea się rozciąga, file ma natywny przycisk). */
input[type=text], input[type=email], input[type=url], input[type=password],
input[type=tel], input[type=number], input[type=date], input[type=datetime-local], select {
    height: 44px;
}
/* input[type=date] ma inaczej dopasowaną wysokość wewnętrznego kontrolera
   przeglądarki (kalendarzyk/spinner) niż reszta pól — bez tego wyrównania
   wyglądał "wyżej" i nie do pary z resztą formularza. Mobile Safari dodatkowo
   renderuje ten kontroler z własną, natywną szerokością minimalną, którą
   ignoruje mimo width:100%/min-width:0 (oba już nie wystarczały) — appearance:none
   każe przeglądarce porzucić natywny "chrom" kontrolki i w pełni respektować
   nasz box-sizing, więc pole faktycznie mieści się w karcie.
   Ten sam appearance:none zdejmuje jednak też natywną ikonkę kalendarza i
   szary podpowiadacz formatu, przez co pole wyglądało na "inne"/puste niż
   reszta formularza — dorysowujemy więc własną ikonkę kalendarza (SVG, ten
   sam kształt co icon('calendar') w includes/icons.php) po prawej stronie,
   żeby pole nadal było rozpoznawalne jako "data" i spójne wizualnie. */
input[type=date] {
    line-height: 1.4;
    -webkit-appearance: none;
    appearance: none;
    max-width: 100%;
    box-sizing: border-box;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b6560' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'%3E%3C/rect%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3Cline x1='8' y1='3' x2='8' y2='7'%3E%3C/line%3E%3Cline x1='16' y1='3' x2='16' y2='7'%3E%3C/line%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 16px;
    padding-right: 36px;
}
/* Widoczne pole własnego date/time pickera (flatpickr altInput, patrz
   assets/datepicker.js) — ta sama ikonka kalendarza co przy dawnym natywnym
   input[type=date] wyżej, żeby pole nadal było wizualnie rozpoznawalne jako
   "data", tylko teraz identyczne na każdym telefonie/przeglądarce. */
.js-datepicker-input {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b6560' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'%3E%3C/rect%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3Cline x1='8' y1='3' x2='8' y2='7'%3E%3C/line%3E%3Cline x1='16' y1='3' x2='16' y2='7'%3E%3C/line%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 16px;
    padding-right: 36px;
    cursor: pointer;
}
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(217,123,46,0.18);
}
textarea { resize: vertical; min-height: 70px; }
.hint { font-size: 11px; color: #8a847d; margin-top: 3px; }

/* Własny, jednolity wygląd checkboxów zamiast natywnego — na iOS Safari
   niezaznaczony i zaznaczony checkbox potrafią wyglądać jak dwie różne
   kontrolki (różny rozmiar/kształt), bo przeglądarka rysuje stan "zaznaczone"
   inaczej niż samą ramkę. appearance:none + własny kwadracik/haczyk daje
   identyczny wygląd zawsze i wszędzie (iOS/Android/desktop).
   !important na width/height/appearance: w wielu miejscach w kodzie checkboxy
   mają jeszcze stary, sprzed tego stylu, inline "style=width:auto;margin:0"
   (pisany pod natywny wygląd) — bez !important te inline style wygrywałyby
   specyficznością i psuły rozmiar własnej kontrolki. */
input[type=checkbox] {
    appearance: none !important;
    -webkit-appearance: none !important;
    width: 19px !important;
    height: 19px !important;
    min-width: 19px;
    flex-shrink: 0;
    margin: 0;
    border: 1.5px solid #c9c2b8;
    border-radius: 4px;
    background: #fff;
    display: inline-block;
    vertical-align: middle;
    position: relative;
    cursor: pointer;
    transition: background .12s, border-color .12s;
}
input[type=checkbox]:checked {
    background: var(--accent);
    border-color: var(--accent);
}
input[type=checkbox]:checked::after {
    content: '';
    position: absolute;
    left: 5.5px;
    top: 1.5px;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
input[type=checkbox]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(217,123,46,0.25);
}

/* --- Własny wybór daty/godziny (flatpickr, patrz assets/datepicker.js) ---
   Kalendarzyk dokleja się do <body>, nie do karty, więc stylujemy go tu na
   stałe w jasnej wersji (tak jak karty/auth-card — te są zawsze jasne,
   niezależnie od ciemnego/jasnego motywu strony, patrz komentarz przy
   .auth-card). max-width chroni przed wystawaniem poza ekran na telefonie —
   dokładnie to, co wcześniej psuło natywne pola daty w formularzu wydarzenia. */
.flatpickr-calendar {
    background: #f6f3ef;
    border: 1px solid var(--card-border, rgba(0,0,0,0.13));
    border-radius: 10px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.28);
    max-width: calc(100vw - 24px);
    font-family: inherit;
}
.flatpickr-calendar.arrowTop:before, .flatpickr-calendar.arrowTop:after { border-bottom-color: #f6f3ef; }
.flatpickr-months, .flatpickr-weekdays { background: #f6f3ef; }
.flatpickr-month { color: #17140f; fill: #17140f; }
.flatpickr-current-month .flatpickr-monthDropdown-months, .flatpickr-current-month input.cur-year { color: #17140f; font-weight: 600; }
.flatpickr-weekday { color: #8a847d; font-weight: 600; }
.flatpickr-day { color: #33302b; border-radius: 6px; }
.flatpickr-day.today { border-color: var(--accent); }
.flatpickr-day.selected, .flatpickr-day.selected:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}
.flatpickr-day:hover { background: rgba(217,123,46,0.16); }
.flatpickr-day.flatpickr-disabled, .flatpickr-day.prevMonthDay, .flatpickr-day.nextMonthDay { color: #c9c2b8; }
.flatpickr-time { border-top: 1px solid var(--card-border, rgba(0,0,0,0.13)); }
.flatpickr-time input { color: #17140f; }
.flatpickr-time .flatpickr-am-pm:hover, .flatpickr-time input:hover { background: rgba(217,123,46,0.1); }
.numInputWrapper span.arrowUp:after { border-bottom-color: #6b6560; }
.numInputWrapper span.arrowDown:after { border-top-color: #6b6560; }

button, .btn {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    border: none;
    padding: 11px 18px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-block;
    transition: transform .12s, opacity .12s;
}
button:hover, .btn:hover { opacity: .95; transform: translateY(-1px); }
button:active, .btn:active { transform: translateY(0); }
.btn.secondary {
    background: transparent;
    color: #eee;
    border: 1px solid rgba(255,255,255,0.28);
    box-shadow: none;
}
.btn.secondary:hover { background: rgba(255,255,255,0.08); box-shadow: none; transform: none; }
/* Wewnątrz jasnej karty potrzebny jest ciemny wariant — inaczej tekst
   znika na jasnym tle (ten sam błąd co z ikonami: kolor dobrany pod
   ciemne tło strony, niewidoczny na jasnej karcie, i na odwrót). */
.card .btn.secondary { color: #171512; border-color: #d8d3cc; }
.card .btn.secondary:hover { background: rgba(0,0,0,0.04); }
.auth-card .btn.secondary { color: #171512; border-color: #d8d3cc; }
.auth-card .btn.secondary:hover { background: rgba(0,0,0,0.04); }
.btn-row { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }

.errors {
    background: #f6d0d0;
    border: 1px solid #d99;
    color: #7a1f1f;
    padding: 10px 12px;
    border-radius: 5px;
    font-size: 13px;
    margin-bottom: 14px;
}

/* --- Wyślij e-mail (mail_compose.php) --- */
.mail-section { margin-bottom: 18px; }
.mail-section:last-of-type { margin-bottom: 0; }
.mail-result {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 6px;
    font-size: 13px;
    background: #e2f2e2;
    color: #285c28;
}
.mail-result.fail { background: #f6d0d0; color: #7a1f1f; }
.recipient-modes { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 14px; }
.recipient-mode-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 20px;
    background: #eee9e2;
    color: #45403a;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    margin: 0;
    border: 1px solid transparent;
    transition: background .15s, color .15s;
}
.recipient-mode-btn input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.recipient-mode-btn:hover { background: #e2dcd0; }
.recipient-mode-btn.active {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
}
.recipient-mode-count {
    background: rgba(0,0,0,0.12);
    border-radius: 20px;
    padding: 1px 7px;
    font-size: 11px;
}
.recipient-mode-btn.active .recipient-mode-count { background: rgba(255,255,255,0.28); }
.recipient-target { margin-bottom: 4px; }

.stop-row {
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr auto;
    gap: 8px;
    margin-bottom: 8px;
    align-items: center;
}
.stop-row .remove-stop {
    background: transparent;
    border: 1px solid #bbb;
    color: #555;
    padding: 8px 10px;
    font-size: 12px;
}
.stop-actions {
    display: flex;
    gap: 4px;
}
.stop-move {
    background: transparent;
    border: 1px solid #bbb;
    color: #555;
    padding: 8px 9px;
    font-size: 12px;
    line-height: 1;
}
.stop-move:disabled {
    opacity: .35;
    cursor: default;
}
/* Przycisk "wskaż na mapie" przy przystanku trasy (assets/route_stops_map.js)
   — geokodowanie wpisanego adresu czasem daje inny punkt na mapie niż
   faktyczne miejsce, więc trzeba dać możliwość dokładnego
   wskazania/poprawienia go ręcznie. */
.stop-map-btn {
    background: transparent;
    border: 1px solid #bbb;
    color: #555;
    padding: 8px 9px;
    font-size: 12px;
    line-height: 1;
}
.stop-map-btn.active {
    background: #2f6fed;
    border-color: #2f6fed;
    color: #fff;
}
.route-map-picker { margin-top: 4px; }

.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
    align-items: start;
}
.gallery-grid figure {
    margin: 0;
    background: #fff;
    border-radius: 6px;
    overflow: hidden;
}
.gallery-grid .media-click {
    position: relative;
    cursor: pointer;
    transition: opacity .15s;
}
.gallery-grid .media-click:hover { opacity: .9; }
.gallery-grid img, .gallery-grid video { width: 100%; height: 130px; object-fit: cover; display: block; }
.gallery-grid .video-fallback-cover {
    width: 100%;
    height: 130px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #3a352e, #17140f);
}
.gallery-grid .video-fallback-cover .play-circle {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
}
.gallery-grid figcaption { font-size: 11px; color: #555; padding: 6px 8px; }
.gallery-grid .play-badge {
    position: absolute;
    top: 6px;
    right: 6px;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: rgba(0,0,0,0.65);
    color: #fff;
    font-size: 10px;
    padding: 3px 7px;
    border-radius: 3px;
}
.gallery-grid .img-fallback {
    display: none;
    height: 130px;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 4px;
    background: #eee;
    color: #999;
    font-size: 20px;
}
.gallery-grid .img-fallback span { font-size: 10px; opacity: .8; }
.gallery-grid .media-click.broken .img-fallback { display: flex; }
.gallery-grid .media-click.broken .play-badge { display: none; }

.gallery-back-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
    color: var(--accent-dark);
    text-decoration: none;
    margin-bottom: 12px;
}
.gallery-back-link:hover { text-decoration: underline; }

.category-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}
.category-head h2 { margin: 0; }
.category-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.category-head .category-rename-form {
    display: none;
    width: 100%;
    margin-top: 8px;
}
.category-head .category-rename-form.open { display: flex; }
.inline-form {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
}
.inline-form input[type=text] {
    width: auto;
    padding: 5px 8px;
    font-size: 12px;
    border-radius: 4px;
    height: auto; /* reset wspólnego "input[type=text] { height:44px }" — patrz komentarz przy .topbar-search input[type=text] */
}
.btn-icon {
    background: #d9d9d9;
    color: #333;
    border: none;
    border-radius: 4px;
    padding: 5px 9px;
    font-size: 11px;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s;
}
.btn-icon:hover { background: #ccc; }
.btn-icon.danger { background: #f3d2d2; color: #7a1f1f; }
.btn-icon.danger:hover { background: #eabcbc; }

.item-tools {
    display: flex;
    gap: 4px;
    padding: 6px;
    background: #eee9e2;
    justify-content: center;
}
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: 4px;
    background: #d8d2c8;
    color: #444;
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: background .15s;
}
.icon-btn:hover { background: #c8c0b3; }
.icon-btn.danger { background: #f3d2d2; color: #7a1f1f; }
.icon-btn.danger:hover { background: #eabcbc; }
.caption-edit {
    display: none;
    gap: 4px;
    padding: 0 6px 6px;
    background: #eee9e2;
    margin: 0;
}
.caption-edit.open { display: flex; }
.caption-edit input[type=text] { flex: 1; padding: 5px 8px; font-size: 11px; border-radius: 4px; height: auto; }

/* --- Zakładki (panel administracyjny) --- */
.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    border-bottom: 1px solid #ccc;
    margin-bottom: 18px;
}
.tabs a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    font-size: 13px;
    font-weight: 500;
    color: #666;
    text-decoration: none;
    border-radius: 5px 5px 0 0;
    position: relative;
    top: 1px;
    transition: color .15s, background .15s;
}
.tabs a:hover { color: #111; background: rgba(0,0,0,0.04); }
.tabs a.active {
    color: #111;
    background: #fff;
    border: 1px solid #ccc;
    border-bottom-color: #fff;
}
.tabs a .count {
    display: inline-block;
    margin-left: 5px;
    background: var(--accent);
    color: #fff;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 6px;
}
.subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 18px;
}
.subtabs a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    font-size: 12.5px;
    font-weight: 600;
    color: #6b6560;
    text-decoration: none;
    border-radius: 20px;
    background: #eee9e2;
    transition: background .15s, color .15s;
}
.subtabs a:hover { background: #ddd5c8; color: #171512; }
.subtabs a.active {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
}
.admin-quicklinks {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
}
.admin-quicklinks a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-chrome-dim);
    text-decoration: none;
    padding: 6px 10px;
    background: var(--chrome-fill);
    border-radius: 4px;
    transition: background .15s, color .15s;
}
.admin-quicklinks a:hover { background: var(--chrome-fill-strong); color: var(--text-chrome); }

.category-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.category-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    background: #2c2c2c;
    color: #eee;
    text-decoration: none;
    font-size: 13px;
    transition: background .15s;
}
.category-pill:hover { background: var(--accent-dark); }
.category-pill .count {
    background: rgba(255,255,255,0.15);
    border-radius: 999px;
    padding: 1px 7px;
    font-size: 11px;
}

.gallery-cat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 16px;
}
.gallery-cat-tile {
    position: relative;
    display: block;
    height: 200px;
    border-radius: 9px;
    overflow: hidden;
    text-decoration: none;
    background-color: #2c2c2c;
    transition: transform .18s;
}
.gallery-cat-tile:hover {
    transform: translateY(-3px);
}
/* Zdjęcie okładkowe kategorii jako osobna, w pełni wypełniająca warstwa
   (zamiast background-image bezpośrednio na kafelku) — dzięki temu powiększenie
   przy najechaniu robimy przez transform: scale(), a nie przez zmianę
   background-size (procentowe background-size liczy się inaczej niż "cover",
   więc zamiana cover -> 108% przy najechaniu potrafiła nagle pokazać zupełnie
   inny fragment/inne proporcje zdjęcia zamiast płynnego zbliżenia). */
.gallery-cat-tile-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    transition: transform .4s;
}
.gallery-cat-tile:hover .gallery-cat-tile-bg {
    transform: scale(1.08);
}
.gallery-cat-tile::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.8) 100%);
}
.gallery-cat-tile.no-image { background-image: none !important; background: linear-gradient(135deg, #2c2c2c, #181818); }
.gallery-cat-tile-icon {
    position: absolute;
    top: 42%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    opacity: .2;
}
.gallery-cat-tile-body {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 14px 16px;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.gallery-cat-tile-name {
    font-size: 16px;
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-shadow: 0 1px 4px rgba(0,0,0,0.4);
}
.gallery-cat-tile-count {
    font-size: 11px;
    font-weight: 600;
    color: #fff;
    background: rgba(255,255,255,0.22);
    backdrop-filter: blur(2px);
    border-radius: 999px;
    padding: 3px 10px;
    flex-shrink: 0;
}
@media (max-width: 640px) {
    .gallery-cat-tiles { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
    .gallery-cat-tile { height: 140px; border-radius: 7px; }
    .gallery-cat-tile-name { font-size: 13px; }
}

.event-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 14px;
}
.event-card {
    display: block;
    background: #232323;
    border-radius: 6px;
    overflow: hidden;
    text-decoration: none;
    color: #eee;
    transition: transform .15s;
}
.event-card:hover { transform: translateY(-2px); }
.event-card img { width: 100%; height: 140px; object-fit: cover; display: block; }
.event-card-placeholder {
    width: 100%;
    height: 140px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #6b6560;
    background: linear-gradient(135deg, #3a3a3a, #262626);
    position: relative;
    overflow: hidden;
}
/* Logo SOG jako blade "watermark" w tle zastępczej miniaturki (Ogłoszenia,
   Wydarzenia) — żeby karty bez własnego zdjęcia nie wyglądały na puste/gołe.
   Sama ikonka działu (announcement/calendar) zostaje na wierzchu, więc każdy
   dział wciąż wygląda inaczej, tylko oba mają teraz w tle to samo logo. */
.event-card-placeholder-logo {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 62%;
    max-height: 82%;
    opacity: 0.16;
    pointer-events: none;
}
.event-card-placeholder svg { position: relative; z-index: 1; }
.event-card-body { padding: 12px 14px; }
.event-card-body .title { margin: 0 0 5px; font-size: 13px; font-weight: 600; color: #fff; }
.event-card-body .meta { margin: 0; font-size: 11px; color: #a8a29a; line-height: 1.5; }

/* Kafelki tras (routes.php) — .event-card z mapką jako "zdjęciem" +
   wyróżnienie tras "szuka towarzystwa", widoczne też na pulpicie, stąd też
   te same kolory/nazwa co plakietka .badge gdzie indziej w serwisie.
   Pomarańczowy pasek z boku
   karty (inset box-shadow, nie border — respektuje zaokrąglone rogi
   .event-card bez dodatkowej matematyki na promieniu) + plakietka na mapce,
   żeby było widać od razu przy przewijaniu listy, bez czytania treści. */
.route-card { position: relative; }
.route-card-companions { box-shadow: inset 4px 0 0 0 #d97b2e; }
.route-card-badge {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 2;
    background: #d97b2e;
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    padding: 4px 9px;
    border-radius: 20px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    box-shadow: 0 1px 4px rgba(0,0,0,.35);
}

.comment {
    padding: 10px 0;
    border-top: 1px solid #cfcfcf;
    font-size: 13px;
}
.comment .who { font-weight: 500; margin-right: 6px; }
.comment .when { color: #888; font-size: 11px; }
.comment-head { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }

/* Odpowiedz/Edytuj/Usuń pod komentarzem — wcześniej to były te same
   szare/różowe "pigułki" co .btn-icon gdzie indziej w serwisie (np. w
   lightboxie galerii), co pod treścią komentarza wyglądało ciężko i
   nieporządnie. Zamiast tego zwykłe, drobne linki tekstowe w stylu
   Facebooka — bez tła, bez
   ramki, tylko pogrubienie/podkreślenie na hover. Celowo NOWA klasa (nie
   zmieniamy .btn-icon), żeby nie ruszać wyglądu przycisków w innych
   miejscach serwisu, które z tej samej klasy korzystają. */
.comment-actions { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.comment-action-btn {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    color: #6b6560;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
}
.comment-action-btn:hover { color: var(--accent-dark); text-decoration: underline; }
.comment-action-btn.danger { color: #a83a2e; }
.comment-action-btn.danger:hover { color: #7a1f1f; }

/* Formularz odpowiedzi/edycji komentarza — dawniej całość (textarea +
   przycisk Wyślij + przycisk emotki) stała w jednym rzędzie flex, więc przy
   wyższej/rozciągniętej textarece przyciski "wisiały z boku", oderwane od
   dołu pola. Teraz textarea zawsze na pełną szerokość, przyciski w osobnym
   rzędzie pod spodem
   — dokładnie ten sam układ co w głównym formularzu "Dodaj komentarz". */
.comment-reply-form, .comment-edit-form { display: none; margin-top: 8px; }
.comment-reply-form textarea, .comment-edit-form textarea { width: 100%; }
.comment-reply-form .btn-row, .comment-edit-form .btn-row { margin-top: 6px; align-items: center; }

/* Przycisk-emotka pod formularzem "dodaj komentarz" (trasy/wydarzenia/
   ogłoszenia) — piker (.emoji-picker, ten sam co w czacie) jest tu
   pozycjonowany względem tego małego wrappera zamiast względem
   .chat-composer, więc dostaje inne wyrównanie niż w czacie. */
.comment-emoji-wrap { position: relative; display: inline-block; }
.comment-emoji-wrap .emoji-picker { bottom: 40px; }
/* .btn-row, który OTACZA .comment-emoji-wrap (przycisk wyślij + przycisk
   emotki) — na telefonie .comment-emoji-wrap przestaje być "kotwicą" dla
   pozycjonowania okienka (patrz reguła position:static w @media niżej w
   pliku), więc TA szersza, pełnej szerokości linia MUSI być position:relative,
   żeby okienko emotek dostało prawidłową szerokość zamiast liczyć left/right
   od wąskiego przycisku — bez tego na telefonie okienko emotek pod
   komentarzem renderowało się jako wąski, wysoki biały pasek zamiast
   siatki emotek. */
.comment-form-actions { position: relative; }
/* left:0 (okienko rozwija się W PRAWO od przycisku) potrafiło wystawać poza
   prawą krawędź ekranu i zostać obcięte przez overflow-x:hidden na <body> —
   zależnie od tego, jak daleko w prawo stoi przycisk-emotka w danej karcie.
   right:0 (rozwija się W LEWO, w stronę wnętrza karty, gdzie zawsze jest
   miejsce) jest bezpieczniejsze
   — ale TYLKO na szerszych ekranach; na wąskich i tak przejmuje pełną-szerokość
   wersja z reguły .emoji-picker niżej w pliku (ta sama, co w czacie). */
@media (min-width: 721px) {
    .comment-emoji-wrap .emoji-picker { left: auto; right: 0; }
}

/* --- Edytor tekstu --- */
.editor-wrap { background: #fff; border-radius: 5px; border: 1px solid #bbb; overflow: hidden; }
.rich-content { font-size: 14px; line-height: 1.6; }
.rich-content p { margin: 0 0 10px; }
.rich-content a { color: var(--accent-dark); }
.rich-content img { max-width: 100%; border-radius: 4px; }
.rich-content table { border-collapse: collapse; width: 100%; margin: 0 0 10px; }
.rich-content table td, .rich-content table th { border: 1px solid #ccc; padding: 6px 8px; }

/* --- Kalendarz --- */
.calendar {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
}
.calendar .day-name {
    font-size: 11px;
    color: #8a847d;
    text-align: center;
    padding-bottom: 8px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.calendar .day-name:nth-child(7n+6), .calendar .day-name:nth-child(7n) { color: var(--accent-dark); }
.calendar .day {
    background: #fff;
    border: 1px solid var(--card-border);
    border-radius: 6px;
    min-height: 62px;
    min-width: 0;
    padding: 7px;
    font-size: 12px;
    position: relative;
    overflow: hidden;
    transition: box-shadow .15s, transform .15s, border-color .15s;
}
.calendar .day:not(.empty):hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); border-color: rgba(0,0,0,0.1); z-index: 2; }
.calendar .day:not(.empty):nth-child(7n+6), .calendar .day:not(.empty):nth-child(7n) { background: #faf6f0; }
.calendar .day.empty { background: transparent; border-color: transparent; }
.calendar .day .num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    color: #45403a;
    font-size: 12px;
}
.calendar .day.today .num {
    background: var(--accent);
    color: #fff;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 999px;
}
.calendar .day.has-events { border-color: rgba(217,123,46,0.35); }
.calendar .day.has-events .num { color: var(--accent-dark); }
.calendar .day.today.has-events .num { color: #fff; }
.year-label {
    font-size: 12px;
    font-weight: 700;
    color: #8a847d;
    margin: 16px 0 8px;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.year-label:first-child { margin-top: 0; }
.year-archive {
    margin-top: 14px;
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 6px;
    padding: 2px 12px 12px;
}
.year-archive summary {
    cursor: pointer;
    padding: 10px 2px;
    font-weight: 700;
    font-size: 13px;
    color: #6b665f;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
}
.year-archive summary::-webkit-details-marker { display: none; }
.year-archive summary::before {
    content: '';
    width: 0; height: 0;
    border-left: 5px solid #8a847d;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform .12s;
    margin-right: 2px;
}
.year-archive[open] summary::before { transform: rotate(90deg); }
.year-archive summary .count-badge {
    background: rgba(0,0,0,0.06);
    color: #6b665f;
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 11px;
    font-weight: 700;
}
.year-archive[open] summary { margin-bottom: 2px; }
.rsvp-details {
    margin-top: 8px;
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 6px;
    padding: 2px 12px 10px;
}
.rsvp-details summary {
    cursor: pointer;
    padding: 9px 2px;
    font-weight: 600;
    font-size: 13px;
    color: #6b665f;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
}
.rsvp-details summary::-webkit-details-marker { display: none; }
.rsvp-details summary::before {
    content: '';
    width: 0; height: 0;
    border-left: 5px solid #8a847d;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform .12s;
    margin-right: 2px;
}
.rsvp-details[open] summary::before { transform: rotate(90deg); }
.rsvp-details summary .count-badge {
    background: rgba(0,0,0,0.06);
    color: #6b665f;
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 11px;
    font-weight: 700;
}
.calendar .day .evt {
    display: block;
    margin-top: 4px;
    font-size: 10px;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    border-radius: 999px;
    padding: 2px 7px;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}
.calendar .day .evt-more {
    display: block;
    margin-top: 3px;
    font-size: 10px;
    color: var(--accent-dark);
    font-weight: 700;
    padding: 0 2px;
}
.calendar-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    gap: 8px;
}
.calendar-nav h2 { margin: 0; font-size: 16px; text-transform: capitalize; }
.calendar-nav-title { display: flex; align-items: center; gap: 10px; }
.calendar-nav-today {
    font-size: 11px;
    font-weight: 700;
    color: var(--accent-dark);
    background: rgba(217,123,46,0.12);
    padding: 4px 10px;
    border-radius: 999px;
    text-decoration: none;
    white-space: nowrap;
}
.calendar-nav-today:hover { background: rgba(217,123,46,0.2); }
.calendar-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    min-width: 34px;
    padding: 0;
    flex-shrink: 0;
    border-radius: 50%;
    background: #eee9e2;
    color: #45403a;
    text-decoration: none;
    flex-shrink: 0;
    transition: background .15s, transform .15s;
}
.calendar-nav-btn:hover { background: var(--accent); color: #fff; transform: translateY(-1px); }

/* --- Lightbox --- */
.lightbox {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.9);
    z-index: 999;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.lightbox.open { display: flex; }
.lightbox-body { display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 100%; }
.lightbox img, .lightbox video { max-width: 100%; max-height: 78vh; border-radius: 5px; display: block; }
.lightbox .close {
    position: absolute;
    top: 18px;
    right: 24px;
    color: #fff;
    background: none;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
}
.lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 46px;
    height: 46px;
    min-width: 46px;
    padding: 0;
    border-radius: 50%;
    background: rgba(255,255,255,0.12);
    color: #fff;
    border: none;
    font-size: 26px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s;
    z-index: 2;
}
.lightbox-nav:hover { background: var(--accent-dark); transform: translateY(-50%); }
.lightbox-nav.prev { left: 16px; }
.lightbox-nav.next { right: 16px; }
.lightbox-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    color: #ddd;
    font-size: 13px;
}
.lightbox-meta .muted { color: #999; }
.lightbox-meta .btn-icon { background: rgba(255,255,255,0.12); color: #fff; text-decoration: none; }
.lightbox-meta .btn-icon:hover { background: var(--accent-dark); }

/* Siatka zdjęć w ogłoszeniu, jak w poście na Facebooku — układ zależy od
   liczby zdjęć (1/2/3/4/5+), z nakładką "+N" na ostatnim kafelku, gdy jest
   ich więcej niż 5 widocznych. Stałe wysokości kontenera (zamiast aspect-ratio na
   pojedynczych kafelkach) trzymają całą siatkę w jednej, przewidywalnej
   wysokości niezależnie od proporcji wgranych zdjęć — dokładnie tak, jak
   robi to Facebook. Klikalne kafelki otwierają lekki lightbox (patrz
   assets/announcement-gallery.js), który używa tych samych klas .lightbox*
   co galeria (assets/style.css), więc bez dublowania stylów. */
.announcement-photo-grid { display: grid; gap: 4px; border-radius: 10px; overflow: hidden; margin-bottom: 14px; }
.announcement-photo-grid .apg-item { position: relative; display: block; overflow: hidden; background: #1a1816; cursor: pointer; }
.announcement-photo-grid .apg-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.announcement-photo-grid.count-1 { grid-template-columns: 1fr; }
.announcement-photo-grid.count-1 .apg-item { aspect-ratio: 16/9; }
.announcement-photo-grid.count-2 { grid-template-columns: 1fr 1fr; height: 240px; }
.announcement-photo-grid.count-3 { grid-template-columns: 1.4fr 1fr; grid-template-rows: 1fr 1fr; height: 300px; }
.announcement-photo-grid.count-3 .apg-item:first-child { grid-row: 1 / span 2; }
.announcement-photo-grid.count-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; height: 300px; }
.announcement-photo-grid.count-5plus { grid-template-columns: repeat(6, 1fr); grid-template-rows: 1fr 1fr; height: 300px; }
.announcement-photo-grid.count-5plus .apg-item:nth-child(1) { grid-column: span 3; }
.announcement-photo-grid.count-5plus .apg-item:nth-child(2) { grid-column: span 3; }
.announcement-photo-grid.count-5plus .apg-item:nth-child(3),
.announcement-photo-grid.count-5plus .apg-item:nth-child(4),
.announcement-photo-grid.count-5plus .apg-item:nth-child(5) { grid-column: span 2; }
.apg-more-overlay {
    position: absolute; inset: 0; background: rgba(0,0,0,0.55);
    color: #fff; display: flex; align-items: center; justify-content: center;
    font-size: 26px; font-weight: 700;
}
@media (max-width: 640px) {
    .announcement-photo-grid.count-2 { height: 180px; }
    .announcement-photo-grid.count-3, .announcement-photo-grid.count-4, .announcement-photo-grid.count-5plus { height: 220px; }
}

/* Miniaturki galerii dodatkowych zdjęć w formularzu edycji ogłoszenia —
   każda z małym przyciskiem "usuń" w rogu. */
.announcement-gallery-edit-grid { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 4px; }
.announcement-gallery-edit-item { position: relative; width: 84px; height: 84px; border-radius: 6px; overflow: hidden; }
.announcement-gallery-edit-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.announcement-gallery-edit-item form { position: absolute; top: 3px; right: 3px; margin: 0; }
.announcement-gallery-edit-item button {
    width: 20px; height: 20px; border-radius: 50%; border: none; cursor: pointer;
    background: rgba(0,0,0,0.65); color: #fff; font-size: 12px; line-height: 1;
    display: flex; align-items: center; justify-content: center; padding: 0;
}
.announcement-gallery-edit-item button:hover { background: #a83a2e; }

/* --- Kadrowanie zdjęcia --- */
.crop-modal {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.8);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.crop-modal.open { display: flex; }
.crop-modal-inner {
    background: #f6f3ef;
    border-radius: 8px;
    padding: 20px;
    max-width: 620px;
    width: 100%;
}
.crop-modal-inner h3 { margin: 0 0 12px; font-size: 15px; color: #17140f; }
.crop-canvas-wrap {
    max-height: 55vh;
    overflow: hidden;
    background: #111;
    border-radius: 5px;
}
.crop-canvas-wrap img { display: block; max-width: 100%; }

/* --- Materiały: podgląd całego gotowego posta (tekst + grafika bez
   przycięcia), zanim ktoś zdecyduje się skopiować/udostępnić. --- */
.material-preview-modal {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.75);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.material-preview-modal.open { display: flex; }
.material-preview-inner {
    position: relative;
    background: #fff;
    color: #171512;
    border-radius: 8px;
    max-width: 520px;
    width: 100%;
    max-height: 88vh;
    overflow-y: auto;
}
.material-preview-inner .close {
    /* position:sticky, NIE absolute — .material-preview-inner sam się
       przewija (overflow-y:auto, długi tekst posta potrafi być wyższy niż
       max-height:88vh). Przy position:absolute przycisk był POZYCJONOWANY
       WZGLĘDEM przewijanej zawartości, więc przy przewinięciu w dół (żeby
       przeczytać dłuższy tekst) wyjeżdżał poza widoczny obszar razem z
       resztą — zgłoszone jako "nie ma zamknij", z koniecznością zamykania
       całej aplikacji (PWA na pulpicie), żeby się stąd wydostać. sticky
       zostaje przyklejony do góry widocznego, przewijanego obszaru przez
       cały czas. */
    position: sticky;
    top: 10px;
    margin: 10px 10px -32px auto;
    z-index: 2;
    width: 32px;
    height: 32px;
    min-width: 32px;
    padding: 0;
    border-radius: 50%;
    background: rgba(0,0,0,0.55);
    color: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.material-preview-inner .close:hover { background: var(--accent-dark); }
/* Podgląd pliku (PDF/TXT/CSV) — ten sam modal co podgląd posta na FB, tylko
   szerszy (dokument potrzebuje więcej miejsca niż mockup posta) i z
   <iframe> zamiast siatki tekst+obrazek. */
.file-preview-inner { max-width: 900px; }
.file-preview-frame-wrap {
    margin: 8px 16px 0;
    width: calc(100% - 32px);
    height: 70vh;
    border: 1px solid #dddfe2;
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}
.file-preview-frame-wrap iframe { width: 100%; height: 100%; border: none; display: block; }
.file-preview-inner .btn-row { margin: 10px 16px 16px !important; }
@media (max-width: 640px) {
    .file-preview-frame-wrap { height: 60vh; }
}

/* Próba renderowania PDF przez PDF.js na <canvas> została wycofana — wynik
   był nieczytelny i bez żadnych narzędzi (bez powiększania, zaznaczania
   tekstu, drukowania). PDF-y teraz otwierają się od razu w nowej karcie
   przeglądarki (link
   target="_blank" w materials.php), co oddaje sterowanie natywnej
   przeglądarce PDF systemu — z pinch-zoom, drukowaniem itd. Stąd brak tu już
   żadnych reguł .file-preview-pdf-container.
*/

/* --- Materiały: przypięte pliki, licznik "przeczytano", komentarze pod
   plikami --- */
.list-item.material-pinned { border-left: 3px solid var(--accent); background: rgba(217,123,46,0.05); }

/* Bogatsza karta pliku — więcej "powietrza", zaokrąglenie, delikatny cień po
   najechaniu i kolorowa plakietka rozszerzenia zamiast płaskiego wiersza
   listy. Klasa .list-item zostaje na elemencie (typografia .title/.meta
   dziedziczona stamtąd), .material-file-card tylko dokłada layout. */
.list-item.material-file-card {
    display: block;
    padding: 14px 16px;
    border-radius: 10px;
    transition: box-shadow .12s, border-color .12s;
}
.list-item.material-file-card:hover { box-shadow: 0 2px 10px rgba(0,0,0,0.06); border-color: rgba(217,123,46,0.25); }
.material-file-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.material-file-main { display: flex; align-items: center; gap: 10px; min-width: 0; }
.material-file-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.material-file-ext {
    display: inline-flex;
    align-items: center;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .03em;
    color: #fff;
    padding: 2px 7px;
    border-radius: 5px;
    margin-right: 6px;
    vertical-align: middle;
}
.material-pin-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--accent-dark);
    background: rgba(217,123,46,0.14);
    border-radius: 20px;
    padding: 2px 8px;
    margin-right: 6px;
    vertical-align: middle;
}
.material-read-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    width: 100%;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(0,0,0,0.06);
}
.material-read-row .material-read-active { border-color: var(--accent); color: var(--accent-dark); font-weight: 600; }
.material-read-who { display: inline-block; }
.material-read-who summary { cursor: pointer; font-size: 12px; color: #8a847c; list-style: none; }
.material-read-who summary::-webkit-details-marker { display: none; }
.material-comments-details { width: 100%; margin-top: 6px; }
.material-comments-details summary {
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: #6b655d;
    padding: 6px 0;
    display: flex;
    align-items: center;
    gap: 6px;
    list-style: none;
}
.material-comments-details summary::-webkit-details-marker { display: none; }
.material-comments-body {
    padding: 10px 0 4px;
    border-top: 1px solid rgba(0,0,0,0.06);
    margin-top: 4px;
}
.material-preview-hint {
    margin: 40px 16px 0;
    font-size: 11px;
    color: #8a847c;
}
.fb-mock {
    margin: 8px 16px 0;
    border: 1px solid #dddfe2;
    border-radius: 6px;
    background: #fff;
    overflow: hidden;
}
.fb-mock-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 12px 6px;
}
.fb-mock-name { margin: 0; font-size: 14px; font-weight: 700; color: #050505; }
.fb-mock-meta {
    margin: 1px 0 0;
    font-size: 12px;
    color: #65676b;
    display: flex;
    align-items: center;
    gap: 4px;
}
.fb-mock-meta .icon { width: 10px; height: 10px; }
.fb-mock-text {
    margin: 4px 0 10px;
    padding: 0 12px;
    font-size: 14px;
    line-height: 1.5;
    color: #050505;
    white-space: pre-line;
}
.fb-mock img {
    width: 100%;
    max-height: 42vh;
    object-fit: cover;
    display: block;
}
.fb-mock-actions {
    display: flex;
    gap: 18px;
    padding: 8px 12px;
    border-top: 1px solid #eee;
    font-size: 13px;
    color: #65676b;
    font-weight: 600;
}
.fb-mock-actions span { display: flex; align-items: center; gap: 5px; }
.material-preview-body { padding: 14px 16px 16px; }
.material-preview-inner .btn.secondary { color: #171512; border-color: #d8d3cc; }
.material-preview-inner .btn.secondary:hover { background: rgba(0,0,0,0.04); }

/* --- Pasek narzędzi nad treścią posta na Facebooka (emotikony, Unicode
   pogrubienie/kursywa, szybki hasztag) --- */
.fb-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
}
.fb-toolbar-emoji-wrap { position: relative; display: inline-block; }
.emoji-popover {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 20;
    background: #fff;
    color: #171512;
    border: 1px solid #d8d3cc;
    border-radius: 5px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 8px;
    width: 220px;
    grid-template-columns: repeat(6, 1fr);
    gap: 2px;
}
.emoji-popover.open { display: grid; }
.emoji-popover-item {
    cursor: pointer;
    font-size: 18px;
    text-align: center;
    padding: 4px;
    border-radius: 4px;
    line-height: 1;
}
.emoji-popover-item:hover { background: #f0ece4; }

/* --- Delikatna ramka wokół map Google (trasa/jazda/wydarzenie) — inaczej
   mapa zlewa się wizualnie z tłem karty. --- */
.map-frame {
    border: 1px solid rgba(0,0,0,0.1);
    overflow: hidden;
}

/* --- Pulpit --- */
.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
}
.stat-card {
    /* Delikatny ciepły, pomarańczowy gradient zamiast płaskiego kremu — na
       tyle subtelny, żeby liczby i etykiety zostały czytelne. */
    background: linear-gradient(150deg, #fdf1e4, #f6f3ef 60%);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 18px;
    transition: transform .15s;
    text-decoration: none;
    color: #171512;
    display: block;
}
.stat-card:hover { transform: translateY(-3px); }
.stat-card .stat-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 7px;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    margin-bottom: 10px;
}
.stat-card .num { font-size: 30px; font-weight: 800; color: #171512; line-height: 1.1; }
.stat-card .label { font-size: 12px; color: #6b6560; margin-top: 4px; }

/* --- Hero/powitanie na pulpicie: awatar + dynamiczne powitanie zależne od
   pory dnia + rząd szybkich akcji, żeby pulpit czuł się jak "centrum
   dowodzenia", a nie tylko nagłówek nad listami. --- */
.welcome-hero {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 26px 4px 6px;
}
.welcome-hero .avatar {
    width: 54px;
    height: 54px;
    font-size: 20px;
}
.welcome-hero .avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.welcome h1 { font-size: 25px; margin: 0 0 3px; font-weight: 700; color: var(--text-hero); }
.welcome p { color: var(--text-hero-muted); font-size: 13px; margin: 0; }

/* Poziom/tytuł przy powitaniu na pulpicie — druga wersja, świadomie cicha
   i mniej rzucająca się w oczy niż wcześniejszy wariant. Zwykły, mały tekst
   pod powitaniem, bez tła/cienia/animacji, tylko emoji się lekko wyróżnia
   rozmiarem. */
.activity-badge-subtle {
    display: inline-block;
    margin-top: 5px;
    font-size: 12px;
    color: var(--text-hero-muted);
    text-decoration: none;
    opacity: .9;
    transition: opacity .15s;
}
.activity-badge-subtle:hover { opacity: 1; text-decoration: underline; }

/* Tytuł honorowy (Prezes/Zastępca itd.) doklejony przez member_link() do
   nazwiska wszędzie w serwisie — sam emoji, bez dodatkowego tła, żeby nie
   rywalizował wizualnie z treścią wokół (czat, komentarze, listy). */
.honorary-badge { font-size: .95em; }

/* --- Kamienie milowe: baner "nowe osiągnięcie" na pulpicie, żeby świętować
   zdobyte kamienie milowe. Ciepły, świąteczny akcent (podobny gradient co
   ranking), ale osobna, jednorazowa
   karta — znika po prostu przy następnym wejściu (nie jest zapisywana jako
   "trzeba pokazać znowu"), bo powiadomienie w dzwoneczku i tak zostaje. */
.milestone-banner {
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: linear-gradient(135deg, #fff4e2, #ffe8c7);
    border: 1px solid rgba(217,123,46,.35);
    border-radius: 8px;
    padding: 12px 16px;
    margin-bottom: 16px;
    font-size: 13px;
    /* Ten div NIE ma klasy .card, więc bez jawnego koloru dziedziczyłby
       jasny kolor tekstu z body (--text-chrome, myślany pod ciemne tło) —
       na jasnym, kremowym tle banera wychodził wtedy prawie niewidoczny,
       "wyblakły" tekst. */
    color: #171512;
}
.milestone-banner-item { display: flex; align-items: center; gap: 8px; }
.milestone-banner-emoji { font-size: 20px; }
.milestone-banner-item .muted { color: #6b6560; }

/* --- Wybornik ikon (Narzędzia -> Kamienie milowe) — przycisk z podglądem +
   wyskakująca siatka ikon do klikania, patrz assets/icon-picker.js. Ten sam
   "przycisk-przełącznik + popup" wzorzec co .emoji-picker, ale mniejsza,
   jedna siatka bez zakładek (ikon jest tylko kilkanaście). Prośba
   użytkownika 02.08.2026: "jak mam wybierać ikonki skoro są na sztywno" —
   zwykły <select> z samym tekstem nie pokazywał, jak dana ikona wygląda. */
.icon-picker-field { position: relative; display: inline-block; }
.icon-picker-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #fff;
    border: 1px solid #d8d3cc;
    border-radius: 5px;
    padding: 7px 10px;
    cursor: pointer;
    color: #171512;
}
.icon-picker-toggle:hover { background: rgba(0,0,0,0.03); }
.icon-picker-preview { display: inline-flex; }
.icon-picker-popup {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 5;
    grid-template-columns: repeat(5, 1fr);
    gap: 4px;
    background: #fff;
    border-radius: 7px;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 2px 10px rgba(0,0,0,0.12);
    padding: 8px;
    width: 210px;
    max-height: 260px;
    overflow-y: auto;
}
.icon-picker-popup.open { display: grid; }
.icon-picker-option {
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid transparent;
    border-radius: 5px;
    padding: 8px 6px;
    cursor: pointer;
    color: #45403a;
}
.icon-picker-option:hover { background: rgba(0,0,0,0.06); }
.icon-picker-option.selected { background: rgba(217,123,46,0.16); border-color: rgba(217,123,46,.4); color: #b8631f; }

/* --- Checklist onboardingowy (uzupełnij profil / dodaj pierwszą trasę /
   dołącz do czatu, z małą nagrodą punktową za każdy krok) — znika z
   pulpitu, gdy wszystkie kroki są zrobione (patrz
   $showOnboardingChecklist w index.php). --- */
.onboarding-checklist-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.onboarding-checklist-head h2 { margin: 0; }
.onboarding-checklist-head form { margin: 0; }
.onboarding-dismiss {
    background: none;
    border: none;
    color: #8a847d;
    font-size: 12px;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 5px;
}
.onboarding-dismiss:hover { background: rgba(0,0,0,0.05); color: #171512; }
.onboarding-step {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid rgba(0,0,0,0.06);
}
.onboarding-step:last-child { border-bottom: none; }
.onboarding-step-check {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid rgba(0,0,0,0.15);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: transparent;
}
.onboarding-step.done .onboarding-step-check {
    background: #3fb950;
    border-color: #3fb950;
    color: #fff;
}
.onboarding-step-label { flex: 1; font-size: 13px; }
.onboarding-step.done .onboarding-step-label { color: #6b6560; text-decoration: line-through; }

/* --- Cotygodniowe podsumowanie — zwykła karta na pulpicie, w tym samym
   stylu co reszta bocznej kolumny, żeby nie konkurowała wizualnie z
   rankingiem tuż pod spodem. --- */
.weekly-digest-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.weekly-digest-list li { font-size: 12.5px; display: flex; align-items: center; gap: 6px; }

/* Ranking aktywności na pulpicie — świadomie stonowany i wąski (mieści się w
   kolumnie bocznej razem z innymi kartami), nie osobny, krzykliwy "widget"
   na pół strony — ważny element, ale ma zostać czymś ładnym i delikatnym,
   nie dominować układu. Zwykłe, ciche wiersze zamiast
   kolorowych kółek/pasków postępu — tylko delikatne podświetlenie własnego
   wiersza i mała, cienka kreska pod spodem oddzielająca pozycje.
   Pomarańczowe tło karty — delikatny gradient, nie płaski kolor, dodający
   trochę koloru na pulpicie, żeby ciemny tekst
   nadal dobrze się czytał. */
.card.leaderboard-compact {
    background: linear-gradient(160deg, #fbe0c2, #f9ead9 55%, #f6f3ef 100%);
    border: 1px solid rgba(217,123,46,.3);
}
.leaderboard-compact-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 2px;
    border-bottom: 1px solid rgba(217,123,46,.14);
    font-size: 12.5px;
}
.leaderboard-compact-row:last-child { border-bottom: none; }
.leaderboard-compact-row.is-me { background: rgba(255,255,255,.6); border-radius: 6px; padding-left: 6px; padding-right: 6px; }
.leaderboard-compact-rank { flex-shrink: 0; width: 14px; color: #a8763f; font-weight: 600; font-size: 11px; }
.leaderboard-compact-row .avatar { width: 22px; height: 22px; font-size: 9px; flex-shrink: 0; }
.leaderboard-compact-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leaderboard-compact-points { flex-shrink: 0; color: #a8763f; font-size: 11px; font-weight: 600; }

.quick-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 14px 4px 20px;
}
.quick-action {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 15px;
    border-radius: 20px;
    background: var(--chrome-fill);
    border: 1px solid var(--chrome-border-strong);
    color: var(--text-chrome);
    font-size: 12px;
    font-weight: 600;
    text-decoration: none;
    transition: background .15s, border-color .15s, transform .15s;
}
.quick-action:hover { background: var(--accent); border-color: var(--accent); color: #fff; transform: translateY(-2px); }
.quick-action .icon { width: 13px; height: 13px; }

/* --- Kafelki "odkryj" na pulpicie (galeria/wydarzenia/ogłoszenia ze zdjęciem) --- */
.discover-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}
.discover-tile {
    position: relative;
    display: block;
    height: 230px;
    border-radius: 9px;
    overflow: hidden;
    text-decoration: none;
    background-color: #232323;
    transition: transform .18s;
}
.discover-tile:hover { transform: translateY(-4px); }
/* Zdjęcie jako osobna warstwa (patrz komentarz przy .gallery-cat-tile-bg) —
   zoom na hover robimy przez transform: scale(), żeby nie skakał na inny
   fragment/proporcję zdjęcia jak przy zmianie samego background-size. */
.discover-tile-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    transition: transform .4s;
}
.discover-tile:hover .discover-tile-bg { transform: scale(1.08); }
.discover-tile::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.78) 100%);
}
.discover-tile.no-image { background: linear-gradient(135deg, #2c2c2c, #181818); }

/* Pasek stronicowania (Poprzednia / Strona X z Y / Następna) — patrz
   paginate() + render_pagination() w includes/helpers.php, używane na
   każdej liście, która z czasem może urosnąć (użytkownicy, galeria,
   materiały, trasy...). */
.pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 16px;
    flex-wrap: wrap;
}
.pagination-info {
    font-size: 12px;
    color: var(--text-chrome-muted, #8a847d);
    text-align: center;
    flex: 1;
}

/* Kafelek Galerii na pulpicie: kilka nałożonych na siebie warstw tła,
   przełączanych klasą .active (przenikanie zamiast twardej zmiany) —
   patrz JS w index.php. Każda warstwa ma własne background-size/position,
   żeby zoom na hover (przejęty tu z .discover-tile:hover) też działał. */
.discover-tile-slide {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    opacity: 0;
    transition: opacity 1s ease, transform .4s;
}
.discover-tile-slide.active { opacity: 1; }
.discover-tile-carousel:hover .discover-tile-slide.active { transform: scale(1.08); }
.discover-tile-dots {
    position: absolute;
    left: 0; right: 0;
    bottom: 10px;
    z-index: 2;
    display: flex;
    justify-content: center;
    gap: 5px;
}
.discover-tile-dots .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255,255,255,0.45);
    transition: background .3s, transform .3s;
    cursor: pointer;
}
.discover-tile-dots .dot.active { background: #fff; transform: scale(1.3); }
.discover-tile-icon-lg {
    position: absolute;
    top: 46%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    opacity: .18;
}
.discover-tile-body {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 14px 16px;
    z-index: 2;
    color: #fff;
}
.discover-tile-title {
    font-size: 15px;
    font-weight: 700;
    margin: 0 0 3px;
    display: flex;
    align-items: center;
    gap: 6px;
    color: #fff;
}
.discover-tile-arrow {
    position: absolute;
    top: 14px;
    right: 14px;
    z-index: 2;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: rgba(255,255,255,0.16);
    backdrop-filter: blur(3px);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .18s, transform .18s;
}
.discover-tile:hover .discover-tile-arrow { opacity: 1; transform: translateX(0); }
.discover-tile-meta {
    font-size: 11px;
    color: rgba(255,255,255,0.82);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- Dwukolumnowy układ list na pulpicie (trasy/ogłoszenia/wydarzenia/czat)
   zamiast jednej długiej kolumny kart jedna pod drugą — na szerokich
   ekranach wygląda jak prawdziwy dashboard, nie lista.
   Dwie NIEZALEŻNE kolumny (każda to własny, pionowy stos kart), a nie
   wspólny grid par w rzędach — karty nie muszą mieć tej samej wysokości
   (np. jedno ogłoszenie obok trzech tras), każda jest tak wysoka, ile
   potrzebuje jej własna treść, i zaczyna się równo od góry kolumny. Wymuszone
   rozciąganie do wysokości sąsiada (poprzednia wersja) tylko dokładało pustej
   przestrzeni w krótszej karcie. */
.dashboard-columns {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}
.dashboard-col {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
@media (max-width: 900px) {
    /* align-items:flex-start (wyżej) był POTRZEBNY w układzie poziomym
       (dwie kolumny obok siebie), żeby kolumny nie rozciągały się do
       wysokości dłuższej sąsiadki. Ale flex-direction:column obraca osie —
       ten sam align-items zaczyna wtedy działać na szerokość zamiast
       wysokości i kurczy każdą kolumnę/kartę do szerokości jej własnej
       treści (stąd wąskie karty z czarnym marginesem po bokach na
       telefonie). Trzeba go tu jawnie nadpisać na stretch. */
    .dashboard-columns { flex-direction: column; align-items: stretch; }

    /* Na telefonie dwie kolumny stają się jedną długą listą kart w
       kolejności dokumentu — a to zostawiało ranking (który w układzie
       dwukolumnowym startuje na górze DRUGIEJ kolumny) daleko na dole, pod
       całą pierwszą kolumną (Trasy + Wydarzenia). Prośba użytkownika
       02.08.2026: "ranking jest na dole pod wydarzeniami... ustaw go nad
       trasami". display:contents "rozpuszcza" oba .dashboard-col (ich
       własne div-y znikają z layoutu, ale karty w środku zostają), dzięki
       czemu wszystkie karty pulpitu stają się jednym wspólnym stosem, w
       którym rankingowi można nadać order:-1, żeby wskoczył na sam początek
       — przed "Trasy społeczności". Reszta kart zachowuje naturalną
       kolejność (order:0 = kolejność w dokumencie). Tylko telefon — na
       szerszych ekranach kolumny zostają bez zmian. */
    .dashboard-col { display: contents; }
    .dashboard-columns .leaderboard-compact { order: -1; }
    /* "W tym tygodniu" (weekly-digest) jest w dokumencie zaraz PO rankingu
       (oba w drugiej kolumnie), ale bez własnego "order" zostawało z
       order:0 razem z resztą kart — czyli lądowało na samym końcu stosu, za
       Trasami/Wydarzeniami/Ogłoszeniami, mimo że ranking (order:-1) skakał
       na górę. Ten sam order:-1 co ranking — przy równym "order" flex
       zachowuje kolejność z dokumentu (ranking, potem weekly-digest), więc
       oba razem trafiają na samą górę, jedno pod drugim — "W tym tygodniu"
       ma stać tuż pod Rankingiem aktywności. */
    .dashboard-columns .weekly-digest { order: -1; }
}

/* --- Miniatury zdjęć wydarzeń --- */
.event-cover {
    width: 100%;
    height: 160px;
    object-fit: cover;
    border-radius: 5px;
    display: block;
    margin-bottom: 12px;
}
.event-cover-sm {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 5px;
    flex-shrink: 0;
}

/* --- Stopka --- */
.site-footer {
    margin-top: 36px;
    padding-top: 20px;
    border-top: 1px solid var(--chrome-border);
    text-align: center;
}
.site-footer-links {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.site-footer-links a {
    color: var(--text-chrome-muted);
    text-decoration: none;
    font-size: 12px;
    transition: color .15s;
}
.site-footer-links a:hover { color: var(--text-chrome); }
/* Rządek "Znajdziesz nas również" — okrągłe, szare, delikatne ikonki mediów
   społecznościowych, celowo stonowane, nie duże i krzykliwe. Osobny wiersz
   pod linkami stopki, wypełniony kolor dopiero po najechaniu. */
.site-footer-social {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.site-footer-social span {
    color: var(--text-chrome-faint);
    font-size: 11px;
    margin-right: 2px;
}
.site-footer-social a {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1.3px solid var(--chrome-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-chrome-muted);
    text-decoration: none;
    font-size: 13px;
    transition: color .15s, border-color .15s, background-color .15s;
}
.site-footer-social a:hover {
    color: #fff;
    background: var(--accent);
    border-color: var(--accent);
}
.site-footer-meta { color: var(--text-chrome-faint); font-size: 11px; margin: 0; }

/* --- Paginacja galerii (po 10 zdjęć na stronę w każdej kategorii) --- */
.gallery-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 14px;
    flex-wrap: wrap;
}
.gallery-pagination .page-btn {
    min-width: 30px;
    height: 30px;
    padding: 0 8px;
    border-radius: 5px;
    border: none;
    background: #eee9e2;
    color: #45403a;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
}
.gallery-pagination .page-btn:hover { background: #ddd5c8; box-shadow: none; }
.gallery-pagination .page-btn.active { background: var(--accent); color: #fff; }

/* --- Komunikator (czat) --- */
.chat-layout {
    display: flex;
    height: 72vh;
    min-height: 480px;
    background: #f6f3ef;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid var(--card-border);
}
.chat-sidebar {
    width: 270px;
    flex-shrink: 0;
    background: #eee9e2;
    border-right: 1px solid rgba(0,0,0,0.08);
    display: flex;
    flex-direction: column;
}
/* Przewijana lista grup, OSOBNO od .chat-sidebar-head nad nią (ten sam
   wzorzec co .chat-header/.chat-messages po prawej) — nagłówek "Czat" +
   przyciski archiwum/nowej grupy mają zostać na stałym miejscu, przewija
   się tylko sama lista pod nimi. min-height:0
   jest konieczne, żeby flex-item w ogóle chciał się skurczyć poniżej
   wysokości swojej treści (ten sam powód co przy .chat-messages niżej). */
.chat-sidebar-list { flex: 1; min-height: 0; overflow-y: auto; }
.chat-sidebar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 14px 12px;
    color: #17140f;
    background: linear-gradient(180deg, rgba(217,123,46,0.10), rgba(217,123,46,0) 90%);
    border-bottom: 1px solid rgba(0,0,0,0.06);
}
.chat-sidebar-head h2 { margin: 0; font-size: 14px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.chat-sidebar-head h2 .icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    vertical-align: middle;
}
.chat-sidebar .empty-state { padding: 20px 14px; color: #6b6560; }
.chat-sidebar .empty-state p { font-size: 12px; }
.chat-group-item {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 8px;
    padding: 9px 10px;
    border-radius: 7px;
    text-decoration: none;
    color: #17140f;
    transition: background .15s, box-shadow .15s, transform .15s;
}
.chat-group-item:hover { background: rgba(0,0,0,0.05); }
.chat-group-item.active {
    background: #f5f3ef;
    box-shadow: inset 3px 0 0 var(--accent);
}
.chat-group-item.active .chat-group-item-name { color: var(--accent-dark); }
.chat-group-item.active .chat-group-item-preview { color: var(--accent-dark); opacity: .75; }
.chat-group-avatar { flex-shrink: 0; box-shadow: 0 0 0 2px #fff, 0 0 0 3px rgba(217,123,46,0.25); }
.chat-group-item-body { min-width: 0; }
.chat-group-item-name { display: block; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-group-item-preview { display: block; font-size: 11px; color: #8a847d; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.chat-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    position: relative;
    background: #efebe4;
    background-image: radial-gradient(rgba(0,0,0,0.025) 1px, transparent 1px);
    background-size: 18px 18px;
}
.chat-main .empty-state { color: #6b6560; }
.chat-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 18px;
    background: linear-gradient(135deg, rgba(217,123,46,0.14), rgba(217,123,46,0.02) 55%), #f6f3ef;
    border-bottom: 2px solid var(--accent);
    color: #17140f;
    flex-shrink: 0; /* nagłówek rozmowy nigdy nie ma się ściskać — na telefonie
                        z otwartą klawiaturą to .chat-messages (flex:1,
                        min-height:0 wyżej) ma oddawać miejsce, nie nagłówek
                        ani pole do pisania (patrz też .chat-composer niżej) */
}
.chat-header-info { display: flex; align-items: center; gap: 10px; min-width: 0; }
.chat-header-avatar { flex-shrink: 0; box-shadow: 0 0 0 2px #fff, 0 0 0 3px rgba(217,123,46,0.3); }
.chat-header-name { margin: 0; font-size: 14px; font-weight: 700; color: var(--accent-dark); }
.chat-header-meta { margin: 2px 0 0; font-size: 11px; color: #8a847d; display: flex; align-items: center; gap: 4px; }

.chat-messages {
    flex: 1;
    min-height: 0; /* bez tego flex-item domyślnie nie chce się skurczyć
                      poniżej wysokości swojej treści — przy długiej historii
                      czatu wypychało to pole do pisania poza widoczny obszar
                      zamiast pozwolić TEJ liście przewijać się wewnętrznie */
    overflow-y: auto;
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.chat-messages::-webkit-scrollbar, .chat-sidebar::-webkit-scrollbar { width: 8px; }
.chat-messages::-webkit-scrollbar-thumb, .chat-sidebar::-webkit-scrollbar-thumb {
    background: rgba(0,0,0,0.15);
    border-radius: 20px;
}
.chat-messages::-webkit-scrollbar-track, .chat-sidebar::-webkit-scrollbar-track { background: transparent; }
.chat-day-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0;
    color: #a8a29a;
    font-size: 11px;
    font-weight: 600;
}
.chat-day-divider::before, .chat-day-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: rgba(0,0,0,0.08);
}
.chat-day-divider span { white-space: nowrap; }
.chat-bubble {
    display: flex;
    gap: 8px;
    max-width: 72%;
    align-self: flex-start;
}
.chat-bubble.own { align-self: flex-end; flex-direction: row-reverse; }
/* align-self:flex-start jest tu KLUCZOWE — .chat-bubble (rodzic, display:flex)
   nie ustawia align-items, więc domyślne "stretch" rozciągało ten link na
   pełną wysokość całej wiadomości (dymek + reakcje + rządek akcji pod spodem,
   czyli sąsiedni flex-item .chat-bubble-stack). Sam <img> nie rósł (obrazki
   nie rozciągają się domyślnie), ale KONTENER .chat-bubble-avatar owszem —
   więc .online-dot (position:absolute; bottom:-1px) lądował na dole TEGO
   rozciągniętego, niewidzialnego pudełka, czyli praktycznie przy rządku
   przycisków odpowiedz/emotka, a nie przy samym awatarze. */
.chat-bubble-avatar { flex-shrink: 0; align-self: flex-start; position: relative; display: inline-block; }
.chat-bubble-content {
    background: linear-gradient(135deg, rgba(217,123,46,0.09), rgba(217,123,46,0.03)), #fff;
    color: #17140f;
    border: 1px solid rgba(217,123,46,0.12);
    border-radius: 14px 14px 14px 4px;
    padding: 9px 13px;
    min-width: 0;
}
.chat-bubble.own .chat-bubble-content {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
    border: none;
    border-radius: 14px 14px 4px 14px;
}
.chat-bubble-author { font-size: 11px; font-weight: 700; margin-bottom: 2px; }
.chat-bubble-author a { color: var(--accent-dark); text-decoration: none; }
.chat-bubble-author a:hover { text-decoration: underline; }
.chat-bubble-avatar:hover .avatar { opacity: 0.85; }
.chat-bubble-text { font-size: 13px; line-height: 1.5; word-wrap: break-word; white-space: pre-wrap; }
.chat-bubble-text a { color: var(--accent-dark); text-decoration: underline; }
.chat-bubble.own .chat-bubble-text a { color: #fff; }
.chat-mention {
    font-weight: 700;
    text-decoration: none !important;
    background: rgba(217,123,46,0.14);
    border-radius: 4px;
    padding: 1px 4px;
}
.chat-bubble.own .chat-mention { background: rgba(255,255,255,0.22); color: #fff; }
.chat-mention-me { background: rgba(217,123,46,0.35); }
.chat-bubble.own .chat-mention-me { background: rgba(255,255,255,0.4); }
.chat-bubble-image { display: block; max-width: 220px; max-height: 220px; border-radius: 5px; margin-bottom: 4px; object-fit: cover; }
.chat-bubble-file {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    background: rgba(0,0,0,0.05);
    border-radius: 5px;
    text-decoration: none;
    color: inherit;
    font-size: 12px;
    margin-bottom: 4px;
}
.chat-bubble.own .chat-bubble-file { background: rgba(255,255,255,0.18); color: #fff; }
.chat-bubble-time { font-size: 10px; color: #a8a29a; margin-top: 3px; text-align: right; }
.chat-bubble.own .chat-bubble-time { color: rgba(255,255,255,0.75); }

.chat-bubble-stack { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.chat-bubble.own .chat-bubble-stack { align-items: flex-end; }

.chat-reply-quote {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 5px 8px;
    margin-bottom: 5px;
    background: rgba(0,0,0,0.05);
    border-left: 3px solid var(--accent);
    border-radius: 4px;
    font-size: 11.5px;
    max-width: 260px;
}
.chat-bubble.own .chat-reply-quote { background: rgba(255,255,255,0.18); border-left-color: rgba(255,255,255,0.7); }
.chat-reply-quote-author { font-weight: 700; color: var(--accent-dark); }
.chat-bubble.own .chat-reply-quote-author { color: #fff; }
.chat-reply-quote-text { color: #6b6560; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.chat-bubble.own .chat-reply-quote-text { color: rgba(255,255,255,0.85); }

.chat-reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.chat-reactions:empty { display: none; margin-top: 0; }
.chat-reaction-pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11.5px;
    padding: 2px 8px;
    border-radius: 20px;
    border: 1px solid rgba(0,0,0,0.08);
    background: #fff;
    color: #45403a;
    cursor: pointer;
    line-height: 1.5;
    transition: transform .1s, border-color .12s;
}
.chat-reaction-pill:hover { transform: translateY(-1px); }
.chat-reaction-pill.mine { border-color: var(--accent); background: rgba(217,123,46,0.14); color: var(--accent-dark); font-weight: 600; }
.chat-reaction-pill span { font-size: 10.5px; }

.chat-bubble-actions {
    display: flex;
    gap: 2px;
    margin-top: 3px;
    opacity: .5;
    transition: opacity .12s;
}
.chat-bubble:hover .chat-bubble-actions, .chat-bubble-actions:focus-within { opacity: 1; }
.chat-bubble-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    min-width: 22px;
    padding: 0;
    flex-shrink: 0;
    border-radius: 50%;
    border: none;
    background: rgba(0,0,0,0.06);
    color: #6b6560;
    cursor: pointer;
}
.chat-bubble-action:hover { background: var(--accent); color: #fff; }
.chat-bubble-action.danger:hover { background: #c0392b; color: #fff; }

/* Placeholder "Wiadomość została usunięta" (usuwanie u wszystkich, jak w
   WhatsApp) — bez zdjęcia/pliku/cytatu/reakcji/akcji, tylko wyszarzony,
   kursywą opisany dymek w tym samym miejscu co oryginał. */
.chat-bubble.deleted .chat-bubble-content { opacity: 0.75; }
.chat-bubble-deleted-text {
    display: flex;
    align-items: center;
    gap: 5px;
    font-style: italic;
    color: #8a8378;
}
.chat-bubble.own .chat-bubble-deleted-text { color: rgba(255,255,255,0.85); }

.chat-quick-react-popover {
    display: none;
    position: absolute;
    background: #fff;
    border-radius: 20px;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 2px 10px rgba(0,0,0,0.12);
    padding: 5px 7px;
    gap: 3px;
    z-index: 25;
}
.chat-quick-react-popover.open { display: flex; }
.chat-quick-react-popover button {
    background: none;
    border: none;
    font-size: 18px;
    cursor: pointer;
    border-radius: 50%;
    padding: 3px;
    line-height: 1;
    transition: transform .1s, background .1s;
}
.chat-quick-react-popover button:hover { background: rgba(0,0,0,0.06); transform: scale(1.2); }

.chat-more-menu {
    display: none;
    position: absolute;
    background: #fff;
    border-radius: 8px;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 2px 10px rgba(0,0,0,0.12);
    padding: 4px;
    z-index: 25;
    min-width: 170px;
}
.chat-more-menu.open { display: block; }
.chat-more-menu-item {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    background: none;
    border: none;
    border-radius: 5px;
    padding: 8px 9px;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    color: #17140f;
}
.chat-more-menu-item:hover { background: rgba(0,0,0,0.06); }
.chat-more-menu-item.danger { color: #c0392b; }
.chat-more-menu-item.danger:hover { background: rgba(192,57,43,0.1); }

.chat-reply-preview {
    display: none;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 7px 10px;
    margin-bottom: 8px;
    background: rgba(217,123,46,0.08);
    border-left: 3px solid var(--accent);
    border-radius: 5px;
    font-size: 12px;
}
.chat-reply-preview-body { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.chat-reply-preview-author { font-weight: 700; color: var(--accent-dark); }
.chat-reply-preview-text { color: #6b6560; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-reply-preview-close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    min-width: 22px;
    padding: 0;
    border-radius: 50%;
    border: none;
    background: rgba(0,0,0,0.06);
    color: #6b6560;
    cursor: pointer;
}
.chat-reply-preview-close:hover { background: rgba(0,0,0,0.12); }

.chat-composer {
    border-top: 1px solid rgba(0,0,0,0.06);
    background: #f6f3ef;
    padding: 12px 16px;
    position: relative;
    flex-shrink: 0; /* pole do pisania nigdy nie ma się ściskać/znikać, gdy na
                        telefonie zabraknie miejsca po otwarciu klawiatury —
                        bez tego domyślny flex-shrink:1 potrafił je razem z
                        nagłówkiem ściskać w stronę zera, zamiast oddać
                        brakujące miejsce WYŁĄCZNIE liście wiadomości
                        (.chat-messages ma flex:1 + min-height:0 właśnie po to) */
}
.chat-composer-row {
    display: flex;
    align-items: center;
    gap: 4px;
    background: #fff;
    border: 1px solid #e2dcd2;
    border-radius: 24px;
    padding: 4px 6px 4px 8px;
    transition: border-color .15s, box-shadow .15s;
}
.chat-composer-row:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(217,123,46,0.14); }
.chat-composer-row input[type=text] {
    flex: 1;
    padding: 9px 6px;
    border-radius: 20px;
    border: none;
    background: transparent;
    /* MUSI być >=16px — poniżej tego iOS Safari łapie ten input jako "mały
       tekst" i przy dotknięciu/pisaniu sam dopasowuje (zooma) widok strony,
       co wygląda jak "rozjeżdżające się" okno czatu w trakcie pisania.
       Ta reguła (klasa+atrybut) ma wyższą specyficzność niż ogólna
       "input { font-size:16px }" z media query niżej, więc jej wcześniejsza
       wartość 13px wygrywała i zoom mimo tamtej reguły dalej występował. */
    font-size: 16px;
    height: auto; /* reset wspólnego "input[type=text] { height:44px }" — patrz identyczny komentarz przy .topbar-search input[type=text] */
}
.chat-composer-row input[type=text]:focus { outline: none; }
.chat-composer .icon-btn { background: rgba(0,0,0,0.045); }
.chat-composer .icon-btn.primary {
    background: linear-gradient(135deg, var(--accent-light), var(--accent-dark));
    color: #fff;
}
.chat-composer .icon-btn.primary:hover { filter: brightness(1.05); }
.chat-readonly-notice {
    border-top: 1px solid rgba(0,0,0,0.06);
    background: #f6f3ef;
    color: #6b655d;
    padding: 12px 14px;
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.chat-attachment-preview:empty { display: none; }
.chat-attachment-preview {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    margin-bottom: 8px;
    background: rgba(0,0,0,0.04);
    border-radius: 5px;
    font-size: 12px;
    color: #45403a;
}
.chat-attachment-preview img { width: 34px; height: 34px; object-fit: cover; border-radius: 4px; }
.chat-attachment-preview .remove-attachment {
    margin-left: auto;
    background: none;
    border: none;
    cursor: pointer;
    color: #a33;
    display: flex;
    align-items: center;
}

/* Podpowiedzi @wzmianki nad polem wiadomości — patrz initMentionAutocomplete()
   w assets/chat.js. Puste :empty { display:none } zapasowo, gdyby JS nie
   dodał klasy .open na czas. */
.chat-mention-suggestions {
    display: none;
    flex-direction: column;
    position: absolute;
    bottom: 58px;
    left: 14px;
    right: 14px;
    background: #fff;
    border-radius: 8px;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 2px 10px rgba(0,0,0,0.12);
    max-height: 190px;
    overflow-y: auto;
    z-index: 21;
}
.chat-mention-suggestions.open { display: flex; }
.chat-mention-suggestion {
    padding: 8px 12px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    color: #45403a;
}
.chat-mention-suggestion:hover, .chat-mention-suggestion.active { background: rgba(217,123,46,0.12); color: var(--accent-dark); }

/* Piker emotek z kategoriami (jak w WhatsApp) — zakładki kategorii u góry,
   przewijana siatka poniżej. Używany zarówno przy polu wiadomości
   (#emoji-picker), jak i w rozszerzonym pikerze reakcji
   (#chat-extended-react-picker). */
/* PODEJŚCIE UPROSZCZONE — zamiast walczyć z rozmiarem okienka, po prostu
   scrolluje się całość. Wcześniejsze podejście z flex:1/min-height:0 na
   wewnętrznej siatce + osobnym scrollu TAM
   było kruche i nadal "obcinało" widok bez wyraźnego sygnału, że jest czego
   szukać niżej. Teraz CAŁE okienko (zakładki + siatka razem) to JEDEN,
   zwykły, przewijany kontener — prościej i niezawodnie. Zakładki kategorii są
   "sticky" u góry, więc nie znikają w trakcie przewijania niżej. */
.emoji-picker {
    display: none;
    flex-direction: column;
    position: absolute;
    bottom: 58px;
    left: 14px;
    background: #fff;
    border-radius: 7px;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 2px 10px rgba(0,0,0,0.12);
    padding: 8px;
    width: 288px;
    max-width: calc(100vw - 28px);
    max-height: 320px;
    overflow-y: auto;
    overflow-x: hidden;
    /* Suwak od razu widoczny (nie tylko po najechaniu myszką) — bez tego
       duże kategorie (np. "Emocje" — prawie 100 emotek) i tak nie mieszczą
       się na ekranie, a bez śladu suwaka wygląda to jak ucięcie, nie jak
       "przewiń dalej". */
    scrollbar-width: thin;
    scrollbar-color: rgba(0,0,0,0.28) transparent;
    z-index: 20;
}
.emoji-picker::-webkit-scrollbar { width: 6px; }
.emoji-picker::-webkit-scrollbar-track { background: transparent; }
.emoji-picker::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.28); border-radius: 3px; }
.emoji-picker.open { display: flex; }
.emoji-picker-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 1px;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid rgba(0,0,0,0.08);
    position: sticky;
    top: 0;
    background: #fff;
    z-index: 1;
}
.emoji-picker-tabs button {
    background: none;
    border: none;
    font-size: 16px;
    padding: 4px 7px;
    border-radius: 5px;
    cursor: pointer;
    flex-shrink: 0;
    line-height: 1;
}
.emoji-picker-tabs button.active { background: rgba(217,123,46,0.16); }
.emoji-picker-tabs button:hover { background: rgba(0,0,0,0.06); }
.emoji-picker-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    align-content: flex-start;
    gap: 3px;
}
.emoji-picker-grid button {
    background: none;
    border: none;
    font-size: 18px;
    cursor: pointer;
    border-radius: 4px;
    padding: 4px;
    line-height: 1;
}
.emoji-picker-grid button:hover { background: rgba(0,0,0,0.06); }

/* --- Reakcje emoji na ogłoszeniach/wydarzeniach/postach (Materiały) --- */
.reaction-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin-top: 10px; }
.reaction-pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 12px;
    padding: 3px 9px;
    border-radius: 20px;
    border: 1px solid rgba(0,0,0,0.1);
    background: #fff;
    color: #45403a;
    cursor: pointer;
    line-height: 1.5;
    transition: transform .1s, border-color .12s;
}
.reaction-pill:hover { transform: translateY(-1px); }
.reaction-pill.mine { border-color: var(--accent); background: rgba(217,123,46,0.14); color: var(--accent-dark); font-weight: 600; }
.reaction-pill span { font-size: 11px; }
.reaction-add-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    min-width: 24px;
    padding: 0;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px dashed rgba(0,0,0,0.18);
    background: transparent;
    color: #8a847d;
    cursor: pointer;
}
.reaction-add-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
/* Pod "+" otwiera się TEN SAM kategoryzowany piker co pod komentarzami
   (.emoji-picker z assets/emoji-picker.js) — dawniejsze 6 emotek szybkiej
   reakcji dawało zbyt ubogi wybór, więc jest ich teraz tyle, ile w pełnym
   pikerze. .reaction-quick-popover dokłada tylko to, czego
   .emoji-picker nie ma z automatu: pozycjonowanie liczone w JS (top/left na
   sztywno, patrz assets/reactions.js), więc trzeba wyzerować bottom/left,
   które .emoji-picker zakłada domyślnie (kotwiczenie nad polem tekstowym). */
.reaction-quick-popover { bottom: auto; left: auto; z-index: 60; }

/* --- Modal ogólny (np. ustawienia grupy czatu) --- */
.modal {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.8);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.modal.open { display: flex; }
.modal-inner {
    position: relative;
    background: #f6f3ef;
    color: #17140f;
    border-radius: 8px;
    padding: 20px;
    max-width: 440px;
    width: 100%;
    max-height: 85vh;
    overflow-y: auto;
}
/* Jasne tło modala potrzebuje ciemnego wariantu przycisku .btn.secondary
   — domyślny wariant jest dobrany pod ciemne tło strony i na jasnym tle
   był praktycznie niewidoczny (wyglądał jak wyłączony/nieklikalny). */
.modal-inner .btn.secondary { color: #171512; border-color: #d8d3cc; }
.modal-inner .btn.secondary:hover { background: rgba(0,0,0,0.04); }
.modal-inner .close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    min-width: 30px;
    padding: 0;
    border-radius: 50%;
    background: rgba(0,0,0,0.08);
    color: #45403a;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.modal-inner .close:hover { background: rgba(0,0,0,0.15); }
.modal-inner h3 { margin: 0 0 12px; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.modal-inner label { display: block; font-size: 12px; font-weight: 600; margin: 12px 0 4px; color: #45403a; }
.modal-inner label:first-of-type { margin-top: 0; }
.modal-inner input[type=text] { width: 100%; padding: 8px 10px; border-radius: 5px; border: 1px solid #ccc; font-size: 13px; }
.member-picker {
    max-height: 180px;
    overflow-y: auto;
    border: 1px solid #ddd;
    border-radius: 5px;
    padding: 8px 10px;
    background: #fff;
}
.member-check { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 0; cursor: pointer; }
.member-check input { margin: 0; }

/* Picker regionów jako tagi + przycisk "dodaj" (zamiast listy checkboxów) */
.tag-picker.member-picker {
    max-height: none;
    overflow: visible;
    border: none;
    padding: 0;
    background: transparent;
}
.tag-picker-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.tag-picker-empty { font-size: 12px; color: var(--text-chrome-dim, #888); margin: 0 0 8px; }
.tag-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--accent-dark);
    background: rgba(217,123,46,0.15);
    padding: 4px 6px 4px 10px;
    border-radius: 20px;
    white-space: nowrap;
}
.tag-pill-remove {
    border: none;
    background: none;
    color: inherit;
    cursor: pointer;
    font-size: 15px;
    line-height: 1;
    padding: 2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.75;
}
.tag-pill-remove:hover { opacity: 1; }
.tag-picker-add-wrap { display: flex; align-items: center; }
.tag-picker-add-btn {
    font-size: 12px;
    font-weight: 500;
    color: var(--accent-dark);
    background: rgba(217,123,46,0.08);
    border: 1px dashed rgba(217,123,46,0.4);
    padding: 5px 12px;
    border-radius: 20px;
    cursor: pointer;
}
.tag-picker-add-btn:hover { background: rgba(217,123,46,0.15); }
.tag-picker-add-wrap { position: relative; }
.tag-picker-dropdown {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 20;
    width: 260px;
    max-width: 80vw;
    background: #fff;
    border: 1px solid #ddd;
    border-radius: 8px;
    box-shadow: 0 6px 18px rgba(0,0,0,0.12);
    padding: 8px;
}
.tag-picker-filter {
    width: 100%;
    font-size: 13px;
    padding: 6px 8px;
    border-radius: 5px;
    border: 1px solid #ccc;
    box-sizing: border-box;
    margin-bottom: 6px;
}
.tag-picker-options { max-height: 220px; overflow-y: auto; }
.tag-picker-option {
    font-size: 13px;
    padding: 7px 8px;
    border-radius: 5px;
    cursor: pointer;
}
.tag-picker-option:hover { background: rgba(217,123,46,0.12); }
.tag-picker-options-empty { font-size: 12px; color: var(--text-chrome-dim, #888); margin: 4px 2px; }

/* =========================================================
   RESPONSYWNOŚĆ — telefony i tablety
   ========================================================= */
@media (max-width: 720px) {
    .wrap { padding: 14px 12px 48px; }

    .topbar { gap: 0; padding-bottom: 10px; }

    /* Krótki, zawsze widoczny pasek: logo (większe niż wcześniej — to był
       jeden z powodów tej zmiany) po lewej, hamburger po prawej. Reszta
       (szukajka/dzwonek/użytkownik/menu główne) chowa się domyślnie i
       wysuwa dopiero po tapnięciu hamburgera — patrz .topbar.menu-open
       niżej i skrypt w includes/layout.php. */
    .topbar-row1 { align-items: center; gap: 10px; flex-wrap: wrap; padding: 2px 0; }
    .topbar .brand { justify-content: flex-start; font-size: 16px; }
    .topbar .brand img { height: 50px; }
    /* Motyw + hamburger razem, dosunięte do prawej krawędzi (margin-left:auto
       na PIERWSZYM z nich wystarczy — flex sam dosunie oba, patrz kolejność w
       includes/layout.php). Oba powiększone do ok. 44px — 38px to za mało
       jak na wygodny cel dotykowy (standard Apple/Google to ok. 44–48px),
       a to jest teraz jedyny ZAWSZE widoczny
       przycisk otwierający resztę menu na telefonie. */
    #theme-toggle-btn { margin-left: auto; width: 44px; height: 44px; }
    .topbar-menu-toggle { display: inline-flex; width: 44px; height: 44px; }

    .topbar-row1-extras {
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        width: 100%;
        order: 5;
        margin-top: 4px;
        padding-top: 10px;
        border-top: 1px solid var(--chrome-border);
    }
    .topbar.menu-open .topbar-row1-extras { display: flex; }
    .topbar-search { max-width: none; }
    .topbar .notif-wrap { display: flex; flex-direction: column; align-items: center; }
    .topbar .user-menu-wrap { display: flex; flex-direction: column; align-items: center; }
    .user-menu-dropdown { left: 0; right: 0; margin: 0 auto; }
    .notif-panel { left: 0; right: 0; margin: 0 auto; }
    /* Na telefonie oba te okienka (profil, powiadomienia) NIE mogą zostać
       "position: absolute" jak na desktopie — nakładałyby się jako pływająca
       warstwa NA wysuwane menu główne poniżej (.topbar-nav-row), zasłaniając
       "Pulpit"/"Trasy": po otwarciu menu profilu na telefonie dwa pierwsze
       linki menu głównego znikały, bo dropdown profilu leżał dosłownie na
       nich, w tym samym miejscu na ekranie. Zamiast nakładki: zwykły element w przepływie
       dokumentu, więc tylko odpycha menu główne niżej, nic nie zasłaniając. */
    .user-menu-dropdown.open, .notif-panel.open {
        position: static;
        margin: 8px auto 0;
    }

    .topbar-nav-row {
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: 6px;
        margin-top: 8px;
    }
    .topbar.menu-open .topbar-nav-row { display: flex; }
    /* Odstęp między pozycjami powiększony z 2px na 6px, a same rzędy trochę
       wyższe (padding 12px zamiast 10px) — łatwiej trafić palcem we
       właściwą pozycję, mniej ryzyka kliknięcia sąsiedniej. */
    .topbar-nav-row a { font-size: 13px; padding: 12px; justify-content: flex-start; }

    .welcome-hero { flex-direction: column; text-align: center; padding-top: 8px; }
    .quick-actions { justify-content: center; }
    .dashboard-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .discover-tiles { grid-template-columns: 1fr; gap: 10px; }
    .discover-tile { height: 180px; }
    .stat-card { padding: 12px; }
    .stat-card .num { font-size: 20px; }

    .card { padding: 14px; border-radius: 6px; }

    /* Trasy: przystanki muszą być użyteczne na telefonie */
    .stop-row {
        grid-template-columns: 1fr;
        gap: 6px;
        background: #d3d3d3;
        padding: 8px;
        border-radius: 5px;
        margin-bottom: 10px;
    }
    .stop-row .remove-stop { width: 100%; }
    .stop-actions { width: 100%; }
    .stop-actions .stop-move, .stop-actions .remove-stop, .stop-actions .stop-map-btn {
        flex: 1;
        padding: 12px 8px;
        font-size: 15px;
        min-height: 44px;
    }

    .list-item { flex-direction: column; align-items: flex-start; gap: 6px; }
    .list-item .badge { align-self: flex-start; }

    .btn-row { flex-direction: column; }
    .btn-row .btn, .btn-row button { width: 100%; text-align: center; }
    /* Wyjątek: przyciski akcji na kartach postów promocyjnych (Materiały) —
       na telefonie pełna szerokość
       zamieniała małe "pigułki" (Podgląd/Kopiuj/Grafika, potem Edytuj/Usuń)
       w wysokie, puste na oko belki, zwłaszcza przy przyciskach z samą
       ikonką. Zostają zwartym, zawijanym rzędem — tak jak .material-file-actions
       przy plikach do pobrania, ten sam wzorzec co tam. */
    .btn-row.materials-post-actions { flex-direction: row; flex-wrap: wrap; }
    .btn-row.materials-post-actions .btn, .btn-row.materials-post-actions button { width: auto; }
    /* .emoji-picker (zakładki kategorii + siatka emotek) leży fizycznie
       WEWNĄTRZ .comment-form-actions/.btn-row (patrz .comment-emoji-wrap
       wyżej w pliku), więc reguła ".btn-row button { width:100% }" tuż nad
       tą — myślana dla głównych przycisków akcji — bez tego wygrywała też
       na malutkich przyciskach zakładek kategorii w pikerze, rozciągając
       każdy do pełnej szerokości i spychając je jeden pod drugim zamiast w
       rządek (zakładki 😀🖐️🐾... każda na osobnym wierszu).
       Wyższa specyficzność (dwie klasy) wygrywa niezależnie od kolejności
       w pliku, więc same przyciski emotek (zakładki i siatka) wracają do
       naturalnej szerokości treści. */
    .btn-row .emoji-picker button { width: auto; text-align: inherit; }
    /* Ten sam problem co wyżej (przy .emoji-picker button), ale dotyczy
       samego PRZYCISKU-EMOTKI (uśmiechnięta buźka), który otwiera piker pod
       komentarzem — to mały, kwadratowy .icon-btn (28×28px), ale leży
       wewnątrz .btn-row razem z przyciskiem "Wyślij"/"Dodaj komentarz",
       więc ogólna reguła ".btn-row button { width:100% }" wygrywała nad
       .icon-btn (wyższa specyficzność: klasa+element kontra sama klasa) i
       rozciągała go na całą szerokość wiersza — zamiast małej kwadratowej
       ikonki wychodził szeroki, płaski "pasek" (zgłoszone jako "przycisk
       emotki wygląda dziwnie"). */
    .btn-row .icon-btn { width: 28px; flex-shrink: 0; }

    .calendar { gap: 3px; }
    .calendar .day { min-height: 46px; padding: 4px; font-size: 10px; }
    .calendar .day .evt { font-size: 8px; padding: 1px 5px; }
    .calendar-nav h2 { font-size: 13px; }
    .calendar-nav-title { gap: 6px; }
    .calendar-nav-today { font-size: 10px; padding: 3px 8px; }
    .calendar-nav-btn { width: 30px; height: 30px; }

    /* Na desktopie kafelki postów promocyjnych mają celowo ograniczoną,
       stałą szerokość (190-220px, patrz .materials-post-grid wyżej w pliku)
       — chodziło o to, żeby POJEDYNCZY post nie rozciągał się na całą
       szerokość karty. Na telefonie i tak wychodzi zwykle jeden kafelek w
       rzędzie (za wąsko na dwa), więc ten sam limit szerokości zostawiał
       kafelek węższy niż dostępne miejsce — widoczny, niewykorzystany pas
       pustego miejsca z boku (zgłoszone jako "powinien być dostosowany do
       szerokości"). Na mobile wracamy więc do pełnej szerokości. */
    .materials-post-grid { grid-template-columns: 1fr; }
    .gallery-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
    .gallery-grid img, .gallery-grid video { height: 100px; }

    .event-grid { grid-template-columns: 1fr; }

    /* Na telefonie lista grup (u góry) i sama rozmowa (nagłówek + wiadomości
       + pole do pisania) to dwa NIEZALEŻNE, osobno ograniczone obszary —
       każdy ma własną, stałą wysokość i własne przewijanie. Dzięki temu
       pole do pisania zawsze stoi w tym samym miejscu, tuż pod wiadomościami
       — nie trzeba przewijać setek wiadomości ani całej strony, żeby je
       zobaczyć, niezależnie od tego, ile osób/wiadomości jest w grupie.
       (Wcześniejsza wersja dawała stronie rosnąć w nieskończoność wraz
       z historią czatu — dobre dla kilku wiadomości, fatalne dla grupy
       ~100 osób z długą historią.) */
    .chat-layout { flex-direction: column; height: auto; max-height: none; overflow: visible; border-radius: 6px; }
    .chat-sidebar { width: 100%; max-height: 200px; border-right: none; border-bottom: 1px solid rgba(0,0,0,0.08); }
    .chat-main { height: 62vh; min-height: 400px; overflow: hidden; }
    .chat-messages { flex: 1; overflow-y: auto; max-height: none; }
    .chat-bubble { max-width: 88%; }
    .emoji-picker { left: 8px; right: 8px; width: auto; max-width: none; }
    /* Pod komentarzami (trasy/wydarzenia/ogłoszenia) okienko emotek musi na
       telefonie liczyć left/right od SZEROKIEGO wiersza przycisków
       (.comment-form-actions, patrz wyżej w pliku), nie od wąskiego,
       "owijającego się w rozmiar przycisku" .comment-emoji-wrap — inaczej
       left:8px/right:8px liczone od kilkudziesięciopikselowego przycisku
       dają w efekcie wąski, wysoki pasek zamiast czytelnej siatki emotek. */
    .comment-emoji-wrap { position: static; }

    /* Dwa „ekrany" jak w typowych komunikatorach: albo lista rozmów, albo
       otwarta rozmowa na całą dostępną wysokość — nigdy oba naraz, więc
       lista grup (mogąca urosnąć wraz z liczbą grup) nigdy nie ściska
       otwartej rozmowy. Przełącznikiem jest zwykły link (?group=... vs
       chat.php bez parametru) — działa bez JS, każdy stan ma swój URL. */
    .chat-layout--list .chat-main { display: none; }
    .chat-layout--list .chat-sidebar { max-height: none; }
    .chat-layout--conversation .chat-sidebar { display: none; }
    .chat-back-link {
        display: none;
        align-items: center;
        justify-content: center;
        width: 30px;
        height: 30px;
        margin-right: 2px;
        border-radius: 50%;
        color: #17140f;
        flex-shrink: 0;
    }
    .chat-layout--conversation .chat-back-link { display: inline-flex; }
    .chat-back-link:hover { background: rgba(0,0,0,0.06); }

    /* Otwarta rozmowa na telefonie = pełny ekran, jak w prawdziwym
       komunikatorze — nie kawałek strony pod headerem/bannerem serwisu.
       body.chat-fullscreen dodawane jest server-side w chat.php dokładnie
       wtedy, gdy pokazujemy konkretną, wybraną rozmowę (a nie listę grup).
       Reszta chrome strony (topbar, baner sekcji, stopka) chowa się na czas
       trwania rozmowy — wraca po kliknięciu "←" (zwykły link, nie JS). */
    body.chat-fullscreen .topbar,
    body.chat-fullscreen .section-banner,
    body.chat-fullscreen .site-footer {
        display: none;
    }
    body.chat-fullscreen .wrap { padding: 0; max-width: none; }
    /* Zabezpieczenie na wypadek, gdyby .chat-layout--conversation przez
       ułamek sekundy (np. w trakcie animacji otwierania klawiatury) było
       niższe niż realnie widoczny obszar — zamiast goły, ciemny motyw
       strony (czarne tło) prześwitujący spod spodu, widać ten sam jasny
       kolor co samo okno czatu (.chat-layout), więc nawet chwilowa
       nieszczelność nie rzuca się w oczy jako "coś się zepsuło". */
    body.chat-fullscreen { overflow: hidden; background: #f6f3ef; }
    .chat-layout--conversation {
        position: fixed;
        inset: 0;
        z-index: 200;
        /* Nadpisuje overflow:visible z ogólnej reguły .chat-layout na telefonie
           (potrzebne TAM dla widoku listy grup, żeby nic się nie ucinało przy
           height:auto) — tu, w widoku otwartej rozmowy, overflow musi być
           hidden, żeby żaden element (np. pole do pisania, gdyby przez
           chwilę nie zmieścił się w nowej, mniejszej wysokości po otwarciu
           klawiatury) nie mógł "wystawać" poza fizycznie widoczny ekran
           zamiast zostać ściśnięty/przewinięty w środku. */
        overflow: hidden;
        height: 100vh;
        /* 100vh na iOS Safari to wysokość "dużego" viewportu — licząc w to
           obszar zasłonięty przez (chowający się) pasek adresu/przyciski na
           dole. Efekt: pole do pisania wypadało pod paskiem przeglądarki i
           nie dało się do niego doscrollować (overflow:hidden na body).
           100dvh liczy realnie widoczny obszar (łącznie z otwartą klawiaturą
           na telefonie, patrz interactive-widget=resizes-content w meta
           "viewport", includes/layout.php) i nadpisuje wartość powyżej w
           przeglądarkach, które to wspierają — starsze po prostu ją
           zignorują i zostaną przy 100vh. Świadomie NIE liczymy tego już w
           JS przez window.visualViewport (patrz historia zmian w chat.js) —
           dvh jest natywne, aktualizowane przez przeglądarkę samo, bez
           ryzyka rozjazdu, na jakie trafialiśmy z ręcznym liczeniem. */
        height: 100dvh;
        max-height: none;
        border-radius: 0;
        border: none;
        box-shadow: none;
        padding-top: env(safe-area-inset-top);
        /* env(keyboard-inset-height) to część VirtualKeyboard API (Chrome/
           Android — patrz navigator.virtualKeyboard.overlaysContent w
           chat.js). Gdy ta API jest dostępna, WŁĄCZAMY overlaysContent, co
           oznacza, że przeglądarka PRZESTAJE w ogóle zmieniać dvh/viewport
           po otwarciu klawiatury (my musimy sami zarezerwować dla niej
           miejsce) — stąd zsumowane z safe-area-inset-bottom, nie zamiast
           niego. Na przeglądarkach bez tej API (iOS Safari, Firefox) ta
           zmienna po prostu liczy się jako 0px — bez zmiany zachowania,
           zostaje sam dvh + interactive-widget jak dotychczas. */
        padding-bottom: calc(env(safe-area-inset-bottom) + env(keyboard-inset-height, 0px));
    }
    .chat-layout--conversation .chat-main { height: auto; flex: 1; min-height: 0; }

    input, textarea, select, button, .btn { font-size: 16px; } /* blokuje auto-zoom na iOS */
}

@media (max-width: 420px) {
    .dashboard-grid { grid-template-columns: 1fr; }
    .gallery-grid { grid-template-columns: repeat(2, 1fr); }
    .event-grid { grid-template-columns: 1fr; }
}

/* --- Blokujący komunikat od moderatora/admina (patrz includes/layout.php,
   pending_system_notice_for + notice_ack.php) — celowo bez przycisku
   zamknięcia w rogu ani zamykania kliknięciem w tło, jedyne wyjście to
   "Rozumiem", żeby faktycznie liczyło się jako potwierdzenie odczytania. --- */
.notice-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.75);
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.notice-modal {
    background: #f6f3ef;
    border-radius: 10px;
    padding: 22px;
    max-width: 440px;
    width: 100%;
    box-shadow: 0 20px 60px rgba(0,0,0,0.4);
}
.notice-modal h3 { margin: 0 0 12px; font-size: 16px; color: #17140f; display: flex; align-items: center; gap: 8px; }
.notice-modal-text { font-size: 14px; color: #33302b; line-height: 1.5; margin-bottom: 18px; white-space: pre-line; }
.notice-modal form { margin: 0; }
.notice-modal button { width: 100%; }
