/* JOBSON 3 — komponenty
   Konvence tříd: blok__prvek--varianta (BEM bez zkratek).
   Prefixy: app-  skořápka | list- seznam | detail- detail
            form- formulář | state- stav obrazovky | u- utilita */

/* =====================================================================
   ZÁKLAD
   ===================================================================== */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--c-canvas);
  color: var(--c-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--c-brand-ink); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-1);
}

.u-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.u-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.u-visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* =====================================================================
   SKOŘÁPKA
   ===================================================================== */
.app { display: flex; flex-direction: column; min-height: 100vh; }

.app__topbar {
  display: flex; align-items: center; gap: var(--space-2);
  height: var(--topbar-h); padding: 0 var(--space-3);
  background: var(--c-surface); border-bottom: 1px solid var(--c-border);
  position: sticky; top: 0; z-index: 20;
  /* Přetečení drží na uzdě smršťování prvků níž, ne overflow: hidden —
     ten by uřízl i rozbalovací panel přepínače, který z lišty visí ven. */
  min-width: 0;
}
/* Ikonová tlačítka si drží velikost, textová se smrsknou a ořežou text.
   Bez toho vytlačí dlouhý název agentury uživatelské menu mimo obrazovku. */
.app__topbar > * { flex-shrink: 0; }
.app__topbar > .btn:not(.btn--icon),
.app__topbar > .switcher { flex-shrink: 1; min-width: 0; }
.app__logo { height: 19px; width: auto; padding-right: var(--space-3); border-right: 1px solid var(--c-border); }
.app__search { flex: 1 1 auto; max-width: 420px; min-width: 120px; position: relative; }
.app__search input { width: 100%; padding-right: 44px; }
.app__search-kbd {
  position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); font-size: 10px; color: var(--c-ink-mute);
  border: 1px solid var(--c-border); border-radius: var(--radius-1);
  padding: 1px 5px; background: var(--c-surface);
}
.app__spacer { flex: 1 1 auto; }

.app__body { display: flex; flex: 1; align-items: stretch; min-height: 0; }

.app__nav {
  flex: none; width: var(--nav-w);
  background: var(--c-surface); border-right: 1px solid var(--c-border);
  padding: var(--space-2) 0; transition: width var(--dur-base) ease;
}
.app__nav--mini { width: var(--nav-w-mini); }
.app__nav-section {
  padding: var(--space-2) 14px var(--space-1);
  font-size: 10px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--c-ink-faint);
}
.app__nav--mini .app__nav-section { display: none; }
.app__nav-section--context { display: grid; gap: 1px; margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--c-border-hair); text-transform: none; letter-spacing: normal; }
.app__nav-section-kind { font-size: 10px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink-faint); }
.app__nav-section-name { font-size: var(--fs-control); font-weight: 600; color: var(--c-ink); text-transform: none; letter-spacing: normal; }
.app__nav-item {
  display: flex; align-items: center; gap: var(--space-2);
  height: 32px; margin: 1px var(--space-2); padding: 0 var(--space-2);
  border-radius: var(--radius-2); color: var(--c-ink);
  font-size: var(--fs-control); white-space: nowrap; overflow: hidden;
}
.app__nav-item:hover { background: var(--c-sunken); text-decoration: none; }
.app__nav-item[aria-current="page"] {
  background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600;
}
.app__nav-icon { flex: none; width: 18px; height: 18px; }
.app__nav-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.app__nav--mini .app__nav-item { justify-content: center; padding: 0; }
.app__nav--mini .app__nav-label, .app__nav--mini .app__nav-count { display: none; }
.app__nav-count {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--c-ink-mute);
  background: var(--c-sunken); border-radius: var(--radius-1); padding: 1px 5px;
}

.app__main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--c-surface); }

/* Tablet: navigace sama na ikonový pruh. Telefon: do šuplíku. */
@media (max-width: 1024px) { .app__nav { width: var(--nav-w-mini); } }
@media (max-width: 720px) {
  .app__nav { position: fixed; inset: var(--topbar-h) auto 0 0; z-index: 30;
              width: var(--nav-w); transform: translateX(-100%); box-shadow: var(--shadow-2); }
  .app__nav[data-open="true"] { transform: none; }

  /* Vysunutá navigace leží přes obsah. Bez ztmavení pozadí to vypadá jako
     dvě obrazovky přes sebe a není poznat, že klik vedle ji zavře. */
  .app__nav[data-open="true"] ~ .app__main::before {
    content: ""; position: fixed; inset: var(--topbar-h) 0 0 0;
    background: rgb(0 0 0 / .35); z-index: 25;
  }

  /* Lišta na telefonu nese jen to, bez čeho se nedá pokračovat: navigaci,
     logo, agenturu, notifikace a účet. Vejde se to i na 360 px.

     Celoaplikační hledání se skryje — pole široké 120 px k ničemu není.
     Na telefonu potřebuje vlastní vstupní bod přes celou obrazovku; ten
     vznikne, až bude co prohledávat. Jazyk a odhlášení patří do
     uživatelského menu, ne do lišty. */
  .app__topbar .app__search { display: none; }
  .app__logo { padding-right: var(--space-2); }

  /* Zůstatek AI kreditů ustoupí ze stejného důvodu jako hledání: volné
     místo na telefonu patří názvu agentury, protože ten rozhoduje, čí
     data jsou na obrazovce. Do Předplatného vede položka v navigaci. */
  .app__topbar .topbar-credits { display: none; }

  /* Uživatelské menu se smrskne na ikonu. Jméno oříznuté na „Ja…" nic
     neříká a zabírá místo, které potřebuje název agentury — ten je pro
     orientaci důležitější, protože rozhoduje, čí data jsou na obrazovce. */
  .app__user-name { display: none; }
}

/* =====================================================================
   HLAVIČKA OBRAZOVKY
   ===================================================================== */
.page-head { padding: 14px var(--space-4) 0; }
.page-head__crumbs { display: flex; flex-wrap: wrap; gap: 6px; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.page-head__row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin-top: 5px; }
.page-head__title { margin: 0; font-size: var(--fs-page); font-weight: 600; letter-spacing: -.015em; }
.page-head__meta { margin-top: 3px; font-size: var(--fs-control); color: var(--c-ink-mute); }
.page-head__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* =====================================================================
   TLAČÍTKA
   ===================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--control-h); padding: 0 var(--space-3);
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); color: var(--c-ink);
  font: inherit; font-size: var(--fs-control); font-weight: 500;
  cursor: pointer; white-space: nowrap;    /* šířka roste s textem — kvůli DE */
}
/* Zakázané tlačítko nese důvod **v textu** (konvence z CLAUDE.md), a důvod
   je věta, ne popisek. `nowrap` z `.btn` ji roztáhl na 674 px a na mobilu
   s ní vyjela do strany celá stránka. Zalomit ho smí právě proto, že se na
   něj neklikne — jeho úkol je vysvětlit, ne být terčem. Platí to pro
   každé zakázané tlačítko, takže se na to u dalšího nemusí nikdo
   rozpomínat. */
.btn:disabled { white-space: normal; text-align: left; max-width: 100%; height: auto; min-height: var(--control-h); padding-top: 4px; padding-bottom: 4px; }
.btn:hover { background: var(--c-sunken); }
.btn--primary { background: var(--c-brand); border-color: var(--c-brand); color: var(--c-on-brand); font-weight: 600; }
.btn--primary:hover { background: var(--c-brand-hover); border-color: var(--c-brand-hover); }
.btn--danger { color: var(--c-danger); border-color: var(--c-danger-line); }
.btn--danger:hover { background: var(--c-danger-soft); }
.btn--quiet { border-color: transparent; background: none; color: var(--c-ink-mute); }
.btn--quiet:hover { background: var(--c-sunken); }
.btn--icon { width: var(--control-h); padding: 0; }
.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--c-sunken); border-color: var(--c-border);
  color: var(--c-ink-faint); cursor: not-allowed;
}
/* Vlastní `display` přebije skrytí prohlížečem, takže by `hidden` na
   tlačítku nic neudělal — a schované tlačítko by dál svítilo na obrazovce. */
.btn[hidden] { display: none; }
.btn__badge {
  position: absolute; top: -6px; right: -6px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--c-danger); color: #fff;
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.btn--badged { position: relative; }

/* =====================================================================
   ŠTÍTEK STAVU — barva + znak + slovo
   ===================================================================== */
.status {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px var(--space-2) 1px 6px; border-radius: var(--radius-1);
  font-size: var(--fs-micro); font-weight: 500; white-space: nowrap;
  border: 1px solid var(--c-inactive-line);
  background: var(--c-inactive-soft); color: var(--c-inactive-ink);
}
.status::before { font-family: var(--font-mono); font-weight: 700; content: "–"; }
.status--ok       { background: var(--c-ok-soft);       border-color: var(--c-ok-line);       color: var(--c-ok-ink); }
.status--ok::before { content: "✓"; }
.status--soon     { background: var(--c-soon-soft);     border-color: var(--c-soon-line);     color: var(--c-soon-ink); }
.status--soon::before { content: "△"; }
.status--expired  { background: var(--c-expired-soft);  border-color: var(--c-expired-line);  color: var(--c-expired-ink); }
.status--expired::before { content: "✕"; }
.status--pending  { background: var(--c-pending-soft);  border-color: var(--c-pending-line);  color: var(--c-pending-ink); }
.status--pending::before { content: "◷"; }
.status--rejected { background: var(--c-rejected-soft); border-color: var(--c-rejected-line); color: var(--c-rejected-ink); }
.status--rejected::before { content: "⊘"; }

/* =====================================================================
   SEZNAM S FILTRY
   ===================================================================== */
.list-views { display: flex; gap: 2px; padding: var(--space-3) var(--space-4) 0; border-bottom: 1px solid var(--c-border); overflow-x: auto; }
.list-views__item {
  height: var(--control-h); padding: 0 var(--space-3);
  border: none; border-bottom: 2px solid transparent; background: none;
  font: inherit; font-size: var(--fs-control); color: var(--c-ink-mute);
  cursor: pointer; white-space: nowrap;
}
.list-views__item[aria-selected="true"] { color: var(--c-brand-ink); font-weight: 600; border-bottom-color: var(--c-brand); }
.list-views__count { font-family: var(--font-mono); color: var(--c-ink-mute); font-weight: 400; }

.list-filters {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: 10px var(--space-4); background: var(--c-sunken);
  border-bottom: 1px solid var(--c-border);
}
/* Odkaz v pruhu filtrů — cesta jinam, ne další volba. Drží výšku ovládacích
   prvků, aby v řádku neposkakoval, ale zůstává odkazem: kdo ho vidí jako
   tlačítko, čeká, že něco přepne. */
.list-filters__link {
  display: inline-flex; align-items: center; height: var(--control-h);
  font-size: var(--fs-control); white-space: nowrap;
}
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: var(--control-h); padding: 0 6px 0 10px;
  border: 1px solid var(--c-brand-line); background: var(--c-brand-soft);
  border-radius: var(--radius-2); font-size: var(--fs-control); color: var(--c-brand-ink);
  max-width: 100%;
}
.chip__value { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip__remove { flex: none; width: 18px; height: 18px; border: none; background: none; cursor: pointer; color: inherit; line-height: 1; }
/* Křížek je u kontextu ta nejdůležitější akce na obrazovce a 18 px se prstem
   netrefí. Rozšiřuje se dotyková plocha, ne znak — chip má zůstat drobný. */
@media (pointer: coarse) {
  .chip__remove { width: var(--control-h); height: var(--control-h); }
}
/* Barevný štítek. Barvu si volí agentura, takže se z ní **odvozuje** pozadí
   i text — natvrdo nastavené pozadí by u tmavé barvy dalo nečitelný text
   a u světlé neviditelný okraj. `color-mix` to řeší jedním výrazem. */
.tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px; border-radius: var(--radius-2);
  border: 1px solid var(--tag, var(--c-border));
  background: color-mix(in oklab, var(--tag, var(--c-border)) 12%, var(--c-surface));
  color: color-mix(in oklab, var(--tag, var(--c-ink)) 80%, black);
  font-size: var(--fs-meta); max-width: 100%;
}
.tag__remove { flex: none; border: none; background: none; cursor: pointer; color: inherit; line-height: 1; }
@media (pointer: coarse) { .tag__remove { min-width: var(--control-h); min-height: var(--control-h); } }
.tag-row { display: flex; flex-wrap: wrap; gap: 3px; }
/* Řádek fáze pipeline (nábor, E15) — v detailu zakázky i v editoru šablony.
   Typ fáze nese barva tečky **i** slovo vedle; tečka je jen zkratka koutkem
   oka. Průběžná fáze modifikátor nemá. Přeneseno z design/e15/e15.css;
   sloupce jsou tady širší o pořadí a o lištu akcí, protože řádek je
   zároveň formulář. */
.stage { display: grid; grid-template-columns: 24px 12px minmax(140px, 1fr) minmax(120px, auto) 90px auto; gap: 10px; align-items: center; padding: 6px 8px; border-bottom: 1px solid var(--c-border-hair); font-size: var(--fs-control); }
.stage__order { color: var(--c-ink-faint); font-size: var(--fs-micro); text-align: right; }
.stage__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--c-inactive-ink); }
.stage--entry .stage__dot { background: var(--c-brand); }
.stage--success .stage__dot { background: var(--c-ok-ink); }
.stage--failure .stage__dot { background: var(--c-rejected-ink); }
.stage__type { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.stage__actions { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.stage__error { grid-column: 3 / -1; margin: 0; }
/* Pod 720 px se řádek fáze láme na sloupec. Grid s třemi sloupci sám
   odsune typ a SLA do 24px a 12px sloupců, kde ze `select`u zbude
   šipka bez textu — vybraný typ pak není vidět vůbec. Pravidlo se
   proto váže na **pozici v řádku**, ne na novou třídu u každého pole:
   co není pořadí ani tečka, stojí v obsahovém sloupci (`CLAUDE.md`). */
@media (max-width: 720px) {
    .stage { grid-template-columns: 24px 12px 1fr; }
    .stage > :not(.stage__order):not(.stage__dot) { grid-column: 3; }
    .stage__error { grid-column: 3 / -1; }
    .stage__actions { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Tři cesty založení (nábor, E15: pro zákazníka · do zásoby · kmenová).
   Karta je `<label>` nad rádiem, takže volba funguje bez skriptů; stav
   nese aria-pressed, ne třída. Přeneseno z design/e15/e15.css. */
.ways { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-3); }
.way { border: 2px solid var(--c-border); border-radius: var(--radius-2); padding: var(--space-3); background: var(--c-surface); cursor: pointer; display: block; color: inherit; text-decoration: none; }
.way:has(input:focus-visible), a.way:focus-visible { outline: 2px solid var(--c-brand); outline-offset: 2px; }
/* Vybraná karta se pozná podle svého obsahu, ne podle třídy ani atributu,
   který dopisuje skript: `:has(input:checked)` platí i pro karty, které
   teprve vzniknou, a hlavně i tam, kde skript neběží. `aria-pressed`
   zůstává kvůli kartám bez rádia (rozcestník prázdné zakázky). */
.way[aria-pressed="true"], .way:has(input:checked) { border-color: var(--c-brand); background: var(--c-brand-soft); }
/* Zakázaná volba se neschovává — skrytá vypadá jako smazaná a člověk ji
   hledá. Zůstane vidět i s důvodem, jen se do ní nedá kliknout. */
.way:has(input:disabled) { border-style: dashed; background: var(--c-sunken); cursor: not-allowed; }
.way__title { display: block; font-weight: 600; margin: 0 0 4px; }
.way__text { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); margin: 0; }
.way__text + .way__text { margin-top: 4px; }
.way__blocked { display: block; font-size: var(--fs-micro); color: var(--c-expired-ink); margin-top: 4px; }

/* Požadavek zakázky se stavem (nábor, E15) — znak i slovo, nikdy jen barva.
   Stavy splněno / nesplněno / vyloučeno přijdou s matchingem; u nové
   zakázky je požadavek vždy „nelze vyhodnotit". Přeneseno z e15.css. */
.req { display: grid; grid-template-columns: 22px 1fr auto; gap: 8px; align-items: start; padding: 6px 0; border-bottom: 1px solid var(--c-border-hair); font-size: var(--fs-control); }
.req__mark { font-family: var(--font-mono); font-weight: 600; text-align: center; padding-top: 6px; }
.req--met .req__mark { color: var(--c-ok-ink); }
.req--unmet .req__mark { color: var(--c-danger); }
.req--unknown .req__mark { color: var(--c-ink-faint); }
.req--excluded .req__mark { color: var(--c-rejected-ink); }
.req .form-grid { margin-bottom: 0; }

/* Štítek účasti s barvou z omezené palety tokenů (nábor, E15). Token je
   modifikátor, ne `style` — paleta je uzavřená a sedí ke stavům. */
.tag--neutral  { --tag: var(--c-inactive-line); }
.tag--brand    { --tag: var(--c-brand); }
.tag--ok       { --tag: var(--c-ok-line); }
.tag--soon     { --tag: var(--c-soon-line); }
.tag--pending  { --tag: var(--c-pending-line); }
.tag--rejected { --tag: var(--c-rejected-line); }
.input--color { width: 44px; padding: 2px; }
.form-inline { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }

/* Štítky v hlavičce detailu. Nabídka visí v popoveru, takže hlavička
   neroste — přidání ani odebrání ji nesmí rozjet o řádek (Jakub 19. 8. 2026). */
.detail__tags { display: flex; flex-wrap: wrap; gap: var(--space-1); align-items: center; margin-top: var(--space-2); }
.detail__tags .popover > summary { list-style: none; }
.detail__tags .popover > summary::-webkit-details-marker { display: none; }

.chip--add { border-style: dashed; border-color: var(--c-border); background: var(--c-surface); color: var(--c-ink-mute); cursor: pointer; padding: 0 10px; }

/* Pás s kontextem stojí nad filtry: kontext zúžil seznam dřív, než se filtr
   vůbec uplatnil, a čte se proto jako první. Štítek je záměrně tentýž `.chip`
   jako u filtrů — kontext v globálním modulu **je** filtr a má tak i vypadat,
   včetně křížku, kterým se sundá. */
.context-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--c-border);
}
.context-bar__hint { margin: 0; font-size: var(--fs-control); color: var(--c-ink-mute); }

.list-bulk {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--c-brand-soft); border-bottom: 1px solid var(--c-brand-line);
  color: var(--c-brand-ink);
}
.list-bulk[hidden] { display: none; }
.list-bulk__count { font-weight: 600; white-space: nowrap; }

.table-wrap { flex: 1; overflow: auto; border-bottom: 1px solid var(--c-border); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
.table th {
  position: sticky; top: 0; z-index: 1;
  height: 32px; padding: 0 10px; text-align: left;
  background: var(--c-canvas); border-bottom: 1px solid var(--c-border);
  font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); white-space: nowrap;
}
.table th[aria-sort] { cursor: pointer; }
.table th[aria-sort="ascending"]::after  { content: " ↑"; font-family: var(--font-mono); }
.table th[aria-sort="descending"]::after { content: " ↓"; font-family: var(--font-mono); }
.table td {
  height: var(--row-h); padding: 0 10px;
  border-bottom: 1px solid var(--c-border-hair);
  max-width: var(--cell-max); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Buňka, ve které stojí vysvětlující věta, se useknout nesmí.

   `.table td` je jednořádková se třemi tečkami na konci, a to je u hodnoty
   správně — jméno delší než sloupec se dočte v detailu. U věty ne: „zdroj
   nemá vyplněný měsíční ná…" je horší než žádné vysvětlení, protože vypadá
   jako celá odpověď. Našlo se to ve statistikách u srovnání s předchozím
   obdobím („srovnat se nedá — ani v jednom obdo…"), ale platí to i pro
   poznámku o ceně za nástup, která tam stojí od zdrojů.

   Rozhoduje **obsah, ne nová třída** (`CLAUDE.md`): buňka s poznámkou se
   zalomí a poznámka jde pod hodnotu. Tím to platí i pro tabulky, které
   teprve vzniknou — na zvláštní třídu by si musel vzpomenout jejich autor. */
.table td:has(> .page-head__meta) { white-space: normal; }
.table td > .page-head__meta { display: block; }

/* Volný text, který se nesmí oříznout — důvod, poznámka, hláška. Ostatní
   buňky zůstávají jednořádkové, jinak by se řádky přestaly skenovat. */
.table td.table__cell--wrap { height: auto; max-width: none; overflow: visible; white-space: normal; }

.table tbody tr:nth-child(even) { background: oklch(0.988 0.002 250); }
.table tbody tr:hover { background: var(--c-sunken); }
.table tbody tr[aria-selected="true"] { background: var(--c-brand-soft); }
.table__cell--num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-control); }
.table__cell--expired { color: var(--c-expired-ink); font-weight: 600; }
.table__cell--soon { color: var(--c-soon-ink); font-weight: 600; }
.table__check { width: 34px; padding-left: var(--space-3); }
.table input[type="checkbox"] { width: 14px; height: 14px; accent-color: var(--c-brand); }

