:root {
  --pg-dark:#1E2749; --pg-blue:#2F5CA8; --pg-green:#92C35D;
  --pg-orange:#E99556; --pg-gray:#CBCDCD;
  /* Červená rodina (5.11.3). Appka ji jako token neměla, a tak si
     každý modul vypsal vlastní odstín — audit jich napočítal sedm
     (var(--pg-red), var(--pg-red), var(--pg-red), var(--pg-red), var(--pg-red), var(--pg-red), var(--pg-red)).
     Teď je jedna a má i tmavou variantu. */
  --pg-red:#A32D2D; --pg-red-light:#FCEBEB; --pg-red-border:#F09595;
  --pg-red-text:#791F1F;
  --pg-green-light:#f0f8e8; --pg-green-dark:#3B6D11;
  --pg-green-border:#c0dd97; --pg-blue-light:#e6f1fb;
  /* Text NA světle modrém podkladu (5.33.1). --pg-blue-light se
     v tmavém motivu překlápí, --pg-blue ne (slouží zároveň jako
     POZADÍ pod bílým textem u desítek tlačítek, takže se překlopit
     nesmí). Dvojice --pg-blue-light / --pg-blue-text se proto
     překlápí SPOLEČNĚ — přesně jak žádá pravidlo o překlápěcích
     tokenech. Bez ní měla aktivní položka menu v Grafitu 2,58:1. */
  --pg-blue-text:#2F5CA8;

  --bg-primary:#ffffff; --bg-secondary:#E8EDF5; --bg-card:#ffffff;
  --bg-input:#ffffff; --bg-hover:#dde4f0;
  /* Horní lišta (5.11.3). Byla světle zelená se zeleným podtržením,
     zatímco menu je navy a obsah bílý — tři různé světy nad sebou.
     Nově je téměř bílá s navy linkou, jak to má vzhled Kompas. */
  /* Horní lišta: SVĚTLE MODROŠEDÁ, ne skoro bílá (5.14.3). Bílá totiž
     splývala s rámem okna Electronu, který je taky bílý — lišta appky
     a lišta okna se slily v jeden pruh. Přesně proto tu dřív byl ten
     zelený pruh. Tón je krok pod plochou stránky, takže se odliší
     nahoru od okna i dolů od obsahu. */
  --topbar-bg:#E4EAF4; --topbar-bd:#1E2749; --pill-bg:#FFFFFF; --pill-bd:#C7D1E2;
  /* Plný kontrast (5.15.4, volba uživatele z pěti návrhů): čerň jako
     tisk. Dřívější modrošedé (#1E2749/#3f4866/#5e677c) byly na 1080p
     monitorech slabé a špatně čitelné. Tmavý motiv se nemění. */
  --text-primary:#000000; --text-secondary:#1C1C1C; --text-muted:#3D3D3D;
  /* Linka karet a polí. POZOR na zjemňování: v 5.11.1 jsem ji zesvětlil
     na #DDE3EE (kontrast na bílé kartě spadl z 1,87 na 1,29) a appka
     začala působit „jako za fólií" — karty ztratily obrys a splynuly
     s podkladem, protože je od plochy neodděluje nic jiného (bílá karta
     vs. plocha je jen 1,1). Uživatel si toho všiml hned. */
  /* --border-color = DEKORACE (linka karty, oddělovač řádků tabulky),
     --border-input = OBRYS OVLÁDACÍHO PRVKU (pole, select, ghost
     tlačítko). Rozdíl je záměrný: na dekoraci norma kontrast
     nepředepisuje, na obrys prvku ano — WCAG 1.4.11 chce 3:1 proti
     sousednímu pozadí. #96AABC dávalo 2,39:1 na bílém poli a 2,04:1
     na ploše stránky; #6E8296 dává 3,96 / 3,37 / 3,10 (bílá /
     --bg-secondary / --bg-hover). Nezesvětlovat zpátky. */
  --border-color:#B0BFD0; --border-input:#6E8296;
  --prstenec:#2F5CA8;    /* obrys při ovládání klávesnicí */
  --posuvnik:#B6C0D4;    /* táhlo posuvníku */
  --posuvnik-hover:#93A0BA;
  /* ── ŠKÁLY (5.10.2) ────────────────────────────────────────────────
     Před nimi měla appka 27 velikostí písma (pět z nich půlbodových),
     22 zaoblení a přes 60 receptů na stín v pěti barvách — každá nová
     obrazovka si prostě vymyslela vlastní hodnotu. Tohle je ten pevný
     seznam, ze kterého se od teď vybírá.
     Pozor na --fs-pole: 16 px není libovůle, pod ní iOS při kliknutí
     do pole zazoomuje celou stránku. */
  --fs-drobne:10px;    /* časy, mikroštítky */
  --fs-popisek:11px;   /* velkopísmenné popisky nad poli */
  --fs-vedlejsi:13px;  /* doplňkový text, buňky tabulek, tlačítka */
  --fs-telo:15px;      /* základní text appky */
  --fs-pole:16px;      /* formulářová pole — pod 16 px iOS zoomuje */
  --fs-karta:17px;     /* nadpis karty */
  --fs-sekce:22px;     /* nadpis sekce */
  --fs-nadpis:32px;    /* nadpis stránky, velká čísla */

  --lh-tesne:1.25;     /* nadpisy */
  --lh-ui:1.4;         /* ovládací prvky, řádky seznamů */
  --lh-text:1.6;       /* odstavce */
  --ls-popisek:.06em;  /* prostrkání verzálkových popisků */
  --ls-nadpis:.02em;

  --r-xs:4px;          /* mikroštítky */
  --r-sm:8px;          /* tlačítka, pole */
  --r-md:12px;         /* karty, řádky, panely */
  --r-lg:16px;         /* okna a velké dlaždice */
  --r-pilulka:999px;   /* pilulky a odznaky */

  --stin-1:0 1px 3px rgba(30,39,73,.06);    /* leží na ploše */
  --stin-2:0 2px 8px rgba(30,39,73,.08);    /* lišty, sticky prvky */
  --stin-3:0 8px 20px rgba(30,39,73,.12);   /* zvednuté karty, panely */
  --stin-4:0 20px 48px rgba(30,39,73,.24);  /* okna a šuplíky */

  --font-heading:'Raleway','Segoe UI',sans-serif;
  --font-body:'Mulish','Segoe UI',system-ui,sans-serif;

  /* ── Stavy zakázky ─────────────────────────────────────────────────
     LOGIKA PALETY (drž ji, jinak se barvy zase rozejdou s významem):
       · SYTÝ odznak se světlým textem  = HOTOVO, čeká se na fakturu
       · SVĚTLÝ odznak s tmavým textem  = práce právě PROBÍHÁ
       · barevná rodina = produkt: ZSP modrá, GP zelená, GAD fialová,
         terén teple/chladně (Vytyčeno oranžová, Zaměřeno mátová)
     Na každý stav trojice proměnných:
       --b-X    pozadí odznaku
       --b-X-t  barva textu odznaku (kontrast vůči pozadí vždy ≥ 4,5:1)
       --b-X-c  proužek řádku v seznamu a tečka v časové ose detailu
                (sytý tón téže rodiny, ať je vidět i na bílé kartě)
     Tmavé varianty jsou v bloku [data-theme="dark"] níž — bez nich by
     světlé pastely na tmavém pozadí zářily. */
  --b-prijata:#F8F7F4;    --b-prijata-t:#4A5568;    --b-prijata-c:#8A94A6;
  --b-plan:#E8DEFF;       --b-plan-t:#3A0CA3;       --b-plan-c:#3A0CA3;
  --b-vytyc:#FFD6A5;      --b-vytyc-t:#8A3D00;      --b-vytyc-c:#C46A00;
  --b-zamer:#B8F7E4;      --b-zamer-t:#064E3B;      --b-zamer-c:#0E9F7E;
  --b-zprac:#E7EAF0;      --b-zprac-t:#33507A;      --b-zprac-c:#33507A;
  --b-zsp-zprac:#DCE8FF;  --b-zsp-zprac-t:#0043C7;  --b-zsp-zprac-c:#0043C7;
  --b-gp-zprac:#D9EDE6;   --b-gp-zprac-t:#064E3B;   --b-gp-zprac-c:#2F7A63;
  --b-gad-zprac:#EDE0FF;  --b-gad-zprac-t:#5A00CC;  --b-gad-zprac-c:#5A00CC;
  --b-odvz:#4B5F8A;       --b-odvz-t:#FFFFFF;       --b-odvz-c:#4B5F8A;
  --b-zsp-odvz:#0057FF;   --b-zsp-odvz-t:#F8F7F4;   --b-zsp-odvz-c:#0057FF;
  --b-gp-odvz:#064E3B;    --b-gp-odvz-t:#F8E7C9;    --b-gp-odvz-c:#064E3B;
  --b-gad-odvz:#6A00F4;   --b-gad-odvz-t:#FFD6A5;   --b-gad-odvz-c:#6A00F4;
  --b-done:#C8FF3D;       --b-done-t:#2D1B69;       --b-done-c:#C8FF3D;  /* Neon Lime — přání uživatele; text musí být tmavý */
  --b-arch:#ECEFF3;       --b-arch-t:#61697A;       --b-arch-c:#61697A;
  --b-stor:#F7E7E7;       --b-stor-t:#982929;       --b-stor-c:#982929;
}

