/* ============================================================================
 * G-DIGITAL SHELL — KANONICZNA POWŁOKA PANELI (logowanie + sidebar)
 *
 * ŹRÓDŁO PRAWDY: shared/src/ui/shell.css (ten plik).
 * Kopie rozwozi `infra/sync-shell.sh` do worker/public/ (Suite), siedmiu
 * paneli i panelu CMS. Zmieniasz TUTAJ, potem uruchamiasz skrypt.
 *
 * TOKENY `--gd-*` SĄ WSPÓLNE DLA POWŁOKI I OBSZARU ROBOCZEGO: `tokens.css`
 * kitu podnosi je do warstwy `@theme` Tailwinda, więc kolor pada w systemie
 * dokładnie raz — tutaj.
 *
 * IDENTYFIKACJA WIZUALNA = STRONA www.digitaldevelopment.pl (2026-08-01).
 * Przeniesione stamtąd 1:1: marka #2A47D1, Eurostile Bold + Mundial, skala
 * szarości (Tailwind `gray`, nie `slate`), promienie 10/12/16/24 px, miękkie
 * cienie o dużym rozmyciu i niskiej sile, brandowana poświata pod CTA,
 * przyciemnienie nakładek z `backdrop-filter: blur`.
 *
 * Wymagane assety w każdym serwisie: /fonts/{Eurostile-Bold,Mundial-Regular}
 * .woff2 + .otf, /img/sygnet.png, /img/logo-text.png, /favicon.webp
 * ========================================================================== */

/* WOFF2 przed OTF — te same kroje co na stronie, ale 45 kB zamiast 74 kB
   (Eurostile) i 68 kB zamiast 170 kB (Mundial). OTF zostaje jako zapas dla
   przeglądarek bez woff2 i dla starszych kopii powłoki. */