.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) var(--space-4); font-size: var(--fs-control); color: var(--c-ink-mute); }
.pager__pages { display: flex; gap: var(--space-1); }
.pager__page { height: 28px; min-width: 28px; padding: 0 var(--space-2); border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); font: inherit; font-size: var(--fs-control); cursor: pointer; }
.pager__page[aria-current="page"] { background: var(--c-brand); border-color: var(--c-brand); color: var(--c-on-brand); font-weight: 600; }

/* Telefon: tabulka se rozpadá na karty (data-label nese název sloupce). */
/* Na telefonu se tabulka rozpadá na karty.

   Původní podoba měla bílé karty na bílém podkladu, oddělené jen vlasovou
   linkou, a popisek se hodnotou splýval na jednom řádku („Doklad do: 20. 8.").
   Při deseti řádcích se v tom nedalo číst.

   Karta proto stojí na tlumeném podkladu, popisek a hodnota jsou ve dvou
   sloupcích pod sebou zarovnané, a jméno funguje jako nadpis karty. */
@media (max-width: 720px) {
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; }

  .table-wrap { background: var(--c-canvas); padding: var(--space-3); }

  .table tr {
    background: var(--c-surface); border: 1px solid var(--c-border);
    border-radius: var(--radius-3); box-shadow: var(--shadow-1);
    margin-bottom: var(--space-3); padding: var(--space-3);
    position: relative;
  }
  .table tr[aria-selected="true"] { border-color: var(--c-brand-line); background: var(--c-brand-soft); }

  .table td {
    height: auto; border: none; max-width: none; white-space: normal;
    display: grid; grid-template-columns: minmax(84px, 34%) 1fr;
    gap: var(--space-3); align-items: baseline; justify-items: start;
    padding: 3px 0;
  }
  .table td::before {
    content: attr(data-label);
    color: var(--c-ink-mute); font-size: var(--fs-meta); line-height: var(--lh-base);
  }

  /* První sloupec je identita záznamu — nadpis karty, ne další řádek.
     „První" znamená první **údaj**, ne první buňka: v tabulce s výběrem
     stojí na kraji zaškrtávátko, které se vytahuje do rohu karty. Dokud
     pravidlo mířilo na `:nth-of-type(1)`, sedalo právě na ně — jméno
     zůstalo obyčejným řádkem a spodní čára nadpisu visela vedle druhého
     údaje jako utržený škrt. Řeší to výběr podle obsahu, ne další třída
     v šabloně (Lukáš 31. 8. 2026): jinak by si na ni musel vzpomenout
     autor každé další tabulky s výběrem. */
  .table tbody td:nth-of-type(1):not(.table__check),
  .table tbody td.table__check + td {
    display: block; font-size: 15px; font-weight: 600;
    padding: 0 var(--space-6) var(--space-2) 0;
    margin-bottom: var(--space-2); border-bottom: 1px solid var(--c-border-hair);
  }
  .table tbody td:nth-of-type(1):not(.table__check)::before,
  .table tbody td.table__check + td::before { content: none; }

  /* Zaškrtávátko a nabídka akcí drží rohy karty, ať nezabírají vlastní
     řádek uprostřed údajů. */
  .table__check { position: absolute; top: var(--space-3); left: auto; right: var(--space-3); width: auto; padding: 0; }
  .table__check::before { content: none; }
  .table__actions { position: absolute; bottom: var(--space-2); right: var(--space-2); padding: 0; }
  .table__actions::before { content: none; }
}

/* =====================================================================
   DETAIL SE ZÁLOŽKAMI
   ===================================================================== */
.detail__head { padding: 14px var(--space-5) 0; border-bottom: 1px solid var(--c-border); background: var(--c-surface); }
.detail__identity { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.detail__facts { display: flex; flex-wrap: wrap; gap: 6px var(--space-5); margin-top: 7px; font-size: var(--fs-control); color: var(--c-ink-mute); }
.detail__tabs { display: flex; gap: 2px; margin-top: var(--space-3); overflow-x: auto; }
.detail__tab {
  height: 32px; padding: 0 var(--space-3);
  border: none; border-bottom: 2px solid transparent; background: none;
  font: inherit; font-size: var(--fs-control); color: var(--c-ink-mute); cursor: pointer; white-space: nowrap;
}
.detail__tab[aria-selected="true"] { color: var(--c-brand-ink); font-weight: 600; border-bottom-color: var(--c-brand); }
.detail__body { display: grid; grid-template-columns: minmax(0,1fr) 320px; align-items: start; }
.detail__content { padding: var(--space-4) var(--space-5); min-width: 0; }
.detail__aside { border-left: 1px solid var(--c-border-hair); background: oklch(0.982 0.003 250); padding: var(--space-4); }

/* Přepínač sekcí dlouhého detailu.

   Karta osoby má osm sekcí; jako jeden svitek splývaly (Jakub 19. 8. 2026).
   Vidět je vždy jedna a přepíná se tímhle seznamem, který se při rolování
   drží na místě — jinak by se uživatel musel po každé sekci rolovat nahoru,
   aby přepnul. */
.detail__aside--sticky { position: sticky; top: var(--topbar-h); max-height: calc(100vh - var(--topbar-h)); overflow-y: auto; }
.section-nav { display: grid; gap: 2px; }
.section-nav__item {
  display: block; padding: 6px var(--space-2);
  border-radius: var(--radius-2); border-left: 2px solid transparent;
  color: var(--c-ink); text-decoration: none; font-size: var(--fs-control);
}
.section-nav__item:hover { background: var(--c-brand-soft); }
.section-nav__item--active { border-left-color: var(--c-brand); background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600; }

/* Na úzké obrazovce je přepínač **nad** obsahem, ne pod ním: nabídka, ke které
   se člověk dostane až po přerolování celé sekce, přepínač být přestane.
   Vodorovný pás se posouvá prstem, tedy stejné gesto jako u záložek seznamu. */
@media (max-width: 1024px) {
  /* `minmax(0,1fr)`, ne `1fr`: holé `1fr` je `minmax(auto,1fr)` a dovolí
     sloupci narůst na šířku nejširšího obsahu uvnitř. Na mobilu tím detail
     zakázky vyjel na 539 px ve výřezu 375 px a pravá půlka přehledu byla
     uříznutá. Široký obsah si roluje vlastní obal, stránka ne. */
  .detail__body { grid-template-columns: minmax(0, 1fr); }
  .detail__aside { order: -1; border-left: none; border-bottom: 1px solid var(--c-border-hair); padding: var(--space-2) var(--space-3); }
  .detail__aside--sticky { position: sticky; top: var(--topbar-h); z-index: 3; max-height: none; overflow: visible; }
  .detail__aside > .section-title { display: none; }
  .section-nav { display: flex; gap: var(--space-1); overflow-x: auto; scrollbar-width: none; }
  .section-nav::-webkit-scrollbar { display: none; }
  .section-nav__item {
    flex: none; white-space: nowrap;
    border: 1px solid var(--c-border); border-radius: var(--radius-2);
    min-height: var(--control-h); display: flex; align-items: center;
  }
  .section-nav__item--active { border-color: var(--c-brand-line); }
}

.section-title { font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--c-ink-mute); margin-bottom: 10px; }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1px; margin: 0 0 var(--space-5); background: var(--c-border-hair); border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); overflow: hidden; }
.facts__item { background: var(--c-surface); padding: var(--space-2) var(--space-3); min-width: 0; }
.facts__key { font-size: var(--fs-micro); color: var(--c-ink-mute); margin-bottom: 2px; }
.facts__value { margin: 0; overflow: hidden; text-overflow: ellipsis; }

.notice { display: flex; align-items: center; gap: 10px; padding: 9px var(--space-3); border: 1px solid var(--c-expired-line); background: var(--c-danger-soft); border-radius: var(--radius-2); margin-bottom: var(--space-4); }
.notice__icon { font-family: var(--font-mono); font-weight: 700; color: var(--c-expired-ink); }
.notice__text { flex: 1; min-width: 0; font-size: var(--fs-control); }

.timeline { display: grid; gap: var(--space-3); }
.timeline__item { display: grid; gap: 2px; padding-left: var(--space-3); border-left: 2px solid var(--c-border); }
.timeline__item--recent { border-left-color: var(--c-brand-line); }
.timeline__when { font-family: var(--font-mono); font-size: 11px; color: var(--c-ink-mute); }
.timeline__who { font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* =====================================================================
   FORMULÁŘE
   ===================================================================== */
/* `align-content: start` neni kosmetika: bez nej se vyska rozdana mrizkou
   rozpusti mezi radky pole a vstupy v jednom radku formulare skonci kazdy
   v jine vysce podle toho, jak dlouhou ma pod sebou napovedu. */
.field { display: grid; gap: var(--space-1); align-content: start; }
/* Tlačítko postavené přímo do pole se v gridu roztáhne na celou šířku
   a jeho popisek skončí uprostřed prázdna — vypadá to jako vada
   zarovnání. Řeší to komponenta podle obsahu, ne třída navíc
   (`CLAUDE.md`); vstupy se roztahovat mají, tlačítko ne. */
.field > .btn { justify-self: start; }
.field__label { font-size: var(--fs-meta); font-weight: 500; color: var(--c-ink); }
.field__required { color: var(--c-danger); font-weight: 700; }
.field__hint { font-size: var(--fs-meta); color: var(--c-ink-mute); }
/* Nápověda, kterou teprve doplní skript (stav nahrávání u diktování),
   je do té doby prázdná — a prázdný odstavec si přesto bere řádek i
   mezery, takže v poli zeje díra. Pozná se to podle obsahu, ne podle
   další třídy: `:empty` přestane platit v tom okamžiku, kdy do ní
   něco přibude. */
.field__hint:empty { display: none; }
.field__error { display: flex; align-items: flex-start; gap: 6px; font-size: var(--fs-meta); color: var(--c-expired-ink); }
.field__error::before { content: "!"; font-family: var(--font-mono); font-weight: 700; }

/* Nabidka delek u data — napriklad zkusebni doba. Tlacitka jsou zkratka
   k vypoctu, ne prepinac: pole zustava obycejne datum, ktere jde prepsat. */
.field__choices { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.field__choices-label { font-size: var(--fs-meta); color: var(--c-ink-mute); }
.btn--tiny { height: auto; padding: 2px 8px; font-size: var(--fs-meta); }
.field__hint--warn { color: var(--c-soon-ink); }

/* Odvozena hodnota misto vstupu — napriklad mzda, ktera plyne z pozice.
   Vypada jako hodnota, ne jako zamcene policko: zamcene policko svadi
   ke klikani a hleda se, cim se odemkne. */
/* Druh prace je jedna veta, ale muze jich byt vic — radky se nesmi slit. */
.field__value { font-weight: 600; color: var(--c-ink); white-space: pre-line; }
.facts__value--lines, .change__now--lines { white-space: pre-line; }

/* Zdedena hodnota: znackovy pruh vlevo rika, ze hodnota ma jiny zdroj nez
   zbytek formulare, odznak u nadpisu rika ktery. */
.field--inherited { padding-left: var(--space-2); border-left: 2px solid var(--c-brand-line); }
/* Dokud neni vybrana pozice, je to misto, ktere ceka na hodnotu — proto
   carkovane a tise, ne tuznym textem jako hotova hodnota. */
.field__value--empty { font-weight: 400; color: var(--c-ink-mute); padding: 4px 8px; border: 1px dashed var(--c-border); border-radius: var(--radius-2); }
.chip--mini { height: auto; padding: 1px 6px; font-size: var(--fs-meta); font-weight: 400; }

.input, .select, .textarea {
  height: var(--control-h); padding: 0 9px; width: 100%;
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); color: var(--c-ink);
  font: inherit; font-size: var(--fs-control);
}
.textarea { height: auto; padding: 7px 9px; resize: vertical; line-height: var(--lh-base); }
.input::placeholder { color: var(--c-ink-faint); }
.input:focus, .select:focus, .textarea:focus { outline: var(--focus-ring); outline-offset: 1px; border-color: var(--c-brand); }
.input--num, .input--date { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* Vlastní počet měsíců v nabídce délek: pole na dvě až tři číslice, ne na
   celou šířku formuláře. Stojí za `.input` schválně — stejná specificita,
   rozhoduje pořadí. */
.input--tiny { height: 24px; width: 8ch; padding: 0 6px; font-size: var(--fs-meta); }
.input[aria-invalid="true"] { border-color: var(--c-danger); background: oklch(0.99 0.008 25); box-shadow: inset 2px 0 0 var(--c-danger); }
.input[disabled], .select[disabled] { background: var(--c-canvas); color: var(--c-ink-mute); cursor: not-allowed; }

.input-group { display: flex; }
.input-group .input { border-radius: var(--radius-2) 0 0 var(--radius-2); flex: 1; min-width: 0; }
/* Doprava se rovná **jen číslo**: u částky má jednotka vedle vstupu
   navazovat na poslední číslici. Zarovnání patřilo celé skupině a tím se
   doprava rovnala i adresa, obec, slug a poznámka — text u pravého okraje
   se čte jako vada. Rozhoduje typ pole, ne třída navíc (`CLAUDE.md`);
   `input--num` už na projektu znamená „tohle je číslo". Našlo se to až
   otevřením obrazovky sdíleného výběru v prohlížeči (krok 30). */
.input-group .input[type="number"],
.input-group .input--num { text-align: right; }
.input-group .select { width: auto; min-width: 64px; border-left: none; border-radius: 0 var(--radius-2) var(--radius-2) 0; background: var(--c-sunken); }

.choice { display: inline-flex; align-items: center; gap: 7px; height: var(--control-h); padding: 0 11px; border: 1px solid var(--c-border); border-radius: var(--radius-2); font-size: var(--fs-control); cursor: pointer; }
.choice:has(:checked) { border-color: var(--c-brand); background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 500; }
.choice:has(:disabled) { color: var(--c-ink-faint); cursor: not-allowed; }
.choice input { accent-color: var(--c-brand); }

/* Rozhodnutí mezi dvěma akcemi, které vypadají podobně, ale jedna je vratná
   a druhá ne — archivace vs. výmaz osobních údajů. Stojí vedle sebe schválně:
   rozdíl je vidět jen ve srovnání, a ten je celý smysl téhle sekce
   (Jakub 19. 8. 2026).

   Pozor na jméno: `.choice` je zabraný přepínač (chip s rádiem), tohle je něco
   jiného a sdílené jméno by rozbilo obojí. */
.decision { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-3); align-items: start; }
.decision__option { border: 1px solid var(--c-border); border-radius: var(--radius-2); padding: var(--space-3); background: var(--c-surface); min-width: 0; }
.decision__option--danger { border-color: var(--c-expired-line); background: var(--c-expired-soft); }
.decision__title { font-size: var(--fs-section); font-weight: 600; margin: 0 0 var(--space-1); }
.decision__option--danger .decision__title { color: var(--c-expired-ink); }
.decision__option--go { border-color: var(--c-brand-line); }
.decision__option--go .decision__title { color: var(--c-brand-ink); }
.decision__text { margin: 0 0 var(--space-2); color: var(--c-ink-mute); }
.decision__list { margin: 0 0 var(--space-3); padding-left: var(--space-4); display: grid; gap: 4px; font-size: var(--fs-meta); }
.decision__list li { margin: 0; }
/*
   Tajemství k opsání — přístupový token, otisk. Monospace proto, že se to
   čte znak po znaku a v proporcionálním písmu splyne nula s velkým O; `wrap:
   anywhere` proto, že šedesátiznakový řetězec by jinak roztáhl stránku do
   šířky a na telefonu by z něj byla vidět třetina.

   Vybrat se dá celý naráz (`user-select: all`) — kdo si token opisuje ručně,
   se v něm splete.
*/
.code { font-family: var(--font-mono); font-size: var(--fs-micro); }
.code--block { display: block; padding: var(--space-2) var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-sunken); overflow-wrap: anywhere; user-select: all; }

.check { display: flex; align-items: flex-start; gap: 9px; font-size: var(--fs-control); cursor: pointer; }
.check input { width: 15px; height: 15px; margin-top: 1px; accent-color: var(--c-brand); }

/* Zaškrtávátka jedné otázky (hodnoty číselníku u požadavku „je jedno z")
   stojí pod sebou. V řádce se různě dlouhé popisky rozjedou a člověk
   nepozná, které zaškrtávátko patří ke kterému slovu. */
.check-group { display: flex; flex-direction: column; gap: var(--space-1); }

.form-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; padding-top: var(--space-3); border-top: 1px solid var(--c-border-hair); }

/* Lišta akcí **uvnitř pole** není patička formuláře, ale tlačítko toho pole
   („přepsat nahrávku" pod nahrávkou). Čára nad ní tvrdí, že formulář končí,
   a odřízne tlačítko od pole, ke kterému patří — v pohovoru to vypadalo, že
   „Přepsat nahrávku" je druhé odeslání celého zápisu.

   Pozná se to podle umístění, ne podle další třídy (Lukáš 31. 8. 2026):
   takhle to platí i pro pole s vlastním tlačítkem, která teprve vzniknou. */
.field .form-actions { padding-top: var(--space-2); padding-bottom: var(--space-3); border-top: none; }

/* Lišta akcí, do které někdo postavil i pole — „přidat další stupeň", „posunout
   období". Nepozná se to podle třídy, ale podle obsahu, a to schválně: kdyby to
   byla druhá třída, musel by si na ni autor vzpomenout a recenzent ji uhlídat.
   Takhle se to spraví samo v každé liště, která pole obsahuje — i v těch, které
   teprve vzniknou (Lukáš 31. 8. 2026).

   Pole se rovnají horní hranou, ne středem. Při rovnání na střed stačí, aby
   jedno z nich mělo pod sebou nápovědu, a jeho vstup vyjede o výšku té nápovědy
   nad ostatní — do jedné linky pak nesedí nic.

   Tlačítko a poznámka se proto spouštějí o řádek popisku dolů: stojí v linii
   se vstupy, ne s popisky. Výška popisku je `--fs-meta` × `--lh-base`. */
.form-actions:has(.field) {
  --form-actions-shift: calc(var(--fs-meta) * var(--lh-base) + var(--space-1));
  align-items: flex-start;
}
.form-actions:has(.field) > .btn,
.form-actions:has(.field) > .page-head__meta { margin-top: var(--form-actions-shift); }
.form-actions:has(.field) > .page-head__meta { line-height: var(--control-h); }

/* Úprava hodnoty přímo v řádku tabulky. Formulář je blokový, takže tlačítko
   „Uložit" spadne pod vstupy, řádek povyroste a jeho obsah se přilepí k hornímu
   okraji. Vedle sebe na jedné lince to drží řádek v normální výšce a svisle na
   středu.

   Opět podle obsahu, ne podle třídy: `<form>` s ovládacími prvky uvnitř buňky
   je vždycky úprava hodnoty na místě a vždycky se má chovat takhle. */