[data-theme="dark"] {
  /* GRAFIT (5.11.0). Dosavadní tmavý režim byl laděný domodra
     (#1e2230 / #161c2a) a působil jako ztmavený světlý motiv.
     Grafit je neutrální, o něco tmavší a karta se od plochy odliší
     víc — na velkém monitoru večer je to znát. Barvy stavů zakázek
     mají vlastní tmavé varianty níž a nechávají se být. */
  --bg-primary:#1E2128; --bg-secondary:#16181D; --bg-card:#1E2128;
  --bg-input:#1E2128; --bg-hover:#252A33;
  --topbar-bg:#1A1D24; --topbar-bd:#2A2E38; --pill-bg:#252A33; --pill-bd:#333842;
  --text-primary:#EDF0F8; --text-secondary:#B6BECD;
  /* #666 na tmavé kartě dávalo kontrast 2,8:1 (norma 4,5) a drží
     přitom skoro všechen vedlejší text — popisky, časy, počty.
     Na grafitovém podkladu (#1E2128) má #8A93A8 kontrast 4,9:1
     a zůstává tlumenější než --text-secondary. */
  --text-muted:#8A93A8;
  /* Obrys prvku v Grafitu: #333842 měl proti poli 1,37:1 — pole
     nebylo od plochy odlišené prakticky ničím. #6B748A dává
     3,45 / 3,80 / 3,08 (--bg-input / --bg-secondary / --bg-hover). */
  --border-color:#2A2E38; --border-input:#6B748A;
  /* Jantarový akcent Grafitu. Zároveň plní roli obrysu klávesnice —
     na grafitu má kontrast 8,6:1, značková modrá jen 2,4:1. */
  --prstenec:#F5A524;
  --posuvnik:#3A4152; --posuvnik-hover:#4E576C;
  --pg-red:#F0A9A4; --pg-red-light:#3a1e1e; --pg-red-border:#7a3330;
  --pg-red-text:#F7C1C1;
  --pg-green-light:#1a2a0e; --pg-green-dark:#92C35D;
  --pg-green-border:#3B6D11; --pg-blue-light:#0c1e33;
  --pg-blue-text:#9DC0FF;

  /* Stavy zakázky v tmavém motivu. Dřív se tu nepřepisovaly vůbec
     a světlé pastely na tmavé kartě přímo zářily. Pravidlo:
       · SYTÉ odznaky (odevzdání, Dokončeno) zůstávají — na tmavém pozadí
         drží kontrast beze změny,
       · SVĚTLÉ pastely se překlopí: tmavé pozadí téže rodiny + světlý
         text téže rodiny,
       · proužky (-c) se naopak ROZSVĚCUJÍ, sytý tón by na tmavé kartě
         splynul. */
  --b-prijata:#2A2E38;    --b-prijata-t:#C6CAD3;    --b-prijata-c:#8A94A6;
  --b-plan:#241A4A;       --b-plan-t:#C9B6FF;       --b-plan-c:#9B7BFF;
  --b-vytyc:#402008;      --b-vytyc-t:#FFC98A;      --b-vytyc-c:#FFA24D;
  --b-zamer:#0A3830;      --b-zamer-t:#7FE9CC;      --b-zamer-c:#2FD6AC;
  --b-zprac:#232A38;      --b-zprac-t:#A9BBD6;      --b-zprac-c:#7E9CC9;
  --b-zsp-zprac:#16264A;  --b-zsp-zprac-t:#9DC0FF;  --b-zsp-zprac-c:#4D8BFF;
  --b-gp-zprac:#10332A;   --b-gp-zprac-t:#8FD9C2;   --b-gp-zprac-c:#4FBF9C;
  --b-gad-zprac:#2A1150;  --b-gad-zprac-t:#CBA8FF;  --b-gad-zprac-c:#A05CFF;
  --b-odvz:#4B5F8A;       --b-odvz-t:#FFFFFF;       --b-odvz-c:#7E93C4;
  --b-zsp-odvz:#0057FF;   --b-zsp-odvz-t:#F8F7F4;   --b-zsp-odvz-c:#2E7BFF;
  --b-gp-odvz:#064E3B;    --b-gp-odvz-t:#F8E7C9;    --b-gp-odvz-c:#17A57E;
  --b-gad-odvz:#6A00F4;   --b-gad-odvz-t:#FFD6A5;   --b-gad-odvz-c:#9A4DFF;
  --b-done:#C8FF3D;       --b-done-t:#2D1B69;       --b-done-c:#C8FF3D;
  --b-arch:#262B36;       --b-arch-t:#A6AEBC;       --b-arch-c:#7C8797;
  --b-stor:#3A1E1E;       --b-stor-t:#FF9E9E;       --b-stor-c:#D46B6B;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* App-shell: OKNO se neroluje. Výška je pevná (viz .app) a posuvník
   patří výhradně obsahovému kontejneru .app-obsah — horní lišta
   a patička tak zůstávají na místě a posuvník začíná pod lištou
   a končí nad patičkou (na mobilu i na PC). */
/* 16px natvrdo, ne přes token: --fs-pole existuje kvůli iOS (pod 16 px
   zoomuje pole) a kdyby na něj někdo sáhl, posunul by celý základ rem. */
html { font-size: 16px; height: 100%; }
h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading); }

/* iPhone PWA safe area */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}
body {
  font-family: var(--font-body);
  /* 400, ne 600 (5.14.12): SemiBold na 13-15 px se na 1920x1080
     roztéká pres dva pixely a text vypadá „za fólií" — na 2560x1440
     to vidět nebylo, doma na Full HD ano. Hierarchii drží prvky
     s vlastní vahou (500/600/700), ty se nemění. */
  font-weight: 400;
  background-color: #F3F5F8;
  /* Vrstvy zezhora: rozeseté geodetické ikony (z logomanuálu PlanGeo) nad
     jemnou "milimetrovou" mřížkou. Krytí ikon (~9 %) je zapečené přímo v SVG. */
  background-image:
    url("/static/img/plangeo-pozadi.svg"),
    repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(47,92,168,.07) 39px, rgba(47,92,168,.07) 40px),
    repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(47,92,168,.07) 39px, rgba(47,92,168,.07) 40px);
  background-repeat: repeat, repeat, repeat;
  background-size: 560px 560px, auto, auto;
  background-attachment: fixed, scroll, scroll;
  color: var(--text-primary);
  height: 100%;
  overflow: hidden;   /* app-shell — roluje jen .app-obsah */
}
[data-theme="dark"] body, [data-theme="dark"] {
  /* Grafit (5.11.3): plocha se musí ladit s kartami. Tady zůstala
     původní modrošedá #1e2230, zatímco karty už byly grafitové —
     rozdíl plochy a karty byl 1,02, tedy žádný. */
  background-color: #16181D;
  background-image:
    url("/static/img/plangeo-pozadi-dark.svg"),
    repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(47,92,168,.08) 39px, rgba(47,92,168,.08) 40px),
    repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(47,92,168,.08) 39px, rgba(47,92,168,.08) 40px);
  background-repeat: repeat, repeat, repeat;
  background-size: 560px 560px, auto, auto;
  background-attachment: fixed, scroll, scroll;
}

/* ════════════════ LAYOUT: Sidebar + App ════════════════ */
:root { --sidebar-w: 260px; --sidebar-w-collapsed: 66px; --topbar-h: 48px;
  /* Skutečná výška horní lišty VČETNĚ výřezu iPhonu — sticky prvky pod
     topbarem musí používat tohle, ne holé --topbar-h (jinak na mobilu
     podjíždějí pod lištu). Na desktopu je safe-top 0, chová se stejně. */
  --topbar-total: calc(var(--topbar-h) + var(--safe-top));
}