@font-face {
  font-family: 'Eurostile';
  src: url('/fonts/Eurostile-Bold.woff2') format('woff2'),
       url('/fonts/Eurostile-Bold.otf') format('opentype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Mundial';
  src: url('/fonts/Mundial-Regular.woff2') format('woff2'),
       url('/fonts/Mundial-Regular.otf') format('opentype');
  font-weight: 400;
  font-display: swap;
}

:root {
  /* --- MARKA -------------------------------------------------------------
     Kolor główny jest white-label: `applyPrimaryColor()` z brandingu
     instalacji nadpisuje w runtime paletę `--color-brand-*`. Te wartości to
     DOMYŚLNA marka Digital Development. */
  --gd-brand: #2A47D1;
  --gd-brand-hover: #243BB0;
  --gd-brand-tint: #EEF2FF;
  /* Pigułka „tagline" ze strony: bg brand/8 + ramka brand/15 */
  --gd-brand-soft: rgb(42 71 209 / 0.08);
  --gd-brand-soft-border: rgb(42 71 209 / 0.15);

  /* --- PALETA DANYCH (od 2026-08-10, KONCEPCJA-WIZUALNA.md §4.1) ----------
     OSIEM barw × TRZY role. Barwa odpowiada na pytanie „co to jest i czyje to
     jest" (lista zadań, etap lejka, linia biznesowa, dział, człowiek), a NIE
     „czy jest dobrze" — na to odpowiadają tony statusu (emerald/amber/rose)
     i dlatego zieleni trawiastej, bursztynu ani czerwieni TU NIE MA. Gdyby
     zielony mógł znaczyć „dział szkoleń", żaden zielony nie znaczyłby już
     „zapłacone".

     Role:
       `tint` — powierzchnia (pigułka, kwadrat ikony, płyta kolumny, nagłówek grupy)
       `line` — krawędź tej powierzchni; NIGDY samodzielny nośnik znaczenia
                (1,3–1,5:1 do bieli — to dekoracja, nie granica kontrolki)
       `ink`  — tekst i ikona na `tint` albo na bieli; ≥4,5:1 w obu wypadkach
                (policzone w infra/check-contrast.mjs, nie „na oko")

     `ink` NIE IDZIE NA WYPEŁNIENIE PRZYCISKU. CTA jest jedno i jest w barwie
     marki; kolorowy przycisk mówiłby „ta akcja jest inna", a jest taka sama.

     Osiem, bo dziewiąta barwa przestaje być rozróżnialna od którejś z ośmiu,
     a dwie nierozróżnialne barwy są gorsze niż jedna. */
  --gd-hue-brand-tint: #EEF2FF;   --gd-hue-brand-line: #C3CFF6;   --gd-hue-brand-ink: #243BB0;
  --gd-hue-violet-tint: #F5F1FF;  --gd-hue-violet-line: #D7CBFB;  --gd-hue-violet-ink: #6D28D9;
  --gd-hue-magenta-tint: #FDF0FB; --gd-hue-magenta-line: #F2C2E9; --gd-hue-magenta-ink: #A21CAF;
  --gd-hue-cyan-tint: #ECFAFF;    --gd-hue-cyan-line: #B6E7F8;    --gd-hue-cyan-ink: #0369A1;
  --gd-hue-teal-tint: #EAFBF6;    --gd-hue-teal-line: #A8E6D5;    --gd-hue-teal-ink: #0F766E;
  --gd-hue-orange-tint: #FFF4EC;  --gd-hue-orange-line: #FBD3B4;  --gd-hue-orange-ink: #C2410C;
  --gd-hue-olive-tint: #F5F8E8;   --gd-hue-olive-line: #D3E2A4;   --gd-hue-olive-ink: #4D7C0F;
  --gd-hue-grafit-tint: #F2F4F7;  --gd-hue-grafit-line: #D3D9E2;  --gd-hue-grafit-ink: #3F4A5A;

  /* --- POWIERZCHNIE I TEKST ---------------------------------------------
     Skala szarości ze strony (Tailwind `gray`). Poprzednio panele stały na
     `slate` — chłodniejszym, lekko niebieskawym; obok marki #2A47D1 dawało
     to wrażenie drugiego, konkurencyjnego błękitu. */
  /* PŁÓTNO Z TINTĄ MARKI (od 2026-08-10). Było `#F9FAFB` (gray-50 ze strony),
     przy którym separacja karta/tło wynosi 1,045:1 — poniżej progu, na którym
     oko widzi krawędź bez pomocy ramki. Stąd wrażenie „wszystko jest jedną
     płaszczyzną z liniami". `#F4F6FC` daje 1,081:1 i jest NAJMOCNIEJSZĄ
     wartością, która jeszcze przechodzi bramkę kontrastu: `--gd-muted` 4,67
     (próg 4,5), `--gd-border-strong` 3,06 (próg 1.4.11 = 3,0). Ciemniejsze
     `#F2F4FB` zostawia zero zapasu — odrzucone świadomie. */
  --gd-bg: #F4F6FC;
  --gd-card: #ffffff;
  /* TRZECI POZIOM: wgłębienie (tor paska postępu, płyta kolumny bez barwy
     etapu, pole tylko do odczytu, szkielet ładowania). Do 2026-08-10 rolę tę
     grał `gray-100` (#F3F4F6), który na nowym płótnie ma 1,018:1 — czyli
     ZNIKA. Zamiana 105 miejsc jest częścią tej zmiany, nie jej następstwem. */
  --gd-sunken: #EDF0F8;
  --gd-text: #111827;        /* gray-900 — nagłówki */
  --gd-text-2: #374151;      /* gray-700 — tekst podstawowy */
  /* Strona ma tu gray-500 (#6B7280). Ściemniany DWUKROTNIE, oba razy z powodu
     progu AA, nie gustu:
       2026-08-01 → #64707E, bo gray-500 na gray-100 dawało 4,39:1;
       2026-08-10 → #606C7A, bo #64707E na nowym wgłębieniu (#EDF0F8) dawało
                    4,43:1 — a wgłębienie jest tłem pola tylko-do-odczytu
                    i podsumowania kolumny kanbana, czyli TEKSTU.
     Teraz: 5,35 na bieli / 4,95 na płótnie / 4,70 na wgłębieniu / 4,79 na
     tincie marki. Wartości pilnuje `infra/check-contrast.mjs`. */
  --gd-muted: #606C7A;
  --gd-border: #E5E7EB;      /* gray-200 — krawędź karty (element dekoracyjny) */
  --gd-border-soft: #F3F4F6; /* gray-100 — podział wewnątrz karty */
  /* Ramka POLA i przycisku wtórnego. Strona używa tu gray-300 (#D1D5DB), ale
     to 1,47:1 — WCAG 1.4.11 wymaga 3:1 dla granicy elementu interfejsu, bo bez
     niej pole nie jest rozpoznawalne przy słabym wzroku i na ekranie w słońcu.
     Ta wartość daje 3,30 na bieli i 3,16 na tle strony. To ŚWIADOME odstępstwo
     od www — jedyne w całej palecie. */
  --gd-border-strong: #868E9B;
  --gd-err: #DC2626;

  /* --- TYPOGRAFIA -------------------------------------------------------- */
  --gd-font: 'Mundial', -apple-system, 'Segoe UI', sans-serif;
  --gd-font-heading: 'Eurostile', 'Mundial', sans-serif;

  /* --- PROMIENIE ---------------------------------------------------------
     Ze strony: pole 10 px, przycisk 12 px, karta 16 px, duża karta 24 px. */
  --gd-radius-field: 10px;
  --gd-radius-control: 12px;
  --gd-radius-surface: 16px;
  --gd-radius-card: 24px;

  /* --- CIENIE: WYSOKOŚĆ, NIE OZDOBA (przebudowane 2026-08-10) -------------
     Cztery poziomy kodujące odległość od płótna. Element zmienia poziom TYLKO
     razem ze zmianą stanu (spoczynek → kursor → przeciąganie); trzy karty obok
     siebie na trzech poziomach to nie hierarchia, to niedbalstwo.

     Rozmycie dostaje GRANAT (23 33 79), nie czerń — czarny cień na tintowanym
     płótnie brudzi, granatowy pogłębia. Poprzednia wartość `raised` miała
     jedną warstwę o sile 4%: karta dostawała obwódkę zamiast wysokości.
     Dwie warstwy (styk + rzut) są tym, co odróżnia „unosi się" od „leży". */
  --gd-shadow-raised: 0 1px 2px rgb(23 33 79 / 0.04), 0 6px 16px -6px rgb(23 33 79 / 0.10);
  --gd-shadow-lifted: 0 2px 4px rgb(23 33 79 / 0.05), 0 12px 28px -8px rgb(23 33 79 / 0.16);
  --gd-shadow-overlay: 0 4px 8px -2px rgb(23 33 79 / 0.06), 0 18px 40px -12px rgb(23 33 79 / 0.22);
  --gd-shadow-modal: 0 24px 60px rgb(17 24 39 / 0.18), 0 8px 20px rgb(17 24 39 / 0.06);
  --gd-shadow-brand: 0 8px 30px rgb(42 71 209 / 0.25);

  /* --- GRADIENT: WYŁĄCZNIE POWIERZCHNIA-BOHATER ---------------------------
     Wolno na: ekranie logowania, `KPISpotlight`, karcie powitalnej, pustym
     stanie „zacznij tutaj". ZAKAZ pod tabelą, pod formularzem, na belce widoku
     i na sidebarze — gradient pod treścią do czytania to najkrótsza droga od
     „żywo" do „tanio". Jeden token, żeby nie powstało osiem kątów i ośmiu
     zestawów przystanków. */
  --gd-grad-brand: linear-gradient(135deg, #243BB0 0%, #3D5CDA 55%, #4C6BE0 100%);

  /* --- CZASY RUCHU -------------------------------------------------------
     Cztery reguły ruchu (KONCEPCJA-WIZUALNA.md §4.6) mają TRZY czasy, nie
     dwanaście: 120 ms na reakcję pod kursorem, 180 ms na zmianę stanu,
     260 ms na potwierdzenie (błysk zapisu, dojeżdżający licznik, arkusz).
     `prefers-reduced-motion` wyłącza je w `tokens.css`. */
  --gd-dur-fast: 120ms;
  --gd-dur: 180ms;
  --gd-dur-slow: 260ms;
  /* Krzywa ze strony (`modalIn .2s ease-out` → wypłaszczona na końcu). Musi
     być TUTAJ, nie tylko w `@theme` kitu: Suite nie ma Tailwinda, więc
     `var(--ease-gd)` byłoby tam puste i ruch szedłby liniowo. */
  --gd-ease: cubic-bezier(0.2, 0, 0.13, 1);

  /* --- WYSOKOŚĆ DOLNEJ NAWIGACJI (od 2026-08-10) --------------------------
     Na biurku 0 px (nawigacja jest z boku). Na telefonie realna wysokość
     paska razem z pasem gestu iPhone'a. Wystawione jako zmienna, bo czyta ją
     `gd-shell` Z INNEGO DRZEWA (Shadow DOM), żeby postawić swoje kółko NAD
     paskiem, a nie na nim. Bez tej zmiennej powłoka musiałaby zgadywać
     wysokość cudzego elementu — i rozjechałaby się przy pierwszej zmianie. */
  --gd-navbar-h: 0px;
}

/* Identyczne wygładzanie glifów wszędzie — Tailwind (panele) używa
   antialiased, czysty CSS (Suite) domyślnie subpixel; różnica wygląda
   jak "inna czcionka" mimo tych samych plików. */
.gd-login-screen, .gd-sidebar {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ---------- EKRAN LOGOWANIA (identyczny; różni się tylko nazwą serwisu) --- */
/* `100dvh`, nie `100vh`: na iOS `100vh` liczy się z UKRYTYM paskiem adresu,
   więc karta logowania była na telefonie zepchnięta o ~60 px poniżej ekranu
   i przycisk Google trzeba było doprzewijać. Zapas dla starszych przeglądarek
   zostaje w pierwszej deklaracji — nieznaną jednostkę silnik po prostu pomija. */
.gd-login-screen { min-height: 100vh; min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  background: var(--gd-bg); position: relative; overflow: hidden; font-family: var(--gd-font); }
/* Rozmyte plamy marki w tle — ten sam zabieg co w hero strony
   (`bg-brand-blue/15 rounded-full blur-[100px]`). */
.gd-login-screen::before { content: ''; position: absolute; top: -160px; right: -160px; width: 600px; height: 600px;
  background: rgba(42,71,209,.10); border-radius: 50%; filter: blur(64px); pointer-events: none; }
.gd-login-screen::after { content: ''; position: absolute; bottom: -160px; left: -160px; width: 500px; height: 500px;
  background: rgba(42,71,209,.05); border-radius: 50%; filter: blur(64px); pointer-events: none; }
.gd-login-card { background: var(--gd-card); border: 1px solid var(--gd-border);
  border-radius: var(--gd-radius-card);
  padding: 48px; text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center;
  width: 100%; max-width: 420px; box-shadow: 0 10px 40px rgba(42,71,209,.12); position: relative; z-index: 1; }
.gd-login-lockup { display: flex; align-items: center; justify-content: center; gap: 12px; }
/* logo instalacji white-label (zastępuje lockup po wgraniu w panelu) —
   ten sam gabaryt co lockup, żeby karta nie zmieniała geometrii */
.gd-login-logo { max-width: 210px; max-height: 40px; object-fit: contain; }
.gd-login-lockup-signet { width: 36px; height: 36px; object-fit: contain; }
.gd-login-lockup-text { width: 122px; object-fit: contain; }
/* Nagłówki na stronie są ZAWSZE Eurostile Bold z ciasną interlinią. */
.gd-login-title { font-family: var(--gd-font-heading); font-size: 26px; letter-spacing: .01em;
  color: var(--gd-text); margin: 0; line-height: 32px; font-weight: 700; }
.gd-login-sub { font-size: 14px; color: var(--gd-muted); margin: 0; line-height: 20px; }
.gd-login-error { font-size: 14px; color: var(--gd-err); margin: 0; }

/* ---------- SIDEBAR (identyczny; różnią się tylko pozycje menu) ----------- */
/* UKRYCIE SIDEBARA ATRYBUTEM `hidden`, NIE KLASĄ `hidden` Tailwinda.
   Reguły tego pliku są POZA warstwami kaskady, a utilities Tailwinda siedzą
   w `@layer utilities` — reguła bezwarstwowa bije warstwową NIEZALEŻNIE od
   swoistości i kolejności (ta sama pułapka, co `.hr-input` vs `pl-9`
   w CLAUDE.md). `display: flex` z `.gd-sidebar` wygrywało więc z `.hidden`
   i w widoku zagłębionym czatu lista rozmów zostawała obok rozmowy,
   wypychając ją poza ekran. Natywny atrybut `hidden` (React: `hidden={bool}`)
   działa w tej samej warstwie co reszta pliku, więc kolizji nie ma. */
.gd-sidebar[hidden] { display: none; }
.gd-sidebar { width: 256px; flex-shrink: 0; background: var(--gd-card); color: var(--gd-text-2);
  border-right: 1px solid var(--gd-border); display: flex; flex-direction: column;
  font-family: var(--gd-font); }
.gd-sidebar-head { display: flex; align-items: center; gap: 12px; padding: 22px 20px;
  border-bottom: 1px solid var(--gd-border-soft); }
.gd-sidebar-signet { width: 34px; height: 34px; object-fit: contain; flex-shrink: 0; }
/* line-height PRZYPIĘTE jawnie — Tailwind (panele) narzuca globalnie 1.5,
   czysty CSS (Suite) ~1.2; bez tego odstęp nazwa→domena różni się per serwis
   i nagłówek "skacze" przy przełączaniu kart */
.gd-sidebar-brand { font-family: var(--gd-font-heading); color: var(--gd-text); font-size: 15px;
  letter-spacing: .02em; line-height: 20px; font-weight: 700; }
.gd-sidebar-domain { font-size: 11px; color: var(--gd-muted); margin-top: 2px; line-height: 14px; }
.gd-sidebar-nav { flex: 1; padding: 14px 12px; overflow-y: auto; }
/* Nagłówek sekcji menu = „tagline" ze strony: wersaliki, szeroki trakt. */
.gd-nav-section-title { font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .2em; color: var(--gd-muted); padding: 0 12px 8px; }
.gd-nav-item { display: flex; align-items: center; gap: 11px; width: 100%; padding: 10px 12px;
  border: none; background: none; border-radius: var(--gd-radius-control); font-size: 14px;
  font-family: inherit; color: var(--gd-text-2); cursor: pointer; transition: all .15s; text-align: left;
  text-decoration: none; }
.gd-nav-item:hover { background: var(--gd-border-soft); color: var(--gd-text); }
.gd-nav-item.active { background: var(--gd-brand-tint); color: var(--gd-brand); font-weight: 600; }
.gd-sidebar-foot { border-top: 1px solid var(--gd-border-soft); padding: 14px 20px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.gd-sidebar-user { font-size: 12px; color: var(--gd-muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.gd-sidebar-logout { background: none; border: none; color: var(--gd-err); font-size: 12px;
  cursor: pointer; font-family: inherit; padding: 6px 10px; border-radius: 8px; flex-shrink: 0; }
.gd-sidebar-logout:hover { background: rgba(239,68,68,.1); }

/* ============================================================================
 * TELEFON — SIDEBAR STAJE SIĘ DOLNYM PASKIEM NAWIGACJI
 *
 * DLACZEGO W OGÓLE: do 2026-08-03 w całej powłoce nie było ANI JEDNEJ reguły
 * `@media`. Panel na telefonie zaczynał się od 256-pikselowego sidebara, więc
 * na ekranie 375 px zostawało 119 px na treść. Nie „wyglądało źle" — było
 * nieużywalne, a to jest jedna z rzeczy blokujących zejście z e-BRM, który
 * jest PWA z dolną nawigacją.
 *
 * DLACZEGO DOLNY PASEK, A NIE SZUFLADA Z HAMBURGEREM: szuflada wymaga
 * przycisku, stanu i obsługi zamykania — czyli zmiany w ośmiu panelach naraz,
 * z których każdy mógłby to zrobić inaczej. Dolny pasek jest CZYSTYM CSS na
 * TYM SAMYM znaczniku, więc wchodzi wszędzie jednocześnie i nie może się
 * rozjechać. Kciuk sięga tam najłatwiej — z tego samego powodu miał to e-BRM.
 *
 * NA CZYM TO STOI: `.gd-sidebar` i `<main>` są RODZEŃSTWEM w każdym panelu
 * (`<nav class="gd-sidebar">` + `<main>`; wiki ma `<aside>`). Dzięki temu
 * `~ main` dokłada treści miejsce pod pasek bez dotykania kodu paneli.
 * Zmiana tej struktury w którymkolwiek panelu urwie odstęp na dole — wtedy
 * ostatni wiersz listy chowa się pod nawigacją.
 * ========================================================================== */
@media (max-width: 767px) {
  /* 66 px = DOKŁADNIE ta sama liczba, co rezerwa `padding-bottom` w `main`
     niżej. Jedna stała na wysokość paska: gdyby kółko powłoki liczyło się
     z innej wartości niż odstęp treści, przy każdej zmianie gęstości menu
     rozjeżdżałyby się w przeciwne strony. */
  :root { --gd-navbar-h: calc(66px + env(safe-area-inset-bottom, 0px)); }

  .gd-sidebar {
    position: fixed;
    inset: auto 0 0 0;
    width: auto;
    flex-direction: row;
    align-items: stretch;
    border-right: none;
    border-top: 1px solid var(--gd-border);
    /* nad treścią, pod modalami (te startują od 50 w kicie) */
    z-index: 40;
    /* pasek gestu na iPhonie — bez tego ostatni rząd ikon leży pod nim */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-shadow: 0 -4px 20px rgb(17 24 39 / 0.06);
  }

  /* Nazwa serwisu, konto i rola zabierają na telefonie miejsce, które należy
     się nawigacji, a nie niosą informacji potrzebnej w trakcie pracy.
     Rola (`gd-sidebar-domain`) występuje w DWÓCH miejscach — w nagłówku
     i w stopce — więc w stopce trzeba ją zdjąć osobno; sam nagłówek już nie
     wystarcza. Bez tego „Administrator" wypycha połowę pozycji menu poza ekran. */
  .gd-sidebar-head,
  .gd-nav-section-title,
  .gd-sidebar-user,
  .gd-sidebar-foot .gd-sidebar-domain { display: none; }

  .gd-sidebar-nav {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 2px;
    padding: 6px 8px;
    overflow-x: auto;
    /* pozycje mieszczą się w kciuku, a nadmiar przewija się poziomo bez paska */
    scrollbar-width: none;
    /* Gdy pozycji jest MAŁO (3–5, czyli docelowy stan po fazie 4), mieszczą się
       w szerokości paska i bez tego skleiłyby się przy lewej krawędzi, zostawiając
       połowę ekranu pustą. `space-evenly` rozkłada je równo, a przy nadmiarze
       nie robi nic — kontener jest wtedy węższy od treści i przewijanie wraca. */
    justify-content: space-evenly;
    /* Przewijanie palcem po pasku nie ma „ciągnąć" strony pod spodem. */
    overscroll-behavior-x: contain;
  }
  .gd-sidebar-nav::-webkit-scrollbar { display: none; }

  .gd-nav-item {
    flex-direction: column;
    gap: 3px;
    padding: 6px 10px;
    /* 44 px to minimalny cel dotykowy (WCAG 2.5.5); przy 40 px trafia się
       w sąsiednią pozycję, a to w nawigacji znaczy „otworzyłem nie ten ekran" */
    min-width: 60px;
    min-height: 44px;
    justify-content: center;
    font-size: 10px;
    line-height: 12px;
    text-align: center;
    white-space: nowrap;
    /* Bazowe `width: 100%` w rzędzie flex rozwiązuje się do szerokości CAŁEGO
       paska, więc pięć pozycji chciało 5 × 375 px i kurczyło się dopiero
       shrinkiem — do 80 px każda, czyli 424 px razem w pasku szerokim na 375.
       Pozycje wyjeżdżały za krawędź mimo tego, że jest ich mało.
       `flex: 1 0 auto` odwraca to: przy KILKU pozycjach rosną równo i wypełniają
       pasek, przy WIELU (Suite ma dziewięć) nie kurczą się poniżej treści
       i pasek wraca do przewijania w poziomie — czyli tam, gdzie ma być. */
    width: auto;
    flex: 1 0 auto;
  }
  .gd-nav-item.active { font-weight: 700; }

  /* STOPKA SIDEBARA NA TELEFONIE — dwa stany, świadomie.
     Domyślnie zostaje jako wąski element na końcu paska: dopóki panel nie ma
     pozycji „Więcej", to JEDYNA droga do wylogowania i schowanie jej zamknęłoby
     człowieka w panelu. Ma wtedy pełny cel dotykowy, bo leży tuż obok pozycji
     menu i chybienie znaczy „wyleciałem z panelu".
     Panel, który ma już arkusz „Więcej" (konto + wylogowanie w środku),
     deklaruje `data-mobile-more` na `.gd-sidebar` — wtedy stopka znika z paska
     i oddaje miejsce nawigacji. Akcja niszcząca nie ma prawa być stałą szóstą
     zakładką w zasięgu kciuka (KONCEPCJA-MOBILE.md §5.4). */
  .gd-sidebar-foot {
    border-top: none;
    border-left: 1px solid var(--gd-border-soft);
    padding: 6px 8px;
    flex-shrink: 0;
    align-items: center;
  }
  .gd-sidebar-logout {
    min-width: 44px; min-height: 44px;
    display: grid; place-items: center;
    font-size: 10px; line-height: 12px; text-align: center; padding: 6px 4px;
  }
  .gd-sidebar[data-mobile-more] .gd-sidebar-foot { display: none; }

  /* ── POZYCJE MENU W ARKUSZU „WIĘCEJ" ────────────────────────────────────
     Arkusz dostaje te same elementy `.gd-nav-item`, co pasek, ale ma je
     pokazać jako WIERSZE LISTY: ikona po lewej, etykieta obok, pełna
     szerokość, 52 px wysokości.

     Reguła stoi TUTAJ, a nie w klasach Tailwinda po stronie kitu, bo
     `.gd-nav-item` w tym pliku jest POZA warstwami kaskady i bije każdą
     regułę z `@layer utilities` — niezależnie od swoistości i kolejności.
     Wariant `[&_.gd-nav-item]:flex-row` po prostu przegrywał, a pozycje
     zostawały wyśrodkowanymi kolumienkami jak w pasku. To ta sama pułapka,
     co `.hr-input` vs `pl-9` (CLAUDE.md) i `.gd-sidebar` vs `.hidden`. */
  [data-mobile-more-sheet] .gd-nav-item {
    flex-direction: row;
    width: 100%;
    min-height: 52px;
    justify-content: flex-start;
    gap: 12px;
    padding: 10px 4px;
    font-size: 15px;
    line-height: normal;
    text-align: left;
    border-radius: 0;
    border-bottom: 1px solid var(--gd-border-soft);
  }
  [data-mobile-more-sheet] .gd-nav-item:last-child { border-bottom: none; }
  [data-mobile-more-sheet] .gd-nav-section-title { display: block; padding: 14px 4px 6px; }

  /* Treść musi kończyć się NAD paskiem. Wysokość paska (58 px) plus zapas —
     bez tego ostatni wiersz listy jest zasłonięty i wygląda na ucięty. */
  .gd-sidebar ~ main { padding-bottom: calc(66px + env(safe-area-inset-bottom, 0px)); }

  /* WIDOK ZAGŁĘBIONY (rozmowa czatu, karta kontaktu, dokument wiki): pasek
     nawigacji znika, bo wyjściem jest strzałka wstecz, a dolna krawędź należy
     się polu wprowadzania albo akcji głównej. Panel dodaje klasę na `<html>`
     — nie na `#root`, bo `.gd-sidebar` bywa jego RODZEŃSTWEM (chat), a nie
     potomkiem, i selektor potomka by go nie dosięgnął. */
  html.gd-nav-hidden .gd-sidebar:not([data-mobile-panel]) { display: none; }
  html.gd-nav-hidden .gd-sidebar ~ main { padding-bottom: 0; }
  /* Kółko powłoki musi zjechać razem z paskiem — inaczej wisi w połowie
     ekranu nad polem wprowadzania czatu. */
  html.gd-nav-hidden { --gd-navbar-h: 0px; }

  /* Karta logowania: 48 px marginesu wewnętrznego zostawiało na 375 px
     ekranie 279 px na treść, więc przycisk Google się nie mieścił. */
  .gd-login-card { padding: 28px 20px; border-radius: var(--gd-radius-surface); }
  .gd-login-title { font-size: 22px; line-height: 28px; }

  /* Pola formularza pod klawiaturą: bez zapasu przewijania pole, w które
     właśnie wszedł fokus, ląduje dokładnie przy górnej krawędzi klawiatury
     i nie widać ani etykiety, ani komunikatu błędu nad nim. */
  input, textarea, select { scroll-margin-block: 96px; }

  /* ── WYJĄTEK: SIDEBAR, KTÓRY NIE JEST NAWIGACJĄ ────────────────────────
     Czat trzyma w `.gd-sidebar` LISTĘ ROZMÓW, a nie pozycje menu. Zwinięta
     w poziomy pasek na dole byłaby rzędem nazw kanałów bez ikon i bez
     kolejności — czymś, czego nikt nie zaprojektował. Ten panel prowadzi
     własny układ (lista pełnoekranowa → rozmowa) i deklaruje to atrybutem.

     DLACZEGO ODWRACAMY REGUŁY, A NIE DOPISUJEMY `:not()` DO KAŻDEGO SELEKTORA
     WYŻEJ: `:not()` przy dwunastu selektorach to dwanaście miejsc, w których
     da się zapomnieć. Jeden blok cofający jest kompletny z definicji i widać
     w nim dokładnie, co wyjątek zmienia. */
  .gd-sidebar[data-mobile-panel] {
    position: static;
    inset: auto;
    width: auto;
    flex: 0 0 auto;
    flex-direction: column;
    border-top: none;
    border-right: 1px solid var(--gd-border);
    z-index: auto;
    padding-bottom: 0;
    box-shadow: none;
  }
  .gd-sidebar[data-mobile-panel] .gd-sidebar-nav {
    flex-direction: column;
    align-items: stretch;
    overflow-x: hidden;
    overflow-y: auto;
    justify-content: flex-start;
    gap: 0;
    padding: 14px 12px;
  }
  .gd-sidebar[data-mobile-panel] .gd-nav-section-title { display: block; }
  .gd-sidebar[data-mobile-panel] .gd-nav-item {
    flex-direction: row;
    width: 100%;
    flex: 0 0 auto;
    justify-content: flex-start;
    font-size: 14px;
    line-height: normal;
    text-align: left;
    padding: 10px 12px;
  }
  .gd-sidebar[data-mobile-panel] ~ main { padding-bottom: 0; }

  /* WIDOK KORZENIOWY panelu z własnym układem: lista zajmuje CAŁY ekran.
     Osobny atrybut, a nie klasa `w-full` po stronie panelu — selektor
     `.gd-sidebar[data-mobile-panel]` wyżej ma swoistość (0,2,0) i bije każdą
     pojedynczą klasę Tailwinda (0,1,0). Panel dostawał wtedy sidebar 256 px
     i pół ekranu pustego tła; zmiana klasy w module NIE POMAGAŁA i wyglądało
     to na błąd panelu, a nie na kolizję z powłoką. */
  .gd-sidebar[data-mobile-panel][data-fullscreen] { width: 100%; flex: 1 1 auto; }
  /* Panel z własnym układem NIE MA dolnego paska, więc nie ma nad czym unosić
     kółka powłoki. `:has()` jest tu jedynym sposobem, żeby powiedzieć o tym
     zmiennej na `:root` — a `gd-shell` czyta ją z zupełnie innego drzewa
     (Shadow DOM) i nie ma jak sprawdzić, co panel narysował u siebie. */
  :root:has(.gd-sidebar[data-mobile-panel]) { --gd-navbar-h: 0px; }