.table td > form:has(.input-group) { display: flex; align-items: center; gap: var(--space-2); }
.table td > form:has(.input-group) .input-group { flex: 1; min-width: 0; }

/* Buňka, ve které stojí odstavec, nese **větu** — a věta se v tabulce
   nezkracuje. `.table td` má `nowrap` a `overflow: hidden`, takže se text
   uřízne uprostřed a bez tří teček; u check-inu po nástupu (krok 28) je
   přitom právě ta věta jediný obsah sloupce („koordinátor musí vidět větu,
   ne vlaječku"). Uříznutá stížnost na ubytovnu je horší než žádná: vypadá
   jako celá.

   Opět podle obsahu, ne podle třídy: `<p>` uvnitř buňky je vždycky próza
   a vždycky se má zalomit. Zvláštní třída by znamenala, že si na ni musí
   vzpomenout autor další tabulky. */
.table td:has(> p) { white-space: normal; overflow: visible; height: auto; padding-top: 6px; padding-bottom: 6px; }
.table td:has(> p) p + p { margin-top: 2px; }

/* =====================================================================
   STAVY OBRAZOVEK
   ===================================================================== */
.state { display: grid; gap: var(--space-2); justify-items: center; text-align: center; align-content: center; padding: 40px var(--space-5); min-height: 210px; }
.state__icon { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--c-border); border-radius: var(--radius-3); font-family: var(--font-mono); font-size: 20px; color: var(--c-ink-mute); }
.state__title { font-size: 14.5px; font-weight: 600; }
.state__text { font-size: var(--fs-control); color: var(--c-ink-mute); max-width: 34ch; text-wrap: pretty; }
.state__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; margin-top: var(--space-1); }
.state__ref { font-family: var(--font-mono); font-size: 11px; color: var(--c-ink-mute); }
.state--error .state__icon { color: var(--c-expired-ink); border-color: var(--c-expired-line); background: var(--c-expired-soft); }
.state--blocked { background: var(--c-pending-soft); border: 1px solid var(--c-pending-line); border-radius: var(--radius-3); }
.state--blocked .state__icon { color: var(--c-pending-ink); border-color: var(--c-pending-line); background: var(--c-surface); }
.state--blocked .state__title { font-size: 16px; color: var(--c-pending-ink); }
.state--blocked .state__text { max-width: 46ch; color: var(--c-ink); }
.lookup { position: relative; margin-top: var(--space-1); border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); max-height: 240px; overflow-y: auto; }
.lookup__item { display: block; width: 100%; text-align: left; padding: 7px var(--space-3); border: 0; background: none; font: inherit; font-size: var(--fs-control); color: var(--c-ink); cursor: pointer; }
.lookup__item:hover, .lookup__item:focus-visible { background: var(--c-brand-soft); }

/* Hlavička sekce v detailu: název vlevo, ovládání vpravo — jeden pruh, ne
   pruh za pruhem („Ovládání nad seznamem je jedna lišta"). Doteď tyhle dvě
   třídy žádné pravidlo neměly, takže se stav k datu a tlačítko skládaly pod
   sebe a sekce začínala třemi řádky ovládání (Jakub 29. 8. 2026). */
.sec__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.sec__head > .section-title { margin: 0; }
.sec__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }

/* Rozcestník na začátku: karta osoby, na které ještě není poměr. Banner se
   jménem řekne, na čem člověk stojí, a pod ním stojí obě cesty vedle sebe
   (Jakub 29. 8. 2026). Není to `.state` — ten je vystředěný prázdný stav přes
   celou plochu a přesně ten tu byl a nefungoval: sdělení uprostřed, akce až
   pod ohybem. */
.start { display: grid; gap: var(--space-4); }
.start__banner { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4); border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-sunken); }
.start__icon { flex: none; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); font-family: var(--font-mono); font-size: 17px; color: var(--c-ink-mute); }
.start__lead { display: grid; gap: var(--space-1); min-width: 0; }
.start__title { font-size: 17px; font-weight: 600; margin: 0; text-wrap: balance; }
.start__text { margin: 0; font-size: var(--fs-base); color: var(--c-ink-mute); max-width: 64ch; text-wrap: pretty; }
/* Obě cesty stejně vysoké a tlačítka na jedné lince: rozdíl mezi nimi je
   v textu, ne v tom, že jedna karta končí dřív. `.decision` má jinde
   `align-items: start` schválně (archivace vs. výmaz stojí na stránce samy),
   tady jsou dvě rovnocenné nabídky vedle sebe. */
.start .decision { align-items: stretch; margin-bottom: 0; }
.start .decision__option { display: flex; flex-direction: column; }
.start .decision__list { flex: 1; }
.start .decision__option > .btn { align-self: flex-start; }

.skeleton { height: 20px; border-radius: var(--radius-1); background: linear-gradient(90deg, var(--c-sunken) 0%, var(--c-surface) 50%, var(--c-sunken) 100%); background-size: 400px 100%; animation: skeleton 1.2s linear infinite; }
.skeleton-rows { display: grid; gap: 7px; }
@keyframes skeleton { from { background-position: -400px 0; } to { background-position: 400px 0; } }
.spinner { width: 14px; height: 14px; border: 2px solid var(--c-border); border-top-color: var(--c-brand); border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .skeleton, .spinner { animation: none; } }

/* =====================================================================
   OBSAHOVÁ OBLAST A KARTY

   Doplněno 8. 8. 2026 při návrhu E3.

   Systém měl odsazení vyřešené jen pro bloky, které už existovaly
   (page-head, list-filters, detail__content). Obrazovka, která ukazuje
   volný obsah — uvítání, formulář, sekce nastavení — neměla se o co
   opřít a lepila se na levou navigaci.

   .page-body je odsazená oblast pro takový obsah.
   .card je plocha uvnitř ní. Tabulka zůstává i nadále přes celou šířku;
   full-bleed je u hustého datového gridu záměr, ne nedopatření.
   ===================================================================== */
.page-body { padding: var(--space-5) var(--space-4) var(--space-6); display: grid; gap: var(--space-4); align-content: start; }
.page-body--narrow { max-width: 560px; }

.card {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--radius-3); padding: var(--space-4);
  display: grid; gap: var(--space-2); align-content: start;
}
.card--accent { background: var(--c-brand-soft); border-color: var(--c-brand-line); }
/* Nadpisy a odstavce si nesou výchozí okraje prohlížeče. Uvnitř karty
   a dialogu o rozestupech rozhoduje grid, ne dědictví z HTML. */
.card__title, .card__text, .dialog__title, .dialog__text { margin: 0; }

.card__eyebrow { font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); letter-spacing: .02em; text-transform: uppercase; }
.card__title { font-size: var(--fs-section); font-weight: 600; line-height: var(--lh-tight); }
.card__text { font-size: var(--fs-control); color: var(--c-ink-mute); text-wrap: pretty; }
/* Delici linka uvnitr karty: oddeluje dusledek od rozhodnuti, ktere ho
   zpusobilo, aniz by z nej delala samostatne tema. */
.card__rule { width: 100%; height: 0; margin: var(--space-2) 0 0; border: 0; border-top: 1px solid var(--c-border); }
.card__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-1); }

/* Řádek jednoho nastavení: vlevo co to je a v jakém je stavu, vpravo úkon.
   Popis stojí vedle přepínače, ne pod ním — kdo o zapnutí rozhoduje, musí
   mít důsledek před očima ve chvíli, kdy mačká. Pod 640 px se to zalomí
   pod sebe a tlačítko zůstane pod textem, ke kterému patří. */
.setting { display: flex; gap: var(--space-4); align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.setting__text { display: grid; gap: var(--space-1); min-width: min(320px, 100%); flex: 1 1 320px; }
.setting__label { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: 0; font-size: var(--fs-control); font-weight: 600; }
.setting__hint { margin: 0; font-size: var(--fs-meta); color: var(--c-ink-mute); text-wrap: pretty; }

/* Mřížka karet, které mají stejnou váhu — kroky uvítání, dlaždice nastavení. */
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-4); }

/* Číslovaný krok. Číslo nese pořadí, barva ho jen doprovází. */
.step-num {
  width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--c-brand-soft); border: 1px solid var(--c-brand-line);
  color: var(--c-brand-ink); font-size: var(--fs-micro); font-weight: 600; font-variant-numeric: tabular-nums;
}

/* =====================================================================
   DIALOG

   Doplněno 8. 8. 2026 při návrhu E3.

   Staví na nativním <dialog> a metodě showModal(). Prohlížeč tím zdarma
   dodá past na fokus, zavření klávesou Esc, vrstvení nad vším ostatním
   a znepřístupnění pozadí pro odečítače obrazovky. Vlastní implementace
   by tohle všechno musela napodobit a udělala by to hůř.

   Dialog je pro krátký úkon, který nemá vlastní adresu: pozvat kolegu,
   potvrdit smazání, přejmenovat. Pro cokoli delšího je to špatná volba —
   dlouhý formulář v okně se na mobilu nedá vyplnit a nejde na něj poslat
   odkaz. Takový obsah patří na vlastní obrazovku.
   ===================================================================== */
/* Dialog, který se nevejde na obrazovku, musí jít dorolovat. Bez toho
   zůstane potvrzovací tlačítko pod dolní hranou a dialog se nedá zavřít
   jinak než Escapem — a to je klávesa, kterou na telefonu nikdo nemá. */
.dialog {
  width: min(520px, calc(100vw - 2 * var(--space-4)));
  max-height: calc(100dvh - 2 * var(--space-4)); overflow: auto;
  padding: 0; border: 1px solid var(--c-border); border-radius: var(--radius-3);
  background: var(--c-surface); color: var(--c-ink); box-shadow: var(--shadow-2);
  /* Vyšší obsah než obrazovka se roluje uvnitř. Bez toho se na nižším
     notebooku uřízne pata s tlačítkem a formulář nejde odeslat — dialog
     hromadné editace má sám 772 px. */
  max-height: calc(100vh - 2 * var(--space-4)); overflow: auto;
}
.dialog::backdrop { background: oklch(0.30 0.02 250 / 0.35); }
.dialog__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4) var(--space-4) 0;
}
.dialog__title { font-size: var(--fs-section); font-weight: 600; line-height: var(--lh-tight); }
.dialog__text { font-size: var(--fs-control); color: var(--c-ink-mute); text-wrap: pretty; margin-top: var(--space-1); }
.dialog__body { display: grid; gap: var(--space-4); padding: var(--space-4); }
.dialog__foot {
  display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end;
  padding: var(--space-3) var(--space-4); border-top: 1px solid var(--c-border-hair); background: var(--c-sunken);
}

/* Na úzké obrazovce vyjíždí zespodu a drží se u spodní hrany — palec tam
   dosáhne, na horní okraj obrazovky ne. */
@media (max-width: 720px) {
  .dialog {
    width: 100vw; max-width: none; margin: auto auto 0; border-radius: var(--radius-3) var(--radius-3) 0 0;
    max-height: calc(100dvh - var(--space-4));
  }
}


/* Skryje prvek na telefonu. Používá se u položek lišty, které mají svůj
   domov v uživatelském menu. */
@media (max-width: 720px) { .u-hide-sm { display: none; } }

/* =====================================================================
   POŽADAVKY NA HESLO

   Doplněno 8. 8. 2026.

   Uživatel se dosud o nesplněném požadavku dozvěděl až po odeslání
   formuláře, a jen obecnou větou. Tenhle seznam se odškrtává při psaní,
   takže je vidět, co ještě chybí, dřív než člověk klikne.

   Stav nese znak i slovo, ne barva. Kdo barvy nerozezná, pozná splněný
   požadavek podle zaškrtnutí.
   ===================================================================== */
.requirements { display: grid; gap: 5px; margin: var(--space-2) 0 0; padding: 0; list-style: none; }
.requirement {
  display: flex; align-items: flex-start; gap: var(--space-2);
  font-size: var(--fs-meta); color: var(--c-ink-mute); line-height: var(--lh-base);
}
.requirement::before {
  content: "○"; flex: none; width: 1em; text-align: center;
  font-family: var(--font-mono); color: var(--c-ink-faint);
}
.requirement[data-met="true"] { color: var(--c-ok-ink); }
.requirement[data-met="true"]::before { content: "✓"; color: var(--c-ok-ink); }

/* Orientační síla hesla. Není to požadavek — proto pruh, ne zaškrtávátko:
   delší heslo je lepší, ale hranice „dost" je jediná a je v seznamu výše. */
.strength { display: grid; gap: 5px; margin-top: var(--space-2); }
.strength__track { display: flex; gap: 3px; }
.strength__step { height: 3px; flex: 1; background: var(--c-border); border-radius: var(--radius-1); }
.strength__label { font-size: var(--fs-meta); color: var(--c-ink-mute); }
.strength[data-level="1"] .strength__step:nth-child(-n+1) { background: var(--c-expired-line); }
.strength[data-level="2"] .strength__step:nth-child(-n+2) { background: var(--c-soon-line); }
.strength[data-level="3"] .strength__step:nth-child(-n+3) { background: var(--c-ok-line); }
.strength[data-level="4"] .strength__step { background: var(--c-ok-ink); }

/* =====================================================================
   AKCE V ŘÁDKU TABULKY

   Doplněno 8. 8. 2026.

   Akce v datagridu byly psané jako .btn--quiet, který má průhledný rámeček —
   výsledek vypadal jako obyčejný text a uživatel nepoznal, že se dá kliknout.

   Pravidlo: akce v řádku má **vždy viditelný rámeček a ikonu**. Tichá
   varianta patří do hlaviček a panelů, kde je kontext zřejmý, ne do mřížky
   plné textu.

   Na úzké obrazovce zůstane jen ikona. Popisek nese aria-label, takže
   odečítač obrazovky ani klávesnice o nic nepřijdou.
   ===================================================================== */
.table__actions { text-align: right; white-space: nowrap; }
.table__actions-group { display: inline-flex; gap: var(--space-1); align-items: center; justify-content: flex-end; }

/* Tichá tlačítka se v mřížce ztrácejí — v tomhle sloupci se z nich stanou
   normální ohraničená. */
.table__actions .btn--quiet { border-color: var(--c-border); background: var(--c-surface); color: var(--c-ink); }
/* Zakázaná akce v řádku musí vypadat zakázaně. Pravidlo nad tímhle vrací
   tichým tlačítkům v tabulce běžný vzhled a přebíjelo tím `.btn[disabled]`,
   takže „nelze smazat" a „smazat" vypadaly stejně. */
.table__actions .btn[disabled] { background: var(--c-sunken); border-color: var(--c-border); color: var(--c-ink-faint); cursor: not-allowed; }
.table__actions .btn { height: 26px; padding: 0 var(--space-2); gap: 5px; }
.table__actions .btn svg { width: 13px; height: 13px; flex: none; }

@media (max-width: 720px) {
  /* Na telefonu jen ikony — text by v kartě zabral řádek navíc. */
  .table__actions .btn__label { display: none; }
  .table__actions .btn { width: var(--control-h); padding: 0; justify-content: center; }
  .table__actions .btn svg { width: 16px; height: 16px; }
}

/* =====================================================================
   ŘÁDEK S VÝCHOZÍ AKCÍ

   Kliknutí kamkoli do řádku otevře detail záznamu. Je to očekávané chování
   a šetří míření na odkaz ve jméně.

   Přístupnost drží skutečný odkaz v první buňce: klávesnice na něj dojede
   tabulátorem a odečítač ho přečte. Kliknutí na řádek je jen pohodlí navíc,
   ne jediná cesta — proto se nikdy nedělá řádek klikatelný bez toho odkazu.
   ===================================================================== */

/* ---------------------------------------------------------------------------
   Navigace druhé úrovně

   Skupina má nadpis s ikonou a odsazené položky. Odsazení drží svislá linka,
   ne jen mezera — bez ní se při delších popiscích ztrácí, kam která položka
   patří. Ve zúžené navigaci linka i odsazení mizí, tam nese příslušnost už
   jen pořadí ikon.
   --------------------------------------------------------------------------- */
.app__nav-group { margin-top: var(--space-2); }
.app__nav-group-label {
  display: flex; align-items: center; gap: var(--space-2);
  height: 32px; padding: 0 var(--space-2);
  color: var(--c-ink-mute); font-size: var(--fs-control); font-weight: 500;
}
.app__nav-group .app__nav-item--sub {
  margin-left: calc(var(--space-2) + 9px);
  padding-left: var(--space-3);
  border-left: 1px solid var(--c-border);
  border-radius: 0 var(--radius-1) var(--radius-1) 0;
}
.app__nav-group .app__nav-item--sub[aria-current="page"] { border-left-color: var(--c-brand); }
.app__nav--mini .app__nav-group-label { justify-content: center; padding: 0; }
.app__nav--mini .app__nav-item--sub { margin-left: 0; padding-left: 0; border-left: 0; }

/* ---------------------------------------------------------------------------
   Matice oprávnění

   Řádek = oprávnění, sloupec = role. První sloupec zůstává při vodorovném
   posunu na místě — bez něj by uživatel po dvou sloupcích nevěděl, které
   oprávnění zaškrtává. Zaškrtávátka jsou vycentrovaná a mají velký klikací
   cíl přes celou buňku, protože se jich prochází desítky za sebou.
   --------------------------------------------------------------------------- */
.matrix { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
.matrix th, .matrix td { border-bottom: 1px solid var(--c-border); }
.matrix thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--c-surface); padding: var(--space-2);
  text-align: center; font-weight: 500; white-space: nowrap;
}
.matrix thead th:first-child { text-align: left; z-index: 3; left: 0; }
.matrix__module th {
  position: sticky; left: 0;
  background: var(--c-sunken); color: var(--c-ink-mute);
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; text-align: left;
}
.matrix__name {
  position: sticky; left: 0; z-index: 1;
  background: var(--c-surface); padding: var(--space-2);
  min-width: 240px;
  /* Buňka je <th scope="row">, prohlížeč jí sám dává na střed a tučně —
     v prvním sloupci matice se to čte jako nadpis, ne jako popisek řádku. */
  text-align: left; font-weight: 400;
}
.matrix__name code {
  display: block; font-family: var(--font-mono); font-size: var(--fs-micro);
  color: var(--c-ink-faint);
}
.matrix__cell { text-align: center; padding: 0; }
.matrix__cell label {
  display: flex; align-items: center; justify-content: center;
  min-height: 38px; cursor: pointer;
}
.matrix__cell input { width: 16px; height: 16px; accent-color: var(--c-brand); }
.matrix__cell input:disabled { cursor: not-allowed; opacity: .8; }
/* Zamčená buňka je zapnutá natrvalo, ne vypnutá. Bez podbarvení se šedé
   zaškrtávátko čte jako „vypnuto", tedy přesně obráceně. */
.matrix__cell[data-locked="true"] { background: var(--c-ok-soft); }
.matrix__cell[data-locked="true"] label:hover { background: none; cursor: not-allowed; }
.matrix__cell label:hover { background: var(--c-brand-soft); }
/* Odchylka od výchozí sady musí být vidět, jinak uživatel nepozná, co si
   agentura vědomě přenastavila a co je jen výchozí stav. */
.matrix__cell[data-customised="true"] { box-shadow: inset 2px 0 0 var(--c-brand); }
.matrix tbody tr:hover .matrix__name { background: var(--c-brand-soft); }

/* Základní .notice je varovná (červená). Potvrzení a neutrální sdělení jsou
   ale častější a v červené by hlásily poplach tam, kde žádný není. */
.notice--ok { border-color: var(--c-ok-line); background: var(--c-ok-soft); }
.notice--info { border-color: var(--c-border); background: var(--c-sunken); }
/* Upozornění, ne chyba — jantarová rodina, protože červená znamená „zápis se
   nepovedl". Pokrývá obojí, co po sloučení výkazů stálo pod dvěma jmény:
   v náboru „brzy" a „čeká" (upozornění, které nic neblokuje — duplicita,
   rozpracovaná položka, blížící se termín), ve výkazech varování, že se něco
   nespočítalo a čeká to na člověka. Byla to jedna sada hodnot pod dvěma
   názvy, takže si autor musel vybrat a recenzent uhlídat — a přesně tenhle
   krok spolehlivě vypadne. Tokeny zůstávají `--c-soon-*`: přejmenovat je
   napříč čtyřiceti pravidly by byla změna bez užitku. */