/* ── Sidebar (levá navigace) ── */
.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--sidebar-w); z-index: 200;
  padding-top: var(--safe-top);
  background: linear-gradient(165deg, var(--pg-dark) 0%, #253562 60%, #2a3d6e 100%);
  display: flex; flex-direction: column;
  box-shadow: 2px 0 16px rgba(0,0,0,.22);
  transition: width .2s ease, transform .25s ease;
  overflow: hidden;   /* ambientní skvrny nesmí přetéct ven */
}
/* Liquid glass: barevné ambientní skvrny POD tlačítky — backdrop-filter
   skla je rozmaže a sklo tím dostane co „lámat". Bez nich by efekt nebyl
   vidět (blur jednobarevného pozadí vypadá jako obyčejná průhlednost). */
.sidebar::before, .sidebar::after {
  content: ""; position: absolute; border-radius: 50%; pointer-events: none;
}
.sidebar::before {
  top: -40px; left: -60px; width: 240px; height: 240px;
  background: radial-gradient(circle, rgba(146,195,93,.34), transparent 70%);
}
.sidebar::after {
  bottom: 60px; right: -80px; width: 300px; height: 300px;
  background: radial-gradient(circle, rgba(47,92,168,.5), transparent 70%);
}
/* Obsah sidebaru musí ležet NAD skvrnami */
.sidebar > * { position: relative; z-index: 1; }
.sidebar-logo {
  display: flex; align-items: center; gap: 11px;
  height: var(--topbar-h); padding: 0 16px; flex: 0 0 auto;
  border-bottom: 1px solid rgba(255,255,255,.08);
  overflow: hidden; white-space: nowrap; text-decoration: none;
}
.sidebar-logo img { height: 30px; width: auto; background: #fff; border-radius:var(--r-xs); padding: 2px 6px; flex: 0 0 auto; }
.sidebar-logo span { color: #fff; font-size:var(--fs-vedlejsi); font-weight: 600; letter-spacing: .02em; }

.sidebar-nav { flex: 1 1 auto; overflow-y: auto; padding: 10px 12px; }
/* ── Liquid glass tlačítka menu ──
   Sklo = průsvitný přechod + backdrop blur + 1px okraj + vnitřní odlesk
   (inset světlo nahoře, stín dole). Bez podpory backdrop-filter zůstane
   jen průsvitný přechod — čitelnost se nezhorší. */
.snav {
  display: flex; align-items: center; gap: 13px; position: relative;
  padding: 9px 13px; margin-bottom: 5px; border-radius:var(--r-md);
  color: rgba(255,255,255,.72); text-decoration: none;
  font-size:var(--fs-vedlejsi); white-space: nowrap; overflow: hidden; cursor: pointer;
  background: linear-gradient(160deg, rgba(255,255,255,.13), rgba(255,255,255,.03));
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.25),
              inset 0 -1px 0 rgba(0,0,0,.12),
              0 3px 10px rgba(0,0,0,.2);
  transition: background .15s, color .15s, border-color .15s, box-shadow .15s;
}
.snav .ico { flex: 0 0 22px; display: flex; align-items: center; justify-content: center; font-size:var(--fs-pole); }
.snav .ico svg, .sidebar-btn .ico svg { width: 20px; height: 20px; display: block; }
.snav .label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
.snav:hover {
  background: linear-gradient(160deg, rgba(255,255,255,.2), rgba(255,255,255,.07));
  border-color: rgba(255,255,255,.28); color: #fff;
}
.snav.active {
  background: linear-gradient(160deg, rgba(146,195,93,.42), rgba(146,195,93,.14));
  border-color: rgba(180,220,140,.5); color: #fff; font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45),
              inset 0 -1px 0 rgba(0,0,0,.1),
              0 4px 14px rgba(146,195,93,.25);
}
.snav .badge {
  flex: 0 0 auto; color: #fff; border-radius:var(--r-pilulka);
  font-size:var(--fs-drobne); font-weight: 700; padding: 1px 7px;
  background: linear-gradient(160deg, rgba(238,160,100,.95), rgba(220,130,66,.9));
  border: 1px solid rgba(255,255,255,.35);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4);
}
/* Patička aplikace (přesunuto z inline stylu base.html kvůli mobilním úpravám) */
.app-footer {
  /* App-shell: patička je PEVNÁ flex položka .app (obsah nad ní roluje
     sám) — žádné sticky ani margin-top:auto už není potřeba. */
  position: relative; flex: 0 0 auto; z-index: 90;
  text-align: center; padding: 9px 20px calc(9px + var(--safe-bottom));
  font-size:var(--fs-popisek); color: #fff; background: var(--pg-blue);
  border-top: 2px solid #1a4a94;
  display: flex; align-items: center; justify-content: center;
  gap: 14px; flex-wrap: wrap; box-shadow: 0 -2px 8px rgba(0,0,0,.15);
}

/* Pojistka pro iPhone (v5.6.3): kdyby appka i tak nedosáhla úplně dolů,
   je pruh domovského indikátoru přebarvený na barvu patičky, takže
   splyne s ní. Na desktopu je --safe-bottom nula, prvek je neviditelný
   a ničemu nepřekáží (pointer-events:none). */
body::after {
  content: ""; position: fixed; left: 0; right: 0; bottom: 0;
  height: var(--safe-bottom); background: var(--pg-blue);
  z-index: 0; pointer-events: none;
}

/* Pulzující odznak nepřečtených zpráv v chatu — upoutá pozornost.
   (inset odlesk je v obou krocích, ať sklo během pulzu nezhasíná) */