.notice--warn { border-color: var(--c-soon-line); background: var(--c-soon-soft); }
.notice--warn .notice__icon { color: var(--c-soon-ink); }

/* Řádek s výchozí akcí. Kurzor a podbarvení jsou jediné, co uživateli napoví,
   že se dá kliknout kamkoli — bez nich se klik hledá jen v buňce akcí. */
/* --- Lišta nad seznamem ---------------------------------------------------
   Hledání, filtr, sloupce a export jsou čtyři různé věci nad týmž seznamem.
   Když má každá vlastní pruh přes celou šířku, vypadá obrazovka, že se skládá
   ze samých ovládacích prvků a tabulka je až někde dole (Jakub 19. 8. 2026). */
.list-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center;
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--c-border-hair);
}
.list-toolbar__search { display: flex; gap: var(--space-2); flex: 1 1 320px; min-width: 0; }
.list-toolbar__search .input { flex: 1 1 auto; min-width: 0; }
.list-toolbar__actions { display: flex; gap: var(--space-2); align-items: center; flex: none; }
.list-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); padding: var(--space-2) var(--space-4); }

/* Panel visící z tlačítka. `<details>` proto, že zavírání a otevírání umí
   prohlížeč sám — včetně klávesnice a čtečky; JavaScript by tu nic nepřidal. */
.popover { position: relative; }
.popover > summary { list-style: none; cursor: pointer; }
.popover > summary::-webkit-details-marker { display: none; }
.popover__panel {
  position: absolute; z-index: 30; top: calc(100% + 4px); left: 0;
  /* Šířka se počítá ze **zbytku obrazovky**, ne pevně: panel otevřený od
     tlačítka u pravého okraje jinak přeteče ven a část ovládání zmizí. */
  width: max-content; min-width: 260px; max-width: calc(100vw - 2 * var(--space-3));
  max-height: 70vh; overflow: auto;
  padding: var(--space-3);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--radius-2); box-shadow: 0 8px 24px oklch(0 0 0 / 0.12);
}
.popover__panel--wide { width: min(560px, calc(100vw - 2 * var(--space-3))); }
.popover--right .popover__panel { left: auto; right: 0; }

/* Nativní popover se kreslí nad stránkou, takže ho neuřízne `overflow` tabulky.
   Volba sloupců je v záhlaví datagridu, a to se vodorovně roluje. */
.popover__panel--floating { position: fixed; inset: auto; margin: auto; }
.popover__panel--floating::backdrop { background: oklch(0 0 0 / 0.25); }
.table__sort { display: inline-flex; align-items: center; gap: 4px; color: inherit; text-decoration: none; }
.table__sort:hover { color: var(--c-brand-ink); }
.table__sort--active { color: var(--c-brand-ink); font-weight: 700; }

.popover__list { display: grid; gap: 1px; margin-top: var(--space-2); max-height: 40vh; overflow: auto; }
.popover__item { display: block; padding: 6px var(--space-2); border-radius: var(--radius-2); color: var(--c-ink); text-decoration: none; }
.popover__item:hover { background: var(--c-brand-soft); color: var(--c-brand-ink); }
.popover__item[hidden] { display: none; }
.list-views__more { align-self: end; }
.list-views__more > summary { cursor: pointer; }

.popover__group { margin: var(--space-2) 0 4px; font-size: var(--fs-micro); color: var(--c-ink-mute); text-transform: uppercase; letter-spacing: .04em; }
.popover__footer {
  display: flex; gap: var(--space-2); align-items: center;
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid var(--c-border-hair);
}
.badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 6px;
  border-radius: 9px; background: var(--c-brand); color: var(--c-surface);
  font-size: var(--fs-micro); font-weight: 600;
}

/* --- Stavitel filtru ------------------------------------------------------
   Podmínky v jednom rámci platí NEBO, rámce mezi sebou A ZÁROVEŇ. Rámec je
   proto vidět: bez ohraničení nejde poznat, co s čím a jak se kombinuje. */
.filter-group {
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  padding: var(--space-2) var(--space-3) var(--space-3); margin: 0 0 var(--space-2);
}
.filter-group__legend { padding: 0 6px; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.filter-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: end; margin-bottom: var(--space-2); }
.filter-row > .select { flex: 1 1 180px; min-width: 0; }
.filter-row__value { flex: 1 1 200px; display: grid; gap: var(--space-1); min-width: 0; }
.filter-row__value .input, .filter-row__value .select { width: 100%; }
/* Na mobilu jsou tři nabídky vedle sebe nepoužitelné — každá na svůj řádek. */
@media (max-width: 640px) {
  .filter-row > .select, .filter-row__value { flex-basis: 100%; }
}

.table__row--actionable { cursor: pointer; }
.table__row--actionable:hover { background: var(--c-brand-soft); }

/* Výběr více hodnot v podmínce filtru. Tlačítko musí vypadat a být vysoké
   jako vstup vedle něj — je to hodnota podmínky, ne akce — a nést popisek
   zarovnaný doleva, protože se na něm čtou vybrané hodnoty, ne jedno slovo. */
.filter-values { width: 100%; }
.filter-values__trigger {
  width: 100%; justify-content: space-between; gap: var(--space-2);
  font-weight: 400; overflow: hidden; text-overflow: ellipsis;
}
.filter-values__trigger::after { content: "▾"; flex: none; color: var(--c-ink-mute); }
.filter-values .popover__panel { min-width: 220px; }
/* Zaškrtávátka drží pohromadě `fieldset` kvůli čtečkám; jeho rámeček a odsazení
   od prohlížeče tu ale nic neznamenají — vzhled dělá `popover__list`. */
.filter-values fieldset.popover__list { border: 0; padding: 0; margin: 0; }

/* --- Chybějící údaje ------------------------------------------------------
   Výpis chybějících polí je rozcestník: každé pole je odkaz do sekce, kde se
   vyplňuje. Samo pole se pak podbarví, aby ho ve formuláři o dvaceti
   kolonkách šlo najít bez čtení. Barva je tatáž `soon`, jakou má upozornění
   na končící doklad — je to totéž sdělení „ozvi se, než bude pozdě", a dvě
   barvy pro jednu věc by uživatel musel rozlišovat zbytečně. */
a.chip--missing, .chip--missing {
  /* Chybět jich může dvacet, takže drobný a zabalitelný — plnovýšký chip by
     z přehledu úplnosti udělal půlstránku. */
  height: auto; padding: 1px 8px; margin: 2px 2px 0 0; font-size: var(--fs-meta);
  border-color: var(--c-soon-line); background: var(--c-soon-soft); color: var(--c-soon-ink);
  text-decoration: none;
}
a.chip--missing:hover { border-color: var(--c-soon-ink); }

.field--missing .field__label { color: var(--c-soon-ink); }
.field--missing .input, .field--missing .select, .field--missing .textarea {
  border-color: var(--c-soon-line); background: var(--c-soon-soft);
}
.field__hint--missing { color: var(--c-soon-ink); }
.facts__item--missing { background: var(--c-soon-soft); }
.facts__item--missing .facts__key { color: var(--c-soon-ink); }

/* Doskok na pole se na chvíli zvýrazní. Bez toho uživatel po kliknutí neví,
   jestli se stránka posunula na to pole, které chtěl — a trvalé zvýraznění by
   po pár kliknutích označilo celou kartu. */
.is-targeted { outline: 2px solid var(--c-soon-ink); outline-offset: 2px; transition: outline-color 1.4s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .is-targeted { transition: none; }
}

/* Rozrážka v patičce dialogu: destruktivní akce vlevo, potvrzení vpravo.
   Vedle sebe by se do „Uložit" dalo trefit omylem. */
.dialog__spacer { flex: 1; }

/* Atribut hidden musí přebít display z komponent. Prohlížeč ho dává přes
   [hidden] { display: none }, což prohraje s .btn { display: inline-flex } —
   skrytý prvek by zůstal vidět. */
[hidden] { display: none !important; }

/* ---------------------------------------------------------------------------
   Přepínač kontextu

   Jeden ovladač pro dvě úrovně: agentura (hranice dat — nic mezi agenturami
   nepřechází) a středisko (zúžení uvnitř agentury). Řádek agentury je sám
   o sobě volba, ne jen rozbalovací nadpis — bez toho by se ze zúžení nedalo
   vrátit zpátky jinak než přes adresní řádek.

   Panel není <dialog>: nemá zaclánět zbytku lišty ani zamykat pozadí, jde
   o rozbalovací nabídku, ne o modální krok.
   --------------------------------------------------------------------------- */
.switcher { position: relative; min-width: 0; }

/* `min(260px, 100%)` — samotných 260 px se drží i tam, kde na ně v liště
   místo není, a tlačítko pak přeteče přes ikonu asistenta. Vnitřní jména
   potřebují `min-width: 0`, jinak se ve flexu odmítnou zkrátit a ořezání
   trojtečkou se nikdy neuplatní. */
.switcher__trigger { max-width: min(260px, 100%); }
.switcher__trigger .switcher__agency,
.switcher__trigger .switcher__context { min-width: 0; }
.switcher__trigger .switcher__agency { color: var(--c-ink); }
.switcher__trigger .switcher__sep { color: var(--c-ink-faint); margin: 0 2px; }
.switcher__trigger .switcher__context { color: var(--c-ink-mute); }
.switcher__caret { flex: none; opacity: .5; }

/* Na telefonu je vidět jen užší z obou jmen. Agentura i hala naráz se do
   430 px nevejdou a rozhoduje ta, která se mění častěji — tedy provozovna.
   Bez tohohle by se ořízlo obojí na tři písmena a nepomohlo ani jedno. */
@media (max-width: 720px) {
  .switcher__trigger:has(.switcher__context) .switcher__agency,
  .switcher__trigger:has(.switcher__context) .switcher__sep { display: none; }

  /* Volné místo lišty patří na telefonu přepínači, ne rozpěrce: název haly
     rozhoduje, čí data jsou na obrazovce, a „hala Nýř…" tu otázku
     nezodpoví. Celoaplikační hledání je tu stejně skryté. */
  .app__topbar > .switcher { flex: 1 1 auto; }
  .app__topbar > .app__spacer { display: none; }
}

.switcher__panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  width: 340px; max-width: calc(100vw - 2 * var(--space-3)); max-height: 60vh;
  overflow: auto;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--radius-2); box-shadow: 0 8px 24px rgb(0 0 0 / .12);
  padding: var(--space-2);
}
/* Na telefonu panel nevisí z tlačítka, ale drží se obrazovky. Přepínač stojí
   uprostřed lišty, takže by mu 340 px vpravo nezbylo — panel by vylezl mimo
   obraz a stránka by se dala odrolovat do strany. */
@media (max-width: 720px) {
  .switcher__panel {
    position: fixed; top: calc(var(--topbar-h) + 4px);
    left: var(--space-2); right: var(--space-2);
    width: auto; max-width: none;
    max-height: calc(100dvh - var(--topbar-h) - var(--space-4));
  }
}

.switcher__search { margin-bottom: var(--space-2); }
.switcher__group + .switcher__group {
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid var(--c-border);
}

.switcher__item {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: 7px var(--space-2); border-radius: var(--radius-1);
  text-align: left; background: none; border: 0; cursor: pointer;
  color: var(--c-ink); font: inherit; font-size: var(--fs-base);
}
.switcher__item:hover { background: var(--c-sunken); text-decoration: none; }
.switcher__item[aria-current="true"] { background: var(--c-brand-soft); font-weight: 500; }

.switcher__body { flex: 1; min-width: 0; }
.switcher__name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.switcher__meta { display: block; font-size: var(--fs-meta); color: var(--c-ink-mute); }
/* Zaškrtnutí se u nevybraných jen zneviditelní, ale místo si drží — jinak by
   se text položek proti sobě posouval podle toho, která je vybraná. */
.switcher__check { flex: none; width: 16px; height: 16px; color: var(--c-brand); }
.switcher__check--empty { visibility: hidden; }

.switcher__item--agency .switcher__name { font-weight: 600; }

/* Zákazník a provozovna pod agenturou drží svislá linka, každý o krok dál.
   Samotné odsazení při delších názvech nestačí — ztratí se, kam která
   položka patří. Stejně to řeší druhá úroveň levé navigace. */
.switcher__item--customer,
.switcher__item--site {
  /* Odsazení je margin, takže se k plné šířce přičítá. Bez odečtení by panel
     dostal vodorovný posuvník; s `width: auto` by se zase podbarvení vybrané
     položky smrsklo na šířku textu. */
  width: calc(100% - var(--space-3));
  margin-left: var(--space-3); padding-left: var(--space-3);
  border-left: 1px solid var(--c-border);
  border-radius: 0 var(--radius-1) var(--radius-1) 0;
}
.switcher__item--site { width: calc(100% - var(--space-5)); margin-left: var(--space-5); }
.switcher__item--customer[aria-current="true"],
.switcher__item--site[aria-current="true"] { border-left-color: var(--c-brand); }

/* Skrytí hledáním. Bez tohohle by `hidden` prohrálo s `display: flex` výš
   a odfiltrovaná položka by dál svítila na obrazovce. */
.switcher__item[hidden], .switcher__entry[hidden], .switcher__group[hidden] { display: none; }

/* Prst není myš: řádek vysoký 30 px se na telefonu trefuje o patro vedle. */
@media (pointer: coarse) {
  .switcher__item { min-height: var(--control-h-tp); }
}

/* Prázdno se čte jako chyba načtení, proto popisek. */
.switcher__empty {
  margin-left: var(--space-3); padding: 6px var(--space-3);
  border-left: 1px solid var(--c-border);
  font-size: var(--fs-meta); color: var(--c-ink-faint);
}

/* ---------------------------------------------------------------------------
   Pás stavu předplatného

   Nese jedno sdělení a nanejvýš jednu akci — dvě akce vedle sebe znamenají,
   že uživatel neví, co se po něm chce.

   Barvu určuje stav, ne důležitost: běžící trial je klidný (zelená), poslední
   týden varuje (jantarová), vypršelý stav je červený. Nezapočatý trial a
   zaplacené předplatné zůstávají bez modifikátoru — není o čem rozhodovat
   a barevný pruh by hlásil poplach tam, kde žádný není.
   --------------------------------------------------------------------------- */
.plan-strip {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); border-radius: var(--radius-2);
  border: 1px solid var(--c-border); background: var(--c-sunken);
  margin-bottom: var(--space-4);
}
.plan-strip__body { flex: 1; min-width: 0; }
.plan-strip__title { font-weight: 600; }
.plan-strip__text { color: var(--c-ink-mute); font-size: var(--fs-control); margin-top: 2px; }
.plan-strip--trial { border-color: var(--c-ok-line); background: var(--c-ok-soft); }
.plan-strip--soon  { border-color: var(--c-soon-line); background: var(--c-soon-soft); }
.plan-strip--expired { border-color: var(--c-expired-line); background: var(--c-expired-soft); }

/* Místo pro pás a odmítnutý zápis v obsahové oblasti skořápky. Bez vlastní
   obálky by se pás lepil na levou navigaci — hlavička obrazovky a tabulka
   si okraje nesou samy, pás nad nimi žádnou nemá. */
.app__banner { padding: var(--space-4) var(--space-4) 0; }

/* ---------------------------------------------------------------------------
   Karta s měřidlem

   Metrika je velká, protože je to jediné číslo, o kterém se dá vést cenový
   spor — a spor, který si zákazník rozklikne, není spor.

   Každá karta má poznámku pod číslem. Nula bez vysvětlení se čte jako chyba
   načtení, ne jako stav.
   --------------------------------------------------------------------------- */
.meters { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-3); }
.meter {
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); padding: var(--space-3);
}
.meter__label { font-size: var(--fs-meta); color: var(--c-ink-mute); text-transform: uppercase; letter-spacing: .04em; }
.meter__value { font-size: 30px; font-weight: 600; line-height: 1.15; margin: 6px 0 2px; }
.meter__unit { font-size: var(--fs-control); color: var(--c-ink-mute); font-weight: 400; }
.meter__note { font-size: var(--fs-meta); color: var(--c-ink-mute); }
.meter__note a { font-size: inherit; }

/* Pruh vyčerpání. Bez známého limitu se nekreslí vůbec — prázdný pruh
   by tvrdil, že limit existuje a je nulový. Proto ho má jen pásmo;
   výše AI a SMS kreditů zatím není nakalibrovaná (otevřený bod C1). */
.meter__bar { height: 6px; border-radius: 3px; background: var(--c-sunken); margin: 10px 0 6px; overflow: hidden; }
.meter__bar span { display: block; height: 100%; background: var(--c-brand); border-radius: 3px; }

/* Docházející zůstatek: pruh mění barvu, ale význam nese i slovo v poznámce
   a banner nad obsahem — barva sama není pro člověka s poruchou barvocitu
   informace. */
.meter__bar--low span { background: var(--c-soon-line); }

/* Naplnění zakázky (nábor, E15): číslo + pruh. Pruh jen tam, kde je známý
   strop — zakázka do zásoby ho nemá a prázdný pruh by tvrdil, že limit
   existuje a je nulový (táž úvaha jako u .meter__bar). Přeneseno
   z design/e15/e15.css. */
.fill { display: inline-flex; align-items: center; gap: 8px; }
.fill__bar { width: 72px; height: 6px; border-radius: 3px; background: var(--c-sunken); position: relative; overflow: hidden; flex: none; }
.fill__bar::after { content: ""; position: absolute; inset: 0; width: var(--w, 0%); background: var(--c-brand); }
.fill--done .fill__bar::after { background: var(--c-ok-ink); }

/* Ceník. Vlastní příčka se vyznačuje přes aria-current, ne modifikátorem —
   stejné pravidlo jako u přepínače kontextu a levé navigace. */
.plan-table td:last-child { text-align: right; white-space: nowrap; }
.plan-table tr[aria-current="true"] { background: var(--c-brand-soft); font-weight: 500; }

/* ---------------------------------------------------------------------------
   Nabídka k nákupu — tarify a balíčky kreditů

   Karta je formulář: jedno tlačítko, jedna položka. Vybraná (současná) se
   značí přes aria-current a klidným odznakem, ne barvou celé karty — čtyři
   barevné karty vedle sebe by si konkurovaly a ta „vaše" by nebyla vidět.
   Tlačítko zakázané s důvodem (title + věta) místo skrytého: skryté vypadá
   jako chybějící funkce.
   --------------------------------------------------------------------------- */
.offers { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-3); }
.offer {
  display: grid; gap: var(--space-2); align-content: start;
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); padding: var(--space-3);
}
.offer[aria-current="true"] { border-color: var(--c-brand-line); }
.offer__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: 22px; }
.offer__price { font-size: 22px; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; }
.offer__list { margin: 0; padding-left: 18px; font-size: var(--fs-control); display: grid; gap: 2px; }
.offer__muted { color: var(--c-ink-mute); }
.offer .btn { justify-self: start; }
.offer .field__hint { margin: 0; }
.u-muted { color: var(--c-ink-mute); }

/* ---------------------------------------------------------------------------
   Panel asistenta

   Doplněno 8. 8. 2026 při návrhu E6 (`specifikace/11-agent-e6.md`).

   Vysouvací panel zprava, dostupný z každé obrazovky. Agent je pomocník
   u toho, co uživatel právě dělá — chat, za kterým se chodí, se přestane
   používat.

   Panel **překrývá obsah, neposouvá ho**. Posun by při každém otevření
   přeskládal celou obrazovku a uživatel by ztratil místo, na které se díval.

   Pod 720 px je to **plnoplošná vrstva, ne zúžený panel**. Koordinátor na
   ubytovně má v ruce telefon; panel o šířce 320 px na displeji o šířce
   390 px je jen horší obrazovka.
   --------------------------------------------------------------------------- */
.assist-mount { position: relative; }

.assist-panel {
  position: fixed; top: var(--topbar-h); right: 0; bottom: 0;
  width: var(--assist-w); max-width: 100%;
  z-index: 40; box-shadow: var(--shadow-2);
}

.assist {
  display: flex; flex-direction: column; height: 100%;
  background: var(--c-surface); border-left: 1px solid var(--c-border);
}

.assist__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--c-border); flex: none;
}
.assist__title { font-weight: 600; flex: 1; min-width: 0; }

/* Odznak „jen čtení". Po vypršení trialu agent odpovídá dál, ale zapisovat
   nenabídne — a říct to dřív, než se uživatel zeptá, je levnější než
   vysvětlovat to potom. */
.assist__badge {
  font-family: var(--font-mono); font-size: var(--fs-micro);
  color: var(--c-ink-mute); background: var(--c-sunken);
  border-radius: var(--radius-1); padding: 1px 6px;
}

.assist__thread {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-3);
}

/* Zpráva uživatele je jediný kanál, kterým do agenta tečou pokyny — proto
   se i vizuálně odlišuje od všeho ostatního, co v panelu je. Výsledky
   nástrojů, náhledy ani upozornění tenhle podklad nedostanou. */
.msg { display: flex; flex-direction: column; gap: var(--space-1); }
.msg__who {
  font-size: var(--fs-micro); color: var(--c-ink-mute);
  text-transform: uppercase; letter-spacing: .04em;
}
.msg__body { font-size: var(--fs-base); line-height: 1.55; }
/* Bublina, kterou hned po odeslání složil prohlížeč. Text se do ní vkládá
   jako text, ne jako HTML, takže konce řádků musí udržet styl — jinak by
   zpráva o dvou odstavcích vypadala jinak před odpovědí a jinak po ní. */
.msg__body--typed { white-space: pre-line; }
.msg--user .msg__body {
  background: var(--c-sunken); border-radius: var(--radius-2);
  padding: var(--space-2) var(--space-3); align-self: flex-start;
}

/* Průběh práce. Nepíše se, který nástroj se volá — uživatele nezajímá
   `invite_colleague`, zajímá ho, že se něco děje a co. */
.assist__work {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-meta); color: var(--c-ink-mute);
}
.assist__work::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-brand); flex: none;
}

/* Návrh zápisu. Věta je generovaná kódem nástroje, ne modelem — jinak by
   nešla při potvrzení porovnat a mohla by popisovat něco jiného, než co
   se skutečně stane. */
.proposal {
  border: 1px solid var(--c-border); border-left: 3px solid var(--c-brand);
  border-radius: var(--radius-2); background: var(--c-surface);
  padding: var(--space-3);
}
.proposal__label {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .04em;
  color: var(--c-ink-mute); margin-bottom: var(--space-1);
}
.proposal__what { font-size: var(--fs-base); line-height: 1.5; }
.proposal__foot {
  display: flex; gap: var(--space-2); align-items: center;
  margin-top: var(--space-3); flex-wrap: wrap;
}
.proposal__expiry { font-size: var(--fs-micro); color: var(--c-ink-faint); margin-left: auto; }

/* Zastaralý návrh: svět se mezi návrhem a potvrzením změnil. Obě věty musí
   být vidět vedle sebe — jinak uživatel potvrzuje něco jiného, než četl. */
.proposal--stale { border-left-color: var(--c-soon-line); }
.proposal__was {
  font-size: var(--fs-control); color: var(--c-ink-mute);
  text-decoration: line-through; margin-bottom: var(--space-1);
}
.proposal__now { font-size: var(--fs-base); font-weight: 500; line-height: 1.5; }

/* Vyrušení z vlastní vůle systému. Musí být na první pohled jiné než
   odpověď na dotaz — uživatel se na to neptal. */
.assist__interrupt {
  border: 1px solid var(--c-expired-line); background: var(--c-expired-soft);
  border-radius: var(--radius-2); padding: var(--space-3);
}
.assist__interrupt-label {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .04em;
  color: var(--c-expired-ink); font-weight: 600; margin-bottom: var(--space-1);
}

.assist__composer {
  flex: none; border-top: 1px solid var(--c-border);
  padding: var(--space-2) var(--space-3);
  display: flex; gap: var(--space-2); align-items: flex-end;
}
.assist__composer textarea {
  flex: 1; min-height: var(--control-h); max-height: 120px; resize: none;
  font: inherit; font-size: var(--fs-base);
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  padding: var(--space-2); background: var(--c-surface); color: var(--c-ink);
}
.assist__hint {
  flex: none; font-size: var(--fs-micro); color: var(--c-ink-faint);
  padding: 0 var(--space-3) var(--space-2); margin: 0;
}

/* Spouštěč v liště. Zavřený stav je to, co uživatel vidí 99 % času — musí
   být poznat, kde asistent je, a jestli na něco čeká. Bez počtů: buď je
   tam něco k vyřízení, nebo není. */
.assist-trigger { position: relative; }
.assist-trigger--active { border-color: var(--c-brand); color: var(--c-brand); }
.assist-trigger__dot {
  position: absolute; top: -3px; right: -3px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--c-brand); border: 2px solid var(--c-surface);
}
/* Jiná barva pro jiný druh čekání: návrh čeká na tebe, tohle čeká na
   vhodnou chvíli. */
.assist-trigger__dot--waiting { background: var(--c-soon-ink); }

@media (max-width: 720px) {
  /* Plnoplošná vrstva, ne zúžený panel. `dvh` je podstatné: s vyjetou
     klávesnicí se `vh` na mobilu nemění, takže by pole pro psaní zůstalo
     pod klávesnicí. */
  .assist-panel {
    top: 0; left: 0; width: auto; height: 100dvh;
    box-shadow: none;
  }
  .assist { border-left: 0; }

  /* Popisek tlačítka by na úzkém displeji sebral místo textu — stejné
     pravidlo jako u akcí v řádku tabulky. */
  .assist__composer .btn--primary { padding-inline: var(--space-3); }
}

/* ---------------------------------------------------------------------------
   Zvoneček

   Vzniká proto, že agent smí vyrušit nejvýš jednou za sezení — zbytek musí
   mít kam spadnout, jinak by se buď ztratil, nebo by vyskakoval pořád.

   Na rozdíl od asistenta **ukazuje počet**: upozornění jsou položky
   k vyřízení a jejich počet něco říká.
   --------------------------------------------------------------------------- */
.bell-mount { position: relative; }
.bell-count {
  position: absolute; top: -6px; right: -6px;
  min-width: 16px; height: 16px; padding: 0 var(--space-1);
  border-radius: 8px; background: var(--c-brand); color: var(--c-on-brand);
  font-size: var(--fs-micro); line-height: 16px; text-align: center;
}
.bell-drop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  width: var(--bell-w); max-width: calc(100vw - var(--space-4) * 2);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--radius-3); box-shadow: var(--shadow-2);
}
.bell-panel { display: block; padding: var(--space-2); }
.bell-panel__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 0 var(--space-2) var(--space-2);
}
.bell-panel__head strong { flex: 1; }
/* Prázdno se čte jako chyba načtení, ne jako stav — proto věta. */
.bell-panel__empty {
  margin: 0; padding: 0 var(--space-2) var(--space-2);
  font-size: var(--fs-control); color: var(--c-ink-mute);
}
.bell-item {
  display: flex; gap: var(--space-2); padding: var(--space-2);
  border-radius: var(--radius-1); align-items: flex-start;
}
.bell-item:hover { background: var(--c-sunken); }
.bell-item__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--c-brand); margin-top: 6px; flex: none;
}
.bell-item__dot--read { background: var(--c-border); }
.bell-item__body { flex: 1; min-width: 0; font-size: var(--fs-control); line-height: 1.45; }
.bell-item__when { display: block; font-size: var(--fs-micro); color: var(--c-ink-faint); }

/* ---------------------------------------------------------------------------
   NASTAVENÍ AGENTURY A POBOČEK (E7)

   Dlouhý formulář rozdělený na sekce. Nastavení agentury má i u nejmenšího
   státu přes dvacet polí — bez rozdělení je to zeď, ve které se nedá najít,
   co člověk hledá.
   --------------------------------------------------------------------------- */
.form-section { border-top: 1px solid var(--c-border); padding: var(--space-4); }
.form-section:first-of-type { border-top: 0; }
.form-section__head { margin-bottom: var(--space-3); }
.form-section__title { font-size: var(--fs-section); font-weight: 600; }
.form-section__hint {
  font-size: var(--fs-control); color: var(--c-ink-mute);
  margin-top: 2px; max-width: 62ch; text-wrap: pretty;
}
.form-section__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }

/* Sloupce se skládají samy podle šířky. Na telefonu z toho vyjde jeden
   sloupec, aniž by na to byl potřeba zlom — sekce zůstávají, protože právě
   ony dělají z dvaceti polí něco procházitelného. */
/* Formular, ktery drzi vic karet, je jejich rozvrzeni — bez toho se karty
   dotykaji, protoze mezery na strance rozdava `.page-body` a formular je
   pro ni jedna polozka. */
.form-stack { display: grid; gap: var(--space-4); align-content: start; }

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-3); }
.form-grid + .form-grid { margin-top: var(--space-3); }
.form-grid--wide { grid-template-columns: 1fr; }
/* Ulice je delší než PSČ, takže dostane víc místa; pod 560 px se stejně
   všechno srovná pod sebe. */
.form-grid--address { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
/* Pole se neroztáhnou přes celou šířku, ale zarovnají se zleva do sloupců
   rozumné šířky. Bez horní mezí rozsype `auto-fit` šest polí do šesti
   různě vysokých sloupců — formálně mřížka, na pohled náhoda. */
.form-grid--tight { grid-template-columns: repeat(auto-fit, minmax(220px, 300px)); }

.form-subhead { margin: var(--space-4) 0 var(--space-2); display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }

.field__check { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-control); }
.field__check input { accent-color: var(--c-brand); }

/* Pole načtené z rejstříku. Uživatel musí poznat, co si vyplnil sám a co
   přišlo odjinud — jinak nepozná, co smí přepsat, aniž by si koledoval
   o přepsání zpátky. */
.from-registry .input { background: var(--c-sunken); }
.from-registry__mark { font-size: var(--fs-micro); color: var(--c-ink-faint); }

/* Náhled změn z rejstříku. Přepsat data, na kterých stojí smlouvy, se nesmí
   potichu — uživatel vidí, co se změní, a potvrdí to. */
.diff { border: 1px solid var(--c-border); border-radius: var(--radius-2); overflow: hidden; }
.diff__row {
  display: grid; grid-template-columns: 180px 1fr 1fr; gap: var(--space-3);
  padding: 9px var(--space-3); border-top: 1px solid var(--c-border);
  font-size: var(--fs-control);
}
.diff__row:first-child {
  border-top: 0; background: var(--c-sunken); font-size: var(--fs-micro);
  text-transform: uppercase; letter-spacing: .04em; color: var(--c-ink-mute);
}
.diff__was { color: var(--c-ink-mute); text-decoration: line-through; }
.diff__now { font-weight: 500; }
.diff__row--same .diff__now { font-weight: 400; color: var(--c-ink-mute); }

/* Lidé, kteří brání zavření pobočky. Seznam je krátký ze své podstaty. */
.holder-list { margin: 0; padding-left: 18px; font-size: var(--fs-control); line-height: 1.7; }
.holder-list__more { color: var(--c-ink-mute); }

@media (max-width: 640px) {
  .form-section { padding: var(--space-3); }
  /* Tři sloupce vedle sebe se na telefonu rozpadnou na nečitelné sloupečky.
     Záhlaví se skryje a role řádku nese pomlčka mezi hodnotami. */
  .diff__row { grid-template-columns: 1fr; gap: 2px; }
  .diff__row:first-child { display: none; }
  .diff__row > div:first-child { color: var(--c-ink-mute); font-size: var(--fs-meta); }
}

/* ---------------------------------------------------------------------------
   PRACOVNÍ POMĚR A JEHO ZMĚNY V ČASE (E11a)

   Čtyři vzory, které v systému chyběly. Všechny jsou postavené z tokenů —
   žádná nová barva, žádný nový rozměr.
   --------------------------------------------------------------------------- */

/* Rámec jednoho poměru. Je to `.card` s vlastní hlavičkou; nové je jen to, že
   hlavička nese stav a akce poměru. */
.emp { margin-bottom: var(--space-4); }
.emp__head {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  margin-bottom: var(--space-3); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--c-border-hair);
}
.emp__title { font-size: var(--fs-body); font-weight: 600; }
.emp__no { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.emp__actions { margin-left: auto; display: flex; gap: var(--space-2); align-items: center; }

/* Původ hodnoty u fakta. Karta musí u každé hodnoty ukázat, odkud platí —
   jinak si koordinátor skládá aktuální stav z dodatků v hlavě. Je to jeden
   řádek uvnitř existujícího `.facts__value`, ne nová komponenta. */
.facts__from { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); font-weight: 400; }

/* Akce na řádku časové osy. `.timeline` byl jen pro čtení; u poměru se
   z položky otevírá oprava zápisu. Přidává se pravý slot. */
.timeline__item { position: relative; }
.timeline__act { position: absolute; right: 0; top: 0; display: flex; gap: var(--space-2); font-size: var(--fs-micro); }
.timeline__kind { font-weight: 600; }

/* Volba dne, ke kterému se karta čte (M3-P2), a krátké formuláře v pásu
   upozornění: popis, jedno pole, jedno tlačítko na jednom řádku. */
.asof { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-control); color: var(--c-ink-mute); }
.asof .input { width: 150px; }

/* Současná hodnota vedle nové. `.form-grid` skládá pole vedle sebe, ale neumí
   ukázat hodnotu PŘED změnou — a dodatek se bez toho zadat nedá: uživatel musí
   vidět, co mění, a prázdné pole musí znamenat „beze změny", ne vymazání. */
.change {
  display: grid; gap: 1px; background: var(--c-border-hair);
  border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); overflow: hidden;
}
.change__head, .change__row {
  display: grid; grid-template-columns: 190px minmax(120px, 1fr) minmax(180px, 1.4fr);
  gap: var(--space-3); align-items: center; background: var(--c-surface); padding: 9px var(--space-3);
}
.change__head {
  background: var(--c-sunken); font-size: var(--fs-micro); font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em; color: var(--c-ink-mute);
}
.change__label { font-size: var(--fs-control); font-weight: 500; }
.change__now {
  font-size: var(--fs-control); color: var(--c-ink-mute);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.change__new { display: grid; gap: 4px; }

/* Výčet dopadů akce. `.facts` je dvojice popis–hodnota o stavu záznamu; tady
   jde o to, co se stane po potvrzení, a řádek nese víc položek. */
.impact {
  display: grid; gap: 1px; background: var(--c-border-hair);
  border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); overflow: hidden;
  margin: 0; padding: 0; list-style: none;
}
.impact__row {
  display: grid; grid-template-columns: 118px minmax(0, 1fr); gap: var(--space-3);
  background: var(--c-surface); padding: 9px var(--space-3); font-size: var(--fs-control);
}
.impact__what {
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--c-ink-mute); padding-top: 2px;
}
.impact__detail { display: grid; gap: 3px; }
.impact__none { color: var(--c-ink-faint); }

@media (max-width: 720px) {
  /* Tři sloupce vedle sebe se na telefonu rozpadnou na nečitelné sloupečky.
     Záhlaví se skryje a roli řádku nese popis nad hodnotami. */
  .change__row { grid-template-columns: 1fr; gap: 4px; }
  .change__head { display: none; }
  .impact__row { grid-template-columns: 1fr; gap: 4px; }
  /* Akce u položky osy by se v absolutním umístění překryla s textem. */
  .timeline__act { position: static; margin-top: 4px; }
}

/* =====================================================================
   KANBAN ZAKÁZKY, KARTIČKA A PANEL ÚČASTI (nábor, E15 krok 3)

   Nový vzor (design/e15/README.md): seznam s filtry neumí sloupce jako
   fáze ani přesun mezi nimi. Sloupec má pevnou šířku, protože se posouvá
   vodorovně — šířka je vlastností vzoru, ne obsahu. Typ fáze nese horní
   linka **i** slovo v hlavičce. Kartička je hustá: 3–4 řádky, jen to, co
   rozhoduje. Panel účasti překrývá, neposouvá (stejné pravidlo jako panel
   asistenta); na telefonu je plnoplošný. Přeneseno z design/e15/e15.css,
   všechno přes tokeny.
   ===================================================================== */
.board-head { border-bottom: 1px solid var(--c-border); background: var(--c-surface); padding-bottom: var(--space-3); }
.board-bar { border-bottom: 1px solid var(--c-border); background: var(--c-surface); }
.seg { display: inline-flex; border: 1px solid var(--c-border); border-radius: var(--radius-1); overflow: hidden; }
.seg__item { padding: 0 10px; height: var(--control-h); line-height: var(--control-h); font-size: var(--fs-control); background: var(--c-surface); border: 0; cursor: pointer; color: var(--c-ink); text-decoration: none; white-space: nowrap; }
.seg__item:hover { text-decoration: none; background: var(--c-sunken); }
.seg__item[aria-pressed="true"], .seg__item[aria-selected="true"] { background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600; }

.board-wrap { position: relative; }
.board-wrap--panel { margin-right: 440px; }
.board { display: flex; gap: var(--space-3); padding: var(--space-3) var(--space-4) var(--space-5); overflow-x: auto; align-items: flex-start; }
.board__col { flex: 0 0 264px; background: var(--c-sunken); border: 1px solid var(--c-border-hair); border-top: 3px solid var(--c-inactive-ink); border-radius: var(--radius-2); display: grid; grid-template-rows: auto 1fr; max-height: calc(100vh - 230px); }
.board__col--entry { border-top-color: var(--c-brand); }
.board__col--success { border-top-color: var(--c-ok-ink); }
.board__col--failure { border-top-color: var(--c-rejected-ink); }
.board__col--over { outline: 2px dashed var(--c-brand); outline-offset: -2px; }
.board__head { display: flex; align-items: center; gap: 6px; padding: 8px 10px; position: sticky; top: 0; background: var(--c-sunken); border-bottom: 1px solid var(--c-border-hair); flex-wrap: wrap; }
.board__name { font-weight: 600; font-size: var(--fs-control); }
.board__type { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.board__count { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.board__late { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-soon-ink); }
.board__more { margin-left: auto; }
.board__body { padding: 8px; display: grid; gap: 8px; align-content: start; overflow-y: auto; min-height: 80px; }
.board__hint { font-size: var(--fs-micro); color: var(--c-ink-mute); padding: 6px 10px; text-align: center; margin: 0; }
.board__notice { margin: var(--space-3) var(--space-4) 0; }
.board-empty { padding: var(--space-4); display: grid; gap: var(--space-3); }
.board-tabs { display: none; margin: var(--space-2) var(--space-4) 0; overflow-x: auto; }

.kcard { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-2); padding: 8px 10px; display: grid; gap: 4px; cursor: pointer; box-shadow: var(--shadow-1); }
.kcard[draggable="true"] { cursor: grab; }
.kcard:hover { border-color: var(--c-brand-line); }
.kcard:focus-visible { outline: 2px solid var(--c-brand); outline-offset: 2px; }
.kcard[aria-selected="true"] { border-color: var(--c-brand); box-shadow: 0 0 0 1px var(--c-brand); }
.kcard--dragging { opacity: .5; }
.kcard--late { border-left: 3px solid var(--c-soon-line); }
.kcard__top { display: flex; align-items: baseline; gap: 6px; }
.kcard__name { font-weight: 600; }
.kcard__name a { color: inherit; }
.kcard__meta { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.kcard__row { display: flex; flex-wrap: wrap; gap: 4px 8px; font-size: var(--fs-micro); color: var(--c-ink-mute); align-items: center; }
.kcard__foot { display: flex; align-items: center; gap: 6px; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.kcard__menu { margin-left: auto; }
.kcard__menu .popover__panel { min-width: 220px; }
.kcard__menu .popover__list button { text-align: left; border: 0; background: none; cursor: pointer; font: inherit; width: 100%; }
@media (pointer: coarse) { .kcard { padding: 10px 12px; } }

/* Varování se znakem i slovem — nikdy jen barva. */
.warn { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-micro); color: var(--c-soon-ink); }
.warn::before { content: "△"; }
.warn--danger { color: var(--c-danger); } .warn--danger::before { content: "✕"; }
.warn--late { color: var(--c-ink-mute); } .warn--late::before { content: "⏱"; }
.score { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-micro); font-weight: 600; padding: 0 5px; border-radius: var(--radius-1); color: var(--c-ok-ink); background: var(--c-ok-soft); }
/* Procento shody matchingu (E15 krok 23). Barva je doprovod, ne informace —
   číslo je v samotné značce, takže se dá přečíst i bez ní. Přeneseno
   z e15.css; `score--low` mockup nemá, ale nula bez odlišení vypadá jako
   vysoká shoda v šedé. */