@keyframes badge-pulz {
  0%, 100% { transform: scale(1);    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 0 0 0 rgba(233,149,86,.55); }
  50%      { transform: scale(1.22); box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 0 0 6px rgba(233,149,86,0); }
}
.snav .badge.pulzuje { animation: badge-pulz 1.3s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .snav .badge.pulzuje { animation: none; } }
.nav-sekce {
  color: rgba(255,255,255,.32); font-size:var(--fs-drobne); font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  padding: 12px 14px 6px; white-space: nowrap; overflow: hidden;
}
.sidebar-foot { flex: 0 0 auto; padding: 10px 12px; border-top: 1px solid rgba(255,255,255,.08); }
.sidebar-btn {
  display: flex; align-items: center; gap: 13px; width: 100%;
  background: transparent; border: none; cursor: pointer; text-align: left;
  color: rgba(255,255,255,.5); font-size:var(--fs-vedlejsi); padding: 9px 13px; border-radius:var(--r-sm);
}
.sidebar-btn:hover { background: rgba(255,255,255,.08); color: #fff; }
.sidebar-btn .ico { flex: 0 0 22px; display: flex; align-items: center; justify-content: center; font-size:var(--fs-telo); }

/* sbalený sidebar (jen ikony) */
body.sidebar-collapsed .sidebar { width: var(--sidebar-w-collapsed); }
body.sidebar-collapsed .sidebar-logo span,
body.sidebar-collapsed .snav .label,
body.sidebar-collapsed .nav-sekce,
body.sidebar-collapsed .sidebar-btn .label { display: none; }
body.sidebar-collapsed .snav .badge { position: absolute; top: 4px; right: 5px; margin: 0; }
/* Sbalení (5.20.4): tlačítka si nechávala plné odsazení rozbaleného
   stavu (13px + gap + ikona = 48px na 42px místa) a overflow:hidden je
   ořezával zprava — v sbaleném režimu se ikona centruje bez odsazení. */
body.sidebar-collapsed .sidebar-nav { padding: 10px 8px; }
body.sidebar-collapsed .snav { justify-content: center; gap: 0; padding: 9px 0; }
body.sidebar-collapsed .sidebar-foot { padding: 10px 8px; }
body.sidebar-collapsed .sidebar-btn { justify-content: center; gap: 0; padding: 9px 0; }
/* Směr šipky musí odpovídat tomu, co tlačítko UDĚLÁ: v rozbaleném menu
   ukazuje «doleva (sbalit), ve sbaleném »doprava (rozbalit). Otočení
   je CSS transformace ikony — šablona zůstává s jedním SVG. */
body.sidebar-collapsed .sidebar-btn .ico svg { transform: rotate(180deg); }
/* Nadpisy sekcí: rolová pravidla v base.html je zapínají ID selektorem
   (#nav-sekce-komunikace { display:block }) — vyšší specificita než
   tohle sbalovací pravidlo, takže ve sbaleném menu prosvítalo uříznuté
   „KO"/„FIN". !important tu je schválně: poráží ID pravidlo rolí. */
body.sidebar-collapsed .sidebar-nav .nav-sekce { display: none !important; }
/* Posuvník přes ikony na 66px šířce jen překáží — schovat (jen webkit
   pravidla, viz zrádný vzor scrollbar-color v CLAUDE.md). */
body.sidebar-collapsed .sidebar-nav::-webkit-scrollbar { display: none; }
body.sidebar-collapsed .app { margin-left: var(--sidebar-w-collapsed); }

/* pravá část aplikace */
/* App-shell: .app je celá výška okna a SÁM se neroluje — je to jen
   svislý flex (topbar | obsah | patička). 100dvh = skutečná výška na
   iPhonu (100vh počítá se SKRYTOU lištou prohlížeče, obsah by o její
   výšku podjel pod patičku); 100vh zůstává jako fallback pro prohlížeče
   bez dvh. V PWA na ploše je dvh == vh, chová se stejně. */
.app {
  margin-left: var(--sidebar-w);
  /* VÝŠKA (v5.6.3): 100% = výška <body>, který díky viewport-fit=cover
     sahá až ke spodní hraně displeje včetně zóny domovského indikátoru.
     Jednotky 100vh/100dvh hlásí na iPhonu v PWA MÉNĚ, takže appka
     končila dřív a pod patičkou prosvítal světlý pruh (Safari ho měl
     jen tenký, PWA velký). 100dvh zůstává jako fallback pro prohlížeče,
     kde by 100 % neprošlo. */
  height: 100dvh;
  height: 100%;
  display: flex; flex-direction: column;
  transition: margin-left .2s ease;
}

/* iPhone PWA (v5.8.8): diagnostika z ostrého zařízení ukázala, že iOS
   dá oknu jen screen − safe-top (812 z 874) a ukotví ho NAHOŘE — celý
   řetěz html/body/.app/patička končí 62 px nad spodní hranou a do
   zbytku appka nemá jak kreslit přes %, dvh ani innerHeight (všechny
   shodně lžou). Jednotky vh/lvh v standalone režimu často hlásí PLNOU
   výšku displeje i tehdy — proto tu .app dostává 100vh/100lvh, ale JEN
   v PWA (media display-mode), aby to v Safari s lištou nic neposunulo.
   Když vh lže taky, pravidlo nezmění nic (bude rovno 100 %) — rozhodnou
   čísla vh/svh/lvh v O aplikaci → Diagnostika displeje. */
@media (display-mode: standalone) {
  .app {
    height: 100vh;
    height: 100lvh;
  }
}

/* JEDINÝ rolovací kontejner appky. Posuvník tedy začíná pod topbarem
   a končí nad patičkou — přesně to, co bylo zadáno.
   · min-height:0 — bez něj flex položka neumí být menší než obsah
     a scroll by se opět přelil na okno
   · overscroll-behavior:contain — gumový dojezd na iOS nerozhoupe
     celou stránku (bary se pak nechvějí)
   · overflow-y:auto SÁM přepne overflow-x z visible na auto (pravidlo
     CSS), takže široká tabulka scrolluje TADY, ne oknem */
/* Obsah smí využít monitor (5.10.3). Stránky bez .page-wrap (seznam
   zakázek, CRM, Pošta) se dosud roztahovaly donekonečna, stránky
   s ním končily na 1200 px — na 2K displeji ležela polovina plochy
   ladem. Společný strop 1600 px platí pro obojí. */
.app-obsah > *:not(.modal-overlay):not(.modal-wrap):not(.crm):not(.po-wrap):not(.email-modal):not(.nen-modal-overlay):not([style*="position:fixed"]):not([style*="position: fixed"]) {
  max-width: 1600px; margin-left: auto; margin-right: auto;
}
/* Závoje modálů se schválně VYNECHÁVAJÍ: jsou position:fixed s inset:0
   a strop šířky by je na širokém monitoru zúžil na 1600 px a vycentroval
   — pozadí by pak nepřekrylo okraje obrazovky. Totéž platí pro lištu
   hromadného výběru v seznamu zakázek, proto je vyloučené i všechno
   s `position:fixed` v atributu style. CRM a Pošta mají vlastní
   rozvržení přes celou plochu, ty taky ne.
   Obě podoby zápisu jsou schválně: jakmile do stylu sáhne JavaScript,
   prohlížeč atribut přepíše znormalizovaně s mezerou za dvojtečkou
   (`position: fixed`) a selektor bez mezery by pak minul.
   `.email-modal` (Podatelna) a `.nen-modal-overlay` (Hlídač VŘ) mají
   pevnou pozici z <style> v šabloně, ne z atributu — proto jsou
   vyjmenované zvlášť. Bez toho by nad 1600 px závoj nepřekryl okraje
   a klik vedle okna by propadl na stránku pod ním.
   POZOR: přibude-li další prvek s pevnou pozicí, patří do výjimky. */

.app-obsah {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* -webkit-overflow-scrolling:touch tu BYLO (v5.6.0) a na iOS
     způsobovalo, že se position:fixed potomci (drawer CRM, overlaye)
     vykreslovali v rolovací vrstvě — drawer pak „jel" s obsahem pod
     topbarem a patičkou. Od iOS 13 je setrvačné rolování výchozí
     a vlastnost je zbytečná; NEVRACET. */
}


/* ── Kam právě šlape klávesnice ────────────────────────────────────
   V celé appce dosud neexistovalo jediné pravidlo pro :focus-visible,
   zato se šestkrát vypínal obrys — kdo ovládá formulář tabulátorem,
   netušil, ve kterém poli stojí. `!important` je tu záměrně: ta pole
   si `outline:none` nastavují sama a bez něj by pravidlo neprošlo.
   :focus-visible se ukáže JEN při klávesnici, myš ho nevyvolá. */
:focus-visible {
  outline: 2px solid var(--prstenec) !important;
  outline-offset: 2px;
}

/* ── Slim topbar (globální: titulek + uživatel) ── */
.topbar {
  /* App-shell: topbar je PEVNÁ flex položka .app (okno se neroluje),
     sticky by tu nemělo co dělat. z-index drží stín/panely nad obsahem. */
  position: relative; flex: 0 0 auto; z-index: 100;
  /* výška = lišta + bezpečná zóna nahoře (iPhone Dynamic Island / notch).
     Bez připočtení k výšce by se s box-sizing:border-box odsazení „schovalo
     dovnitř" a obsah lišty by lezl pod stavové ikony iPhonu. */
  height: calc(var(--topbar-h) + var(--safe-top));
  padding-top: var(--safe-top);
  background: var(--topbar-bg); border-bottom: 2px solid var(--topbar-bd);
  display: flex; align-items: center; justify-content: space-between;
  padding-left: 18px; padding-right: 18px; gap: 12px;
}
.topbar-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.topbar-title { font-size:var(--fs-telo); font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-right { display: flex; align-items: center; gap: 10px; }
.theme-btn { background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size:var(--fs-pole); padding: 6px; border-radius:var(--r-sm); }
.theme-btn:hover { background: var(--pill-bd); }
.online-ind { display: flex; align-items: center; gap: 5px; background: var(--pill-bg); border: 1px solid var(--pill-bd); border-radius:var(--r-pilulka); padding: 4px 10px 4px 6px; cursor: pointer; user-select: none; }
#online-pocet { color: var(--text-secondary); font-size:var(--fs-popisek); font-weight: 600; }
.user-pill {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 12px 4px 5px;
  background: var(--pill-bg); border: 1px solid var(--pill-bd); border-radius:var(--r-pilulka); cursor: pointer;
  transition: background .15s;
}
.user-pill:hover { background: var(--pill-bd); }
.avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--pg-green); display: flex; align-items: center;
  justify-content: center; font-size:var(--fs-drobne); font-weight: 700; color: var(--pg-dark);
}
#current-user-name { color: var(--text-primary); font-size:var(--fs-vedlejsi); font-weight: 500; }
/* Tečka stavu docházky vedle jména (5.21.0, přání uživatele). Barvy
   NATVRDO (--pg-green/--pg-orange/--pg-blue/--pg-gray) — žádná z nich
   se v tmavém motivu nepřeklápí, takže tečka svítí stejně v obou. */