.score--hi { color: var(--c-ok-ink); background: var(--c-ok-soft); }
.score--mid { color: var(--c-soon-ink); background: var(--c-soon-soft); }
.score--low { color: var(--c-ink-mute); background: var(--c-sunken); }
/* „Nelze vyhodnotit" nemá procento a nesmí splynout s nulou: vlastní
   podbarvení a v odznaku slovo, ne číslo (M2-P15). Odznak je pak širší než
   procento, proto `white-space: nowrap` — zalomený stav vedle jména vypadá
   jako druhý údaj. */
.score--unknown { color: var(--c-ink-mute); background: var(--c-sunken); border: 1px dashed var(--c-line); white-space: nowrap; }

/* Seznam návrhů matchingu — kartičky pod sebou (E15 § 6.8, mockup
   7-matching). Vlastní třída místo `style` na kontejneru, aby ji uměla
   i sbalená část pod čarou. */
.match-list { display: grid; gap: 8px; }
.match-list .kcard { cursor: default; }

/* Řádek posuvníku váhy v nastavení matchingu (E15 § 6.9). Přeneseno
   z e15.css beze změny. */
.wrow { display: grid; grid-template-columns: 170px 1fr 40px; gap: var(--space-3); align-items: center; font-size: var(--fs-control); padding: 4px 0; }
/* `accent-color` jako u ostatních vstupů: bez něj kreslí prohlížeč
   posuvník svou systémovou modrou a jediná obrazovka v aplikaci má
   jinou barvu ovládání než všechny ostatní. */
.wrow input[type="range"] { width: 100%; accent-color: var(--c-brand); }
.wrow__v { font-family: var(--font-mono); text-align: right; }

/* Panel účasti: fixovaný vpravo, tři pruhy (hlava, tělo, patička). */
.side { position: fixed; top: var(--topbar-h, 52px); right: 0; bottom: 0; width: 440px; background: var(--c-surface); border-left: 1px solid var(--c-border); box-shadow: var(--shadow-2); display: grid; grid-template-rows: auto 1fr auto; z-index: 20; }
.side[hidden] { display: none; }
.side__head { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--c-border); display: grid; gap: 4px; position: relative; }
.side__close { position: absolute; right: 8px; top: 8px; }
.side__title { font-size: var(--fs-section); font-weight: 600; margin: 0; }
.side__body { overflow-y: auto; padding: var(--space-3) var(--space-4); display: grid; gap: var(--space-4); align-content: start; }
.side__foot { padding: var(--space-2) var(--space-4); border-top: 1px solid var(--c-border); display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.side__tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--c-border); margin-top: 4px; }
.side__tab { padding: 6px 10px; font-size: var(--fs-control); border: 0; background: none; border-bottom: 2px solid transparent; cursor: pointer; color: var(--c-ink-mute); text-decoration: none; }
.side__tab:hover { text-decoration: none; color: var(--c-ink); }
.side__tab[aria-selected="true"] { color: var(--c-brand-ink); border-bottom-color: var(--c-brand); font-weight: 600; }
.side__inline { display: flex; gap: var(--space-2); align-items: center; margin-top: var(--space-2); }
.side__inline .select { flex: 1; min-width: 0; }
.side .req__mark { padding-top: 0; }
.side .tag form { display: inline; }

/* Lišta hromadných akcí nad tabulkou. */
.bulk-bar { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4); background: var(--c-brand-soft); border-bottom: 1px solid var(--c-brand-line); font-size: var(--fs-control); }
.bulk-bar[hidden] { display: none; }
.table__cell--check { width: 32px; }

/* Editace preferencí na kartě: rozbalí se pod tlačítkem, formulář je Turbo rámec. */
.pref-edit { margin-bottom: var(--space-3); }
.pref-edit > summary { list-style: none; display: inline-block; }
.pref-edit > summary::-webkit-details-marker { display: none; }
.pref-edit[open] > summary { margin-bottom: var(--space-3); }

/* Telefon: jeden sloupec na obrazovku, přepínání záložkami; panel plnoplošný (§ 6.12). */
@media (max-width: 720px) {
  .board-tabs { display: inline-flex; }
  .board { padding: var(--space-2) var(--space-3) var(--space-4); }
  .board__col { flex: 1 1 100%; max-height: none; }
  .board__col:not([data-active="true"]) { display: none; }
  .board-wrap--panel { margin-right: 0; }
  .side { width: 100%; top: 0; }
}
@media (max-width: 1024px) and (min-width: 721px) {
  .board-wrap--panel { margin-right: 0; }
  .side { width: min(440px, 80vw); }
}

/* =====================================================================
   Trychtýř statistik náboru (E15 § 6.10). Řádek = fáze, pod ní odpad
   s důvody. Přeneseno z design/e15/e15.css, všechno přes tokeny.
   Pruh je poměr k první fázi; šířku nese `--w`, aby se dala nastavit
   jedním číslem z šablony.
   ===================================================================== */
.funnel { display: grid; gap: 6px; }
.funnel__row { display: grid; grid-template-columns: minmax(120px, 200px) 1fr 72px; gap: var(--space-3); align-items: center; font-size: var(--fs-control); }
.funnel__bar { height: 18px; background: var(--c-sunken); border-radius: var(--radius-1); position: relative; overflow: hidden; }
.funnel__bar::after { content: ""; position: absolute; inset: 0; width: var(--w, 0%); background: var(--c-brand); }
.funnel__row--lost .funnel__bar::after { background: var(--c-rejected-ink); }
.funnel__row--lost { color: var(--c-ink-mute); }
.funnel__n { font-family: var(--font-mono); text-align: right; }
.funnel__why { grid-column: 2 / span 2; font-size: var(--fs-micro); color: var(--c-ink-mute); padding-left: 2px; }
@media (max-width: 720px) {
  .funnel__row { grid-template-columns: minmax(90px, 1fr) 2fr 56px; }
}

/* =====================================================================
   PŘÍCHOZÍ (nábor, E15 krok 7, mockup 4-prichozi). Řádek fronty je karta:
   kanál a čas, jméno a kontakt, co AI vytěžila (nepotvrzené podtržené
   čárkovaně), duplicita jako zvýrazněný řádek, akce vpravo. Přeneseno
   z design/e15/e15.css, všechno přes tokeny. Obarvený okraj nese stav
   (duplicita / nezpracováno) — a slovo v řádku ho nese taky.
   ===================================================================== */
.inbox { display: grid; gap: 8px; padding: var(--space-3) var(--space-4); }
.inb { display: grid; grid-template-columns: 1fr auto; gap: 6px var(--space-3); background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-2); padding: 10px 12px; }
.inb--dup { border-color: var(--c-soon-line); }
.inb--stuck { border-color: var(--c-danger-line); }
.inb--done { color: var(--c-ink-mute); }
.inb__src { font-size: var(--fs-micro); color: var(--c-ink-mute); display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.inb__name { font-weight: 600; }
.inb__name a { color: inherit; }
.inb__ai { font-size: var(--fs-control); color: var(--c-ink-mute); }
.inb__ai .ai { border-bottom: 1px dashed var(--c-brand-line); }
.inb__src, .inb__name, .inb__ai, .inb__dup { grid-column: 1; min-width: 0; }
.inb__act { grid-column: 2; grid-row: 1 / span 4; display: flex; flex-direction: column; gap: 6px; align-items: stretch; justify-content: center; }
.inb__act form { display: contents; }
.inb__dup { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: var(--fs-control); color: var(--c-soon-ink); }
.inb__split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); padding: var(--space-3) var(--space-4); }
.raw { font-family: var(--font-mono); font-size: var(--fs-micro); white-space: pre-wrap; background: var(--c-sunken); padding: 10px; border-radius: var(--radius-1); border: 1px solid var(--c-border-hair); max-height: 360px; overflow: auto; }
/* Pole z AI ve formuláři přijetí: jistota vedle popisku, ne barva. */
.field__origin { font-size: var(--fs-micro); color: var(--c-ink-mute); font-weight: 400; }
@media (max-width: 900px) {
  .inb { grid-template-columns: 1fr; }
  .inb__act { grid-column: 1; grid-row: auto; flex-direction: row; flex-wrap: wrap; }
  .inb__split { grid-template-columns: 1fr; }
}

/* =====================================================================
   Přidat kandidáta (E15 krok 9b, mockup 11-novy-kandidat)

   Vlevo vstup zvolené cesty (dokument, text), vpravo karta kandidáta.
   Cesta „ručně" žádný vstup navíc nemá, takže karta zabere celou šířku —
   prázdný sloupec vedle formuláře vypadá jako něco, co se nenačetlo.
   ===================================================================== */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); align-items: start; }
.split--single { grid-template-columns: 1fr; }
.drop { display: grid; gap: var(--space-3); justify-items: center; text-align: center; padding: var(--space-5); border: 2px dashed var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); color: var(--c-ink-mute); font-size: var(--fs-control); }
.drop .input { max-width: 320px; }
.field--wide { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
}

/* =====================================================================
   Dotazníky (E15 krok 9, mockup 12-dotazniky)

   Generátor formuláře je nový vzor etapy: vlevo řazený seznam otázek
   s mapováním na katalog polí, vpravo živý náhled na telefonu. Náhled
   není ozdoba — otázka „vejde se to na displej" je u formuláře, který
   vyplňuje kandidát v autobuse, ta hlavní.
   ===================================================================== */
.gen { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-4); align-items: start; }
.gen__list { display: grid; gap: var(--space-2); min-width: 0; }

.qrow { display: grid; grid-template-columns: 20px minmax(0, 1fr) 180px auto; gap: var(--space-2); align-items: center; padding: 6px 8px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-1); background: var(--c-surface); font-size: var(--fs-control); }
.qrow__grip { color: var(--c-ink-faint); }
.qrow__map { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); overflow-wrap: anywhere; }
.qrow__map--free { color: var(--c-ink-faint); font-style: italic; }
.qrow__actions { display: inline-flex; gap: 2px; align-items: center; }
.qrow__actions form { display: inline; }

/* Rám telefonu: náhled má vypadat jako displej, ne jako další sloupec
   formuláře — jinak se na něj přestane koukat jako na náhled. */
.phone { width: 320px; border: 8px solid var(--c-ink); border-radius: 28px; background: var(--c-canvas); padding: 14px 12px; box-shadow: var(--shadow-2); position: sticky; top: calc(var(--topbar-h) + var(--space-3)); }
.phone__head { text-align: center; margin: 0 0 6px; }
.phone__title { font-weight: 600; margin: 0 0 8px; }
.phone .field { margin-bottom: 8px; }
.phone__submit { width: 100%; margin-top: 8px; justify-content: center; }
.input--ghost { display: block; height: var(--control-h); border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); }

/* Tři způsoby vložení pod sebou, kód k překopírování. */
.embed { display: grid; gap: var(--space-3); }
.embed__code { font-family: var(--font-mono); font-size: var(--fs-micro); background: var(--c-sunken); border: 1px solid var(--c-border-hair); padding: 8px 10px; border-radius: var(--radius-1); overflow-x: auto; white-space: pre; }

/* Podíl vyplnění v řádku seznamu: pruh **i číslo** — barva sama není pro
   člověka s poruchou barvocitu informace. */
.rate { display: inline-flex; align-items: center; gap: 6px; }
.rate__bar { width: 60px; height: 6px; background: var(--c-sunken); border-radius: 3px; position: relative; overflow: hidden; flex: none; }
.rate__bar::after { content: ""; position: absolute; inset: 0; width: var(--w, 0%); background: var(--c-ok-ink); }

/* Kolonka s chybou se pozná i bez barvy — hláška pod ní je povinná. */
.field--invalid .input, .field--invalid .select { border-color: var(--c-danger-line); }

/* Dvojice „originál – překlad" v kontrole překladů. */
.form-grid--pair { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

@media (max-width: 1100px) {
  .gen { grid-template-columns: 1fr; }
  .phone { position: static; width: 100%; max-width: 340px; }
}

@media (max-width: 700px) {
  .qrow { grid-template-columns: 20px minmax(0, 1fr); }
  .qrow__map, .qrow__actions { grid-column: 2; }
}

/* =====================================================================
   KANÁL ZPRÁV — karta se zaškrtávátkem a průvodcem (E15 krok 12)
   =====================================================================
   Průvodce se ukáže **až po zaškrtnutí** „chci používat" (Jakub 5. 9. 2026),
   proto je `.chan-card__guide` samostatný blok oddělený linkou, ne součást
   hlavičky karty. Krok hotový a krok před sebou se liší **znakem** (✓ proti
   pořadovému číslu), ne jen barvou. */
.chan { display: grid; grid-template-columns: 40px 1fr auto; gap: var(--space-3); align-items: center; }
.chan__ico {
  width: 40px; height: 40px; border-radius: var(--radius-2);
  display: grid; place-items: center;
  font-family: var(--font-mono); font-weight: 600;
  background: var(--c-sunken); border: 1px solid var(--c-border);
}
.chan__name { font-weight: 600; }
.chan__meta { font-size: var(--fs-micro); color: var(--c-ink-mute); }

.chan-card { display: grid; gap: var(--space-3); align-content: start; }
.chan-card__guide { border-top: 1px solid var(--c-border-hair); padding-top: var(--space-3); }

.steps { counter-reset: s; display: grid; gap: var(--space-3); margin: var(--space-2) 0 0; padding: 0; list-style: none; }
.steps li { counter-increment: s; display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 8px; align-items: baseline; font-size: var(--fs-control); }
.steps li::before {
  content: counter(s);
  font-family: var(--font-mono); font-size: var(--fs-micro);
  width: 20px; height: 20px; border-radius: 50%;
  display: inline-grid; place-items: center;
  background: var(--c-sunken); border: 1px solid var(--c-border);
}
.steps li[data-done="true"]::before { content: "✓"; background: var(--c-ok-soft); color: var(--c-ok-ink); border-color: var(--c-ok-line); }
.steps__body { display: grid; gap: 6px; }

/* ── Vlákno konverzace a editor šablony (E15 krok 13) ─────────────────────
   Vlákno je nový vzor (design/e15/README.md): směr nese **podklad**, ale
   stav doručení stojí u zprávy slovem — barva sama není pro člověka
   s poruchou barvocitu informace. Nedoručeno je proto červené i napsané.

   `.composer` je jeden řádek „kanál · text · poslat". Na mobilu se láme
   pod sebe: tři prvky vedle sebe na 375 px znamenají pole na dva znaky. */
.chat { display: grid; gap: 6px; margin-bottom: var(--space-3); }
.chat__msg { max-width: 88%; padding: 6px 10px; border-radius: var(--radius-2); font-size: var(--fs-control); background: var(--c-sunken); border: 1px solid var(--c-border-hair); }
.chat__msg--out { margin-left: auto; background: var(--c-brand-soft); border-color: var(--c-brand-line); }
.chat__meta { display: block; font-size: var(--fs-micro); color: var(--c-ink-faint); margin-top: 2px; font-family: var(--font-mono); }
.chat__msg--failed { border-color: var(--c-danger-line); background: var(--c-danger-soft); }
.composer { display: grid; grid-template-columns: auto 1fr auto; gap: 6px; align-items: center; }

@media (max-width: 640px) {
    .composer { grid-template-columns: 1fr; }
}

/* Editor šablony: proměnné se vkládají klikem, ne přepisováním (Jakub, § 6.0).
   Chip je `<button>`, ne `<span>` — musí jít na něj klávesnicí a musí být
   slyšet ve čtečce, protože je to jediná cesta, jak proměnnou vložit. */
.vars { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; }
.var {
    font-family: var(--font-mono); font-size: var(--fs-micro); padding: 2px 8px;
    border: 1px solid var(--c-brand-line); background: var(--c-brand-soft);
    color: var(--c-brand-ink); border-radius: 10px; cursor: pointer;
}
.var:hover { border-color: var(--c-brand); }
.tpl-preview { border: 1px solid var(--c-border); border-radius: var(--radius-2); padding: 10px 12px; background: var(--c-surface); font-size: var(--fs-control); }

/* ── Landing pages: náhled a pravý sloupec (E15 krok 16) ──────────────────
   Nový vzor z `design/e15/e15.css` (`.lp`). Obrazovka je **dvousloupcová**:
   vlevo náhled stránky v rámu, vpravo verze a nastavení. Krokem 17 sem
   vedle verzí přijde asistent (vibecoding) — proto je pravý sloupec sloupec,
   ne panel: panel by se musel na příchod asistenta přestavět.

   Náhled je `<iframe>`, ne vložené HTML: stránka agentury má vlastní CSS
   bez našich tokenů a vložená rovnou do obrazovky by přepsala vzhled celé
   aplikace.

   Pod 1100 px se sloupce skládají pod sebe — dvakrát 380 px se na tablet
   nevejde a náhled zúžený na půlku už neukazuje, jak stránka vypadá. */
.lp { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 0; align-items: start; }
.lp__preview { background: var(--c-sunken); padding: var(--space-3); overflow: auto; }
.lp__frame { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-2); box-shadow: var(--shadow-1); margin: 0 auto; max-width: 900px; overflow: hidden; }
.lp__iframe { display: block; width: 100%; height: 70vh; min-height: 480px; border: 0; }
/* Telefon: šířka zařízení, ne zmenšenina — kandidát je vždy na telefonu
   (§ 6.12) a agentura potřebuje vidět, kde se text zalomí. */
.lp__iframe--phone { width: 390px; margin: 0 auto; }
.lp__aside { border-left: 1px solid var(--c-border); background: var(--c-surface); display: grid; gap: var(--space-4); align-content: start; padding: var(--space-3); }
.lp__versions { display: grid; gap: var(--space-2); }
.lp__settings { display: grid; gap: var(--space-2); }

/* ── Editor: náhled vlevo, panel se záložkami vpravo (E15 § 6.11a, 14b) ──
   Zpětná vazba Jakuba 8. 9. 2026: „editor je nepřehledný, pravý panel se
   přelévá za náhled a musí být rolovatelný." Panel je proto **sloupec
   pevné výšky, který se roluje sám** — drží se při rolování stránky
   (`sticky`) a nikdy nepřeteče za náhled. Bez toho se člověk k tlačítku
   dole v panelu dostal až po přerolování celé stránky, tedy nikdy.

   Do 1024 px jde panel **pod náhled** a rolování se vrací stránce: dva
   posuvníky v sobě jsou na telefonu horší než jeden dlouhý sloupec.
   (U kartotéky je nabídka nad obsahem, tady pod ním schválně — nahoře je
   náhled, kvůli kterému se obrazovka otevírá.) */
.lp--editor { align-items: stretch; }
.lp__aside--tabs {
    position: sticky; top: var(--topbar-h); height: calc(100vh - var(--topbar-h));
    display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 0; padding: 0; overflow: hidden;
}
.lp__tabs { padding: var(--space-2) var(--space-2) 0; }
.lp__pane { overflow-y: auto; padding: var(--space-3); display: grid; gap: var(--space-4); align-content: start; min-height: 0; }
.lp__assistant, .lp__timeline, .lp__settings { display: grid; gap: var(--space-3); align-content: start; }

/* Rozsah pokynu je vidět v hlavičce chatu: „upravuji celou stránku" nebo
   „blok: Ubytování ×". Pokyn poslaný na jiný rozsah, než člověk čekal, je
   utracený kredit. */
.lp__scope {
    display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
    padding-bottom: var(--space-2); border-bottom: 1px solid var(--c-border-hair);
    font-size: var(--fs-control);
}
.lp__thread { display: grid; gap: var(--space-2); }
.lp__composer, .lp__block, .lp__images, .lp__translate, .lp__compare, .lp__withdraw, .lp__pick { display: grid; gap: var(--space-2); }
.lp__compare ul { margin: 0; padding-left: var(--space-3); font-size: var(--fs-control); }

/* Ovládání bloku pod náhledem — tytéž akce, které v náhledu kreslí lišta
   u bloku. Je to jeden rám, ne pruh za pruhem. */
.lp__tools {
    display: grid; gap: var(--space-2); margin-top: var(--space-3); padding: var(--space-3);
    background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-2);
}
.lp__tool-head { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: var(--fs-control); }
.lp__tool-name { font-weight: 600; color: var(--c-brand-ink); }
.lp__arrange, .lp__version-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.lp__add { display: grid; gap: var(--space-2); border-top: 1px dashed var(--c-border); padding-top: var(--space-2); }

/* Galerie obrázků stránky: čtverečky, ne seznam názvů — fotku ubytovny
   pozná člověk podle fotky, ne podle „IMG_2043.jpg". */
.lp__gallery { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.lp__gallery img {
    width: 72px; height: 72px; object-fit: cover; display: block;
    border: 1px solid var(--c-border); border-radius: var(--radius-1);
}

@media (max-width: 1100px) {
    .lp { grid-template-columns: 1fr; }
    .lp__aside { border-left: 0; border-top: 1px solid var(--c-border); }
    .lp__iframe--phone { width: 100%; max-width: 390px; }
    /* Pod sebou už panel nemusí šetřit místem — omezená výška by tu
       udělala druhý posuvník uvnitř posuvníku stránky. */
    .lp__aside--tabs { position: static; height: auto; overflow: visible; }
    .lp__pane { overflow: visible; }
}

/* ── Kalendář pohovorů (E15 krok 19, mockup 6-kalendar) ───────────────────
   Nový vzor etapy: mřížka sloupce = dny, řádky = hodiny. Události nesou
   stav **barvou i textem** — barva sama není pro člověka s poruchou
   barvocitu informace (`CLAUDE.md`).

   Počet sloupců neurčuje CSS, ale obsah: den má jeden, týden pět. Kdyby
   byl počet natvrdo, musel by se přepínač rozsahu tvářit jako dva různé
   vzhledy téhož. */
.cal {
    display: grid;
    grid-template-columns: 56px repeat(var(--cal-days, 5), minmax(0, 1fr));
    border: 1px solid var(--c-border);
    border-radius: var(--radius-2);
    overflow: hidden;
    background: var(--c-surface);
}
.cal__day {
    padding: 6px 8px; font-size: var(--fs-control); font-weight: 600;
    border-bottom: 1px solid var(--c-border); border-left: 1px solid var(--c-border-hair);
    position: sticky; top: 0; background: var(--c-surface); z-index: 2;
}
.cal__day small { display: block; font-weight: 400; color: var(--c-ink-mute); font-size: var(--fs-micro); }
.cal__day--today { color: var(--c-brand-ink); background: var(--c-brand-soft); }
.cal__corner { border-bottom: 1px solid var(--c-border); background: var(--c-surface); position: sticky; top: 0; z-index: 2; }
.cal__hour {
    font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-faint);
    padding: 2px 6px; border-top: 1px solid var(--c-border-hair); height: 44px;
}
.cal__cell { border-top: 1px solid var(--c-border-hair); border-left: 1px solid var(--c-border-hair); height: 44px; position: relative; padding: 0; background: none; }
.cal__cell:hover { background: var(--c-sunken); }
.cal__cell:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }

/* Událost: výška podle délky (`--h` je počet hodinových řádků). */
.ev {
    position: absolute; left: 3px; right: 3px; top: 2px;
    height: calc(var(--h, 1) * 44px - 4px);
    padding: 3px 6px; border-radius: var(--radius-1);
    font-size: 11px; line-height: 1.25; overflow: hidden; text-align: left;
    border-left: 3px solid var(--c-brand); background: var(--c-brand-soft); color: var(--c-brand-ink);
    z-index: 1; display: block; text-decoration: none;
}
.ev:hover { text-decoration: none; filter: brightness(0.98); }
.ev strong { display: block; font-weight: 600; }
/* Obsazenost z cizího kalendáře (krok 20): šrafování bez detailu. */
.ev--busy { background: repeating-linear-gradient(135deg, var(--c-sunken) 0 4px, var(--c-surface) 4px 8px); border-left-color: var(--c-border); color: var(--c-ink-mute); }
/* Nabídnutý termín (krok 21): čas je držený, ale schůzka ještě není.
   Přerušovaný okraj to říká i bez barvy — kartička navíc nese slovem,
   kolik termínů kandidát dostal. */
.ev--offer { border-left-style: dashed; border-left-color: var(--c-ink-faint); background: var(--c-surface); color: var(--c-ink-mute); }
.ev--done { border-left-color: var(--c-ok-ink); background: var(--c-ok-soft); color: var(--c-ok-ink); }
.ev--noshow { border-left-color: var(--c-rejected-ink); background: var(--c-rejected-soft); color: var(--c-rejected-ink); }
.ev--cancelled { border-left-color: var(--c-border); background: var(--c-sunken); color: var(--c-ink-mute); text-decoration: line-through; }

/* Na telefonu je vidět jen den (§ 6.7): pět sloupců na 375 px je pět
   sloupců, ve kterých se nedá nic přečíst. Týden se proto na úzké
   obrazovce nevykreslí zmenšený, ale **nahradí odkazem na den** — mřížka
   zmáčknutá na třetinu je horší než poctivé „tohle se sem nevejde,
   tady je to, co se vejde". */
.cal-narrow { display: none; }

@media (max-width: 720px) {
    .cal { grid-template-columns: 48px minmax(0, 1fr); }
    .cal--week { display: none; }
    .cal--week + .cal-narrow { display: block; }
}

/* Volné místo v mřížce je odkaz přes celou buňku: klikací plocha musí být
   celá buňka, ne text uvnitř ní. Události leží nad ním (`z-index`), takže
   kliknutí na pohovor vede na pohovor, ne na zakládání dalšího. */
.cal__slot { position: absolute; inset: 0; z-index: 0; }
.cal__slot:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }

/* =====================================================================
   AI RECRUITER — okruhy a náhled rozhovoru (E15 krok 27,
   mockup 13-ai-recruiter)
   =====================================================================
   Sekce má dvě poloviny, které se čtou zleva doprava: **co se ptáme**
   a **co z toho vyleze**. Náhled vedle seznamu, ne pod ním — nastavení,
   jehož výsledek je vidět až po přerolování, se nastavuje naslepo.

   `.topic` je řádek okruhu. Vypadá jako `.qrow` u generátoru formuláře
   schválně: je to týž druh věci (otázka + kam míří + co s ní jde dělat)
   a dva různé vzory pro jednu věc znamenají, že se jeden z nich opraví.
   Liší se jedním sloupcem navíc — „povinný / volitelný". */
.twocol { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--space-4); align-items: start; }

.topic { display: grid; grid-template-columns: 20px minmax(0, 1fr) 200px 110px auto; gap: 8px; align-items: center; padding: 6px 8px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-1); background: var(--c-surface); font-size: var(--fs-control); }
.topic__from { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Odvozený okruh je podbarvený **a** nese slovo „odvozeno" v popisku:
   barva sama není pro člověka s poruchou barvocitu informace. */
.topic--auto { background: var(--c-sunken); }

/* Vypnutý okruh se nemaže a nemizí — zůstává vidět zeslabený, protože
   jinak vypadá jako smazaný a člověk ho hledá. */
.topic--off { opacity: .55; }

@media (max-width: 1100px) {
    .twocol { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
    .topic { grid-template-columns: 20px minmax(0, 1fr); }
    .topic > :nth-child(n+3) { grid-column: 2; }
}

/* =====================================================================
   MŘÍŽKA VÝKAZU — osoby × dny (E13, úkol #92)

   Třetí uspořádání vedle „seznamu s filtry" a „detailu se záložkami".
   Nezavádí novou barvu ani nový rozměr: víkend a svátek berou existující
   „soft" tokeny stavů, hustota jde z --row-h a --control-h.

   ## table-layout: fixed a určitá šířka jsou podmínka, ne optimalizace

   Zmrazená pásma stojí na tom, že se `left` a `right` dopočítají z šířek
   sloupců. V tabulce s automatickým layoutem je `width` jen návrh —
   prohlížeč si sloupce naměří podle obsahu a odsazení přestane sedět.
   První verze makety měla přesně proto mezery 13, 37 a 18 px, kterými při
   rolování prosvítaly dny.

   `fixed` ale drží deklarované šířky jen tehdy, když je šířka tabulky
   **určitá**. `auto` se pod `fixed` řeší proti kontejneru a prohlížeč sloupce
   proporcionálně smrskne; `max-content` se doměří podle obsahu, takže jedna
   příliš dlouhá buňka roztáhne svůj sloupec i celou tabulku — a odsazení
   zmrazených pásem zase přestane sedět. Zjištěno na skutečném výstupu:
   sloupec „Typ PP" s názvem poměru vyrostl z 54 na 106 px.

   Šířku proto **počítá šablona** z týchž hodnot jako odsazení; sem nepatří
   ani jedna. Vedlejší užitek je výkon (M4-P12): prohlížeč nemusí měřit obsah
   patnácti tisíc buněk, aby zjistil, jak široká je tabulka.
   ===================================================================== */
.grid-wrap {
  position: relative; overflow: auto;
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
  max-height: calc(100vh - 300px);
}
/* Fond je pole, ne číslo. Vypadá jako číslo, dokud se do něj neklikne:
   sloupec souhrnů je čtení a rámeček u každého řádku by z něj udělal
   formulář. Ohlásí se zaostřením a najetím myší. */
.g-sum__input {
  width: 100%; padding: 2px 4px; border: 1px solid transparent; border-radius: var(--radius-1);
  background: none; font: inherit; text-align: right;
  font-variant-numeric: tabular-nums; color: inherit;
}
.g-sum__input:hover { border-color: var(--c-border); }
.g-sum__input:focus { border-color: var(--c-brand); outline: none; background: var(--c-surface); }
.g-sum__input[aria-invalid="true"] { border-color: var(--c-danger); background: var(--c-rejected-soft); }
/* Uložený fond se nepřepočítává, a to musí být vidět — jinak vypadá stejně
   jako návrh a nikdo nepozná, proč se po opravě úvazku nezměnil. */
.g-sum--stated .g-sum__input { font-weight: 600; box-shadow: inset 2px 0 0 var(--c-brand-line); }

/* Dorovnání pod saldem. Je to tlačítko, protože otevírá seznam položek —
   a musí vypadat jako odkaz, jinak si ho nikdo nevšimne. */
.g-sum--balance { line-height: 1.15; }
.g-sum__note--link {
  width: 100%; padding: 0; border: 0; background: none;
  font-family: inherit; text-align: right; color: var(--c-brand-ink);
  text-decoration: underline; cursor: pointer;
}

/* --- kalendář dnů v hromadné editaci (E13, Lukáš 5. 9. 2026) ---------- */
/* Měsíc srovnaný po týdnech, ne pás jedenatřiceti čísel: „pondělí, úterý
   a pak až sobota" se ve sloupcích odklikne, v pásu se hledá. */
.daypick {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px;
  padding: var(--space-2);
  background: var(--c-sunken); border: 1px solid var(--c-border); border-radius: var(--radius-2);
}
.daypick__head {
  text-align: center; padding-bottom: 2px;
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--c-ink-faint);
}
.daypick__day {
  display: flex; align-items: center; justify-content: center; height: 32px;
  background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-1);
  font-size: var(--fs-control); font-variant-numeric: tabular-nums;
  cursor: pointer; user-select: none;
}
/* Víkend a svátek jsou tlumené, ale klikatelné: v nepřetržitém provozu se
   v sobotu běžně pracuje (M4-P20). */
.daypick__day--rest { background: var(--c-canvas); color: var(--c-ink-mute); }
.daypick__day:hover { border-color: var(--c-brand); }
.daypick__day:has(:checked) {
  background: var(--c-brand-soft); border-color: var(--c-brand);
  color: var(--c-brand-ink); font-weight: 600;
}
.daypick__day:has(:focus-visible) { outline: 2px solid var(--c-brand); outline-offset: 1px; }
.daypick__quick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.daypick__count { margin-left: auto; font-size: var(--fs-meta); color: var(--c-ink-mute); }

/* --- celá obrazovka (E13, Lukáš 5. 9. 2026) --------------------------- *
   „Fullscreen má užívateľa zafokusovať na výkaz — menu, topbar a podobne sa
   prekryjú, zobrazí sa väčší výkaz, viac informácií, menej scrollovania."

   Není to `requestFullscreen()`. Ten skryje lištu **prohlížeče**, ale menu
   a topbar aplikace nechá stát — a právě o ty tady jde. Navíc si bere celou
   obrazovku i na druhém monitoru, což při přepisování z papíru vedle vadí.

   Skořápka se proto jen schová třídou na `<html>`. Vedle svislého místa to
   vrací i 220 px vodorovně po navigaci — a to jsou další čtyři dny vidět
   bez rolování.

   Mřížka pak **není omezená odhadem** `100vh - 300px`, ale dopočítá se:
   `.sheet` je sloupec přes celou výšku a `.grid-wrap` v něm zbytek. Lišty
   nad mřížkou si tak můžou přibývat a ubývat, aniž by se pod tabulkou
   objevil pruh prázdna nebo druhý posuvník.
   ===================================================================== */
html.sheet-full, html.sheet-full body { height: 100%; overflow: hidden; }
.sheet-full .app { height: 100vh; min-height: 0; }
.sheet-full .app__topbar, .sheet-full .app__nav,
.sheet-full .app__banner, .sheet-full .page-head { display: none; }
.sheet-full .app__main { min-height: 0; }
/* Pruh filtrů zůstává: provozovna, měsíc, hledání a přepínač zobrazení patří
   k práci s výkazem stejně jako mřížka sama. */
.sheet-full .sheet { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.sheet-full .grid-wrap { flex: 1; max-height: none; min-height: 0; }

.grid { table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: var(--fs-base); }
.grid th, .grid td { border-bottom: 1px solid var(--c-border-hair); white-space: nowrap; overflow: hidden; }

.grid thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--c-sunken);
  font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute);
  text-align: center; padding: 4px var(--space-2);
  border-bottom: 1px solid var(--c-border);
}
.grid tbody td { height: var(--row-h); padding: 0 var(--space-2); }
.grid tbody tr:hover td { background: var(--c-canvas); }

/* Zmrazená pásma. Odsazení počítá šablona z týchž šířek jako colgroup —
   psát je sem natvrdo znamená, že se rozejdou při první změně sloupce. */
.g-id  { position: sticky; z-index: 2; background: var(--c-surface); text-align: left; }
.g-sum { position: sticky; z-index: 2; background: var(--c-surface); text-align: right;
         font-variant-numeric: tabular-nums; }
.grid thead .g-id, .grid thead .g-sum { z-index: 4; background: var(--c-sunken); }
.grid tbody tr:hover .g-id, .grid tbody tr:hover .g-sum { background: var(--c-canvas); }
.g-id--type, .g-id--group { text-align: center; }
.g-id--group { box-shadow: 1px 0 0 var(--c-border); }
.g-sum--days { box-shadow: -1px 0 0 var(--c-border); }
.g-sum--hours { font-weight: 600; }
/* --- fond, saldo (E13, ukol #94) ------------------------------------- */
/* Fond je sirsi nez ostatni souhrny, protoze pod nim stoji poznamka
   o hodinach v jine hale. Bez ni by signal „chybi hodiny" u soubehu
   klamal (M4-P21). */