.doch-tecka { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; cursor: pointer; }
.doch-tecka.ts-vpraci  { background: var(--pg-green); }
.doch-tecka.ts-pauza   { background: var(--pg-orange); }
.doch-tecka.ts-skoncil { background: var(--pg-blue); }
.doch-tecka.ts-neni    { background: var(--pg-gray); }
.topbar-logout {
  background: transparent; border: 1px solid var(--border-color);
  color: var(--text-muted); border-radius:var(--r-sm); padding: 5px 10px;
  cursor: pointer; font-size:var(--fs-vedlejsi); transition: background .15s, color .15s;
}
.topbar-logout:hover { background: var(--bg-hover); color: var(--text-primary); }

/* ── Hamburger + overlay (mobil) ── */
.hamburger {
  display: none; flex-direction: column; gap: 4px;
  background: transparent; border: none; cursor: pointer; padding: 6px;
}
.hamburger span {
  display: block; width: 20px; height: 2px;
  background: var(--text-secondary); border-radius:var(--r-xs);
}
.sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 150; }
.sidebar-overlay.show { display: block; }

/* ── Mobil: sidebar jako off-canvas ── */
@media (max-width: 900px) {
  .sidebar { transform: translateX(-100%); }
  body.sidebar-open .sidebar { transform: translateX(0); }
  .app { margin-left: 0 !important; }
  .hamburger { display: flex; }
  /* na mobilu sidebar nesbalujeme do ikon */
  body.sidebar-collapsed .sidebar { width: var(--sidebar-w); }
  body.sidebar-collapsed .sidebar-logo span,
  body.sidebar-collapsed .snav .label,
  body.sidebar-collapsed .nav-sekce,
  body.sidebar-collapsed .sidebar-btn .label { display: initial; }
  body.sidebar-collapsed .sidebar-btn .ico svg { transform: none; }
}

/* ── Modál výběru uživatele ── */
.modal-overlay {
  display: none; position: fixed; inset: 0; z-index: 500;
  background: rgba(0,0,0,.5); align-items: center; justify-content: center;
}
.modal-overlay.open { display: flex; }
.modal-box {
  background: var(--bg-card); border-radius:var(--r-md); padding: 24px;
  width: min(400px, 90vw); box-shadow:var(--stin-4);
}
/* Záhlaví okna jako odlišený pruh (5.19.21, přání uživatele) — záporné
   okraje vyrovnávají padding .modal-box (24px), pruh sahá od kraje
   ke kraji. Za pruh se okno na počítači i TAHÁ (app2.js). */
.modal-title { font-size:var(--fs-pole); font-weight: 600;
  margin: -24px -24px 16px; padding: 14px 24px;
  background: var(--bg-secondary); border-bottom: 1px solid var(--border-color);
  border-radius: var(--r-md) var(--r-md) 0 0; }
@media (pointer: fine) {
  .modal-title, .pg-okno-uchyt { cursor: move; }
}
/* ── Potvrzovací dialog (nahrazuje systémový confirm) ── */
.pg-potvrd-text { font-size:var(--fs-vedlejsi); line-height: 1.6; color: var(--text-secondary); white-space: pre-line; }
.pg-potvrd-pole { width: 100%; margin-top: 14px; padding: 9px 12px; font-size:var(--fs-vedlejsi);
  font-family: inherit; border: 1px solid var(--border-input); border-radius:var(--r-sm);
  background: var(--bg-input); color: var(--text-primary); }
.pg-potvrd-pole:focus { outline: none; border-color: var(--pg-green);
  box-shadow: 0 0 0 3px rgba(146,195,93,.22); }
.pg-potvrd-akce { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
/* Tvar a velikost bere ze spolecneho zakladu v components.css. */
/* Sytá červená NATVRDO: --pg-red se v tmavém motivu překlápí na
   světlou a bílý text na ní měl kontrast 1,9:1 — a to u každého
   potvrzení mazání v celé appce. */
.btn-nebezpecne { background: #A32D2D; color: #fff; border-color: #A32D2D; }
.btn-nebezpecne:hover:not(:disabled) { background: #791F1F; border-color: #791F1F; }
.uzivatel-btn {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 10px 14px; margin-bottom: 8px;
  background: var(--bg-secondary); border: 1px solid var(--border-color);
  border-radius:var(--r-sm); cursor: pointer; font-size:var(--fs-vedlejsi); color: var(--text-primary);
  transition: background .15s;
}
.uzivatel-btn:hover { background: var(--bg-hover); }
.uzivatel-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--pg-green); display: flex; align-items: center;
  justify-content: center; font-size:var(--fs-vedlejsi); font-weight: 700; color: var(--pg-dark);
  flex-shrink: 0;
}

/* ── Změna stavu se rozsvítí (5.10.1) ──────────────────────────────
   Když někdo posune zakázku dál, řádek nebo hlavička krátce pulzne
   barvou NOVÉHO stavu. Barvu si prvek nese v --pulz-c (nastavuje ji
   JS z barvy stavu), takže jedna animace slouží všem stavům.
   Vyvolává se přidáním třídy — viz pgPulz() v app2.js. */
@keyframes pg-pulz {
  0%   { box-shadow: 0 0 0 0 var(--pulz-c, rgba(146,195,93,.7)); }
  100% { box-shadow: 0 0 0 16px transparent; }
}
/* Dvakrát tatáž třída schválně: `.detail-hero` je zároveň
   `.form-section`, a ta má o kus níž `animation: pg-child-in` se
   STEJNOU specificitou — pozdější pravidlo tedy vyhrávalo a pulz se
   nikdy nespustil. Zdvojení selektoru ho zvedne nad ni.
   (Odhaleno recenzí; test proto měří animationName, ne přítomnost
   třídy — třída tam byla, animace ne.) */
.pg-pulz.pg-pulz { animation: pg-pulz .85s cubic-bezier(.22, 1, .36, 1); }

/* ── Kostra se prolne v obsah (5.10.1) ─────────────────────────────
   Dosud kostra zmizela a obsah nastoupil skokem — bliklo to. Krátké
   prolnutí ten cukanec odstraní. Nasazuje se přes pgNabeh(). */
@keyframes pg-nabeh {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.pg-nabeh { animation: pg-nabeh .28s cubic-bezier(.22, 1, .36, 1) both; }

/* ── Přehled klávesových zkratek (5.10.3) ────────────────────────── */
.zkratky-seznam { display:flex; flex-direction:column; gap:2px; }
.zkratky-radek {
  display:grid; grid-template-columns:minmax(120px, auto) 1fr; gap:14px;
  align-items:baseline; padding:7px 0; border-bottom:1px solid var(--bg-secondary);
  font-size:var(--fs-vedlejsi); color:var(--text-secondary);
}
.zkratky-radek:last-child { border-bottom:none; }
.zkratky-radek kbd {
  font-family:inherit; font-size:var(--fs-popisek);
  font-weight:700; color:var(--text-primary); background:var(--bg-secondary);
  border:1px solid var(--border-color); border-radius:var(--r-xs);
  padding:3px 8px; white-space:nowrap; text-align:center;
}
/* Příkaz v hledání ať je poznat od nalezených dat */
.hled-prikaz .hled-titulek::before {
  content:"▸ "; color:var(--pg-blue); font-weight:700;
}

/* ── Řádek vybraný klávesnicí (5.10.3) ───────────────────────────── */
.pg-vybran {
  outline:2px solid var(--pg-blue); outline-offset:-2px;
  position:relative; z-index:1;
}

/* Odkazy v tmavém motivu (5.11.3). Značková modrá #2F5CA8 má na
   grafitovém podkladu jen 2,4:1, takže odkazy v textu byly sotva
   čitelné. Rozsvítí se jen tam, kde je modrá BARVOU PÍSMA — tlačítka,
   kde je pozadím, se nemění. */
[data-theme="dark"] .app-obsah a:not([class*="btn"]):not(.snav),
[data-theme="dark"] .subnav .back-btn { color: #7EA8FF; }

/* ── PRÁZDNÉ STAVY: jedno provedení pro celou appku (5.12.0) ───────
   Appka měla devět způsobů, jak říct „nic tu není" — od ikony v kolečku
   přes emoji po holou větu. Hezký vzor `.pg-empty` existoval, ale
   používala ho necelá polovina modulů. Ostatní třídy se sem přidávají
   jako aliasy: nemusí se sahat do šablon a všechny se hned srovnají. */
.no-results, .empty-state, .fa-prazdno, .pub-empty, .np-empty,
.crm .empty {
  /* `display` se tu SCHVÁLNĚ nenastavuje: nápověda si svůj prázdný stav
     přepíná z JavaScriptu a pravidlo by jí ho buď natrvalo schovalo,
     nebo naopak trvale ukázalo. Na vystředění stačí text-align. */
  text-align: center; padding: 48px 20px;
  color: var(--text-secondary); font-size: var(--fs-vedlejsi);
  line-height: var(--lh-text);
}
/* Ikona: emoji i SVG dostane stejné kolečko jako `.pg-empty`. */
.no-results-icon, .empty-state > svg, .empty-state .ico {
  width: 60px; height: 60px; border-radius: 50%;
  background: var(--bg-secondary); color: var(--text-muted);
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; line-height: 1; margin: 0 auto 14px; opacity: 1;
}

/* ── Posuvníky (5.14.2, přepsáno 5.14.10) ──────────────────────────
   Windows kreslí v Electronu klasické široké posuvníky, ve Firefoxu
   jsou tenké — tady se to sjednocuje.

   PŮVODNÍ ZÁPIS BYL ŠPATNĚ: rozdělovala to podmínka
   `@supports selector(::-webkit-scrollbar)`, jenže tu hlásí jako
   splněnou OBA prohlížeče (Firefox ty pseudoprvky parsuje kvůli
   kompatibilitě, jen podle nich nekreslí). Větev pro Firefox se tedy
   nikdy nepoužila a tenké posuvníky tam nenaskočily.
   Standardní vlastnosti proto sedí na :root — Chromium webkit pravidla
   ignoruje jen tehdy, když je `scrollbar-width` na TÉMŽE prvku. */
/* ŽÁDNÉ `scrollbar-width`/`scrollbar-color` — vlastní past (5.14.11):
   `scrollbar-color` se DĚDÍ, takže nastavené na :root doputuje na každý
   prvek a Chromium kvůli němu přestane brát ::-webkit-scrollbar. Jenže
   `scrollbar-width` se NEDĚDÍ, takže potomci zůstali na „auto" —
   výsledkem byly zase široké systémové posuvníky, jen bez našeho stylu.
   Electron (Chromium) proto jede čistě na webkit pravidlech níž.
   Firefox je nepotřebuje: na Windows kreslí tenké překryvné sám. */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--posuvnik); border-radius: 999px;
  border: 3px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--posuvnik-hover); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }
.sidebar ::-webkit-scrollbar-thumb, .sidebar::-webkit-scrollbar-thumb,
.po-levy ::-webkit-scrollbar-thumb, .po-levy::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.28); background-clip: padding-box;
}


/* Štítky se světle modrým podkladem (5.14.10). Pozadí
   `--pg-blue-light` se v tmavém motivu překlápí na tmavé, ale text
   `--pg-blue` ne — kontrast spadl na 2,6:1. Text se proto v tmavém
   rozsvítí, stejným receptem jako u stavů zakázek a CRM. */
[data-theme="dark"] .po-pop3,
[data-theme="dark"] .sub-chip-blue,
[data-theme="dark"] .pub-badge,
[data-theme="dark"] .mz-tag,
[data-theme="dark"] .badge-nov { color: #9dc0ff; }

/* ── Toast notifikace ── */
/* Hlášení se skládají do sloupce (5.10.1). Dřív měla každá hláška
   `position:fixed` na stejném místě, takže dvě po sobě — typicky po
   hromadné akci — se prostě překryly a druhou nebylo vidět. Nově je
   drží společný kontejner; `column-reverse` = nová přijede zespodu
   a starší se posunou nahoru. */
#pg-toasty {
  position: fixed; bottom: 24px; right: 24px; z-index: 9999;
  display: flex; flex-direction: column-reverse; align-items: flex-end;
  gap: 8px; pointer-events: none; max-width: min(360px, 92vw);
}
.toast {
  position: fixed; bottom: 24px; right: 24px; z-index: 9999;
  padding: 10px 18px; border-radius:var(--r-sm); font-size:var(--fs-vedlejsi); font-weight: 500;
  opacity: 0; transform: translateY(8px); transition: opacity .25s, transform .25s;
  max-width: 320px;
}
/* Uvnitř kontejneru se hláška pozicuje TOKEM, ne fixed — jinak by
   všechny ležely na sobě jako dřív. */
#pg-toasty .toast {
  position: relative; bottom: auto; right: auto; z-index: auto;
  overflow: hidden; pointer-events: auto;
}
.toast.show { opacity: 1; transform: translateY(0); }
/* Ubývající proužek: ukazuje, kolik času do zmizení zbývá. Šířka se
   animuje po skutečnou dobu zobrazení (JS ji vloží do stylu). */