.g-sum--fond { line-height: 1.15; }
.g-sum__note {
  display: block; font-size: 10px; font-weight: 600;
  color: var(--c-soon-ink); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* Saldo. Znamenko nese cislo samo — barva jen doprovazi, protoze barva
   nikdy nestoji sama. Chybejici hodiny jsou vyraznejsi nez prebytek:
   prebytek se resi dohodou, chybejici hodiny reklamaci. */
.g-sum--balance { font-weight: 600; }
.g-sum--short { color: var(--c-expired-ink); }
.g-sum--over { color: var(--c-ink-mute); }

/* --- pasmo slozek odmenovani (E13, ukol #95) --------------------------- */
/* Stoji mezi dny a souhrnem a **neni zmrazene**: souhrn u praveho okraje ano,
   slozky ne. Rolovani jde „dny → slozky" a soucet je videt porad (navrh #92). */
.g-comp {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
  background: var(--c-surface);
}
.grid tbody tr:hover .g-comp { background: var(--c-canvas); }
/* Svisla linka jen na zacatku pasma, ne mezi slozkami — pasmo se ma cist
   jako jeden blok, ne jako pet tabulek vedle sebe. */
.g-comp--first { box-shadow: inset 1px 0 0 var(--c-border); }

.grid thead .g-comp {
  text-align: center;
  font-family: var(--font-sans);
  /* Barva slozky z ciselniku jako 3px prouzek, ne vypln: vypln by u peti
     slozek udelala z pasma duhu a prebila by barvu typu dne, ktera v mrizce
     nese vyznam. */
  border-top: 3px solid var(--c-border);
}
.gh { display: grid; gap: 1px; line-height: 1.15; }
.gh__code { font-family: var(--font-mono); font-weight: 700; font-size: 11px; letter-spacing: .02em; }
.gh__name { font-size: 10px; font-weight: 400; color: var(--c-ink-mute);
            overflow: hidden; text-overflow: ellipsis; }

/* Spocitana hodnota **neni pole**. Kdo chce jine cislo, opravi dochazku —
   dve pravdy o teze veci jsou to, cemu brani ADR-016. */
.g-comp__value { display: block; padding-right: 4px; font-weight: 600; }
/* Nula je odpoved, jen slabsi: „vikend se nedelal" je informace. */
.g-comp__zero { color: var(--c-ink-faint); font-weight: 400; }

.g-comp__box { display: flex; align-items: center; gap: 2px; }
.g-comp__input {
  width: 100%; height: 26px; min-width: 0; padding: 0 4px; text-align: right;
  font: inherit; font-variant-numeric: tabular-nums;
  border: 1px solid transparent; border-radius: var(--radius-1);
  background: transparent; color: var(--c-ink);
}
.g-comp__input:hover { border-color: var(--c-border); background: var(--c-surface); }
.g-comp__input:focus { outline: var(--focus-ring); outline-offset: -1px;
                       border-color: var(--c-brand); background: var(--c-surface); }
/* „Z podkladu zakaznika" — tyz prouzek, jakym mrizka znaci puvod hodnoty.
   Zatim se vyplnuje rucne, protoze import se v teto etape nestavi. */
.g-comp--customer .g-comp__input { box-shadow: inset 2px 0 0 var(--c-pending-line); }

/* Neda se spocitat. Jantarova jen dokud je prazdno; jakmile v bunce cislo je,
   je to vyrizene. Barva nikdy nestoji sama, proto je vedle ni znacka. */
.g-comp--mute { background: var(--c-soon-soft); }
.grid tbody tr:hover .g-comp--mute { background: var(--c-soon-soft); }
.grid thead .g-comp--mute { background: var(--c-soon-soft); color: var(--c-soon-ink); }
/* Souhrn radku hrube mzdy (#98). Tucne, protoze je to to cislo, kvuli
   kteremu se obrazovka otevira. */
.g-comp--total { box-shadow: inset 1px 0 0 var(--c-border); }
.g-comp--total .g-comp__value { font-weight: 700; font-size: var(--fs-control); }

.g-comp__mark {
  display: block; text-align: center; font-family: var(--font-sans);
  font-weight: 700; color: var(--c-soon-ink); cursor: help;
}

.btn--tiny { padding: 2px 6px; font-size: var(--fs-micro); min-height: 0; }

.g-comp__flag {
  flex: none; width: 12px; text-align: center; font-family: var(--font-sans);
  font-weight: 700; font-size: 12px; color: var(--c-soon-ink); cursor: help;
}

.g-id__second { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* --- buňka dne ------------------------------------------------------- */
.day { padding: 0 2px !important; text-align: center; }
.day__input {
  width: 100%; height: 26px;
  border: 1px solid transparent; border-radius: 3px;
  background: transparent; font: inherit; font-variant-numeric: tabular-nums;
  text-align: center; color: var(--c-ink); padding: 0 2px;
}
.day__input:hover { border-color: var(--c-border); background: var(--c-surface); }
.day__input:focus-visible {
  outline: 2px solid var(--c-brand); outline-offset: -1px;
  background: var(--c-surface); border-color: var(--c-brand);
}
.day__input[aria-invalid="true"] { border-color: var(--c-danger-line); background: var(--c-danger-soft); }
.day__input[readonly] { color: var(--c-ink-mute); }
/* Den mimo přidělení není buňka k vyplnění: ten den člověk na hale nebyl,
   takže tam **reálně nemohl pracovat** (potvrdil Lukáš 3. 9. 2026). Pole tam
   proto vůbec není a plocha se zašedne.

   ## Šrafa, ne plná barva

   `--c-inactive-soft` má světlost 0,955 a plocha tabulky 0,965 — rozdíl je tak
   malý, že „zašedlé" dny prostě nebyly poznat. Šrafa nestojí na rozdílu
   odstínů a v téhle mřížce už znamená „sem nic nepatří" (pásmo složek
   odměňování v maketě), takže se nezavádí nová barva ani nový jazyk.

   Vyhrává i nad víkendem, svátkem a nad `:hover`, proto ta selektivita.
   Barva typu dne by tady lhala: mimo přidělení se nepracovalo a příplatek za
   svátek se z ničeho nepočítá. */
.grid tbody td.day--outside,
.grid tbody tr:hover td.day--outside,
.grid tbody tr.g-row--mismatch:hover td.day--outside {
  background: repeating-linear-gradient(135deg,
    var(--c-canvas) 0 5px, var(--c-inactive-soft) 5px 10px);
}

/* Původ hodnoty — proužek na levé hraně, ne ikona. V buňce 34 px vysoké
   sní ikona místo, které patří číslu. */
.day--ai .day__input { box-shadow: inset 2px 0 0 var(--c-pending-line); }
.day--import .day__input { box-shadow: inset 2px 0 0 var(--c-border); }

/* Typ dne. Barva nikdy nestojí sama — v hlavičce je zkratka dne v týdnu
   a u svátku navíc značka a jeho jméno v `title`. */
.d-weekend { background: var(--c-soon-soft); }
.d-holiday { background: var(--c-rejected-soft); }
.d-agency  { background: var(--c-inactive-soft); }
.grid thead .d-weekend { background: var(--c-soon-soft); color: var(--c-soon-ink); }
.grid thead .d-holiday { background: var(--c-rejected-soft); color: var(--c-rejected-ink); }
.dh { display: grid; gap: 1px; line-height: 1.15; }
.dh__num { font-variant-numeric: tabular-nums; }
.dh__dow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.dh__mark { font-size: 10px; }

/* Příznak nepřítomnosti. Buňka nese buď hodiny, nebo příznak, nikdy obojí.
   Je to pořád pole, jen vypadá jako štítek — dovolená se musí dát přepsat
   na hodiny týmž pohybem, jakým se zapsala. */
.day__input--flag {
  border-color: var(--c-pending-line);
  background: var(--c-pending-soft); color: var(--c-pending-ink);
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase;
}

.list-bulk__sep { width: 1px; height: 20px; background: var(--c-brand-line); }

/* =====================================================================
   UZAVERKOVA CHECKLISTA (E13, ukol #96)

   Pocitadlo je `chip` ze systemu v jantarove variante, ne nova komponenta.
   Klika se na nej, takze je to tlacitko — chip, ktery nic nedela, vypada
   stejne, a to je prave ta past.
   ===================================================================== */
.chip--warn {
  border-color: var(--c-soon-line); background: var(--c-soon-soft); color: var(--c-soon-ink);
  cursor: pointer; font-weight: 600;
}
.chip--warn:hover { border-color: var(--c-soon-ink); }

/* Blok nalezu. Seznam s nadpisem, poctem, jmeny a cestou k naprave v systemu
   nebyl a tabulka ho neunese: nutila by vsechny ctyri druhy nalezu do tychz
   sloupcu, a ty se lisi. */
.finds { display: grid; gap: var(--space-3); }
.find {
  border: 1px solid var(--c-border); border-left: 3px solid var(--c-soon-line);
  border-radius: var(--radius-2); padding: var(--space-3);
  background: var(--c-surface);
}
.find__head { display: flex; align-items: baseline; gap: var(--space-2); }
.find__title { font-weight: 600; font-size: var(--fs-control); }
.find__count {
  margin-left: auto; flex: none;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: 700; color: var(--c-soon-ink); white-space: nowrap;
}
.find__who { margin: 4px 0 0; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.find__fix { margin: 6px 0 0; font-size: var(--fs-micro); }

.legend { display: flex; gap: var(--space-4); flex-wrap: wrap;
          font-size: var(--fs-micro); color: var(--c-ink-mute); padding: var(--space-2) var(--space-4); }
.legend__item { display: flex; align-items: center; gap: 6px; }
.legend__swatch { width: 14px; height: 14px; border: 1px solid var(--c-border); border-radius: 3px; }

/* Tablet: mřížka zůstává mřížkou, jen zmrazené je míň. Koordinátor na hale
   s tabletem doplní chybějící den — to je to, co tam skutečně dělá. */
@media (max-width: 1024px) {
  .grid tbody td { height: var(--row-h-tp); }
  .g-id--num, .g-id--type, .g-id--group { position: static; }
}

/* Telefon: mřížka se nezobrazí. Je to horší než mřížka, ale poctivější než
   mřížka, ve které se nedá trefit buňka (U1 — Lukáš 3. 9. 2026: „na telefone
   to nikto nerobí"). */
.grid-narrow { display: none; }
@media (max-width: 720px) {
  .grid-wrap, .list-bulk, .legend { display: none; }
  .grid-narrow { display: block; }
}

/* =====================================================================
   DETAIL DNE — zaznamy o case (E13, ukol #93)

   Dialog, formularova pole, pas upozorneni i prazdny stav jsou existujici
   komponenty. Nove je jen to, ze se **skupina poli opakuje**, a k tomu
   patri tri tridy nizsi.
   ===================================================================== */

/* Ramecek, ne jen mezera: u tri zaznamu se bez neho nepozna, ktere pole
   patri ke kteremu — a „Smazat

/* =====================================================================
   DETAIL DNE — zaznamy o case (E13, ukol #93)

   Dialog, formularova pole, pas upozorneni i prazdny stav jsou existujici
   komponenty. Nove je jen to, ze se **skupina poli opakuje**, a k tomu
   patri tridy nizsi.
   ===================================================================== */

/* Ramecek, ne jen mezera: u tri zaznamu se bez neho nepozna, ktere pole
   patri ke kteremu — a „Smazat" pak maze naslepo. */
.fset {
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  padding: var(--space-3); display: grid; gap: var(--space-2);
  background: var(--c-surface);
}
/* Novy zaznam se odlisi carkovanim, ne barvou: je to prazdny formular,
   ne stav. Taz uvaha jako u `.chip--add`. */
.fset--new { border-style: dashed; }
/* Vyrazeny interval smeny. Zustava citelny, protoze se jim v lednu
   vyplnovaly dny — jen se uz nenabizi. */
.fset--retired { background: var(--c-canvas); }
.fsets { display: grid; gap: var(--space-2); margin-top: var(--space-2); }

.fset__row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2); }
.fset__row .field { min-width: 0; }
.fset__time { width: 92px; }
.fset__break { width: 78px; }
.fset__shift { min-width: 150px; flex: 1 1 150px; }

/* Dopoctene hodiny **nejsou pole**. Kdo chce jine cislo, opravi casy nebo
   prestavku — dve pravdy o teze veci jsou to, cemu brani ADR-016. */
.fset__sum {
  margin-left: auto; align-self: center;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: 600; font-size: var(--fs-section); white-space: nowrap;
}
.fset__sum small {
  display: block; font-family: var(--font-sans); font-size: var(--fs-micro);
  font-weight: 400; color: var(--c-ink-mute); text-align: right;
}
/* Konec driv nez zacatek znamena druhy den — nocni smena, ne chyba. */
.fset__over { color: var(--c-soon-ink); font-weight: 600; }

/* Soucet za cely den. Pravidlo nahore, ne ramecek — je to uzaver bloku. */
.day-sum {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); border-top: 2px solid var(--c-border);
  padding-top: var(--space-2); margin-top: var(--space-3);
}
.day-sum__value {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: 18px;
}

/* Nadpis skupiny poli v dialogu. Neni to `.section-title` — ten je nadpis
   sekce detailu a nese jinou velikost. */
.fieldset-label {
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--c-ink-mute);
  border-bottom: 1px solid var(--c-border-hair); padding-bottom: 4px;
}

/* Sirky poli, ktera stoji sama. Nabidka priznaku musi unest cely nazev
   duvodu, ne jen kod; pole s hodinami dve desetinna mista a stitek. */
.day-flag { min-width: 240px; }
.day-hours { width: 140px; }

/* Kostra pri nacitani detailu. Mrizka ma znamy tvar, dialog taky — skok
   z prazdna do plna je horsi nez postupne doplneni. */
.skel { background: var(--c-sunken); border-radius: var(--radius-2); height: 12px; }
.skel--tall { height: 76px; }
.skel--half { width: 55%; }

/* Ukazatel postupu vytezovani (design/e13-import).
   Nativni <progress>, ne vlastni div se sirkou: ctecka obrazovky pak sama
   rekne, kolik z kolika je hotovo, a nemusi se to nikam dopisovat rucne. */
.progress {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: var(--space-2);
}

.progress__bar {
    inline-size: 12rem;
    block-size: 6px;
    border: 0;
    border-radius: 999px;
    background: var(--c-sunken);
    accent-color: var(--c-brand);
}

.progress__count {
    color: var(--c-ink-mute);
    font-size: var(--fs-meta);
    font-variant-numeric: tabular-nums;
}

/* Modal s prubehem (design/e13-import). Jobson 2 tu ma okno pres celou
   obrazovku; tady jde zavrit — vykaz se vytezovanim neblokuje a
   koordinator muze mezitim psat rucne. */
.import-run { display: grid; gap: var(--space-2); }
.import-run + .import-run {
    padding-top: var(--space-4);
    border-top: 1px solid var(--c-border-hair);
}
.import-run__files { font-size: var(--fs-meta); color: var(--c-ink-mute); overflow-wrap: anywhere; }
.import-run__bar { inline-size: 100%; }
.import-run__line { font-size: var(--fs-control); }
.import-run__done { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

/* =====================================================================
   Režim náhledu vytěženého výkazu (design/e13-nahled)
   ===================================================================== */

/* Návrh není zapsaná hodnota a musí to jít poznat i bez barvy: barva už
   nese příznak dne a na tiskárně ani při poruše barvocitu nepomůže.
   Čárkovaný rámeček funguje všude a nese jediné tvrzení — „tohle ještě
   ve výkazu není". */
.day__input--proposed,
.g-comp__input--proposed {
    border-style: dashed;
    border-color: var(--c-pending-line);
    background: transparent;
}

/* Select v hlavicce sloupce slozky (#160). Uzsi nez sloupec byt nemuze -
   sloupec ma 88 px a nazev polozky je dlouhy - takze se orezava a cely
   text nese `title`. */
.gh__map { margin-block-start: 4px; }

.gh__select {
    inline-size: 100%;
    max-inline-size: 100%;
    font-size: 11px;
    padding: 1px 2px;
    block-size: auto;
}

/* Řádek, kde se rozešel součet z papíru se součtem ze dnů. Jediné
   kritérium, ať se dá vysvětlit jednou větou — barva doprovází, nestojí
   sama: totéž říká i hodnota ve sloupci „Z dokladu".

   Podbarvuje se **celý řádek**, souhrny a složky odměňování vpravo
   včetně. Zmrazená pásma mají vlastní pozadí, takže barva na `tr` se pod
   ně nedostane — a řádek pak vypadal roztržený: podbarvená docházka
   vlevo, bílý souhrn vpravo, přesně tam, kde se to nesedící číslo čte
   (Lukáš 11. 9. 2026).

   Druhá polovina selektorů je pro `:hover`. Ten má vyšší selektivitu než
   samotná třída řádku, takže by se řádek při přejezdu odbarvil — zrovna
   ve chvíli, kdy na něj člověk míří. */
.g-row--mismatch .g-id,
.g-row--mismatch .day,
.g-row--mismatch .g-comp,
.g-row--mismatch .g-sum,
.grid tbody tr.g-row--mismatch:hover .g-id,
.grid tbody tr.g-row--mismatch:hover .day,
.grid tbody tr.g-row--mismatch:hover .g-comp,
.grid tbody tr.g-row--mismatch:hover .g-sum {
    background: var(--c-danger-soft);
}

.g-sum--stated { color: var(--c-ink-mute); }

/* Řádek, u kterého dokument součet neuvádí (#172). Jantarová, ne červená:
   červená tvrdí „tady něco nesedí", jantarová „tady jsme nic neověřili".
   Dvě různá tvrzení nesmí mít jednu barvu, jinak koordinátor hledá chybu
   tam, kde žádná hlášená není.

   Druhá polovina selektorů je pro `:hover` — ze stejného důvodu jako
   u `.g-row--mismatch` výš. */
.g-row--unchecked .g-id,
.g-row--unchecked .day,
.g-row--unchecked .g-comp,
.g-row--unchecked .g-sum,
.grid tbody tr.g-row--unchecked:hover .g-id,
.grid tbody tr.g-row--unchecked:hover .day,
.grid tbody tr.g-row--unchecked:hover .g-comp,
.grid tbody tr.g-row--unchecked:hover .g-sum {
    background: var(--c-soon-soft);
}

/* Otazník místo pomlčky. Pomlčka je tichá a vedle sedících řádků splyne;
   otazník je otázka a ta si o pohled řekne. */
.g-sum--unchecked {
    color: var(--c-soon-ink);
    font-weight: 600;
    cursor: help;
}

/* Rozhodnutí o řádku. Dvě tlačítka vedle sebe, ne přepínač: zapsat
   a zahodit mají různý následek a přepínač by je smíchal do „uložit". */
.g-sum--review { padding: 0 var(--space-1); }

.g-sum__review {
    display: flex;
    gap: 4px;
    align-items: center;
}

/* Seznam nespárovaných v hlášce nad mřížkou. */
.review-list {
    display: grid;
    gap: var(--space-2);
    margin: var(--space-2) 0 0;
    padding: 0;
    list-style: none;
}

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

.review-list__who { font-weight: 600; }

.review-list__hint {
    flex-basis: 100%;
    color: var(--c-ink-mute);
    font-size: var(--fs-meta);
}

/* Vzorek barvy priznaku v ciselniku. Ctverecek, ne text: kod #7dd3fc
   nikomu nerekne, jak to v mrizce vypada. */
.swatch {
    display: inline-block;
    inline-size: 18px;
    block-size: 18px;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-1);
    vertical-align: middle;
}

.input--colour {
    inline-size: 52px;
    padding: 2px;
}

/* --- pas mapovani slozek z vykazu (design/e13-priplatky, #160) -------------
   Radek je polozka z cele davky, ne clovek: mapovani je vlastnost haly.
   Nova barva se nezavadi - jantarova rodina uz v nahledu znamena
   "podivej se na to". */

.map {
    border: 1px solid var(--c-border);
    border-radius: var(--radius-2);
    background: var(--c-surface);
    margin-block-end: 16px;
    overflow: hidden;
}

.map__head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-block-end: 1px solid var(--c-border-hair);
    background: var(--c-sunken);
}

.map__title {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
}

.map__count {
    font-size: 12px;
    color: var(--c-ink-mute);
}

.map__table {
    inline-size: 100%;
    border-collapse: collapse;
}

.map__table th {
    text-align: start;
    font-size: 11px;
    font-weight: 500;
    color: var(--c-ink-mute);
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 6px 14px;
    border-block-end: 1px solid var(--c-border-hair);
}

.map__table td {
    padding: 7px 14px;
    border-block-end: 1px solid var(--c-border-hair);
    vertical-align: middle;
}

.map__table tbody tr:last-child td { border-block-end: none; }

/* Nazev nese vahu radku - podle nej se koordinator rozhoduje. Ucet je pamet,
   ne rozhodovaci udaj, takze stoji vedle nej drobne (U1). */
.map__name { font-weight: 500; }

.map__acct {
    display: block;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--c-ink-faint);
}

.map__was {
    display: block;
    font-size: 11px;
    color: var(--c-soon-ink);
}

.map__num {
    text-align: end;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.map__people {
    color: var(--c-ink-mute);
    font-size: 12px;
    white-space: nowrap;
}

/* Jantarovy prouzek = "nekdo to musi odklepnout". Tyz jazyk, jakym mrizka
   od #95 znaci bunku, ktera se neda spocitat. */
.map__table tr[data-state="new"],
.map__table tr[data-state="open"] { background: var(--c-soon-soft); }

.map__table tr[data-state="new"] td:first-child,
.map__table tr[data-state="open"] td:first-child { box-shadow: inset 3px 0 0 var(--c-soon-line); }

.map__table tr[data-state="off"] .map__name {
    color: var(--c-ink-mute);
    font-weight: 400;
}

.map__tag {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 1px 5px;
    border-radius: 3px;
    background: var(--c-soon-line);
    color: var(--c-soon-ink);
    margin-inline-start: 6px;
}

/* Na telefonu se pas nezalamuje do necitelnosti: hlavicka zmizi a radek se
   sklada pod sebe, stejne jako to dela tabulka v .table od 640 px. */
@media (max-width: 640px) {
    .map__table thead { display: none; }

    .map__table tr {
        display: block;
        border-block-end: 1px solid var(--c-border-hair);
        padding-block: 6px;
    }

    .map__table td {
        display: block;
        border-block-end: none;
        padding-block: 3px;
    }

    .map__num { text-align: start; }
}

/* --- starsi obdobi v prehledu (design/e14-obdobi) --------------------------
   Rozbalovaci sekce pod pasmem poslednich sesti mesicu. `<details>` schvalne
   misto prepinace na JavaScriptu: stav si drzi prohlizec, funguje to bez
   skriptu a ctecka to oznami jako rozbalovaci oblast sama. */

.periods-older {
    margin-block-start: 16px;
    border-block-start: 1px solid var(--c-border-hair);
}

.periods-older__summary {
    padding-block: 10px;
    font-size: 13px;
    font-weight: 600;
    color: var(--c-brand-ink);
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
}

.periods-older__summary::-webkit-details-marker { display: none; }

/* Sipka se otaci podle stavu. Je to jediny signal, ze se da rozbalit —
   text sam o tom nerika nic. */
.periods-older__summary::before {
    content: "";
    inline-size: 0;
    block-size: 0;
    border-inline-start: 5px solid currentColor;
    border-block-start: 4px solid transparent;
    border-block-end: 4px solid transparent;
    transition: transform .12s ease;
}

.periods-older[open] > .periods-older__summary::before { transform: rotate(90deg); }

.periods-older__summary:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