.toast-cas {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: currentColor; opacity: .5; transform-origin: left center;
  animation: pg-toast-cas linear forwards;
}
@keyframes pg-toast-cas { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.toast-ok   { background: #27500A; color: #C0DD97; }
.toast-err  { background: #791F1F; color: #F7C1C1; }
.toast-warn { background: #633806; color: #FAC775; }

/* ── Badges ── */
/* ── ŠTÍTKY: jedna rodina pro celou appku (5.12.0) ─────────────────
   Appka měla dvanáct druhů štítku a lišily se velikostí písma (10–13 px),
   zaoblením i odsazením — vedle sebe pak nedržely linku. Rozměry teď
   drží tahle dvojice tříd, BARVU si každé použití nese dál samo
   (u stavů zakázek je to výslovné přání uživatele).
     (rodina .stitek--* z 5.12.0 smazána — žádná šablona ji
     nepoužila, živý je jen .badge; nález recenze) */
.stitek, .badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: var(--r-pilulka);
  font-size: var(--fs-popisek); font-weight: 700;
  line-height: var(--lh-ui); white-space: nowrap; vertical-align: middle;
}
/* Jedna třída = jeden stav. Dřív tři dvojice stavů sdílely třídu
   (Vytyčeno + Zaměřeno, GP + GAD zpracování, všechna odevzdání), takže
   se v seznamu nedaly rozeznat od sebe. Klíč → třída drží app2.js
   (konstanta STAVY), hlídá backend/test/test_stavy.py. */
.b-prijata   { background: var(--b-prijata);   color: var(--b-prijata-t); }
.b-plan      { background: var(--b-plan);      color: var(--b-plan-t); }
.b-vytyc     { background: var(--b-vytyc);     color: var(--b-vytyc-t); }
.b-zamer     { background: var(--b-zamer);     color: var(--b-zamer-t); }
.b-zprac     { background: var(--b-zprac);     color: var(--b-zprac-t); }
.b-zsp-zprac { background: var(--b-zsp-zprac); color: var(--b-zsp-zprac-t); }
.b-gp-zprac  { background: var(--b-gp-zprac);  color: var(--b-gp-zprac-t); }
.b-gad-zprac { background: var(--b-gad-zprac); color: var(--b-gad-zprac-t); }
.b-odvz      { background: var(--b-odvz);      color: var(--b-odvz-t); }
.b-zsp-odvz  { background: var(--b-zsp-odvz);  color: var(--b-zsp-odvz-t); }
.b-gp-odvz   { background: var(--b-gp-odvz);   color: var(--b-gp-odvz-t); }
.b-gad-odvz  { background: var(--b-gad-odvz);  color: var(--b-gad-odvz-t); }
.b-done      { background: var(--b-done);      color: var(--b-done-t); }
.b-arch      { background: var(--b-arch);      color: var(--b-arch-t); }
.b-stor      { background: var(--b-stor);      color: var(--b-stor-t); }
/* ZPĚTNÁ KOMPATIBILITA — třídy, které appka už negeneruje, ale můžou
   přijít ze staré zakešované app2.js v prohlížeči (nebo z ručně uloženého
   HTML). Bez definice by odznak zůstal úplně bez barvy.
     .b-mereni = prapůvodní jméno pro Zaměřeno
     .b-gp     = dřív sdílená třída GP i GAD zpracování → GP zpracování */
.b-mereni    { background: var(--b-zamer);     color: var(--b-zamer-t); }
.b-gp        { background: var(--b-gp-zprac);  color: var(--b-gp-zprac-t); }
/* Stav, který PRÁVĚ PROBÍHÁ (Zpracování, GP zpracování, …), má navíc
   obrys. Pravidlo „-ní = běží, -o = hotovo" tak jde poznat i pohledem,
   bez znalosti té gramatiky.
   POZOR: obrys se kreslí NAVRCH výplně. Dřív tu bylo
   `background: transparent`, které pozadí odznaku úplně zahodilo — nová
   paleta by u čtyř stavů „zpracování" nebyla vidět vůbec. */
.badge.badge-probiha {
  box-shadow: inset 0 0 0 1.5px currentColor;
}

/* ── Mobilní responzivita ── */
@media (max-width: 700px) {
  body { font-size:var(--fs-karta); }
}


/* ════════════════ Animace přepínání obrazovek („Přiblížení", 200 ms) ════════════════
   Obsah stránky se při každém načtení jemně přiblíží z 93 % + prolne.
   Sidebar, topbar a patička zůstávají bez animace — působí to pak tak,
   že se "přepíná jen obsah". Odsouhlaseno na návrhu 3a (Tweaks: Přiblížení, 200 ms). */
@keyframes pg-screen-in {
  /* Dřív scale(.93) — obsah „vlétl" a při každém přepnutí to trhalo
     okem. Jemný posun zdola o 10 px dělá totéž (je poznat, že se
     stránka vyměnila), ale nepůsobí nervózně. */
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes pg-child-in {
  from { opacity: 0; transform: scale(.9); }
  to   { opacity: 1; transform: none; }
}

/* Obsah stránky (vše uvnitř rolovacího kontejneru kromě modálů).
   POZOR: animuje se OBSAH kontejneru, NIKDY sám .app-obsah — animace
   dává prvku transform a ten by z rolovacího kontejneru udělal
   containing block pro position:fixed potomky (drawery, overlaye,
   toasty by se přestaly pozicovat vůči oknu; viz .crm níž). */
.app-obsah > *:not(.modal-overlay):not(script):not(style):not(.crm) {
  animation: pg-screen-in .2s cubic-bezier(.22, 1, .36, 1) both;
}

/* CRM je výjimka: animujeme jeho VNITŘNÍ obsah, ne celý blok.
   Proč: animace dává prvku `transform`, a transform na rodiči vytvoří
   containing block pro position:fixed potomky. .crm jich obsahuje čtyři
   (.overlay, .drawer, .modal-wrap, .toast) — ty se pak nepozicovaly vůči
   OKNU, ale vůči .crm: drawer poptávky se centroval vůči .crm (a jeho horní
   hrana s .dr-head, za kterou se okno chytá, zmizela pod topbarem),
   max-height:90vh nechránilo a závoj overlaye nepřekryl sidebar.
   Stejný důvod, proč je výše z animace vyjmutý .modal-overlay. */
.crm > .pg-hlavicka, .crm > .content-inner {
  animation: pg-screen-in .2s cubic-bezier(.22, 1, .36, 1) both;
}

/* Kaskáda: řádky zakázek a karty se objeví postupně */
.zakazka-row, .form-section, .crm .stat, .crm .pcard {
  animation: pg-child-in .24s cubic-bezier(.22, 1, .36, 1) both;
}
.form-section:nth-of-type(1), .crm .stat:nth-child(1) { animation-delay: .04s; }
.form-section:nth-of-type(2), .crm .stat:nth-child(2) { animation-delay: .08s; }
.form-section:nth-of-type(3), .crm .stat:nth-child(3) { animation-delay: .12s; }
.form-section:nth-of-type(4), .crm .stat:nth-child(4) { animation-delay: .16s; }
/* Řádky zakázek: krok 40 ms až do dvanáctého. Dřív kaskáda končila
   u osmého a devátý naskočil bez zpoždění — na delším seznamu bylo
   vidět, jak se animace „utne". Dvanáctý je na hraně obrazovky, pod
   ním už na pořadí nezáleží. */
.zakazka-row:nth-child(1)  { animation-delay: .04s; }
.zakazka-row:nth-child(2)  { animation-delay: .08s; }
.zakazka-row:nth-child(3)  { animation-delay: .12s; }
.zakazka-row:nth-child(4)  { animation-delay: .16s; }
.zakazka-row:nth-child(5)  { animation-delay: .20s; }
.zakazka-row:nth-child(6)  { animation-delay: .24s; }
.zakazka-row:nth-child(7)  { animation-delay: .28s; }
.zakazka-row:nth-child(8)  { animation-delay: .32s; }
.zakazka-row:nth-child(9)  { animation-delay: .36s; }
.zakazka-row:nth-child(10) { animation-delay: .40s; }
.zakazka-row:nth-child(11) { animation-delay: .44s; }
.zakazka-row:nth-child(12) { animation-delay: .48s; }
/* Od třináctého už na pořadí nezáleží, ale bez tohohle by měly delay 0
   a naskočily by DŘÍV než řádky nad nimi. */
.zakazka-row:nth-child(n+13) { animation-delay: .48s; }

/* Modální okna dostanou stejné přiblížení */
.modal-overlay.open .modal-box {
  animation: pg-screen-in .2s cubic-bezier(.22, 1, .36, 1) both;
}

/* ════════════════ Hover bočního menu — „Zelené podsvícení" (návrh 4c) ════════════════
   Pruh zeleného světla se při najetí rozjede zleva doprava.
   Aktivní položka zůstává se solidním podkladem beze změny. */
.snav:not(.active) {
  background-image: linear-gradient(90deg, rgba(146,195,93,.3), rgba(146,195,93,.04));
  background-repeat: no-repeat;
  background-size: 0% 100%;
  transition: background-size .28s ease, color .2s ease;
}
.snav:not(.active):hover {
  background-color: transparent;
  background-image: linear-gradient(90deg, rgba(146,195,93,.3), rgba(146,195,93,.04));
  background-size: 100% 100%;
  color: #fff;
}

/* Respektovat omezení pohybu v systému */
@media (prefers-reduced-motion: reduce) {
  .app-obsah > *, .zakazka-row, .form-section, .crm .stat, .crm .pcard,
  .crm > .pg-hlavicka, .crm > .content-inner,
  .modal-overlay.open .modal-box { animation: none !important; }
  .snav:not(.active) { transition: none; }
}

/* ════════════════ MOBIL — telefonní vrstva (iPhone ~402 px) ════════════════
   Systémová pravidla pro všechna okna. Stránkově specifické úpravy
   (seznam zakázek, CRM) jsou v components.css ve stejném breakpointu. */
/* Zámek rolování pod otevřeným šuplíkem menu / modálem. Okno samo
   neroluje (app-shell), takže `body { overflow:hidden }` by nic neudělal
   — zamykat se musí SKUTEČNÝ rolovací kontejner .app-obsah. */
body.mobnav-lock .app-obsah,
body.pg-modal-lock .app-obsah { overflow: hidden; }

@media (max-width: 480px) {
  /* iOS Safari zazoomuje při focusu do pole s písmem < 16 px a už se nevrátí.
     input:not([type]) — spousta polí v šablonách atribut type vůbec nemá
     (default je text), atributový selektor by je minul. */
  input[type="text"], input[type="search"], input[type="email"],
  input[type="password"], input[type="number"], input[type="date"],
  input:not([type]), input[type=time], input[type=tel], input[type=url],
  input[type=datetime-local], input[type=number], input[type=search],
  select, textarea { font-size:var(--fs-pole) !important; }

  /* patička: jen značka a verze, zbytek schovat — nebrat viewport dvěma řádky */
  /* MOBIL (v5.6.1, přání uživatele): patička nemá krást místo. Text
     se zmenší a hlavně SPODNÍ ODSAZENÍ = přesně bezpečná zóna, takže
     modrý pruh vyplní zaoblený okraj displeje (kde stejně nic být
     nemůže) a nad ním zbude jen tenký proužek. */
  .app-footer {
    gap: 8px;
    padding-top: 4px;
    padding-bottom: calc(4px + var(--safe-bottom));
    font-size:var(--fs-drobne);
    line-height: 1.2;
  }
  .app-footer .foot-extra { display: none; }
  .app-footer img, .app-footer svg { max-height: 14px; }

  /* toasty nad home indicator */
  #pg-toasty, .toast { bottom: calc(18px + var(--safe-bottom)); }

  /* modály: nesmí přetéct při vyjeté klávesnici */
  .modal-box { max-height: calc(100dvh - 24px - var(--safe-top) - var(--safe-bottom)); overflow-y: auto; }

  /* ── Horní lišta na telefonu ──────────────────────────────────────
     Na 402 px se do lišty nevejde všechno naráz. Titulek i jméno
     u avataru jsou duplicitní (název stránky je hned pod lištou,
     jméno v postranním menu), tak ustoupí ovládání.
     KLÍČOVÉ: tlačítka se nesmí smrsknout pod svůj obsah. Bez
     flex-shrink:0 hamburger zúžil na pár pixelů, jeho proužky
     přetekly pod lupu a menu nešlo trefit prstem (iPhone 17 Pro). */
  .topbar { padding-left: 8px; padding-right: 8px; gap: 4px; }
  .topbar-title { display: none; }
  .topbar-left, .topbar-right { gap: 2px; }
  .hamburger, .topbar .theme-btn, .topbar-logout,
  .user-pill, .online-ind { flex: 0 0 auto; }

  /* dotykový terč 44 px (doporučení Apple) */
  .hamburger, .topbar .theme-btn, .topbar-logout {
    min-width: 44px; height: 44px; padding: 0;
    align-items: center; justify-content: center;
  }
  .topbar .theme-btn, .topbar-logout { display: flex; }
  .hamburger span { width: 22px; }

  /* avatar jako tlačítko „změnit heslo", jméno je v menu */
  #current-user-name { display: none; }
  .user-pill { padding: 4px; }

  /* Z online uživatelů jen dva avatary — počet vedle zůstává správný.
     !important je nutné: avatary skládá app2.js s inline stylem
     (display:flex), a ten by pravidlo ze stylopisu přebil. */
  #online-avatary > div:nth-child(n+3) { display: none !important; }
  .online-ind { padding: 4px 9px 4px 5px; }
}

/* ── Horní lišta na tabletu ───────────────────────────────────────
   Telefonní vrstva výše lištu přeskládá celou, tady stačí ubrat okraje
   a zkrátit jméno. Rozsah je schválně ohraničený i zdola: dokud tahle
   pravidla bydlela v components.css jako `max-width: 700px`, přebíjela
   telefonní vrstvu z theme.css — components.css se v base.html linkuje
   AŽ ZA ním, takže při stejné specificitě vyhrával pozdější soubor bez
   ohledu na to, že jeho media query je širší. */
@media (min-width: 481px) and (max-width: 700px) {
  .topbar { padding-left: 12px; padding-right: 12px; }
  #current-user-name { max-width: 80px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
  .hamburger { padding: 6px; }
}

/* ════════════════ Globální hledání (Ctrl+K / ⌘K) ════════════════
   Vlastní skeleton (ne components.css .pg-skel) — okno je v base.html,
   tedy na KAŽDÉ stránce, i na těch, co components.css nenačítají. */
#modal-hledani { align-items: flex-start; padding-top: 12vh; }
.hled-box {
  width: min(640px, 94vw); padding: 0; overflow: hidden;
  display: flex; flex-direction: column; max-height: min(70vh, 560px);
}
.hled-input-wrap {
  display: flex; align-items: center; gap: 10px; padding: 14px 18px;
  border-bottom: 1px solid var(--border-color); flex-shrink: 0;
}
.hled-input-ico { width: 18px; height: 18px; color: var(--text-muted); flex-shrink: 0; }
.hled-input {
  flex: 1; border: none; background: transparent; color: var(--text-primary);
  font-family: inherit; font-size:var(--fs-telo); outline: none; min-width: 0;
}
.hled-input::placeholder { color: var(--text-muted); }
.hled-zavrit {
  background: none; border: none; color: var(--text-muted); cursor: pointer;
  font-size:var(--fs-telo); padding: 4px; border-radius:var(--r-sm); flex-shrink: 0;
}
.hled-zavrit:hover { background: var(--bg-hover); color: var(--text-primary); }
.hled-vysledky { overflow-y: auto; padding: 8px; }
.hled-skupina { margin-bottom: 6px; }
.hled-skupina-nadpis {
  font-size:var(--fs-popisek); font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em; padding: 8px 10px 4px;
}
.hled-polozka {
  display: block; padding: 8px 10px; border-radius:var(--r-sm); cursor: pointer;
  text-decoration: none; color: var(--text-primary);
}
.hled-polozka:hover, .hled-polozka.vybrana { background: var(--bg-hover); }
.hled-titulek { font-size:var(--fs-telo); font-weight: 600; }
.hled-popis { font-size:var(--fs-vedlejsi); color: var(--text-muted); margin-top: 1px; }
.hled-napoveda, .hled-prazdno, .hled-chyba {
  padding: 32px 20px; text-align: center; font-size:var(--fs-vedlejsi); color: var(--text-muted); line-height: 1.6;
}
.hled-chyba { color: var(--pg-red); }
.hled-skel-radek { display: flex; flex-direction: column; gap: 6px; padding: 10px; }
.hled-skel {
  height: 12px; border-radius:var(--r-sm); width: 85%;
  background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--border-color) 37%, var(--bg-secondary) 63%);
  background-size: 260px 100%; animation: pg-skel 1.15s ease-in-out infinite;
}
/* ── Jednotný prázdný stav (ikona v kolečku + přátelský text) ── */
.pg-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:48px 20px;}
.pg-empty .pg-empty-ico{width:60px;height:60px;border-radius:50%;background:var(--bg-secondary);display:flex;align-items:center;justify-content:center;margin-bottom:14px;color:var(--text-muted);}
.pg-empty .pg-empty-ico svg{width:28px;height:28px;}
.pg-empty h4{font-size:var(--fs-telo);font-weight:600;color:var(--text-primary);margin:0 0 4px;}
.pg-empty p{font-size:var(--fs-vedlejsi);color:var(--text-secondary);margin:0;line-height:1.6;max-width:320px;}

/* ── Loading skeletony (jemné šedé bloky s přejezdem místo „Načítám…") ── */
@keyframes pg-skel{0%{background-position:-260px 0}100%{background-position:calc(260px + 100%) 0}}
.pg-skel{background:linear-gradient(90deg,var(--bg-secondary) 25%,var(--border-color) 37%,var(--bg-secondary) 63%);background-size:260px 100%;border-radius:var(--r-sm);animation:pg-skel 1.15s ease-in-out infinite;}
.pg-skel-row{display:flex;align-items:center;gap:14px;padding:13px 16px;border:1px solid var(--border-color);border-radius:var(--r-md);margin-bottom:8px;background:var(--bg-card);}
.pg-skel-row .b1{width:70px;height:16px;flex-shrink:0;}
.pg-skel-row .b2{flex:1;height:12px;}
.pg-skel-row .b3{width:70px;height:12px;flex-shrink:0;}
.pg-skel-card{padding:12px 14px;border:1px solid var(--border-color);border-radius:var(--r-md);margin-bottom:8px;background:var(--bg-card);}
.pg-skel-card .l{height:11px;margin:6px 0;}

@media (max-width: 480px) {
  #modal-hledani { padding-top: 0; }
  .hled-box { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; border-radius: 0; }
  .hled-input-wrap { padding-top: calc(14px + var(--safe-top)); }
}

/* ════════════════ TISK — app-shell se pro tisk ROZPADNE ════════════════
   Klasická past app-shellu: pevná výška okna (html/body height:100 %) +
   overflow:hidden by tiskárně řekly „obsah je přesně jedna obrazovka"
   a vytiskla by se JEDNA stránka s useknutým zbytkem. Pro tisk se proto
   výška i přetečení ruší a .app přestává být flex sloupec.
   (Pošta a Podatelna navíc tisknou jen #tisk-obsah — přesouvají ho pod
   <body> a schovávají zbytek; jejich pravidlo je specifičtější a vyhraje,
   viz `body.tisk-rezim > :not(#tisk-obsah)`.) */
@media print {
  html, body {
    height: auto !important;
    overflow: visible !important;
    background: #fff !important;
  }
  .app {
    height: auto !important;
    min-height: 0 !important;
    display: block !important;
    margin-left: 0 !important;
  }
  .app-obsah {
    flex: none !important;
    min-height: 0 !important;
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }
  /* navigace, lišta a patička na papír nepatří */
  .sidebar, .sidebar-overlay, .topbar, .app-footer, #splash { display: none !important; }
  /* žádné animace ani transformy při tisku */
  .app-obsah > *, .zakazka-row, .form-section { animation: none !important; }
}

/* ════════════════ Omezit pohyb — pojistka ════════════════════════
   Jednotlivá pravidla výš pokrývala jen část animací; nekonečné
   přejezdy koster, tečky na úvodní obrazovce ani nové animace
   z 5.10.1 mezi nimi nebyly. Tohle je poslední síto: kdo má
   v systému zapnuté omezení pohybu, nedostane žádný pohyb.
   Musí zůstat NA KONCI souboru — přebíjí se tu vším, co je nad ním. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
