/* 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; }
/* `relative` kvůli bublině: bez něj by se odsazovala od stránky, ne od ikony,
   a skončila by u levého horního rohu okna. */
.app__nav--mini .app__nav-item { justify-content: center; padding: 0; overflow: visible; position: relative; }
.app__nav--mini .app__nav-count { display: none; }
/* Popisek se schová oku, ne čtečce. `display: none` by ho vzal i z přístupového
   stromu a ze všech položek by zbyly odkazy bez jména — ikona je `aria-hidden`,
   takže by nezbylo vůbec nic. */
.app__nav--mini .app__nav-label {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* Bublina s názvem. Jen ve sbaleném pruhu — vedle popisku, který je vidět,
   by jen překážela. Vlastní, ne `title`: ten se objeví až po vteřině čekání
   a v pruhu, kterým člověk projíždí očima, přijde pozdě.

   Vystupuje z navigace do obsahu, takže potřebuje vrstvu nad ním; `aria-hidden`
   nepotřebuje, protože obsah z `content` čtečka nečte jako prvek. */
.app__nav--mini .app__nav-item::after {
  content: attr(data-label);
  position: absolute; left: calc(100% + 6px); top: 50%; transform: translateY(-50%);
  z-index: 40; pointer-events: none;
  padding: 3px var(--space-2); border-radius: var(--radius-1);
  background: var(--c-ink); color: var(--c-canvas);
  font-size: var(--fs-micro); font-weight: 500; white-space: nowrap;
  box-shadow: var(--shadow-2);
  opacity: 0; visibility: hidden; transition: opacity var(--dur-fast) ease;
}
.app__nav--mini .app__nav-item:hover::after,
.app__nav--mini .app__nav-item:focus-visible::after { opacity: 1; visibility: visible; }
.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.

   Pruh je tu úzký z rozhodnutí, ne z volby uživatele, takže se nedá zapnout
   třídou — a popisky se musí schovat týmž způsobem jako u sbalení. Bez toho
   byla navigace 52 px široká, ale popisky se dál vykreslovaly a ořezávaly se
   uprostřed slova. */
@media (min-width: 721px) and (max-width: 1024px) {
  .app__nav { width: var(--nav-w-mini); }
  .app__nav-section { display: none; }
  .app__nav-item { justify-content: center; padding: 0; }
  .app__nav-count { display: none; }
  .app__nav-label {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  /* Tentýž pruh, tytéž důvody — jen ho tu nezapnul uživatel, ale šířka okna. */
  .app__nav-group-label { display: none; }
  .app__nav-group { padding-top: var(--space-2); border-top: 1px solid var(--c-border-hair); }
  .app__nav-item--sub { margin-left: 0; padding-left: 0; border-left: 0; }
  .app__nav-item { overflow: visible; position: relative; }
  .app__nav-item::after {
    content: attr(data-label);
    position: absolute; left: calc(100% + 6px); top: 50%; transform: translateY(-50%);
    z-index: 40; pointer-events: none;
    padding: 3px var(--space-2); border-radius: var(--radius-1);
    background: var(--c-ink); color: var(--c-canvas);
    font-size: var(--fs-micro); font-weight: 500; white-space: nowrap;
    box-shadow: var(--shadow-2);
    opacity: 0; visibility: hidden; transition: opacity var(--dur-fast) ease;
  }
  .app__nav-item:hover::after, .app__nav-item:focus-visible::after { opacity: 1; visibility: visible; }
}
@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; }

  /* Sbalení je nastavení široké obrazovky, ne vlastnost navigace. V šuplíku
     přes celou šířku by samé ikony byly hádanka — a cookie si člověk přiveze
     z počítače, aniž by o ní na telefonu věděl. */
  .app__nav--mini .app__nav-section,
  .app__nav--mini .app__nav-count { display: revert; }
  .app__nav--mini .app__nav-label {
    position: static; width: auto; height: auto;
    overflow: hidden; clip-path: none;
  }
  .app__nav--mini .app__nav-item { justify-content: flex-start; padding: 0 var(--space-2); overflow: hidden; }
  /* V šuplíku jsou popisky vidět, takže bublina nemá co dodat. */
  .app__nav--mini .app__nav-item::after { content: none; }
  .app__nav--mini .app__nav-group-label { display: flex; }
  .app__nav--mini .app__nav-group { padding-top: 0; border-top: 0; }
  .app__nav--mini .app__nav-item--sub {
    margin-left: calc(var(--space-2) + 9px);
    padding-left: var(--space-3);
    border-left: 1px solid var(--c-border);
  }

  /* 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; }

/* Karta volby s drátěnkou — volba formátu šablony (M7, Tomáš 15. 9. 2026).
   Táž `.way` jako tři cesty zakázky, jen s obrázkem nad názvem, aby bylo
   vidět, co z formátu vypadne, dřív než se dočte popisek. */
/* Čtyři formáty ve dvou řadách po dvou. `auto-fit` je rozsypal na 3 + 1,
   což se čte jako by ten čtvrtý patřil jinam. */
.ways--tight { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.way--wired { padding: var(--space-2); text-align: center; }
.way__wire { display: block; margin-bottom: 6px; color: var(--c-ink-mute); }
.way__wire svg { width: 100%; max-width: 64px; height: auto; }
.way[aria-pressed="true"] .way__wire { color: var(--c-brand); }

/* Provozovny se ukážou až po volbě „vyjmenované provozovny" (Tomáš 15. 9.
   2026). `:has()` nad fieldsetem, ne JavaScript ani druhá třída — vzhled
   závislý na obsahu řeší komponenta (CLAUDE.md, Lukáš 31. 8. 2026), takže
   to platí i bez skriptů. Zaškrtávátka zůstávají v DOM, jen nejsou vidět:
   odeslaný formulář tak nese, co v nich bylo. */
.scope-field__sites { display: none; }
.scope-field:has(.scope-field__pick:checked) .scope-field__sites { display: block; }

/* Pole Znění v okně Nová šablona (spec 27 § 4.1, CRM #262): výběr souboru
   jen u volby „Z dokumentu Word", obě volby jen u tiskové šablony — datová
   nemá stránku, do které by se Word dal převést, a místo voleb stojí věta
   proč (CLAUDE.md: chybu ukaž dřív). Stejný vzor jako `.scope-field`:
   vzhled podle vybraného přepínače, bez skriptu a bez druhé třídy. */
.wording-field__file { display: none; margin-top: var(--space-2); }
.wording-field:has(.wording-field__word:checked) .wording-field__file { display: block; }
.wording-field__print-only { display: none; }
form:has(input[name="vystup"]:not([value="print"]):checked) .wording-field__choices { display: none; }
form:has(input[name="vystup"]:not([value="print"]):checked) .wording-field__print-only { display: block; }

/* Další podepisující u šablony (ADR-028, M7 § 6.1 v0.37): řádky role
   s akcí Odebrat, pod nimi „Přidat dalšího podepisujícího"
   (`template-parties`). Prázdný seznam nemá mezeru nad tlačítkem. */
.parties__roles { display: grid; gap: var(--space-2); }
.parties__roles:not(:empty) { margin-top: var(--space-2); }
.parties__role { display: flex; gap: var(--space-2); align-items: center; }
.parties__role .input { flex: 1; min-width: 0; }
.parties__add { margin-top: var(--space-2); }

/* Náhled podpisového bloku (M7-P32) — zmenšený opis `.sign` z tiskové
   stránky: po dvou vedle sebe, „V … dne …" nad linkou s popiskem strany. */
.parties__preview { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--c-border-hair); }
.parties__sign { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4) var(--space-5); margin: var(--space-2) 0; }
.parties__sign:empty { display: none; }
.parties__sign-cell { display: flex; flex-direction: column; gap: var(--space-5); font-size: var(--fs-meta); }
.parties__sign-place { color: var(--c-ink-mute); }
.parties__sign-name { border-top: 1px solid currentColor; padding-top: var(--space-1); overflow-wrap: anywhere; }

/* Místo dalšího podepisujícího při generování (ADR-028 § 3): kdo je vybraný
   z rejstříku, nepotřebuje ruční pole. */
.signer-slot + .signer-slot { margin-top: var(--space-4); }
.signer-slot:has(select option:checked:not([value=""])) .signer-slot__manual { display: none; }

/* 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; }
/* Pole štítku v liště nesmí zabrat celý řádek — `.input` má jinak plnou
   šířku a tlačítka akcí by spadla pod něj (nalezeno s E10, kdy přibylo
   „Zadat úkol"). */
.list-bulk > .input { width: auto; flex: 0 1 220px; min-width: 140px; }

/* `position: relative` dělá z obalu výchozí bod pro absolutně umístěné
   prvky uvnitř (skryté popisky pro čtečku v buňkách). Bez něj se počítaly
   od stránky, z posuvného obalu vylézaly a na telefonu roztáhly stránku
   do strany — matice oprávnění o 388 px (24. 9. 2026). */
.table-wrap { flex: 1; overflow: auto; border-bottom: 1px solid var(--c-border); position: relative; }
.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; }
/* Otisk souboru (SHA-256) je 64 znaků bez jediné mezery — bez zlomu by
   se jeho šířka počítala jako nejmenší přípustná (min-content) a pod
   720 px, kde buňka drží dvousloupcovou mřížku se sloupcem širokým
   desítky pixelů (`.table td` níž), by tenhle jediný „nezlomitelný"
   řádek roztáhl celou kartu do strany, i kdyby vedle stálo jen pár
   slov textu. Zlom kdekoli je ošklivý u prózy, ale otisk se nečte,
   jen se porovnává — a to, že tabulka nevyjede za okraj obrazovky, je
   tu důležitější. */
.table td > .page-head__meta { display: block; overflow-wrap: anywhere; }

/* 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; }

/* Kniha pokladny (M5, design/m5-pokladna N1): příjem ve vlastním sloupci
   zeleně. Výdej zůstává v barvě textu — kniha se čte po sloupcích
   a znaménko ani červená by nic nepřidaly, jen by křičely u každého řádku. */
.money-in { color: var(--c-ok-ink); }

/* Stornovaný pohyb zůstává v knize (M5-P6), jen přeškrtnutý. Buňka akcí se
   nepřeškrtává — nese štítek „stornováno", který se má číst. */
.table__row--void td:not(.table__actions) { color: var(--c-ink-faint); text-decoration: line-through; }
.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 zůstává tabulkou a roluje se doprava.

   Dřív se na telefonu rozpadala do karet. Lukáš 24. 9. 2026: „dlaždice sú
   nepoužiteľné, mal by tam byť datagrid, ktorý aj na mobile by sa mal
   scrolovať doprava" — a potom „urob datagrid všade". Karty se sloupci
   pod sebou nejdou porovnávat řádek s řádkem, a to je u seznamů hlavní
   práce.

   Roluje obal (`.table-wrap`, `overflow: auto`). Tabulka, která obal nemá
   (v dialogu, na kartě osoby), se stane posuvnou sama — bez toho by na
   telefonu roztáhla celou stránku do strany.

   Zaškrtávátko a první sloupec stojí přilepené vlevo, ať je při rolování
   vidět, o čem řádek je. */
@media (max-width: 720px) {
  .table:not(.table-wrap *),
  .matrix:not(.table-wrap *) { display: block; max-width: 100%; overflow-x: auto; }

  .table :is(th, td):first-child,
  .table :is(th, td).table__check + :is(th, td) {
    position: sticky; left: 0; z-index: 1;
    background: var(--c-surface);
  }
  .table thead th:first-child,
  .table thead th.table__check + th { z-index: 2; background: var(--c-canvas); }

  /* Zaškrtávátko má pevnou šířku i s odsazením, ať první sloupec přiléhá
     přesně k němu. */
  .table :is(th, td).table__check { box-sizing: border-box; width: 34px; min-width: 34px; max-width: 34px; padding: 0 0 0 10px; }
  .table :is(th, td).table__check + :is(th, td) { left: 34px; box-shadow: 1px 0 0 var(--c-border); }
  .table:not(:has(.table__check)) :is(th, td):first-child { box-shadow: 1px 0 0 var(--c-border); }
}

/* =====================================================================
   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); }
/* Výčet, ne řada samostatných údajů: mezi „Agentura" a „Osoba" nemá být
   tolik místa jako mezi „Formát Dokument" a „Jazyk Čeština" — jsou to
   položky jednoho seznamu, ne dva různé údaje (Tomáš 15. 9. 2026). */
.detail__facts--list { gap: 4px 6px; align-items: center; }
.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;
    /* `gap`, protože flexbox zahodí mezeru mezi popiskem a počtem: v bloku
       se „Založené <span>2</span>“ čte s mezerou, ve flexu se slepí na
       „Založené2“ a číslo vypadá jako konec slova. Platí pro všechny tři
       obrazovky s touhle nabídkou (Spárování, Návrh změn, Report) i pro ty,
       které teprve vzniknou. */
    gap: var(--space-1);
  }
  .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; margin: 0; font-size: var(--fs-control); }
/* Text upozornění je většinou `<p>` (206×), občas `<span>`: s okrajem
   prohlížeče bylo `p` upozornění o 25 px vyšší než `span` a výška závisela
   na značce, ne na obsahu. Odstup drží `padding` upozornění. */

.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 a chyba jsou odstavce: okraj prohlížeče by se v gridu `.field`
   sečetl s `gap` a text by odskočil od svého vstupu stejně daleko jako od
   dalšího pole — nebylo by vidět, ke kterému patří. Odstup drží jen `gap`. */
.field > .field__hint, .field > .field__error { margin: 0; }
/* 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); }

/* `<pre>` má z principu `white-space: pre`, takže se jeho obsah nezalomí ani
   v úzkém sloupci — a `.code` sám nastavuje jen písmo. Plochý tvar formátu
   JOBSON je přitom **jeden řádek** názvů sloupců slepených středníkem: na
   stránce „Formát a API" to bylo 5 658 px obsahu v boxu širokém 848 px, a
   protože `pre` nic neodstřihává, roztáhlo to celý dokument na 5 910 px na
   1440 px a 5 678 px na 375 px. Stránka se dala odscrollovat do strany.

   Zalomení je tu správnější než vlastní posuvník: středníkem oddělený výčet
   se čte po částech a `user-select: all` z `.code--block` dál kopíruje celý
   řádek. Podle obsahu, ne podle třídy — `pre.code` je vždycky delší útvar,
   ať ho příště někdo vloží kamkoli. */
pre.code { white-space: pre-wrap; overflow-wrap: anywhere; }
.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; }
/* Mezeru mezi zaškrtávátkem a textem dává `gap` — výchozí okraj prohlížeče
   kolem `input[type=radio/checkbox]` (vlevo/vpravo/dole) k němu jen
   přičítal pár px navíc, takže políčko nesedělo pod ostatním textem se
   stejným odsazením (review „radios stick out a few px"). Zůstává jen
   `margin-top`, který vyrovnává políčko s první řádkou popisku. */
.check input { width: 15px; height: 15px; margin: 1px 0 0; 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; }

/* Dvojice tlačítek v buňce (rozhodnutí o konfliktu ve frontě synchronizace,
   E9 krok 18) se na úzké obrazovce **musí zlomit**. Pod 720 px se tabulka
   láme na karty, takže buňka je široká jako obrazovka minus okraje — a dvě
   tlačítka vedle sebe, která se nezlomí, drží celý dokument o pár pixelů
   širší, než je viewport. Vyjetí do strany se přitom nepozná jinak než
   měřením: stránka vypadá v pořádku a jen se dá o kousek odscrollovat.

   Podle obsahu, ne podle třídy: skupina ovládacích prvků uvnitř buňky se má
   takhle chovat vždycky — i v tabulkách, které teprve vzniknou. */
.table td > .input-group { flex-wrap: wrap; gap: var(--space-1); }

/* 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; }
/* Položka mřížky má výchozí `min-width: auto`, tedy nejméně šířku svého
   obsahu. Rozbalovací seznam s dlouhým názvem provozovny tak roztáhl lištu
   i dlaždice pod ní o 16 px do strany (Zálohy na telefonu, M5 řez 3).
   Pravidlo patří stránce, ne té jedné liště — jinak se to stane u příští. */
.page-body > * { min-width: 0; }
.context-bar .select { max-width: 100%; }
.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); }
/* Dvě karty vedle sebe, které se liší **následkem**: „odstraní se"
   × „zůstane" v dialogu Vrátit běh (E9 krok 10), archivace × výmaz.
   Tón je význam té karty, ne vlastnost jejího obsahu, takže ho nese
   modifikátor — `:has()` by se neměl čeho chytit. Barva sama informace
   není: v obou kartách stojí eyebrow se slovem. */
.card--danger { background: var(--c-danger-soft); border-color: var(--c-danger-line); }
.card--ok { background: var(--c-ok-soft); border-color: var(--c-ok-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);
  /* Dialog žije v top layeru, ale `white-space` se dědí přes něj dál —
     tabulkový `.table__actions` (mazací dialog sedí v řádku, vedle
     tlačítka) dá dialogu `nowrap` a dlouhý text (varování u archivovaného
     typu, ADR-027 § 6) se pak nezalomí, ale odjede za okraj a dialog
     dostane vlastní vodorovný posuvník. Reset patří na dialog, ne na
     jednotlivé odstavce uvnitř — jinak se to spraví jen tam, kde si toho
     někdo všiml, a příště nastane znovu u jiného textu v jiné tabulce. */
  white-space: normal;
}
/* Stejná potíž jako `white-space` výš, jiná vlastnost: mazací dialog sedí
   v DOM uvnitř `.table__actions` (dialog žije v top layeru, ale rodičem
   zůstává), a kontejnerový/mediální dotaz níž v souboru zmenšuje `.btn`
   v úzkém sloupci akcí na čtvercovou ikonu bez textu (`width:
   var(--control-h); padding: 0`). Tlačítka v patě dialogu ale nejsou ta
   ikonová akce — nesou celou větu ("Smazat nenávratně") — a s vynucenou
   šířkou 28 px se text zpod tlačítka nezalomí (`.btn` má `white-space:
   nowrap`) a přeteče: na obrazovce se dvě tlačítka v patě překryjí a
   část textu zmizí za okrajem i s vodorovným posuvníkem uvnitř dialogu.
   Tři třídy mají vyšší specificitu než dvě u pravidla, které to
   způsobuje, takže vyhraje bez ohledu na pořadí v souboru. */
.table__actions .dialog .btn { width: auto; padding: 0 var(--space-3); justify-content: center; }
  /* 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, který se otevírá **adresou** (E9 krok 10: `?vraceni=1`), musí
   jít použít i bez JavaScriptu. `open` ho vykreslí do stránky, jenže
   nemodální dialog není vrstva nad obsahem — je to blok uvnitř ní, takže
   šířka 100vw z pravidla pro telefon by stránku vyhnala do strany.
   Rozliší to `:modal`, tedy **stav**, ne druhá třída (`CLAUDE.md`).
   S JavaScriptem se dialog otevře modálně a platí pravidla výš. */
.dialog:not(:modal) {
  position: static; width: auto; max-width: none; max-height: none;
  margin: 0; overflow: visible;
}

/* Srovnání dvou následků („odstraní se" × „zůstane") se do 520 px
   nevejde. Šířku rozhoduje **obsah**, ne druhá třída: dialog, ve kterém
   stojí dva sloupce, je širší. Na telefonu se nic nemění — tam se sloupce
   staví pod sebe a platí pravidlo o vyjetí zespodu níž. */
@media (min-width: 721px) {
  .dialog:has(.split) { width: min(880px, calc(100vw - 2 * var(--space-4))); }
}
.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); }
/* Totéž o úroveň výš: odstavec přímo v těle dialogu (úvod, nápověda pod
   polem) nese okraj navíc ke `gap` a mezi poli pak zejí různé díry. */
.dialog__body > p { margin: 0; }
.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.
     Jen u tlačítka, které **ikonu má** (`:has(svg)`): tlačítko bez ikony by
     se jinak změnilo v prázdný obdélník bez jména, i pro čtečku. Tak dopadlo
     „Zneaktivnit" v Typech dokumentů a Podepisujících mimo systém (CRM #230).
     Hlídá to komponenta podle obsahu, ne pamětlivost autora další tabulky
     (CLAUDE.md, Lukáš 31. 8. 2026). */
  .table__actions .btn:has(svg) .btn__label { display: none; }
  .table__actions .btn:has(svg) { width: var(--control-h); padding: 0; justify-content: center; }
  .table__actions .btn svg { width: 16px; height: 16px; }
}

/* Totéž, ale podle šířky MÍSTA, ne podle šířky okna.
   Pravidlo výše visí na okně, takže tabulka v úzkém sloupci uprostřed
   širokého okna zůstane s popisky a vyjede. Doložený případ (10. 9. 2026):
   sekce Úložiště na kartě osoby je široká 833 px i při okně 1440 px,
   protože vpravo stojí nabídka sekcí — tabulka si řekla o 886 px a akce
   „Smazat" skončila za okrajem, takže se k ní muselo dojet posuvníkem.
   Bylo to vidět už u jediného dokumentu.
   Řešit to breakpointem okna nejde: okno je široké, místo ne. Řešit to
   vlastní třídou na téhle jedné tabulce jde, ale musel by si na ni
   vzpomenout autor každé další sekce — a přesně ten krok vypadne.
   Kontejnerový dotaz platí pro každou tabulku v úzkém místě, i pro ty,
   které teprve vzniknou. 880 px je naměřená přirozená šířka řádku
   s popisky, ne odhad. */
.table-wrap { container-type: inline-size; container-name: table-wrap; }

@container table-wrap (max-width: 880px) {
  /* Táž podmínka jako v bloku pro telefon: popisek zmizí jen tam, kde
     zůstane ikona (CRM #230). */
  .table__actions .btn:has(svg) .btn__label { display: none; }
  .table__actions .btn:has(svg) { width: var(--control-h); padding: 0; justify-content: center; }
  .table__actions .btn svg { width: 16px; height: 16px; }
  /* Zakázané tlačítko nese důvod v textu (konvence z CLAUDE.md), takže
     u něj se popisek schovat nesmí — jinak zmizí to jediné, co říká proč.
     Místo toho se zalomí, na to je pravidlo `:has(.btn[disabled])` níž. */
  .table__actions .btn[disabled] .btn__label { display: inline; }
  .table__actions .btn[disabled] { width: auto; padding: 3px var(--space-2); }
}

/* Akce zůstanou vidět, i když se tabulka nevejde.
   Schovat popisky (pravidlo výš) stačilo na prázdnou tabulku, ne na
   skutečná data: „Pokyn k dočasnému přidělení" je delší než „Smlouva"
   a sloupce se roztáhnou tak, že akce vyjedou ven i s ikonami — doloženo
   11. 9. 2026, kdy u Jana Nováka chybělo 95 px a „Smazat" bylo za okrajem.
   Honit se za prahem kontejnerového dotazu je slepá ulička: příště přijde
   delší název typu a přebije ho. Sloupec akcí proto zůstává přišpendlený
   u pravého okraje a vodorovně se roluje obsah pod ním. Platí to pro
   každou tabulku s akcemi, i pro ty, které teprve vzniknou. */
/* Platí jen tam, kde tabulka zůstává tabulkou. Pod 720 px se rozpadá na
   karty a sloupec akcí tam neexistuje — drží roh karty přes `absolute`
   (pravidlo výš v souboru). Bez tohohle omezení by ho tenhle blok přebil,
   protože stojí níž; stálo to jeden pokus. */
@media (min-width: 721px) {
  .table-wrap:has(.table__actions) { position: relative; }

  .table__actions {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--c-surface);
  }
  /* Přišpendlená buňka má vlastní pozadí, takže by pruhování i zvýraznění
     řádku končilo před sloupcem akcí. Barvy jsou tytéž jako u řádku výš. */
  .table tbody tr:nth-child(even) > .table__actions { background: oklch(0.988 0.002 250); }
  .table tbody tr:hover > .table__actions { background: var(--c-sunken); }
  .table tbody tr[aria-selected="true"] > .table__actions { background: var(--c-brand-soft); }

  /* Záhlaví sloupce akcí se lepí ve dvou osách naráz, aby při rolování
     nahoru ani do strany nezůstalo viset nad prázdnem. */
  thead .table__actions { z-index: 2; }
}

/* Hrana, aby bylo poznat, že pod přišpendleným sloupcem něco je.
   Ukazuje se jen tam, kde se opravdu roluje — u tabulky, která se vejde,
   by to byla čára bez významu. */
@container table-wrap (max-width: 880px) {
  .table__actions { box-shadow: -1px 0 0 var(--c-border); }
}

/* =====================================================================
   ŘÁ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); }
/* Nadpis skupiny ve sbaleném pruhu mizí. Není to odkaz — a ikona, která nic
   neudělá a nic neřekne, je v řadě tlačítek past: Lukáš 17. 9. 2026 na ni
   klikal a divil se, proč se nic neděje. Skupinu tu drží pohromadě linka,
   ne nadpis; odsazení odrážkou taky ne, na to je pruh úzký. */
.app__nav--mini .app__nav-group-label { display: none; }
.app__nav--mini .app__nav-group {
  padding-top: var(--space-2);
  border-top: 1px solid var(--c-border-hair);
}
.app__nav--mini .app__nav-item--sub { margin-left: 0; padding-left: 0; border-left: 0; }

/* ---------------------------------------------------------------------------
   Sbalovací skupina a účet dole (návrh design/e16-menu, 23. 9. 2026)

   Navigace je sloupec: moduly se rolují, účet dole stojí. Stojí i tehdy,
   když roluje stránka — jinak by u dlouhého seznamu osob ujel pod ohyb.

   Skupina je `<details>`: nadpis je tlačítko, které skupinu rozbalí, a to
   i ve sbaleném pruhu. Dřív tam nadpis mizel, protože ikona, která nic
   neudělá, byla past (Lukáš 17. 9. 2026) — teď něco dělá.
   --------------------------------------------------------------------------- */
.app__nav {
  display: flex; flex-direction: column; padding: 0; min-height: 0;
  position: sticky; top: var(--topbar-h); align-self: flex-start;
  height: calc(100vh - var(--topbar-h));
  /* Přilepený prvek je vlastní vrstva, a nabídka účtu uvnitř by bez tohohle
     ležela pod přilepenou hlavičkou tabulky osob. Pod horní lištou (20). */
  z-index: 15;
}
.app__nav-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-2) 0; }

.app__nav-group-toggle {
  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); cursor: pointer; list-style: none;
  font-size: var(--fs-control); color: var(--c-ink); white-space: nowrap;
}
.app__nav-group-toggle::-webkit-details-marker { display: none; }
.app__nav-group-toggle:hover { background: var(--c-sunken); }
.app__nav-group-toggle:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }
/* Šipka je poslední ikona v nadpisu — menší a tlumená, otočí se při rozbalení. */
.app__nav-group-toggle > .app__nav-icon:last-child,
.account__trigger > .app__nav-icon:last-child,
.account__langs > summary > .app__nav-icon:last-child {
  width: 12px; height: 12px; color: var(--c-ink-mute); transition: transform var(--dur-fast) ease;
}
.app__nav-group[open] > .app__nav-group-toggle > .app__nav-icon:last-child,
.account__langs[open] > summary > .app__nav-icon:last-child { transform: rotate(90deg); }
/* Součet jen u sbalené skupiny — u rozbalené by opakoval čísla o řádek níž. */
.app__nav-group[open] > .app__nav-group-toggle .app__nav-count { display: none; }
/* Sbalená skupina, ve které je aktuální stránka: nadpis se podbarví, ať je
   vidět, kde člověk je, i když položka sama je schovaná. */
.app__nav-group--here:not([open]) > .app__nav-group-toggle {
  background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600;
}

.app__nav-foot { flex: none; position: relative; padding: var(--space-2); border-top: 1px solid var(--c-border); }
.account > summary { list-style: none; }
.account > summary::-webkit-details-marker, .account__langs > summary::-webkit-details-marker { display: none; }
.account__trigger {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-2); border-radius: var(--radius-2); cursor: pointer;
}
.account__trigger:hover, .account[open] > .account__trigger { background: var(--c-sunken); }
.account__trigger:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }
.account__trigger > .app__nav-icon:last-child { transform: rotate(-90deg); }
.account__avatar {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--c-brand); color: var(--c-on-brand); font-size: 12px; font-weight: 600;
}
.account__who { flex: 1; min-width: 0; display: grid; line-height: 1.2; }
.account__name, .account__agency { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account__name { font-size: var(--fs-control); font-weight: 600; }
.account__agency { font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Nabídka vyjede nad tlačítko, jako v Claude Desktop. */
.account__menu {
  position: absolute; left: var(--space-2); bottom: calc(100% - var(--space-1)); z-index: 50;
  width: 272px; max-height: calc(100vh - var(--topbar-h) - 80px); overflow-y: auto;
  padding: var(--space-1) 0;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--radius-2); box-shadow: var(--shadow-2);
}
.account__head { padding: var(--space-2) var(--space-3); font-size: var(--fs-micro); color: var(--c-ink-mute); overflow: hidden; text-overflow: ellipsis; }
.account__section {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: 10px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink-faint);
}
.account__sep { height: 1px; margin: var(--space-1) 0; background: var(--c-border-hair); }
.account__value { color: var(--c-ink-mute); font-size: var(--fs-micro); }
.account__langs > summary { list-style: none; cursor: pointer; }
.account__lang-list { display: grid; padding-left: 28px; }
.account__menu form { margin: 0; }

/* Položky nabídky jsou položky navigace — ale sbalený pruh (volbou i šířkou
   okna) je nesmí smrsknout na ikony. Nabídka má svou šířku vždycky. */
.app__nav .account__menu .app__nav-item {
  justify-content: flex-start; padding: 0 var(--space-2); overflow: hidden; position: static;
  width: calc(100% - 2 * var(--space-2)); border: 0; background: none; font: inherit;
  font-size: var(--fs-control); color: var(--c-ink); cursor: pointer; text-align: left;
}
.app__nav .account__menu .app__nav-item:hover { background: var(--c-sunken); }
.app__nav .account__menu .app__nav-item[aria-current] { background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600; }
.app__nav .account__menu .app__nav-item::after { content: none; }
.app__nav .account__menu .app__nav-label {
  position: static; width: auto; height: auto; clip-path: none; overflow: hidden;
}

/* Sbalený pruh: z účtu zbude kolečko, ze skupiny ikona s číslem. */
.app__nav--mini .account__who,
.app__nav--mini .account__trigger > .app__nav-icon:last-child { display: none; }
.app__nav--mini .account__trigger { justify-content: center; padding: 6px 0; }
.app__nav--mini .app__nav-group-toggle { justify-content: center; padding: 0; position: relative; }
.app__nav--mini .app__nav-group-toggle > .app__nav-icon:last-child { display: none; }
.app__nav--mini .app__nav-group-toggle .app__nav-count {
  display: inline; position: absolute; top: 1px; right: 4px;
  padding: 0 3px; font-size: 9px; background: var(--c-brand); color: var(--c-on-brand);
}
.app__nav--mini .app__nav-group { padding-top: 0; border-top: 0; }
@media (min-width: 721px) and (max-width: 1024px) {
  .account__who, .account__trigger > .app__nav-icon:last-child { display: none; }
  .account__trigger { justify-content: center; padding: 6px 0; }
  .app__nav-group-toggle { justify-content: center; padding: 0; position: relative; }
  .app__nav-group-toggle > .app__nav-icon:last-child { display: none; }
  .app__nav-group-toggle .app__nav-count {
    display: inline; position: absolute; top: 1px; right: 4px;
    padding: 0 3px; font-size: 9px; background: var(--c-brand); color: var(--c-on-brand);
  }
  .app__nav-group { padding-top: 0; border-top: 0; }
}
/* Na telefonu je navigace šuplík přes celou výšku; účet sedí na jeho spodku
   a sbalení pruhu tam neplatí (viz výše), takže se ukáže celý. */
@media (max-width: 720px) {
  .app__nav { position: fixed; z-index: 30; }
  .app__nav--mini .account__who { display: grid; }
  .app__nav--mini .account__trigger { justify-content: flex-start; padding: 6px var(--space-2); }
  .app__nav--mini .app__nav-group-toggle { justify-content: flex-start; padding: 0 var(--space-2); }
  .app__nav--mini .app__nav-group-toggle > .app__nav-icon:last-child { display: inline; }
  .app__nav--mini .app__nav-group-toggle .app__nav-count { position: static; font-size: 10.5px; background: var(--c-sunken); color: var(--c-ink-mute); padding: 1px 5px; }
}

/* ---------------------------------------------------------------------------
   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; }
/* `flex-wrap` a `min-width: 0` navíc oproti `.list-toolbar` samotné: dokud
   lišta nesla jen jedno tlačítko (kartotéka, E8), `flex: none` nikdy
   nepřetekl. Úložiště napříč agenturou do ní dalo tři filtry a přepínač
   vedle sebe (M7-ux-návrh § 10) — na 375 px se bez zalomení nevejdou a lišta
   vyjede do strany (`CLAUDE.md`, zpětná vazba po náboru). Bez `min-width: 0`
   `flex-wrap` samo nestačí: `flex: none` drží položku na její obsahové
   šířce a nedovolí jí se v rodičovském flexu zúžit, takže by se nezalomila
   ona sama, ale přetekla by ven jako celek. Komponenta se přizpůsobuje podle
   obsahu, ne druhá třída vedle první. */
.list-toolbar__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; flex: 0 1 auto; min-width: 0; }
.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; }
/* Zavřený nativní popover je skrytý, ať mu třída panelu (`display: grid`
   u nabídky úkolu) nastaví cokoli — jinak visí otevřený přes stránku. */
[popover]:not(:popover-open) { display: none; }
.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; }
/* Věta pod nadpisem skupiny. Dvě skupiny odkazů se stejnými názvy („CSV",
   „JSON") se bez ní čtou jako totéž dvakrát — a rozdíl mezi exportem
   obrazovky a formátem, který jde nahrát zpátky, je přesně to, co má
   člověk vědět dřív, než klikne. */
.popover__note { margin: 0; font-size: var(--fs-micro); color: var(--c-ink-mute); max-width: 32ch; }
.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); }
/* Upozornění s odkazem (E10 F3) vypadá jako to bez něj — odkazem je celý
   řádek, ne podtržená věta. */
a.bell-item { color: inherit; text-decoration: none; }
a.bell-item:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }
.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; }
/* Upozornění pod poli, ke kterým patří (např. důsledek volby zdroje importu). */
.form-grid + .notice { margin-top: var(--space-3); margin-bottom: 0; }
/* 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); }

/* Tentýž rozdíl s volbou u každého pole — návrh změn importu (E9 krok 9,
   G6): „na kartě → ve zdroji", přijmout × ponechat kartu. Sloupec s volbou
   přibývá **podle obsahu**, ne druhou třídou (`CLAUDE.md`), takže ho dostane
   i rozdíl, který někdo přidá příště. */
.diff:has(.diff__acts) .diff__row { grid-template-columns: 180px 1fr 1fr auto; align-items: center; }
.diff__acts form { display: flex; gap: var(--space-2); flex-wrap: wrap; }

@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:has(.diff__acts) .diff__row { grid-template-columns: 1fr; }
  .diff__row:first-child { display: none; }
  .diff__row > div:first-child { color: var(--c-ink-mute); font-size: var(--fs-meta); }
  /* Bez záhlaví by u sebe stály dvě hodnoty bez toho, která je odkud.
     Stranu nese `data-side` — táž úvaha jako u `.cmp`. */
  .diff__row > div[data-side]::before { content: attr(data-side) ": "; color: var(--c-ink-mute); font-weight: 400; }
}

/* ---------------------------------------------------------------------------
   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; }
}

/* =====================================================================
   NÁHLED DOKUMENTU (M7 § 6.2 — generování)
   Vzor z návrhu `design/m7/1-detail-dokumentu.html`, kde `.docview` zatím
   žil jen v mockupu. Přenáší se sem beze změny hodnot — všechny přes
   tokeny, aby to uneslo tmavý režim i změnu hustoty.
   ===================================================================== */
.docview { border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-sunken); overflow: hidden; }
.docview__bar { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-border-hair); background: var(--c-surface); }
.docview__name { font-size: var(--fs-control); font-weight: 600; }
.docview__meta { font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Znění je **jen ke čtení** (ADR-015 § 3) — žádné `contenteditable`, žádná
   akce uvnitř stránky. Roluje se ve svém kontejneru, aby formulář nahoře
   a lišta akcí dole zůstaly vidět (návrh: tablet je hlavní zařízení
   koordinátora na nástupním dni). */
.docview__page {
    max-height: 60vh;
    overflow: auto;
    margin: var(--space-3) auto;
    padding: var(--space-5);
    max-width: 720px;
    background: var(--c-surface);
    border: 1px solid var(--c-border-hair);
    border-radius: var(--radius-2);
    font-size: var(--fs-control);
    line-height: var(--lh-base);
}
.docview__page h1, .docview__page h2, .docview__page h3 { font-size: var(--fs-section); text-align: center; margin: 0 0 var(--space-4); }
.docview__page p { margin: 0 0 var(--space-2); }

/* Prázdné místo po chybějící nekritické hodnotě. Značku vydává
   `ResolvedVariables::forTwig()`; tady dostává podklad. Nese **slovo**
   (popisek proměnné) i podtržení — barva sama není pro člověka s poruchou
   barvocitu informace. */
.missing-value { padding: 0 4px; border-bottom: 2px dotted var(--c-soon-line); background: var(--c-soon-soft); color: var(--c-soon-ink); font-weight: 600; }

/* Turbo si při výměně rámu sám nastaví `aria-busy` — probíhající práce je
   tím vidět bez vlastního ovladače a bez pollingu. */
turbo-frame[aria-busy="true"] { opacity: .55; }

/* ---------------------------------------------------------------------------
   Úložiště na kartě osoby (M7-ux-návrh § 1)

   Tři věci, které jinde na projektu nejsou: souhrn nad tabulkou, lišta
   ovládání uvnitř sekce (ne přes celou stránku) a strom vazeb v datagridu.
   Zbytek je `.meters`, `.list-filters`, `.table` a `.pager` beze změny —
   nová obrazovka nemá vyrábět druhou sadu tříd pro totéž.
   --------------------------------------------------------------------------- */

/* Souhrn je „měřidlo bez pruhu": strop není známý (kolik dokumentů má osoba
   mít?), a prázdný pruh by tvrdil, že známý je a je nulový. Karty jsou užší
   než na fakturačním přehledu — jsou to tři čísla, ne tři témata. */
.storage-summary { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: var(--space-3); }
.storage-summary .meter__value { font-size: 24px; }
.storage-summary .meter__note { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }

/* Štítek v poznámce pod číslem nese VĚTU, ne stavové slovo — „1 dokument
   expiruje do 30 dnů", ne „Expiruje". Základní `.status` má
   `white-space: nowrap`, protože stavové slovo se lámat nemá; tady to ale
   znamená, že štítek vyjede z dlaždice ven. Doloženo 10. 9. 2026 na 375 px:
   228 px štítku v rámečku širokém 169 px.
   Neřeším to zkrácením textu ani zvláštní třídou u tohohle jednoho štítku —
   pravidlo patří k MÍSTU: co stojí v poznámce, je věta a smí se zalomit.
   Platí to i pro poznámky, které teprve vzniknou. */
.meter__note .status { white-space: normal; text-align: left; }

/* Lišta ovládání sekce. Uvnitř karty nemá spodní linku přes celou šířku ani
   ostré rohy — není to hlavička stránky, je to pruh nad tabulkou. */
.storage-bar { border: 1px solid var(--c-border); border-radius: var(--radius-2); margin-bottom: var(--space-3); }
.storage-bar .field { margin: 0; }
/* Hledání roste, filtry ne: pole, do kterého se píše, potřebuje šířku,
   nabídka se dvěma slovy ne. */
.storage-bar__search { flex: 1 1 200px; min-width: 160px; max-width: 280px; }
/* Akce vpravo — „hledání vlevo, akce vpravo" (vzor E8). */
.storage-bar__actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* Strom vazeb v první buňce. Odsazení nese svislá linka — tentýž vizuální
   vzor jako druhá úroveň navigace (`.app__nav-item--sub`), aby se „tohle
   patří pod to" četlo stejně na obou místech.

   Hloubka jde z `--tree-depth`, ne z třídy na každý stupeň: dodatek k dodatku
   je běžný případ a `.tree--level-3` by znamenalo, že se na čtvrtou úroveň
   zapomene. */
.tree { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tree[style*="--tree-depth"] { margin-left: calc(var(--tree-depth, 0) * var(--space-4)); }
.tree[style*="--tree-depth"]:not([style*="--tree-depth: 0"]) {
  padding-left: var(--space-3);
  border-left: 1px solid var(--c-border);
}

/* Rozbalovátko je `button` (kvůli `aria-expanded`), ale stav ukládá do
   adresy, takže sedí ve vlastním GET formuláři. Formulář nesmí zabrat řádek
   ani rozhodit rovnání buňky. */
.tree__toggle { display: inline-flex; margin: 0; }
.tree__button {
  width: 22px; height: 22px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--c-border); border-radius: var(--radius-1);
  background: var(--c-surface); color: var(--c-ink-mute); cursor: pointer;
  font-size: var(--fs-meta); line-height: 1;
}
.tree__button:hover { color: var(--c-ink); border-color: var(--c-ink-faint); }

/* Rozpracovaný dodatek (M7-P23) je to jediné v úložišti, co na sebe má
   upozornit: nedokončená práce mezi hotovými dokumenty. Podklad **a** štítek
   — barva sama není pro člověka s poruchou barvocitu informace. */
.table tbody tr.table__row--draft,
.table tbody tr.table__row--draft:nth-child(even) { background: var(--c-pending-soft); }

@media (max-width: 720px) {
  /* Na kartách je odsazení svislou linkou k ničemu (karty jsou pod sebou přes
     celou šířku) a jen ukrajuje místo z názvu. Vazbu drží štítek typu. */
  .tree[style*="--tree-depth"] { margin-left: 0; padding-left: 0; border-left: 0; }
  .storage-bar__actions { margin-left: 0; width: 100%; }
  .storage-bar__search { flex-basis: 100%; }
}

/* Zakázaná volba nese důvod ve **svém textu** (`CLAUDE.md`), takže je delší
   než tlačítko s jedním slovem. Buňka akcí se kvůli ní musí umět zalomit —
   jinak tabulku rozšíří a řádek uteče do vodorovného rolování.

   Rozhoduje obsah, ne třída navíc: `:has()` platí i pro tabulky, které teprve
   vzniknou, kdežto `.table__actions--wrapping` by si musel někdo pamatovat. */
.table__actions:has(.btn[disabled]) { white-space: normal; }
.table__actions:has(.btn[disabled]) .table__actions-group { flex-wrap: wrap; }
.table__actions .btn[disabled] { height: auto; min-height: 26px; padding-block: 3px; text-align: left; }

@media (max-width: 720px) {
  /* Na telefonu se z akcí v řádku stávají ikony a buňka visí absolutně
     v pravém dolním rohu karty. To platí pro tlačítko s jedním slovem —
     zakázané tlačítko ale nese **důvod ve svém textu**, takže by se z něj
     stala samotná ikona bez vysvětlení (tedy přesně ta bublina, které se
     vyhýbáme) a přetekla by přes okraj karty.

     Buňka s takovým tlačítkem se proto vrací do toku karty a popisek
     zůstává vidět. Rozhoduje obsah, ne třída navíc (`CLAUDE.md`), takže to
     platí i pro tabulky, které teprve vzniknou. */
  .table__actions:has(.btn[disabled]) {
    position: static; margin-top: var(--space-2); padding-top: var(--space-2);
    border-top: 1px solid var(--c-border-hair); text-align: left;
  }
  .table__actions:has(.btn[disabled])::before { content: none; }
  .table__actions:has(.btn[disabled]) .table__actions-group { justify-content: flex-start; width: 100%; }
  .table__actions .btn[disabled] { width: auto; padding: 3px var(--space-2); }
  .table__actions .btn[disabled] .btn__label { display: inline; }
}

/* ---------------------------------------------------------------------------
   DETAIL DOKUMENTU (M7-ux-návrh § 9, prototyp `design/m7/1-detail-dokumentu.html`)

   Pět komponent, které v systému nebyly, protože žádná obrazovka dosud
   neukazovala **soubor** ani **několik podpisových cest vedle sebe**. Rám
   obrazovky (`.detail__head`, `.detail__tabs`, `.detail__body`,
   `.detail__aside`, `.facts`, `.timeline`, `.notice`) se přebírá beze změny —
   nová obrazovka nemá vyrábět druhou sadu tříd pro totéž.
   --------------------------------------------------------------------------- */

/* 1 · PŘEDMĚT — čeho se dokument týká.

   Popisky leží ve snímku dokumentu (ADR-015 § 7), takže se nikoho neptají
   a přejmenování haly nemění, co stálo u podepsané smlouvy. Vlastní prvek
   proto, že `.chip` je odebíratelný filtr (má křížek a zavazuje k tomu, že
   ho jde zrušit) a `.tag` je barevný odznak bez místa na druhý řádek textu.
   Tady jde o dvojici „druh + jméno", kde druh je to menší z obou. */
.subjects { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.subject {
  display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0;
  padding: 5px var(--space-3);
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); font-size: var(--fs-control);
}
.subject__kind { flex: none; font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* 2 · CESTA JEDNÉ PODEPISUJÍCÍ STRANY.

   `.timeline` je jedna svislá osa událostí záznamu. Tady jich běží několik
   vedle sebe: každá strana má vlastní stav a stav dokumentu se z nich teprve
   odvozuje (M7-P16). Kdyby se všechny podpisy slily do jedné osy, zmizí právě
   ta informace, na které celé workflow stojí — na koho se čeká. */
.party { border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); background: var(--c-surface); padding: var(--space-3); margin-bottom: var(--space-2); }
.party__head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-2); }
.party__name { font-weight: 600; }
.party__role { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.party__actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.party__steps { display: flex; flex-wrap: wrap; gap: var(--space-2) 0; }
.party__step {
  display: grid; gap: 1px; min-width: 148px; flex: 1 1 148px;
  padding: 0 var(--space-3) 0 var(--space-2); border-left: 2px solid var(--c-border);
}
.party__step--done { border-left-color: var(--c-brand-line); }
.party__step--refused { border-left-color: var(--c-rejected-line); }
.party__step--expired { border-left-color: var(--c-expired-line); }
/* Krok, který teprve přijde, je čárkovaný: plná linka u „čeká na podpis"
   se čte jako hotovo. */
.party__step--waiting { border-left-style: dashed; }
.party__when { font-family: var(--font-mono); font-size: 11px; color: var(--c-ink-mute); }
.party__what { font-size: var(--fs-control); }
.party__detail { font-size: var(--fs-micro); color: var(--c-ink-faint); }

/* 3 · OTISK.

   Šedesát čtyři znaků, které se nikdy nečtou celé — kontrolují se prvními
   a posledními. Vlastní prvek proto, aby šel zkrátit uprostřed a přesto
   zůstal celý ke zkopírování; `.u-num` samo řeší jen písmo.

   Zkracuje se **v textu**, ne `text-overflow`em: výpustka uprostřed
   (`a3f5c9e1…d8b76204`) ověří obě strany otisku, kdežto uříznutý konec
   neověří nic. Celá hodnota zůstává v `title` a ve vlastním prvku pod ním,
   aby ji šlo označit myší. */
.hash { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.hash__value { font-family: var(--font-mono); font-size: 11px; color: var(--c-ink); min-width: 0; overflow-wrap: anywhere; }

/* 4 · ŘETĚZ DOKUMENTŮ.

   Táž třída `.tree` jako strom vazeb v buňce úložiště, protože je to **táž
   věc**: dodatek patří pod smlouvu. Liší se jen tím, co v ní stojí — v řádku
   tabulky jeden uzel vedle sebe, tady celý řetěz pod sebou. Rozhoduje proto
   obsah, ne druhá třída (`CLAUDE.md`, Lukáš 31. 8. 2026): `:has(.tree__row)`
   platí i pro řetězy, které teprve vzniknou, kdežto `.tree--vertical` by si
   musel autor vzpomenout a recenzent uhlídat.

   Odsazení nese `--tree-depth` na řádku, ne třída na každý stupeň — dodatek
   k dodatku je běžný případ a `.tree__row--level-3` znamená, že se na čtvrtou
   úroveň zapomene. Je to táž proměnná jako v úložišti, takže obě obrazovky
   odsazují stejně. */
.tree:has(.tree__row) { display: grid; gap: var(--space-2); }
.tree__row {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--c-border-hair); border-radius: var(--radius-2);
  background: var(--c-surface);
  margin-left: calc(var(--tree-depth, 0) * var(--space-5));
}
.tree__row--child { border-left: 2px solid var(--c-border); }
/* Rozpracovaný dodatek (M7-P23) je to jediné v řetězu, co na sebe má
   upozornit: nedokončená práce mezi hotovými dokumenty. Podklad **a** štítek
   — barva sama není pro člověka s poruchou barvocitu informace. */
.tree__row--draft { background: var(--c-soon-soft); border-color: var(--c-soon-line); }
/* Dokument, jehož detail je otevřený. Bez tohohle se v řetězu pěti dodatků
   nepozná, kde člověk zrovna stojí. */
.tree__row--current { border-color: var(--c-brand-line); background: var(--c-brand-soft); }
.tree__kind { font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--c-ink-mute); }
.tree__name { font-weight: 600; }
.tree__meta { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* 5 · NÁHLED SOUBORU.

   `.docview` už v systému je (generování dokumentu), ale vykresluje **HTML
   znění**. Detail ukazuje uložený soubor, takže potřebuje dvě věci navíc:
   rám prohlížeče PDF a miniaturu do postranního sloupce. */
.docview__tools { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* Prohlížeč PDF si kreslí prohlížeč sám; my dodáváme jen plochu. Výška je
   relativní k výřezu, protože dokument se čte na tabletu na výšku i na
   monitoru na šířku. */
.docview__frame { display: block; width: 100%; height: min(70vh, 720px); border: 0; background: var(--c-sunken); }
/* Miniatura není jiná komponenta, je to týž list zmenšený — proto sdílí
   třídu a mění jen rozměr. */
.docview--mini .docview__frame { height: 180px; }

/* Blok postranního sloupce. `.section-title` je nadpis sekce v hlavním
   proudu; tady jde o tři užší bloky pod sebou, které potřebují mezeru mezi
   sebou, ne nad tabulkou. */
.aside-block { margin-bottom: var(--space-5); }
.aside-block:last-child { margin-bottom: 0; }
.aside-block__title { font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--c-ink-mute); margin-bottom: var(--space-2); }

@media (max-width: 720px) {
  /* Odsazení svislou linkou ukrajuje z názvu na úzké obrazovce víc, než kolik
     přidá — vazbu drží štítek typu, stejně jako v tabulce úložiště. */
  .tree__row { margin-left: 0; }
  .tree__meta { margin-left: 0; width: 100%; }
  .party__step { min-width: 0; flex-basis: 100%; }
  .docview__frame { height: 60vh; }
}

/* =====================================================================
   PODPISOVÝ OBŘAD (M7-ux-návrh § 4, CRM #15)

   Jediná obrazovka v JOBSONu bez systémové skořápky. Cílové zařízení není
   monitor, ale TABLET NA VÝŠKU držený v ruce — často venku na stavbě, na
   slunci, mokrýma rukama nebo v rukavici. Proto se tu proti zbytku systému
   mění tři věci, a jenom ty tři:

     · písmo 18 px místo 13 px (základ `--fs-base` se čte ve stínu kanceláře,
       ne na přímém slunci),
     · dotykové cíle 56 px místo 44 px (systémových 44 je minimum pro prst
       v suchu; prst v rukavici mine),
     · obsah v jednom sloupci do 600 px na střed (delší řádek se na výšku
       čte hůř a dvousloupec by rozhodnutí rozdělil).

   Barvy, poloměry ani stíny se nemění — všechno je z `tokens.css`. Nová
   barva v obřadu by znamenala, že se JOBSON na jedné obrazovce tváří jako
   jiný produkt. */

/* Turbo rám je vlastní prvek: dokud se skript nenačte (nebo se nenačte
   nikdy), je pro prohlížeč `display: inline` a rozvržení uvnitř se rozpadne.
   Tohle je jediné místo, kde se rám podílí na vzhledu. */
turbo-frame.ceremony { display: block; }

.ceremony-body {
  margin: 0; min-height: 100dvh;
  background: var(--c-canvas); color: var(--c-ink);
  font-family: var(--font-sans); font-size: 18px; line-height: var(--lh-base);
}
.ceremony { display: block; min-height: 100dvh; }

/* Jeden sloupec na střed. `100dvh` (ne `100vh`): na telefonu s vysouvací
   lištou prohlížeče by `vh` schovalo tlačítko pod ohyb a člověk by hledal,
   kam kliknout. */
.ceremony__stage {
  max-width: 600px; margin: 0 auto;
  min-height: 100dvh; padding: var(--space-6) var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-4);
  justify-content: center; text-align: center;
}
/* Krok podpisu se necentruje svisle: plocha zabírá většinu obrazovky
   a centrování by tlačítka vytlačilo pod ohyb. */
.ceremony__stage--sign { justify-content: flex-start; text-align: left; }
.ceremony__stage--done { gap: var(--space-3); }

/* Přepínač jazyka. Šest odkazů, ne rozbalovací nabídka: `select` je na
   tabletu v rukavici past a bez JavaScriptu by se neodeslal. Vodorovné
   rolování místo mřížky — na 320 px se šest jazyků do mřížky nevejde
   (M7-ux-návrh § 4, „Mobil a tablet"). */
.ceremony__langs {
  display: flex; gap: var(--space-2); justify-content: center; flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.ceremony__lang {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; min-width: 64px; 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-size: 16px; font-weight: 500; text-decoration: none;
}
.ceremony__lang[aria-current="true"] {
  border-color: var(--c-brand); background: var(--c-brand-soft);
  color: var(--c-brand-ink); font-weight: 600;
}

.ceremony__label { font-size: 14px; letter-spacing: .08em; text-transform: uppercase; color: var(--c-ink-mute); }
/* Název dokumentu a jméno podepisujícího jsou to jediné, podle čeho
   podepisující pozná, že obrazovka patří jemu. `text-wrap: balance`, aby
   se dlouhý název nezlomil na jedno osamělé slovo. */
.ceremony__headline { margin: 0; font-size: 30px; font-weight: 700; line-height: var(--lh-tight); text-wrap: balance; }
.ceremony__name { margin: 0; font-size: 34px; font-weight: 700; line-height: var(--lh-tight); text-transform: uppercase; }
.ceremony__title { margin: 0; font-size: 26px; font-weight: 700; line-height: var(--lh-tight); }
.ceremony__sub { margin: 0; font-size: 17px; color: var(--c-ink-mute); }
.ceremony__note { margin: 0; font-size: 15px; color: var(--c-ink-mute); text-wrap: pretty; }
.ceremony__moment { margin: 0; font-size: 17px; color: var(--c-ink-mute); }
.ceremony__error { font-size: 16px; text-align: left; }

/* Hlavní tlačítko kroku: celá šířka, minimálně 56 px. Víc než systémových
   44 px schválně — venku, mokré ruce, rukavice. `height: auto` přebíjí
   pevnou výšku z `.btn`, protože překlad tlačítka se v němčině nebo
   ukrajinštině na jeden řádek nevejde. */
.ceremony__go {
  width: 100%; min-height: 56px; height: auto;
  padding: var(--space-3) var(--space-4);
  font-size: 19px; font-weight: 600; white-space: normal;
}

/* ---- Krok 3 · čtení -------------------------------------------------- */
.ceremony__read { display: flex; flex-direction: column; height: 100dvh; }
.ceremony__bar {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  background: var(--c-surface); border-bottom: 1px solid var(--c-border);
}
.ceremony__bar-title { font-size: 17px; font-weight: 600; }
.ceremony__bar-meta { font-size: 15px; color: var(--c-ink-mute); }
.ceremony__bar-lang { margin-left: auto; font-size: 15px; color: var(--c-ink-mute); }

/* Vlastní roletka, ne roletka stránky: lišta s potvrzením musí zůstat na
   očích, jinak tlačítku pod prstem zmizí opora. */
.ceremony__reader { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; background: var(--c-sunken); }
/* Rám je vyšší než výřez schválně: dokument se má rolovat, ne mlčky
   skončit na první stránce. Kdyby byl rám vysoký jako výřez, byla by
   značka konce vidět hned a brána by nic nehlídala. */
.ceremony__doc { display: block; width: 100%; height: 160dvh; border: 0; background: var(--c-surface); }
.ceremony__end {
  margin: 0; padding: var(--space-5) var(--space-4);
  text-align: center; font-size: 15px; color: var(--c-ink-mute);
}
.ceremony__foot {
  padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--c-surface); border-top: 1px solid var(--c-border);
}
.ceremony__hint { margin: 0 0 var(--space-2); font-size: 15px; color: var(--c-ink-mute); text-align: center; }
/* Nápověda zmizí, jakmile brána povolí — schovává ji `hidden`, a vlastní
   `display` by ho přebil. */
.ceremony__hint[hidden] { display: none; }

/* ---- Krok 4 · podpis ------------------------------------------------- */
.ceremony__clear-row { margin: 0; display: flex; justify-content: flex-end; }
.ceremony__clear { min-height: 44px; height: auto; font-size: 16px; text-decoration: underline; }

/* Plocha zabírá 60 % výšky obrazovky (návrh), nejméně 280 px na tabletu.
   Relativní obal drží nápovědu uprostřed plochy. */
.ceremony__pad { position: relative; height: 60dvh; min-height: 240px; }
.ceremony__canvas {
  display: block; width: 100%; height: 100%;
  background: var(--c-surface);
  border: 2px dashed var(--c-border); border-radius: var(--radius-3);
  /* Bez tohohle prohlížeč při tahu prstem roluje stránku místo kreslení.
     Platí JEN na ploše — dokument v kroku 3 se rolovat musí. */
  touch-action: none;
  /* Přiblížení dvěma prsty by změnilo měřítko gesta uprostřed tahu. */
  -ms-touch-action: none; user-select: none;
}
.ceremony__pad-hint {
  position: absolute; inset: 50% var(--space-4) auto; transform: translateY(-50%);
  margin: 0; text-align: center; font-size: 16px; color: var(--c-ink-faint);
  pointer-events: none;
}
.ceremony__pad-hint[hidden] { display: none; }

/* Dvě rovnocenné akce vedle sebe (tablet). Rovnocenné znamená stejně velké
   — menší „Odmítnout" by z odmítnutí udělalo výjimku, a ono je to platná
   odpověď. */
.ceremony__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.ceremony__reason { width: 100%; min-height: 96px; font-size: 17px; }

/* ---- Krok 5 · potvrzení ---------------------------------------------- */
/* Znak nese význam spolu se slovem pod ním, nikdy sám — barva by pro
   člověka s poruchou barvocitu informace nebyla (`design/README.md`). */
.ceremony__mark {
  margin: 0 auto; width: 96px; height: 96px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: 48px; line-height: 1;
}
.ceremony__mark--ok { background: var(--c-ok-soft); color: var(--c-ok-ink); border: 2px solid var(--c-ok-line); }
.ceremony__mark--danger { background: var(--c-danger-soft); color: var(--c-danger); border: 2px solid var(--c-danger-line); }
.ceremony__mark--soon { background: var(--c-soon-soft); color: var(--c-soon-ink); border: 2px solid var(--c-soon-line); }
.ceremony__mark--idle { background: var(--c-sunken); color: var(--c-ink-mute); border: 2px solid var(--c-border); }
.ceremony__reason-shown { margin: 0; font-size: 17px; text-wrap: pretty; }
/* Poslední věta obřadu. Musí být vidět bez hledání — je to jediný pokyn,
   který podepisující ještě dostane. */
.ceremony__handback {
  margin: var(--space-4) 0 0; padding: var(--space-4);
  border: 1px solid var(--c-border); border-radius: var(--radius-3);
  background: var(--c-surface); font-size: 18px; font-weight: 600;
}
/* „Hotovo" po konci obřadu (M7-P41 bod 5) — vede jen na neutrální obrazovku,
   nikam do systému. */
.ceremony__finish { margin-top: var(--space-2); justify-content: center; }

/* Telefon: tlačítka pod sebe. Dvě velká tlačítka vedle sebe by na úzkém
   displeji byla obě příliš malá (M7-ux-návrh § 4, wireframe „mobil"). */
@media (max-width: 600px) {
  .ceremony__actions { grid-template-columns: 1fr; }
  .ceremony__pad { height: 50dvh; min-height: 200px; }
  .ceremony__name { font-size: 28px; }
  .ceremony__headline { font-size: 25px; }
  .ceremony__langs { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; }
  .ceremony__lang { flex: none; }
}

/* Nabídka stran v přípravě obřadu (krok 1, systémová zóna).

   `.choice` je chip na jeden řádek s pevnou výškou. Strana, po které podpis
   chtít nelze, k sobě ale nese **větu s důvodem** (`CLAUDE.md`: zakázaná
   volba nese důvod v textu), a ta se do řádku nevejde — proto se tady
   z chipu stane položka seznamu a věta (nebo odznak, třeba cesta podpisu
   u šablony k tisku) se zalomí na vlastní řádek pod popisek. Vzhled podle
   obsahu řeší komponenta, ne druhá třída vedle první. */
.choice:has(.choice__why) { height: auto; flex-wrap: wrap; align-items: flex-start; padding: var(--space-2) 11px; }
.choice:has(.choice__why) .choice__label { flex: 1 1 0; min-width: 0; }
.choice__why { display: block; width: 100%; font-size: var(--fs-meta); color: var(--c-ink-mute); text-wrap: pretty; }
.choice--off { flex-wrap: wrap; }
/* Skupina voleb pod jedním popiskem — například „kdo podepisuje" v přípravě
   obřadu. `fieldset` je tu kvůli klávesnici a čtečce (legenda patří ke všem
   volbám, ne k té první), ale nese výchozí rámeček prohlížeče, který
   v designovém systému nic neznamená a čte se jako druhá karta uvnitř karty.
   Volby stojí pod sebou, protože nesou větu s důvodem. */
.choice-group { border: 0; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.choice-group .choice { width: 100%; }

/* Lišta neuložených změn (design/README, CRM #272): na konci formuláře,
   `sticky` u spodního okraje okna, dokud je co uložit. Šířkou drží obsahový
   sloupec, ne celé okno — nepřekryje navigaci. Stav nese tečka **i slovo**. */
.save-bar {
  position: sticky; bottom: var(--space-3); z-index: 5;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-top: var(--space-3); padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); box-shadow: var(--shadow-2);
}
.save-bar__state { display: flex; align-items: center; gap: var(--space-2); margin: 0; font-weight: 600; }
.save-bar__state::before {
  content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--c-soon-ink);
}
.save-bar .btn svg { width: 16px; height: 16px; }
/* Upozornění k uložení (`save-bar:note`, CRM #261) — vedle stavu, před
   tlačítkem; na úzké liště se zalomí pod stav. */
.save-bar { flex-wrap: wrap; }
.save-bar__note { flex: 1 1 16rem; margin: 0; font-size: var(--fs-meta); color: var(--c-soon-ink); }
@media (max-width: 720px) {
  /* Na telefonu přes celou šířku u spodní hrany — tlačítko v dosahu palce. */
  .save-bar { bottom: 0; margin-inline: calc(-1 * var(--space-4)); border-radius: 0; border-inline: 0; }
}

/* =====================================================================
   EDITOR ŠABLON DOKUMENTŮ (M7, #154)
   Dva pohledy na jedno pole `zdroj` (ADR-009 dodatek 1 § 3): vizuální
   (Tiptap, jen tisková šablona) a zdrojový (textarea + gutter, vždy).
   Zdroj je jediná pravda — plocha vizuálního editoru je jen jeho zobrazení,
   proto tu není nic, co by ukládalo druhý stav vedle `<textarea>`.
   ===================================================================== */
.tpl-editor { display: grid; gap: var(--space-3); }
/* Přepínač Vizuální editor / Zdroj je `.seg` z designového systému (tentýž
   ovladač jako přepínač pohledu na nástěnce) — zvýraznění otevřeného režimu
   nese `.seg__item[aria-pressed="true"]`. Stojí nad lepivou lištou, ne v ní
   (Tomáš 15. 9. 2026) — přepíná se jednou na začátku, ne při psaní. */
.tpl-editor__modes { width: fit-content; justify-self: start; }
/* Horní řádek editoru: přepínač zobrazení vlevo, Uložit vpravo (Tomáš
   15. 9. 2026). Tlačítko stálo dole pod plochou, kam se u třístránkové
   smlouvy muselo dorolovat. U datové šablony vlevo nic není a `space-between`
   nechá Uložit vpravo samotné. */
.tpl-editor__top {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-2); margin-bottom: var(--space-2); min-width: 0;
}
/* Náhled a Uložit text vpravo v horním řádku (CRM #269); Náhled je v DOM
   za Uložit kvůli Enteru ve formuláři, `order` ho staví vlevo. */
.tpl-editor__save { display: flex; align-items: center; gap: var(--space-2); }
.tpl-editor__save > .tpl-editor__preview-open { order: -1; }
/* Zhaslé Uložit si drží tvar: obecné `.btn:disabled` roztahuje tlačítko na
   text s důvodem (lišty akcí), tady žádný důvod k vypsání není — zhaslé
   tlačítko samo říká, že není co uložit. */
.tpl-editor__save .btn:disabled {
  white-space: nowrap; height: var(--control-h); padding-block: 0;
}
.tpl-editor__visual { display: grid; gap: var(--space-2); }

/* Obyčejná lišta pod hlavičkou sekce — NE sticky pod topbarem, ta drží
   navigaci sekcí detailu (E8), druhá lepící se lišta hned pod ní by byla
   druhá vrstva, na kterou si nikdo nevzpomene uhlídat při rolování. */
/* Lišta ve skupinách s popiskem nad každou (Písmo, Nadpisy, Zarovnání,
   Seznamy, Tabulka, Vložit, Historie) — rozhodnutí Tomáše 15. 9. 2026:
   jako ve Wordu, ale po našem. Popisek je součást lišty, ne bublina,
   takže ho přečte i dotyk a čtečka (`aria-labelledby` na skupině). */
/* Horní řádek: lišta vlevo, Vložit proměnnou úplně vpravo (`margin-left:
   auto`) v primárním tónu — je to vložení dat, ne formátování, a má se od
   nástrojů lišit na první pohled. */
.tpl-editor__bar {
  display: flex; flex-wrap: nowrap; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-2) 0; margin-bottom: var(--space-2);
  /* Formulář je mřížka a její položka se bez tohohle roztáhne na nejužší
     možnou šířku obsahu — na telefonu to byla celá lišta v jednom kuse
     (1020 px) a s ní se vodorovně posouvala celá stránka. S `0` se lišta
     smrskne na sloupec a přebytek si odroluje sama. */
  min-width: 0;
  border-bottom: 1px solid var(--c-border);
  /* Lišta drží při rolování pod horním pruhem aplikace (Tomáš 15. 9. 2026) —
     stránka je dlouhá a formátovat odstavec na třetí straně bez lišty by
     znamenalo rolovat nahoru a zpátky. Nad plochou, pod modálem.
     Přepínač Vizuální editor / Zdroj v ní schválně **není**: přepíná se
     jednou na začátku, ne při psaní, a v lepivé liště by jen ubíral výšku. */
  position: sticky; top: var(--topbar-h); z-index: 4; background: var(--c-surface);
}
/* Skupina Údaje a podpisy úplně vpravo (CRM #268); Náhled se přestěhoval
   nahoru k Uložit text (CRM #269), aby se lišta vešla na jeden řádek. Ve
   zdrojovém režimu je lišta jinak prázdná a skupina v ní zůstává sama. */
.tpl-editor__actions {
  display: flex; align-items: flex-end; gap: var(--space-2);
  flex: none; margin-left: auto;
}
.tpl-editor__actions .tpl-editor__group-buttons { gap: 6px; }
/* Zobáček vedle textového tlačítka: stejně úzký jako v liště; skrytý
   (zdrojový režim) vrací hlavní části kulaté rohy — `:has()`, ne druhá třída. */
.tpl-editor__actions .tpl-menu__toggle { width: 22px; min-width: 22px; padding: 0; }
.tpl-menu:not(:has(> .tpl-menu__toggle:not([hidden]))) > .btn:first-child { border-radius: var(--radius-2); }
/* Kontextová nabídka tabulky: `fixed` u ukazatele, položky pod sebou. */
.tpl-table-menu {
  position: fixed; z-index: 6; display: flex; flex-direction: column; gap: 2px; min-width: 180px;
  padding: 4px; border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); box-shadow: var(--shadow-2);
}
.tpl-table-menu .btn { justify-content: flex-start; }

/* Popup nad blokem proměnné: `fixed`, pozici dává JS podle bloku. */
.tpl-var-menu {
  position: fixed; z-index: 5; display: flex; gap: 4px;
  padding: 4px; border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); box-shadow: var(--shadow-2);
}
.tpl-editor__page .ProseMirror .tpl-var { cursor: pointer; }
/* Tabulky na ploše (Tomáš 15. 9. 2026): buňka bez rámečku dostane čárkovanou
   pomocnou čáru, ať je vidět, že jde o tabulku a kde má buňky — ve smlouvě je
   tabulka nejčastěji rozvržení (strany vedle sebe, podpisová doložka) a
   v tiskovém stylu rámeček nemá. Třídu dává `markTables()` podle **spočítaného**
   rámečku, takže buňka, která rámeček má, druhou čáru nedostane. `outline`,
   ne `border`: nezabírá místo, takže se plocha nerozejde s tiskem.
   Do zdroje ani do PDF se nic z toho nedostane — je to jen vzhled plochy.
   Platí na obou plochách, stránce šablony i pásu záhlaví/zápatí
   (`.tpl-band-page`) — pás tabulku používá na rozvržení (text vlevo, číslo
   stránky vpravo) a bez čar nebylo vidět, kde buňky jsou. */
:is(.tpl-editor__page, .tpl-band-page) .ProseMirror .tpl-cell--bare { outline: 1px dashed var(--c-border); outline-offset: -1px; }
/* Tabulka, ve které stojí kurzor — druhá polovina odpovědi na „stojím
   v tabulce?"; ta první je rozsvícená skupina Tabulka v liště. Třída padne na
   obal tabulky (`.tableWrapper` od Tiptapu), ne na `table` — proto bez značky
   prvku v selektoru. */
/* Jen dokud se v editoru píše: po odchodu z plochy zůstával kurzor
   v tabulce a slabý rámeček visel u tabulky bez důvodu. Na ploše pásu
   se nekreslí vůbec — tabulka tam bývá celý obsah pásu a rámeček by
   jen zdvojil zvýraznění listu. */
.tpl-editor__page .ProseMirror:focus .tpl-table--active { outline: 1px solid var(--c-brand-line); outline-offset: 2px; }
/* Vybrané záhlaví/zápatí kreslené do okrajů plochy (ADR-029 § 11 bod 2,
   CONTRACT-UX.md § B) — jen pro čtení, ale je to plnohodnotný ovládací
   prvek: hover pozadí + tooltip s názvem, levý klik otevře výběr, pravý
   kontextovou nabídku (`.tpl-band-menu` níž). Barva je token, ne obrys —
   `outline` tu dřív jen naznačoval odkaz, teď je to hover stav jako
   u ostatních klikatelných řádků (`.table__row--actionable:hover`). */
.tpl-band-surface {
  display: block; width: 100%; box-sizing: border-box; cursor: pointer;
  border-radius: var(--radius-1); transition: background-color .1s ease;
}
.tpl-band-surface:hover,
.tpl-band-surface:focus-visible { background: var(--c-sunken); }
.tpl-band-surface:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }
/* Prázdný okraj (žádná položka vybraná): tenký pruh u těla, ne celý
   okraj — `position: absolute` ať nepřidá plochu výšku navíc, kterou
   PDF nemá (bez pásu se do PDF žádná rezerva nesází). U záhlaví sedí na
   spodní hraně (u těla), u zápatí na horní — obojí `.rm-page-header`/
   `.rm-page-footer` jsou `position: relative`, `width: 100%` (vendor). */
.tpl-band-surface--empty { position: absolute; left: 0; right: 0; min-height: 6mm; }
.rm-page-header .tpl-band-surface--empty { bottom: 0; }
.rm-page-footer .tpl-band-surface--empty { top: 0; }
/* Kontextová nabídka pásu — stejný vzhled jako `.tpl-table-menu`, vlastní
   třída (ne sdílená): jiný obsah, jiný spouštěč, náhoda podoby je
   nepodstatná (vzor `.tpl-var-menu`/`.tpl-table-menu` vedle sebe). */
.tpl-band-menu {
  position: fixed; z-index: 6; display: flex; flex-direction: column; gap: 2px; min-width: 200px;
  padding: 4px; border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); box-shadow: var(--shadow-2);
}
.tpl-band-menu .btn { justify-content: flex-start; }
/* Obrázek s úchytem změny velikosti: úchyt v pravém dolním rohu, vidět při
   najetí a u vybraného obrázku; šířka se ukládá jako atribut `width`. */
.tpl-editor__page .ProseMirror .tpl-img { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
.tpl-editor__page .ProseMirror .tpl-img img { max-width: 100%; height: auto; display: block; }
.tpl-editor__page .ProseMirror .tpl-img__handle {
  display: none; position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px;
  border: 2px solid var(--c-brand); border-radius: 2px; background: #fff; cursor: nwse-resize;
}
.tpl-editor__page .ProseMirror .tpl-img:hover .tpl-img__handle,
.tpl-editor__page .ProseMirror .tpl-img--selected .tpl-img__handle { display: block; }
.tpl-editor__page .ProseMirror .tpl-img--selected { outline: 2px solid var(--c-brand); outline-offset: 1px; }
.tpl-editor__bar .tpl-editor__toolbar { flex: 1 1 0; min-width: 0; }
.tpl-editor__toolbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2);
}
/* Mezera i oddělovač skupin po 8 px (CRM #269): lišta tiskové šablony se tak
   na běžném notebooku s otevřeným bočním menu vejde na jeden řádek. */
.tpl-editor__bar .tpl-editor__group { padding-right: var(--space-2); }
.tpl-editor__bar .tpl-menu--select .tpl-menu__toggle { min-width: 104px; }
@media (min-width: 721px) {
  /* Na desktopu ikonová tlačítka lišty po 28 px (dotyk na telefonu drží
     plnou výšku ovladače). Zobáčky dělených tlačítek mají vlastní šířku. */
  .tpl-editor__bar .btn--icon:not(.tpl-menu__toggle) { width: 28px; }
  .tpl-editor__bar .tpl-editor__size-field { width: 42px; }
}
/* Editor je celá obrazovka detailu, takže tělo detailu nemá pravý sloupec. */
.detail__body--wide { grid-template-columns: minmax(0, 1fr); }

/* Náhled: jedno okno, dva pohledy. Široké a vysoké, protože se v něm
   kontroluje stránka A4 — menší okno by nutilo rolovat kvůli každé straně. */
.dialog--preview { width: min(980px, calc(100vw - 2 * var(--space-4))); }
.dialog--preview .dialog__head { align-items: center; gap: var(--space-2); }
.tpl-preview__tabs { display: inline-flex; gap: 2px; margin-left: auto; }
.tpl-preview__tabs .btn[aria-pressed="true"] { background: var(--c-brand-soft); border-color: var(--c-brand-line); color: var(--c-brand-ink); }
.tpl-preview__pane { min-height: min(70vh, 720px); }
.dialog--preview .tpl-frame { height: min(70vh, 720px); }

/* Na telefonu okno zabírá celou obrazovku (CRM #275, M7-Q29): PDF
   potřebuje na 375 px maximum místa ke čtení, ne zúžený panel, který
   obecné `.dialog` vyjíždí zespodu s mezerou nahoře (vidět kus stránky
   za oknem). `display: flex` jen u otevřeného, ze stejného důvodu jako
   `.dialog--settings[open]` výš — jinak by přebilo výchozí `display: none`
   zavřeného `<dialog>` a okno by viselo pod stránkou i po zavření. Hlavička
   a patička drží svou výšku, roluje jen tělo mezi nimi — táž úvaha jako
   u `.dialog--settings .dialog__body`. */
@media (max-width: 720px) {
  .dialog--preview {
    width: 100vw; height: 100dvh; max-height: none; margin: 0;
    border-radius: 0; flex-direction: column;
  }
  .dialog--preview[open] { display: flex; }
  .dialog--preview .dialog__head,
  .dialog--preview .dialog__foot { flex: none; }
  .dialog--preview .dialog__body {
    flex: 1 1 auto; min-height: 0; overflow: auto;
    display: flex; flex-direction: column; gap: var(--space-3);
  }
  .dialog--preview .tpl-preview__pane { flex: 1 1 auto; min-height: 0; }
  .dialog--preview .tpl-frame { height: 100%; }
}

/* Pole s nabídkou, která se dá přepsat (`combobox_controller.js`).
   Nabídka se vysouvá **v toku**, ne nad obsahem: okno zakládání má
   `overflow-y: auto`, takže absolutně umístěný panel by se uřízl o jeho
   okraj (CLAUDE.md — panel uvnitř `overflow` kontejneru). Odsune tedy pole
   pod sebou a roluje si uvnitř sebe. */
.combo__list {
  margin-top: 4px; max-height: 240px; overflow-y: auto;
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); box-shadow: var(--shadow-1);
}
.combo__list .popover__item {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2);
  width: 100%; padding: 6px var(--space-2); text-align: left;
  border: 0; background: none; font: inherit; cursor: pointer; color: var(--c-ink);
}
.combo__list .popover__item:hover { background: var(--c-sunken); }
.combo__list .popover__item:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
/* „Založit nový" je jiná věc než výběr z nabídky — oddělená linkou, ne barvou. */
.combo__create { border-top: 1px solid var(--c-border-hair) !important; }

/* Okno zakládání: širší než nastavení, protože nese čtyři karty formátu
   vedle sebe. */
.dialog--new-template { width: min(640px, calc(100vw - 2 * var(--space-4))); }
.dialog--new-template .dialog__body { max-height: min(76vh, 760px); overflow-y: auto; }

/* Nastavení šablony: formulářové okno, užší než náhled. Jeden formulář
   (Tomáš 24. 9. 2026) — sekce (`section.form-stack`) drží stejné mezery
   jako pole uvnitř (`--space-4` z `.form-stack`), ne vlastní odsazení.

   **Jeden posuvník, ne dva** (Tomáš 24. 9. 2026, revize). Dřív měl vlastní
   `max-height`/`overflow-y: auto` jen `.dialog__body` — ale nativní
   `<dialog>` má ve výchozím stylu prohlížeče `overflow: auto` i vlastní
   `max-height` (`dialog:modal`) sám na sobě. Když se obsah (hlavička +
   omezené tělo + patička) i tak vejde těsně nad viditelnou výšku okna,
   posouvaly se **oba** — dialog jako celek i tělo uvnitř něj (review „two
   scrollbars side by side"). Řešení: dialog je `flex` sloupec s vlastním
   stropem výšky a `overflow: hidden` (posuvník na něm se tím nikdy
   neukáže), hlavička a patička drží svou výšku (`flex: none`), roluje
   jen tělo mezi nimi. */
.dialog--settings {
  width: min(640px, calc(100vw - 2 * var(--space-4)));
  max-height: min(88vh, 800px);
  flex-direction: column;
  overflow: hidden;
}
/* `display: flex` jen u otevřeného — na zavřeném `<dialog>` by přebil
   výchozí `display: none` prohlížeče a dialog by visel pod stránkou
   (Tomáš 25. 9. 2026). */
.dialog--settings[open] { display: flex; }
/* Hlavička/tělo/patička nejsou přímé děti `<dialog>` — sedí ve `<form>`
   (jeden formulář, jedno odeslání, viz komentář výš). `display: contents`
   formulář z vykreslování vyjme, aniž by přestal být tím, čemu se
   odesílá — `.dialog__head/__body/__foot` se tak chovají, jako by byly
   přímo v `.dialog--settings`, a jen tak se můžou zúžit podle jejího
   `max-height` (flex item, který zůstane obalený v běžném bloku, se
   nezmenší pod velikost svého obsahu, i kdyby měl `flex-shrink`). */
.dialog--settings > form { display: contents; }
.dialog--settings .dialog__head,
.dialog--settings .dialog__foot { flex: none; }
/* Věta o neuloženém textu (CRM #268) zabere řádek patičky vlevo od tlačítek. */
.dialog--settings .dialog__foot > .field__error { flex: 1 1 280px; margin: 0; align-self: center; }
.dialog--settings .dialog__body { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; }

/* Stejný rytmus mezer všude (Tomáš 24. 9. 2026): mezeru mezi nadpisem
   sekce, obsahem a další sekcí drží výhradně `gap` gridu `.form-stack`
   (`--space-4`). Odstavec (`<p>`, `.field__hint`, `.notice`) si ale nese i
   vlastní okraj prohlížeče/komponenty — v mřížce se nesčítá s okolím,
   **sčítá se s `gap`** (grid mezery mezery položek nekolabují), takže
   některé sekce měly o deset až dvacet px víc než jiné podle toho, kolik
   takových prvků zrovna obsahovaly. Nulujeme ho tady, ne v `.section-title`
   / `.field__hint` / `.notice` samotných — mimo tenhle dialog (mimo grid,
   nebo v gridu s jiným rytmem) svůj okraj pořád mít mají. */
.dialog--settings .dialog__body .section-title { margin-bottom: 0; }
.dialog--settings .dialog__body p { margin: 0; }
.dialog--settings .dialog__body .notice { margin: 0; }

/* Dvojitý nadpis sekce (review „double headings: a section title in
   capitals plus a field label with the same meaning below it") — rozsah
   platnosti i podepisující mají legendu se stejným významem, jako má
   nadpis sekce nad nimi (`.section-title`), ale legendu jinde v aplikaci
   (`_new_dialog.html.twig`, kde vlastní nadpis sekce není) potřebujeme
   vidět — nemění se sdílený partial, schovává se jen tady, kde už jednou
   nadepsáno je. Zůstává v přístupnostním stromu (`.u-visually-hidden`
   vzor), jen se nevykresluje podruhé. */
.dialog--settings .scope-field > legend,
.dialog--settings .parties > legend {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* `fieldset` uvnitř `.field` (rozsah, strany) nemá vlastní rámeček ani
   odsazení prohlížeče — vzhled dává `.field`/`.form-stack`, ne dvojitý
   vnořený rámeček uvnitř dialogu (kontrakt UX, Tomáš 24. 9. 2026). */
fieldset.field { border: 0; margin: 0; padding: 0; min-width: 0; }

/* Řádek záhlaví/zápatí v Nastavení šablony (ADR-029 § 6, § 11): jméno,
   malý náhled a tlačítko „Změnit…" na jednom řádku. `<select>` zůstává
   v DOM (`hidden`, ne `display: none`) — je to skutečné pole formuláře,
   JS ho jen schová (ADR-009 dodatek 1 § 4). */
.band-field__row { display: flex; align-items: center; gap: var(--space-2); }
.band-field__name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.band-field__preview {
  width: 72px; height: 40px; overflow: hidden; border: 1px solid var(--c-border); border-radius: var(--radius-1);
  background: var(--c-surface); flex: 0 0 auto; pointer-events: none;
}
.band-field__preview > * { transform: scale(.18); transform-origin: top left; width: 555%; }

/* Řádek „Vyžaduje: …" se přestěhoval mezi rychlé údaje v hlavičce detailu
   (Tomáš 15. 9. 2026) — vlastní pravidlo tam nepotřebuje, nese ho `.detail__facts`. */


/* Nabídka proměnných jako modální okno na středu se ztmaveným pozadím
   (nativní `<dialog>`, `.dialog::backdrop`); seznam roluje uvnitř okna. */
.dialog--picker { width: min(640px, calc(100vw - 2 * var(--space-4))); }
.dialog--picker .tpl-editor__picker-list { max-height: min(60vh, 560px); margin-top: 0; }
.dialog--picker .popover__group { padding: var(--space-2) 0; margin: 0; font-size: var(--fs-control); text-transform: none; letter-spacing: normal; color: var(--c-ink); }
.dialog--picker .popover__group > strong { display: block; padding: 0 var(--space-2) 4px; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .06em; color: var(--c-ink-mute); }
.dialog--picker .popover__item { width: 100%; text-align: left; border: 0; background: none; font: inherit; cursor: pointer; }
/* Patička výběru údajů: „Nové pole k vyplnění" vlevo s větou, co to je (CRM #268). */
.dialog--picker .dialog__foot { justify-content: flex-start; align-items: center; }
.dialog--picker .popover__item:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* Výběr záhlaví/zápatí s náhledem (CONTRACT-UX.md § B) — sdílený modal
   plochy editoru šablony i dialogu Nastavení. Karta místo řádku (`.popover__item`
   dostane rámeček a náhled vlevo), protože se rozhoduje podle vzhledu
   položky, ne jen podle jejího jména. */
.dialog--band-picker { width: min(720px, calc(100vw - 2 * var(--space-4))); }
.dialog--band-picker .popover__list { max-height: min(60vh, 560px); margin-top: 0; gap: var(--space-2); }
.dialog--band-picker .popover__item {
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-2); width: 100%;
  padding: var(--space-2); border: 1px solid var(--c-border); border-radius: var(--radius-2);
  background: none; font: inherit; text-align: left; cursor: pointer;
}
.dialog--band-picker .popover__item:hover { background: var(--c-sunken); color: inherit; }
.dialog--band-picker .popover__item:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
/* Aktuálně vybraná (i stažená, kterou šablona už používá) — barva, ne jen
   text, ale slovo `bands_retired` u stažené nese totéž i bez barvy. */
.dialog--band-picker .popover__item[aria-current="true"] { border-color: var(--c-brand); background: var(--c-brand-soft); }
/* Výška se nezadává tady — pevná výška s `overflow: hidden` uřezávala pás,
   jehož skutečná (zmenšená) výška do ní neseděla, logo v hlavičce
   nevyjímaje (review „the preview of a band cuts it off"). Dopočítá ji
   `band_picker_controller.js#sizePreviews()` inline, ze skutečné výšky
   pásu při skutečné šířce stránky, takže rámeček obsah skoro vždycky
   obepne přesně — `overflow: hidden` tu zůstává jen jako pojistka proti
   zaokrouhlení na sub-pixel, ne aby dělal práci za správný výpočet. */
.band-picker__preview {
  flex: none; width: 100%; overflow: hidden; position: relative;
  border: 1px solid var(--c-border-hair); border-radius: var(--radius-1); background: var(--c-surface);
}
/* `.band` samo sází na 100% svého obalu (`PageBandStyle::css()`) — obal tu
   dostane skutečnou šířku stránky (`band_picker_controller.js`, `width` a
   `transform: scale()` inline) a zmenší se na šířku rámečku náhledu, ať
   náhled ukáže rozvržení (a logo) celé, v poměru, bez ohledu na to, kolik
   místa má rámeček. */
.band-picker__preview .band {
  position: absolute; top: 0; left: 0; transform-origin: top left;
  pointer-events: none;
}
.band-picker__meta { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); min-width: 0; }
.band-picker__height { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.tpl-editor__group {
  display: flex; flex-direction: column; gap: 3px;
  padding-right: var(--space-3); border-right: 1px solid var(--c-border-hair);
}
.tpl-editor__group:last-child { padding-right: 0; border-right: 0; }
.tpl-editor__group-label {
  font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--c-ink-mute); padding-left: 2px;
}
.tpl-editor__group-buttons { display: flex; gap: 2px; }

@media (max-width: 720px) {
  /* Na telefonu se lišta **posouvá do strany**, nerozpadá se do řádků
     (Tomáš 15. 9. 2026): sedm skupin pod sebou zabralo celou obrazovku
     a na dokument nezbylo místo. Skupiny jedou v jednom pruhu a přebytek
     se odroluje prstem. Náhled a Vložit proměnnou zůstávají na vlastním
     řádku nad ním, kde je vidět pořád — do rolovacího pruhu nepatří,
     protože právě po nich se na telefonu sahá nejčastěji. */
  .tpl-editor__bar { flex-wrap: wrap; }
  .tpl-editor__actions { margin-top: 0; order: -1; width: 100%; flex-wrap: wrap; }
  .tpl-editor__bar .tpl-editor__toolbar { flex: 1 1 100%; }
  .tpl-editor__toolbar {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin;
    /* Setrvačné rolování na iOS a zastavení na hraně skupiny. */
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* Poslední skupina má mít kam dorolovat, jinak ji urve okraj stránky. */
    padding-bottom: 4px;
  }
  .tpl-editor__toolbar .tpl-editor__group { flex: none; scroll-snap-align: start; }
}
/* Velikost písma: −, pole, + drží pohromadě jako jeden ovladač (spojené
   rámečky, zaoblení jen na koncích) — tři samostatná tlačítka vedle sebe se
   čtou jako tři nesouvisející věci. Vzor `.input-group`, jen se dvěma
   tlačítky místo jednotky. */
.tpl-editor__size { display: inline-flex; align-items: stretch; margin-left: 4px; }
.tpl-editor__size > .btn,
.tpl-editor__size > .input {
  border-radius: 0;
  border-color: var(--c-border);
  margin: 0;
}
.tpl-editor__size > .btn:first-child { border-radius: var(--radius-2) 0 0 var(--radius-2); }
.tpl-editor__size > .btn:last-child { border-radius: 0 var(--radius-2) var(--radius-2) 0; }
/* Sousední rámečky se překrývají, ať mezi prvky není dvojitá linka. */
.tpl-editor__size > .input,
.tpl-editor__size > .btn:last-child { margin-left: -1px; }
.tpl-editor__size-field {
  width: 52px; height: var(--control-h); text-align: center; padding: 0 2px;
  font-variant-numeric: tabular-nums;
}
/* Aktivní prvek musí být nad sousedem, jinak ho jeho rámeček přerušuje. */
.tpl-editor__size > .btn:hover,
.tpl-editor__size > .btn:focus-visible,
.tpl-editor__size > .input:focus,
.tpl-editor__size > .input:focus-visible { position: relative; z-index: 1; }
/* Dělené tlačítko lišty (`tpl_menu_controller.js`): hlavní část udělá
   nejčastější věc, úzký zobáček vedle otevře zbytek. Obě části drží
   pohromadě jako jeden ovladač — stejný vzor jako `.tpl-editor__size`. */
.tpl-menu { display: inline-flex; align-items: stretch; }
.tpl-menu > .btn { border-radius: 0; margin: 0; }
.tpl-menu > .btn:first-child { border-radius: var(--radius-2) 0 0 var(--radius-2); }
.tpl-menu > .btn:last-of-type { border-radius: 0 var(--radius-2) var(--radius-2) 0; }
.tpl-menu > .btn:only-of-type { border-radius: var(--radius-2); }
.tpl-menu > .btn + .btn { margin-left: -1px; }
.tpl-menu > .btn:hover,
.tpl-menu > .btn:focus-visible { position: relative; z-index: 1; }
.tpl-editor__toolbar .tpl-menu__toggle { width: 18px; min-width: 18px; padding: 0; }
.tpl-menu__toggle[aria-expanded="true"] { background: var(--c-brand-soft); border-color: var(--c-brand-line); color: var(--c-brand-ink); }
.tpl-menu__chevron { width: 10px; height: 10px; }
/* Výběr hodnoty (písmo): jedno tlačítko s textem a zobáčkem uvnitř. */
.tpl-menu--select .tpl-menu__toggle { width: auto; min-width: 128px; padding: 0 6px 0 8px; gap: 6px; justify-content: space-between; }
.tpl-menu__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 160px; font-size: var(--fs-meta); }

/* Panel je nativní popover — kreslí se nad stránkou, takže ho neuřízne
   vodorovně rolovaná lišta na telefonu. Polohu (`left`/`top`) mu dopočítá
   kontroler pod zobáček; tady se ruší výchozí vystředění popoveru. */
.tpl-menu__panel {
  position: fixed; inset: auto; margin: 0;
  min-width: 200px; max-width: calc(100vw - 16px); max-height: min(60vh, 420px); overflow: auto;
  padding: 4px;
  background: var(--c-surface); color: var(--c-ink);
  border: 1px solid var(--c-border); border-radius: var(--radius-2);
  box-shadow: 0 8px 24px oklch(0 0 0 / 0.12);
}
.tpl-menu__item {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  min-height: 32px; padding: 4px var(--space-2);
  border: 0; border-radius: var(--radius-2); background: none;
  color: var(--c-ink); font: inherit; font-size: var(--fs-control); text-align: left; cursor: pointer; white-space: nowrap;
}
.tpl-menu__item:hover:not(:disabled) { background: var(--c-brand-soft); color: var(--c-brand-ink); }
.tpl-menu__item:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
.tpl-menu__item:disabled { color: var(--c-ink-mute); opacity: .55; cursor: not-allowed; }
/* Zvolená hodnota nese fajfku — slovo stojí v textu položky, fajfka jen ukazuje. */
.tpl-menu__item[role="menuitemradio"]::before { content: ''; flex: none; width: 1em; text-align: center; }
.tpl-menu__item[aria-checked="true"]::before { content: '✓'; color: var(--c-brand-ink); }
.tpl-menu__item[aria-checked="true"] { font-weight: 600; }
.tpl-menu__separator { margin: 4px 2px; border: 0; border-top: 1px solid var(--c-border-hair); }
.tpl-menu__item--danger { color: var(--c-danger); }
.tpl-menu__item--danger:hover:not(:disabled) { background: var(--c-danger-soft); color: var(--c-danger); }
/* Číslo stránky na ploše pásu otevírá klikem nabídku — ukazatel to napoví. */
.tpl-band-page .band-page-number { cursor: pointer; }
.tpl-menu__icon { flex: none; width: 1.8em; color: var(--c-ink-mute); font-variant-numeric: tabular-nums; }
/* Ukázka stylu číslování (1.1., (1), 1.a.) je delší než glyf tabulkové
   operace — v nabídce s volbou (zaškrtávací položky) dostane širší sloupec. */
.tpl-menu__item[role="menuitemradio"] .tpl-menu__icon { width: 2.6em; }
@media (pointer: coarse) {
  /* Na dotyku položka i zobáček potřebují prst, ne kurzor. */
  .tpl-menu__item { min-height: 44px; }
  .tpl-editor__toolbar .tpl-menu__toggle { width: 28px; min-width: 28px; }
}
/* Vypnuté Zpět/Znovu: obecné `.btn[disabled]` roztahuje tlačítko na text
   s důvodem (lišty akcí), ikonové tlačítko v liště editoru má zůstat
   čtvercové — jen zesvětlí. */
.tpl-editor__toolbar .btn--icon:disabled { height: var(--control-h); padding: 0; white-space: nowrap; opacity: .45; cursor: not-allowed; }
.tpl-editor__toolbar .btn--icon svg { width: 16px; height: 16px; }
.tpl-editor__toolbar .btn[aria-pressed="true"] {
  background: var(--c-brand-soft); border-color: var(--c-brand-line); color: var(--c-brand-ink);
}

/* Plocha A4 (bod 1): `.tpl-editor__desk` je šedý podklad pod stránkou,
   `.tpl-editor__page` je stránka sama — rozměry a okraje jí podle `@page`
   ze zdroje šablony nastavuje `print_template_controller.js#applyPageStyle`
   jako proměnné (`--tpl-page-w/h`, `--tpl-pad-*`). Vzhled uvnitř (nadpisy,
   tabulky, patička) dodává `<style data-print-template-style>`, který si
   tentýž kontroler prefixuje ze `<style>` v hlavičce šablony přes CSSOM —
   tady proto nestojí nic, co by vzhled dokumentu předjímalo; kdyby ano,
   šablona s jiným stylem by na ploše vypadala jinak, než jak se vytiskne. */
.tpl-editor__desk {
  background: var(--c-sunken);
  padding: var(--space-4);
  overflow-x: auto; /* stránka pod 720 px přeteče vodorovně, nezmenšuje se */
}
/* Stránkování dělá `tiptap-pagination-plus` (rešerše 20 § 9): šířku,
   okraje a rámeček nastavuje na `.ProseMirror` samo podle `@page` šablony
   (`print_template_controller.js#paginationFor`), stránky kreslí jako
   dekorace s mezerou mezi nimi. `.tpl-editor__page` proto plochu jen
   vystředí a dá jí stín papíru — žádné vlastní okraje, ty by se s těmi
   z knihovny sečetly. */
.tpl-editor__page { display: flex; justify-content: center; }
/* `border-box`: knihovna zapisuje `width` = šířka papíru a k tomu okraje
   jako `padding`; bez `border-box` by byl list o oba okraje širší než A4
   a tabulka se `width: 100%` širší než tisková strana. */
/* `geometricPrecision`: na obrazovce Chromium zaokrouhluje šířky znaků kvůli
   hintingu, při tisku počítá s desetinnými — a řádek se pak láme o slovo
   jinak (nález Tomáše 15. 9. 2026: „jeden" na konci druhého řádku). Tohle
   vypne hinting i na ploše, takže editor sází stejnými čísly jako tiskárna. */
.tpl-editor__page .ProseMirror {
  text-rendering: geometricPrecision;
  box-sizing: border-box;
  background: #fff;
  box-shadow: var(--shadow-1);
  min-height: 360px;
}
.tpl-editor__page-count {
  display: inline-block; margin-top: var(--space-2);
  font-size: var(--fs-micro); color: var(--c-ink-mute); font-variant-numeric: tabular-nums;
}
/* Knihovna stránkování si tabulky přepíná na `display: contents`, aby jim
   mohla lámat řádky přes stránky — u běžných tabulek Tiptapu to ale
   rozbije šířky sloupců a rámečky ze stylu šablony. Tabulka se proto drží
   jako blok a přes stránku se neláme (stejný ústupek udělala dvojka). */
/* Knihovna stránkování si píše rámeček přímo do `style` prvku; s `border-box`
   by ukrojil 2 px ze šířky sazby a plocha by lámala řádky jinak než tisk.
   Okraj listu kreslí stín, rámeček k ničemu není — proto `!important`, jinak
   inline styl knihovny přebít nejde. */
.tpl-editor__page .ProseMirror.rm-with-pagination { border: 0 !important; }
.tpl-editor__page .ProseMirror.rm-with-pagination table { display: table; }
.tpl-editor__page .ProseMirror.rm-with-pagination table tbody { display: table-row-group; max-height: none; overflow: visible; }
.tpl-editor__page .ProseMirror.rm-with-pagination table tr td,
.tpl-editor__page .ProseMirror.rm-with-pagination table tr th { word-break: normal; }
/* Záhlaví/zápatí knihovny na ploše šablony (ADR-029 § 9). Knihovna sází
   pás jako `inline-flex` na řádek textu, takže pod ním zůstala výška dotahu
   řádku (~1,6 mm, o které plocha sázela níž než PDF). A sloupec pásu je
   plovoucí na šířku obsahu — text zarovnaný vpravo nedosáhl na pravý okraj
   sazby. Pás si boční odsazení nese sám (okraj šablony), proto obal knihovny
   jde přes celou šířku sazby a pás bez vlastního bočního odsazení. CRM #240,
   měřeno v prohlížeči proti PDF z Gotenbergu. */
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-header,
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-footer { vertical-align: top; }
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-header-left:has(.band),
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-footer-left:has(.band) { float: none; display: block; }
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-header-left:has(.band),
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-page-footer-left:has(.band) { margin-right: var(--rm-margin-right); }
.tpl-editor__page .ProseMirror.rm-with-pagination .rm-first-page-header .rm-page-header-left:has(.band) { margin-right: 0; }
.tpl-editor__page .ProseMirror.rm-with-pagination .band { padding-left: 0 !important; padding-right: 0 !important; }

/* Fokusový prsten **na ploše samotné** obkroužil všechny stránky najednou
   i šedou mezeru mezi nimi a četl se jako rámeček dokumentu, ne jako fokus
   (nález Tomáše 15. 9. 2026). Plocha je jeden prvek přes celý dokument, tvar
   stránek do ní kreslí až stránkování — prsten se proto přesouvá na pracovní
   plochu kolem papíru, kde nic nepředstírá. Že se v editoru píše, ukazuje
   kurzor; `:focus-visible` tím nemizí, jen se přesouvá o úroveň výš. */
.tpl-editor__page .ProseMirror:focus,
.tpl-editor__page .ProseMirror:focus-visible { outline: none; }
.tpl-editor__desk:has(.ProseMirror:focus-visible) { outline: var(--focus-ring); outline-offset: calc(-1 * var(--space-2)); }

/* Zlom stránky (bod 3): čárkovaná linka, popisek vpravo nahoře. `data-label`
   vkládá JS z překladu (`documents.templates.toolbar.page_break`) — do
   zdroje šablony se nezapisuje, je to jen popisek na ploše. */
.tpl-editor__page .ProseMirror div[data-page-break] {
  border-top: 1px dashed var(--c-border);
  height: 0; /* skutečnou výšku (zbytek stránky) zapisuje JS inline — measurePageBreaks */
  position: relative;
  box-sizing: border-box;
  background: repeating-linear-gradient(-45deg, transparent 0 10px, var(--c-sunken) 10px 11px);
}
.tpl-editor__page .ProseMirror div[data-page-break]::after {
  content: attr(data-label);
  position: absolute;
  right: 0;
  top: -0.7em;
  font-size: var(--fs-micro);
  color: var(--c-ink-mute);
  background: #fff;
  padding: 0 4px;
}

/* Podpisové bloky (M7-P32): na ploše náhled řádků ve stejném rozložení
   a rozměrech jako `.sign` v tiskové stránce (PrintPageShell) — blok zabírá
   tolik místa jako v PDF. Zelený podklad a popisek vpravo nahoře říkají,
   že je to vložený prvek; řádky dosadí server podle stran šablony. */
.tpl-editor__page .ProseMirror div[data-signature-blocks] {
  position: relative; margin: calc(26pt + var(--sign-push, 0px)) 0 0; padding: 6pt 8pt 4pt;
  border: 1px dashed var(--c-brand-line); border-radius: var(--radius-2);
  background: var(--c-brand-soft); cursor: default;
}
.tpl-editor__page .ProseMirror div[data-signature-blocks]::after {
  content: attr(data-label); position: absolute; right: 6px; top: -0.75em;
  padding: 0 4px; background: var(--c-brand-soft); color: var(--c-brand-ink); font-size: var(--fs-micro);
}
.tpl-editor__page .ProseMirror div[data-signature-blocks] table.sign { width: 100%; margin: 0; border-collapse: collapse; }
.tpl-editor__page .ProseMirror div[data-signature-blocks] td { width: 45%; border: none; padding: 0; font-size: 9pt; vertical-align: top; }
.tpl-editor__page .ProseMirror div[data-signature-blocks] td.gap { width: 10%; }
.tpl-editor__page .ProseMirror div[data-signature-blocks] td.place { padding-bottom: 44pt; }
.tpl-editor__page .ProseMirror div[data-signature-blocks] td.name { border-top: 1px solid currentColor; padding-top: 3pt; }
.tpl-editor__page .ProseMirror div[data-signature-blocks] .fill { display: inline-block; min-width: 70pt; border-bottom: 1px dotted currentColor; }
.tpl-editor__page .ProseMirror div[data-signature-blocks].ProseMirror-selectednode { outline: 2px solid var(--c-brand); }
/* Šablona bez podepisujících (CRM #271): blok se v PDF nevykreslí — výstražný
   tón místo zeleného a věta, co s tím. */
.tpl-editor__page .ProseMirror div[data-signature-blocks][data-empty] {
  cursor: pointer; border-color: var(--c-soon-line); background: var(--c-soon-soft);
}
.tpl-editor__page .ProseMirror div[data-signature-blocks][data-empty]::after { background: var(--c-soon-soft); }
.tpl-editor__page .ProseMirror div[data-signature-blocks] .sign-empty { margin: 0; text-align: left; font-size: var(--fs-meta); color: var(--c-ink); }

/* Proměnná je nesmazatelný blok (M7-ux-návrh § 7) — jiný podklad a rámeček,
   ne jen barva textu, aby šla poznat i bez čtení věty kolem. */
.tpl-var {
  display: inline-block; background: var(--c-brand-soft); border: 1px solid var(--c-brand-line);
  border-radius: var(--radius-1); padding: 0 4px; font-weight: 600; white-space: nowrap;
}
/* Pole k vyplnění (M7-P33): hodnotu nedosadí systém, vyplní ji člověk při
   generování. Jiný podklad **a** čárkovaný rámeček než `.tpl-var` — rozdíl
   nesmí nést jen barva. Hvězdička u povinného je i v `title` štítku. */
.tpl-input {
  display: inline-block; background: var(--c-pending-soft); border: 1px dashed var(--c-pending-line);
  color: var(--c-pending-ink); border-radius: var(--radius-1); padding: 0 4px; font-weight: 600; white-space: nowrap;
}
.tpl-input__required { margin-left: 2px; }
/* Nepřiřazené místo (specifikace 27 § 3, CRM #261): zástupná značka
   z vloženého textu, pro kterou se nenašla proměnná. Tvar štítku proměnné,
   tón upozornění **a** tečkovaný rámeček — neznámou značku nesmí odlišit
   jen barva. Klik nabídne výběr proměnné jako u `.tpl-var`. */
.tpl-var--unassigned {
  background: var(--c-soon-soft); border: 1px dotted var(--c-soon-line); color: var(--c-soon-ink); font-weight: 500;
}
.tpl-editor__page .ProseMirror .tpl-input { cursor: pointer; }
.tpl-editor__page .ProseMirror-selectednode { outline: 2px solid var(--c-brand); outline-offset: 1px; border-radius: var(--radius-1); }

/* ---- Zdrojový editor (gutter + textarea) ------------------------------ */
.source-editor {
  display: grid; grid-template-columns: auto 1fr;
  border: 1px solid var(--c-border); border-radius: var(--radius-3); overflow: hidden;
}
.source-editor__gutter {
  margin: 0; padding: 7px 9px; font-family: var(--font-mono); font-size: var(--fs-control);
  text-align: right; color: var(--c-ink-mute); background: var(--c-sunken);
  overflow: hidden; user-select: none; white-space: pre;
}
.source-editor__field {
  font-family: var(--font-mono); font-size: var(--fs-control);
  min-height: 360px; border: 0; border-radius: 0; resize: vertical;
  white-space: pre; overflow-wrap: normal; overflow-x: auto;
}
/* Nese barvu i tučné písmo, ale řádek vedle sebe má vždy i číslo a chybu
   ve `.field__error` pod polem — barva sama tu jen doprovází, neurčuje. */
.source-editor__line--error { color: var(--c-rejected-line); font-weight: 600; }


/* Náhled na zkušebních datech (`document_template_preview`) — sandboxovaný
   iframe s vygenerovaným HTML, ne turbo-frame obsah přímo. */
.tpl-frame { display: block; width: 100%; min-height: 640px; border: 1px solid var(--c-border); background: var(--c-surface); }

@media (max-width: 720px) {
  /* Zalamování lišty tu bývalo, ale nahradilo ho rolování do strany —
     pravidlo pro ně je u `.tpl-editor__toolbar` výš. Zůstává jen výška
     tlačítka, aby se na dotyk dalo trefit. */
  .tpl-editor__toolbar .btn { min-height: var(--control-h); }
}

/* =====================================================================
   EDITOR ZÁHLAVÍ A ZÁPATÍ (ADR-029, kontrakt #238)
   List A4 s pásem nahoře (záhlaví) nebo dole (zápatí, sloupec obrácený);
   tělo šablony je jen naznačené šedými pruhy — needituje se tady, jen
   ukazuje, kde na skutečné stránce pás sedí. Vzhled obsahu pásu dodává
   `<style data-page-band-style>` z `PageBandStyle::css()` (ADR-029 § 5,
   `.band`/`.band--header`/`.band--footer`) — sem patří jen tokeny a
   rozvržení plochy, žádná barva ani písmo natvrdo. Lišta a stavy tlačítek
   (`aria-pressed`, `disabled`) znovupoužívají pravidla `.tpl-editor__*`
   výš, plocha má vlastní třídy, protože není stránkovaná knihovnou. */
.tpl-band-desk { background: var(--c-sunken); padding: var(--space-4); overflow-x: auto; }
.tpl-band-page {
  display: flex; flex-direction: column;
  width: var(--tpl-band-page-w, 210mm); margin: 0 auto;
  background: #fff; box-shadow: var(--shadow-1); box-sizing: border-box;
}
/* Zápatí sedí na spodku listu: pás (`.band`) jde v DOM až za tělem
   (`_editor.html.twig`), takže obyčejné `column` už samo dá tělo nahoru
   a pás dolů — čtecí pořadí (a fokus klávesnicí) tak odpovídá tomu, co je
   na listu první, BEZ obrácení směru. `column-reverse` by tu udělalo
   přesně opak (pás by vyšel nahoru, tělo dolů) — vadu prototypu zachytilo
   ověření v prohlížeči (CRM #238). */
/* Tělo je jen naznačené (ADR-029 § 11): šedé pruhy bez textu, `aria-hidden`
   — needituje se a čtečce nic neříká. */
.tpl-band-page__body { display: grid; gap: var(--space-2); padding: var(--space-6) var(--space-4); flex: 1 1 auto; }
.tpl-band-page__body-bar { height: 8px; border-radius: var(--radius-1); background: var(--c-sunken); }
.tpl-band-page__body-label { font-size: var(--fs-micro); color: var(--c-ink-mute); text-align: center; }
/* `.band` nese styl z `PageBandStyle::css()`; okraj tu jen naznačuje, kde
   pás na listu končí (ADR-029 § 5 bod 4 — skutečný odstup od okraje listu
   a od těla drží obal fragmentu pro Gotenberg, #240, ne tahle plocha). */
.tpl-band-page .band { outline: 1px dashed var(--c-border); outline-offset: -1px; }
.tpl-band-page__surface { min-height: 1.35em; outline: none; }
/* Vlastní blok formátování (BFC) na uzlu, který `page_band_controller.js#measureHeight`
   měří (`editor.view.dom`, tj. `.ProseMirror`): bez něj by se horní okraj
   prvního a spodní okraj posledního potomka (`ul`/`ol` výchozích 1em, `hr`)
   zhroutil ven z měřeného boxu do paddingu `.band`, a naměřená výška by byla
   nižší než skutečná vysázená (nesedělo by to s Gotenbergem, ADR-029 § 5). */
.tpl-band-page__surface .ProseMirror { display: flow-root; }
/* Fokus drží editor **uvnitř** plochy (`.ProseMirror`), ne plocha sama —
   pravidlo jen na `__surface` minulo a obecný prstenec fokusu obtáhl text
   těsně kolem tabulky (Tomáš 25. 9. 2026). Zvýrazní se celý list, jako
   `.tpl-editor__desk` u šablony. */
.tpl-band-page__surface:focus,
.tpl-band-page__surface:focus-visible,
.tpl-band-page__surface .ProseMirror:focus,
.tpl-band-page__surface .ProseMirror:focus-visible { outline: none; }
.tpl-band-page:has(.tpl-band-page__surface:focus-visible, .tpl-band-page__surface .ProseMirror:focus) { outline: var(--focus-ring); outline-offset: 2px; }
/* Číslo stránky (ADR-029 § 4): stejný nesmazatelný blok jako `.tpl-var`,
   jiná barva, ať se od proměnné (jiný editor) i pohledem nepletou.
   Zvýraznění nesmí zvětšit řádkový box (CRM #238 ověření v prohlížeči):
   žádný `border` (přidává výšku), žádné svislé `padding` a žádné
   `display: inline-block` (ten by měl vlastní výšku obsahu místo toho, aby
   se choval jako běžný text uvnitř řádku) — jinak by jeden řádek 9pt vyšel
   v editoru vyšší, než kolik ho vysází Gotenberg. Rámeček nahrazuje
   `outline`, ten do rozvržení nepočítá. */
.band-page-number {
  background: var(--c-brand-soft); outline: 1px solid var(--c-brand-line); outline-offset: -1px;
  border-radius: var(--radius-1); padding: 0 4px; font-weight: 600; white-space: nowrap;
}
/* Výška podle obsahu (ADR-029 § 5, § 11) — stejný tón jako počet stran
   tiskové šablony (`.tpl-editor__page-count`). */
.tpl-band-height {
  display: inline-block; margin-top: var(--space-2);
  font-size: var(--fs-micro); color: var(--c-ink-mute); font-variant-numeric: tabular-nums;
}

/* Výběr ve filtru, jehož nevybraná volba nese název filtru („Typ dokumentu",
   „Stav podpisu") místo „Všechny…" (Úložiště, Tomáš 24. 9. 2026). Dokud je
   nevybraný, čte se jako nápověda, ne jako zvolená hodnota — a zapnutý filtr
   je tím vidět na první pohled. Řídí se obsahem (`option[data-placeholder]`
   a `:has()`), ne další třídou, takže platí jen tam, kde si to volba sama
   řekne (CLAUDE.md, Lukáš 31. 8. 2026). */
.select:has(option[data-placeholder]:checked) { color: var(--c-ink-mute); }
.select option { color: var(--c-ink); }

/* Detail dokumentu — issue #10: na mobilu má náhled zůstat nad hlavním
   obsahem, ale otisk souboru a „Naposledy" mají jít až pod něj. Základní
   `.detail__body`/`.detail__aside` (karta osoby, uchazeč, …) umí přesunout
   jen celý postranní sloupec najednou (`order: -1`), ne jeho část — proto
   vlastní modifikátor jen pro tuhle obrazovku, s postranním sloupcem
   rozděleným na dva bloky (`--preview`, `--extra`) a rozmístěným přes
   `grid-template-areas`. Stejný vzor jako existující `.detail__body--wide`
   výše v souboru: modifikátor navíc, ne úprava sdílené třídy, aby ostatní
   obrazovky se stejnými třídami zůstaly beze změny. */
.detail__body--document {
  grid-template-areas: "content preview" "content extra";
}
.detail__body--document .detail__content { grid-area: content; }
.detail__body--document .detail__aside--preview { grid-area: preview; }
.detail__body--document .detail__aside--extra { grid-area: extra; }

@media (max-width: 1024px) {
  /* Pořadí na mobilu: náhled nahoře, pak hlavní obsah, pak otisk souboru
     a „naposledy" — ne celý postranní sloupec před obsahem jako u ostatních
     detailů se sdílenou `.detail__body`. */
  .detail__body--document {
    grid-template-areas: "preview" "content" "extra";
  }
}

/* Šablony — detail: řádek „Vyžaduje“ (#tpl-requires) čte entity jako
   informaci, ne jako nerozhodnutý/vyřazený stav. `.tag--neutral` sama
   zůstává beze změny (dál ji čtou verze a typ šablony o řádek výš i jiné
   obrazovky mimo tenhle rozsah) — dobarvuje se jen tady. */
#tpl-requires .tag--neutral {
  --tag: var(--c-border);
  color: var(--c-ink);
  background: var(--c-surface);
}

/* Nahrání souboru: vlastní plocha místo nativního „Choose File“, který se
   nedá přeložit. Skutečné pole leží neviditelné přes celou plochu, takže
   klik, klávesnice i přetažení fungují bez JavaScriptu; ovladač
   `dropzone` jen dopíše jméno souboru a zvýrazní plochu při přetahování. */
.dropzone { position: relative; }
.dropzone__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 1; }
.dropzone__zone {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: var(--control-h); padding: 6px 10px;
  border: 1px dashed var(--c-border); border-radius: var(--radius-2);
  background: var(--c-surface); color: var(--c-ink-mute); font-size: var(--fs-control);
}
.dropzone__icon { flex: none; }
.dropzone__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dropzone:has(.dropzone__input:focus-visible) .dropzone__zone { outline: 2px solid var(--c-brand); outline-offset: 1px; }
.dropzone:hover .dropzone__zone, .dropzone--over .dropzone__zone { border-color: var(--c-brand); background: var(--c-brand-soft); }
.dropzone:has(.dropzone__input:valid) .dropzone__zone { border-style: solid; color: var(--c-ink); }
.dropzone:has(.dropzone__input[aria-invalid="true"]) .dropzone__zone { border-color: var(--c-expired-ink); }

/* Společný důvod zakázaných akcí u nového dokumentu. Klíče jsou psané jako
   dovětek k tlačítku („nejprve vyberte šablonu"), tady stojí samostatně —
   velké první písmeno bez druhé sady překladů. */
#document-actions-reason::first-letter { text-transform: uppercase; }

/* Zaškrtávací seznam na ploše editoru i u starších šablon (nález Tomáše
   25. 9. 2026). Plocha kreslí styly opsané ve zdroji šablony a starší kopie
   nesou čtvereček přes `::before`, který se zalomí nad text. Tahle pravidla
   ho vypnou a použijí nativní značku seznamu — tatáž oprava jako
   `PrintPageShell::CURRENT_FIXES` pro PDF a náhledy; vyšší specificita
   (`.tpl-editor`) přebije opsaná pravidla plochy. */
.tpl-editor .tpl-editor__page .ProseMirror ul[data-bullet="box"] { list-style: none; }
.tpl-editor .tpl-editor__page .ProseMirror ul[data-bullet="box"] > li { list-style-type: '☐  '; }
.tpl-editor .tpl-editor__page .ProseMirror ul[data-bullet="box"] > li[data-checked="true"] { list-style-type: '☑  '; }
.tpl-editor .tpl-editor__page .ProseMirror ul[data-bullet="box"] > li::before { content: none; display: none; }

/* Styl číslování číslovaného seznamu na ploše editoru (Tomáš 30. 9. 2026) —
   tatáž pravidla jako `PrintPageShell::LIST_NUMBERING` pro PDF a náhled,
   jen s předponou plochy; shodu hlídá `ListNumberingCssTest`. */
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering] { padding-left: 20pt; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering] > li::marker, .tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering] ol > li::marker { content: var(--jobson-numbering); }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="outline"] { --jobson-numbering: counters(list-item, ".") ". "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="outline"] ol:not([data-numbering]) { padding-left: 26pt; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-alpha"] { --jobson-numbering: counter(list-item) ". "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-alpha"] > li { counter-increment: jobson-numbering-top; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-alpha"] ol:not([data-numbering]) { --jobson-numbering: counter(jobson-numbering-top) "." counter(list-item, lower-alpha) ". "; padding-left: 26pt; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-alpha"] ol:not([data-numbering]) ol:not([data-numbering]) { --jobson-numbering: counter(list-item, lower-roman) ". "; padding-left: 20pt; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-paren"] { --jobson-numbering: counter(list-item) ") "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="decimal-parens"] { --jobson-numbering: "(" counter(list-item) ") "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="lower-alpha-paren"] { --jobson-numbering: counter(list-item, lower-alpha) ") "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="lower-alpha"] { --jobson-numbering: counter(list-item, lower-alpha) ". "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="upper-alpha"] { --jobson-numbering: counter(list-item, upper-alpha) ". "; }
.tpl-editor .tpl-editor__page .ProseMirror ol[data-numbering="upper-roman"] { --jobson-numbering: counter(list-item, upper-roman) ". "; }

/* Dialog „Doplnit údaje" (M7-P33). Věta o tom, co chybí, stojí v hlavičce
   dialogu barvou chyby — slovo nese text, barva jen zvýrazní. Souhrn nad
   náhledem: nadpis vlevo, „Upravit údaje" vpravo, na mobilu pod sebou. */
.dialog__text--error { color: var(--c-expired-ink); font-weight: 500; }
.inputs-summary { margin-bottom: var(--space-4); }
.inputs-summary__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.inputs-summary__head .section-title { margin: 0; }
.inputs-summary .facts { margin-bottom: 0; }
/* Zadané údaje v detailu dokumentu: dlouhý text (zvláštní ujednání) drží
   zalomení a nevyjede z tabulky — buňky tabulky jinak nezalamují. */
.table td.facts__value--lines { white-space: pre-line; min-width: 16ch; }

/* ---------------------------------------------------------------------------
   Tiskové sady a hromadné generování (M7-P12, M7-P35; CRM #14)

   Editor sady: šablony jako tabulka (pořadí, dokument, kdo podepisuje, Výš /
   Níž / Odebrat) a pod ní jedna nabídka „Přidat šablonu" — nabídka nepřesáhne
   šířku, ve které se název šablony ještě čte. Seznam šablon sady (s tím, kdo
   podepisuje) je číslovaný, protože pořadí je obsah.
   --------------------------------------------------------------------------- */
.print-set-name { max-width: 60ch; }
.print-set-table { margin-bottom: 0; }
.print-set-table td[data-part="number"] { width: 4ch; }
.print-set-empty { margin: var(--space-2) 0; color: var(--c-ink-mute); }
.print-set-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2); margin: var(--space-3) 0; }
.print-set-add[hidden] { display: none; }
.print-set-add .field { margin: 0; flex: 0 1 44ch; min-width: 0; }
/* Na telefonu se šablony sady (editor i generování) nerozpadají na
   rolovanou tabulku jako datagrid: podpis i akce řádku by se schovaly za
   okraj a sada má jen pár řádků. Řádek je pořadí, pod názvem kdo podepisuje
   a jak, vpravo tlačítka. */
@media (max-width: 720px) {
  .print-set-table thead { display: none; }
  .print-set-table, .print-set-table tbody { display: block; }
  .table.print-set-table tr {
    display: grid; grid-template-columns: 3ch minmax(0, 1fr) auto; column-gap: var(--space-2); row-gap: 4px;
    align-items: center; padding: var(--space-2) 0; border-bottom: 1px solid var(--c-border-hair);
  }
  .table.print-set-table td { display: block; height: auto; padding: 0; border: 0; position: static; box-shadow: none; background: none; white-space: normal; overflow: visible; }
  .table.print-set-table td:first-child { grid-row: 1 / span 3; box-shadow: none; }
  .table.print-set-table td .field__hint { margin: 2px 0 0; }
  .table.print-set-table td:not(:first-child, .table__actions) { grid-column: 2; }
  .table.print-set-table td.table__actions { grid-column: 3; grid-row: 1 / span 3; }
  /* Hlavička se skryla, tak popisek stojí u hodnoty — „jen agentura" bez
     něj nic neříká. Pořadí a název popisek nepotřebují. */
  .table.print-set-table td[data-part="signers"]::before { content: attr(data-label) ": "; color: var(--c-ink-mute); font-size: var(--fs-micro); }
}
.print-set-items { margin: 0; padding-left: 1.4em; display: grid; gap: 6px; }
.print-set-items li { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px; }
.print-set-items__signers { flex-basis: 100%; font-size: var(--fs-micro); }
.print-batch__counts { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0; }
.print-batch__progress { margin-bottom: var(--space-3); }
.print-batch__doc { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 6px; }
.print-batch__details { margin: 4px 0; padding-left: 1.2em; }
.print-batch__fix { display: flex; flex-wrap: wrap; gap: 4px var(--space-3); margin: 0; }
/* Šablony vynechané u všech — jedna zpráva nad výsledkem i pod seznamem
   dokumentů v nastavení (M7-P35). */
.notice.print-batch__excluded { align-items: flex-start; }
.print-batch__excluded p { margin: 0; }
.print-batch__excluded ul { margin: 4px 0; padding-left: 1.2em; }
.print-batch__retry { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: var(--space-3) 0; }
.print-batch__retry .field__hint { margin: 0; flex: 1 1 280px; }
/* Volba vazby u osoby čekající v dávce (M7-P38, CRM #276) — vlastní řádek,
   ne vedle sebe s popiskem sloupce, jinak se na telefonu zúží pod použitelnost. */
.print-batch__choice { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: 6px; }
.print-batch__choice .select { min-width: 220px; flex: 1 1 220px; }

/* Nastavení dávky (M7-ux-návrh § 3, UX revize 30. 9. 2026): jedna karta,
   řádky „popisek vlevo | obsah vpravo" v pořadí rozhodování. `.form-section`
   staví nadpis nad obsah — pro pět krátkých voleb pod sebou by to byl svitek
   nadpisů. Pod 720 px stojí popisek nad obsahem. */
.card.gen-form { padding: 0; gap: 0; }
.gen-form__row {
  display: grid; grid-template-columns: minmax(120px, 180px) minmax(0, 1fr); gap: var(--space-4);
  padding: var(--space-4); border-top: 1px solid var(--c-border-hair);
}
.gen-form__row:first-of-type { border-top: 0; }
.gen-form__label { margin: 0; padding-top: 7px; font-size: var(--fs-control); font-weight: 600; }
.gen-form__label small { display: block; margin-top: 2px; font-size: var(--fs-meta); font-weight: 400; color: var(--c-ink-mute); }
.gen-form__body { display: grid; gap: var(--space-2); align-content: start; min-width: 0; }
.gen-form__body > p { margin: 0; }
.gen-form__fields { gap: var(--space-3); }
.gen-form__fields .section-title { margin: var(--space-2) 0 0; }
.gen-form__choices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.gen-form__counts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.gen-form__people { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: var(--fs-control); }
.gen-form__people li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-2); }
.gen-form__all summary { cursor: pointer; font-size: var(--fs-control); color: var(--c-brand-ink); }
.gen-form__all[open] summary { margin-bottom: var(--space-2); }
/* Seznam dokumentů sady je číslovaný — pořadí je pořadí tisku. */
.gen-form__docs { margin: 0; padding: 0; list-style: none; counter-reset: gen-doc; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); }
.gen-form__docs li {
  counter-increment: gen-doc; display: flex; align-items: center; gap: 4px var(--space-2);
  padding: 7px var(--space-3); border-top: 1px solid var(--c-border-hair); font-size: var(--fs-control);
}
.gen-form__docs li:first-child { border-top: 0; }
.gen-form__docs li::before { content: counter(gen-doc); width: 2ch; font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--c-ink-faint); }
/* Název a štítek vlevo, ovládání vpravo na témže řádku i na telefonu —
   štítek se zalomí pod název, ne ovládání pod štítek. */
.gen-form__doc-name { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-2); }
.gen-form__doc-actions { flex: none; margin-left: auto; }
/* Zakázaná šipka (první nahoru, poslední dolů) nemá co nabídnout — vypadala
   jako zmáčknutá; místo zůstává, aby ostatní šipky neuskakovaly. */
.gen-form__doc-actions .btn[disabled] { visibility: hidden; }
.gen-form__lead { font-size: var(--fs-control); font-weight: 500; }
.gen-form__from { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-size: var(--fs-control); color: var(--c-ink-mute); }
.gen-form__sets { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.gen-form__sets-label { flex-basis: 100%; font-size: var(--fs-meta); font-weight: 500; }
.gen-form__add { display: grid; gap: var(--space-1); }
.gen-form__add .select { width: 100%; max-width: 44ch; }
.gen-form__replace summary { cursor: pointer; font-size: var(--fs-control); color: var(--c-brand-ink); }
.gen-form__replace[open] { display: grid; gap: var(--space-2); }
.gen-form__replace .field__hint { margin: 0; }
/* Překreslení v rámu trvá chvilku — ať je vidět, že kliknutí něco dělá. */
turbo-frame#print-batch-setup[busy] .gen-form { opacity: .6; transition: opacity var(--dur-base) ease; }
.gen-form__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-4); border-top: 1px solid var(--c-border);
  background: var(--c-sunken); border-radius: 0 0 var(--radius-3) var(--radius-3);
}
.gen-form__summary { margin: 0; font-size: var(--fs-control); color: var(--c-ink-mute); }
.gen-form__background { flex-basis: 100%; margin: 0; }
@media (max-width: 720px) {
  .gen-form__row { grid-template-columns: 1fr; gap: var(--space-2); }
  .gen-form__label { padding-top: 0; }
}

/* =====================================================================
   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); }

/* --- souctovy radek (E13, ukol #190) ---------------------------------- */
/* Drzi se u spodniho okraje stejne, jako se pasma drzi u bocnich: u stovky
   lidi je soucet jinak videt az po dorolovani na konec. Zmrazene rohy musi
   zustat nad nim, proto maji vyssi vrstvu nez zbytek paticky. */
.grid tfoot td, .grid tfoot th {
  position: sticky; bottom: 0; z-index: 3;
  height: var(--row-h); padding: 0 var(--space-2);
  background: var(--c-sunken);
  font-weight: 600;
  border-top: 1px solid var(--c-border);
  border-bottom: 0;
}
.grid tfoot .g-id, .grid tfoot .g-sum, .grid tfoot .g-comp { z-index: 5; background: var(--c-sunken); }
.g-total__day, .grid tfoot .g-comp {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
}
/* Sloupec dne je siroky na `7,50`; soucet za halu ma az sedm znaku. Mensi
   pismo a temer zadny okraj jsou jedine, co se v 46 px da udelat, aniz by
   se roztahla cela tabulka a rozjela zmrazena pasma. */
.grid tfoot .g-total__day { padding: 0 2px; font-size: 10px; }
/* Vysvetlujici veta k filtru stoji pod slovem „Celkem", ne vedle nej: sloupec
   s osobou je uzky a vedle by ji orizlo prave tam, kde zacina cislo. */
.g-total__note {
  display: block; font-size: 10px; font-weight: 600;
  color: var(--c-soon-ink); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.grid tfoot .g-id--person { line-height: 1.15; }

/* --- 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í". */
/* Návrh, který pod sebou něco má. Plná linka u spodního okraje, ne jiná
   barva rámečku: čárkovaný rámeček znamená „návrh" a přebarvit ho by ten
   význam přepsal. Co je pod tím, stojí v nápovědě — barva nikdy nestojí sama. */
.day__input--replaces { box-shadow: inset 0 -2px 0 var(--c-soon-line); }

.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; }

/* ==============================================================   Průvodce importem kartotéky (E9, design/e9)
   ===================================================================== */

/* --- Hlavička průvodce ------------------------------------------------
   Krok je adresa (E9 § 6.2): hotový krok je odkaz (dá se vrátit), aktuální
   je zvýrazněný, budoucí klikatelný není. `list-views` je pás záložek bez
   pořadí a bez směru, `.steps` je svislá checklista uvnitř karty — průvodce
   potřebuje obojí. Stav nese znak (✓ / číslo) i postavení, ne barva. */
.wizard {
    padding: var(--space-3) var(--space-4);
    background: var(--c-surface);
    border-block-end: 1px solid var(--c-border);
    display: grid;
    gap: var(--space-2);
}

.wizard__top { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.wizard__file { font-weight: 600; }
.wizard__meta { font-size: var(--fs-control); color: var(--c-ink-mute); }
.wizard__tools { margin-inline-start: auto; display: flex; gap: var(--space-2); flex-wrap: wrap; }

.wizard__steps {
    display: flex; flex-wrap: wrap; gap: 2px var(--space-1);
    align-items: center; list-style: none; margin: 0; padding: 0;
}

/* Krok je `span`, `a` nebo `button` — vzhled drží třída, ne značka. */
.wizard__step {
    display: flex; align-items: center; gap: 6px;
    padding: 4px var(--space-2); border-radius: var(--radius-2);
    font: inherit; font-size: var(--fs-control); color: var(--c-ink-mute);
    border: 1px solid transparent; background: transparent; text-align: start;
}

/* Kroky jsou položky seznamu, takže spojku nese `li + li` — sousední
   `.wizard__step` spolu nesousedí. */
.wizard__steps li + li .wizard__step::before { content: "›"; color: var(--c-ink-faint); margin-inline-end: 4px; }

.wizard__num {
    inline-size: 19px; block-size: 19px; flex: none;
    display: inline-grid; place-items: center; border-radius: 50%;
    border: 1px solid var(--c-border); background: var(--c-sunken);
    font-family: var(--font-mono); font-size: 10.5px;
}

a.wizard__step, button.wizard__step { color: var(--c-ink); cursor: pointer; }
a.wizard__step:hover, button.wizard__step:hover { background: var(--c-sunken); text-decoration: none; }
a.wizard__step:focus-visible, button.wizard__step:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

.wizard__step--done .wizard__num { background: var(--c-ok-soft); border-color: var(--c-ok-line); color: var(--c-ok-ink); }
.wizard__step--now { background: var(--c-brand-soft); border-color: var(--c-brand-line); color: var(--c-brand-ink); font-weight: 600; }
.wizard__step--now .wizard__num { background: var(--c-brand); border-color: var(--c-brand); color: var(--c-on-brand); }
.wizard__step--todo { color: var(--c-ink-faint); }

/* Důvod, proč je krok neaktivní („formát JOBSON — sloupce známe").
   Píše se za název kroku, ne místo něj: krok, který zmizí, vypadá jako
   vada a člověk ho hledá, a zakázaná volba bez důvodu je odmítnutí bez
   vysvětlení. Na úzké obrazovce se láme pod název — schovat ho tam by
   znamenalo, že se na mobilu nedozví, proč krok nejde otevřít, právě
   ten člověk, který má nejmíň místa na hledání. */
.wizard__why { color: var(--c-ink-faint); font-size: var(--fs-micro); }
@media (max-width: 719px) {
    .wizard__step:has(.wizard__why) { flex-wrap: wrap; }
    .wizard__why { flex-basis: 100%; }
}

/* Krok zpět mění data, takže je to tlačítko formuláře — formulář uvnitř
   položky seznamu se nesmí chovat jako blok, jinak se pás zlomí. */
.wizard__steps form { display: contents; }

/* Lidský fallback je v průvodci vidět trvale (§ 6.2), ne až v patičce. */
.wizard__help { font-size: var(--fs-meta); color: var(--c-ink-mute); margin: 0; }

/* --- Zóna pro přetažení souboru ---------------------------------------
   `.drop` existuje; průvodce do ní přidává obsah (nadpis, věta, průběh). */
.drop__icon {
    inline-size: 40px; block-size: 40px; display: grid; place-items: center;
    border: 1px solid var(--c-border); border-radius: var(--radius-3);
    font-family: var(--font-mono); font-size: 19px; color: var(--c-ink-mute);
}

.drop__title { font-size: var(--fs-section); font-weight: 600; margin: 0; color: var(--c-ink); }
.drop__text { font-size: var(--fs-control); color: var(--c-ink-mute); margin: 0; max-inline-size: 52ch; text-wrap: pretty; }
.drop--busy { border-style: solid; background: var(--c-sunken); }

/* Přetažení souboru nad zónu. Drží to Stimulus (`import-drop`), protože
   `:hover` o přetahovaném souboru nic neví. */
.drop--over { border-color: var(--c-brand); background: var(--c-brand-soft); }

/* --- Tabulka mapování sloupců -----------------------------------------
   Modifikátor `.table`, ne nová tabulka: buňky nesou ovládací prvky, ne
   text, takže se nesmí ořezávat na --cell-max a select má vyplnit sloupec.
   Jmenuje se `colmap`, protože `.map` v aplikaci už znamená něco jiného
   (mapování složek vytěženého výkazu). */
.colmap td { max-inline-size: none; white-space: normal; vertical-align: top; padding-block: 6px; }
.colmap td .select, .colmap td .input { inline-size: 100%; }
.colmap__col { font-weight: 600; }
.colmap__letter { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-faint); }
.colmap__sample { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); display: block; overflow-wrap: anywhere; }
.colmap__why { font-size: var(--fs-meta); color: var(--c-ink-mute); display: block; margin-block-start: 3px; text-wrap: pretty; }
.colmap__why--blocked { color: var(--c-soon-ink); }

/* Rozpad složeného sloupce visí pod svým řádkem se svislou linkou — je to
   vlastnost toho sloupce, ne další řádek tabulky (E9 G8). */
.colmap__split {
    margin-block-start: 6px; padding-inline-start: var(--space-3);
    border-inline-start: 2px solid var(--c-brand-line);
    display: grid; gap: 6px;
}

.colmap__part { display: grid; grid-template-columns: minmax(0, 120px) minmax(0, 1fr); gap: var(--space-2); align-items: center; font-size: var(--fs-control); }
.colmap__part-label { color: var(--c-ink-mute); }
.colmap__note { font-size: var(--fs-meta); color: var(--c-ink-mute); margin: 0; }

/* Stav „model ještě navrhuje" nad tabulkou. Nenápadný schválně (E9 § 6.2):
   obrazovka jde mezitím normálně používat, takže to není banner. */
.colmap__pending {
    display: flex; align-items: center; gap: var(--space-2);
    font-size: var(--fs-meta); color: var(--c-ink-mute);
    margin: 0 0 var(--space-2);
}

@media (max-width: 720px) {
    /* Popisek nad hodnotou, ne vedle ní: do 1fr vedle 34 % popisku se
       select ani věta s důvodem nevejdou čitelně. */
    .colmap td { grid-template-columns: 1fr; gap: 2px; }
    .colmap__part { grid-template-columns: 1fr; gap: 2px; }
}

/* --- Štítek návrhu AI (E9 krok 4, design/e9/e9.css) -------------------
   `.status` je stav záznamu (platné / končí / odmítnuté). Návrh stavem
   není — je to **původ hodnoty v poli**, a proto vlastní třída: kdyby se
   kreslil jako stav, četl by se „pole je ve stavu navrženo".

   Přerušovaný rámeček nese totéž, co slovo: je to zatím jen návrh. Jistota
   u něj stojí **slovem, nikdy procentem** (§ 6.2) — procento se čte jako
   měřená pravděpodobnost a ta se nikde nepočítá. */
.suggest {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--fs-micro); color: var(--c-brand-ink);
    background: var(--c-brand-soft);
    border: 1px dashed var(--c-brand-line); border-radius: var(--radius-1);
    padding: 0 6px; white-space: nowrap;
}

.suggest::before { content: "AI"; font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; }

/* Slabší jistota má vlastní barvu, ne jen jiné slovo: barva sama informace
   není (`CLAUDE.md`), ale vedle slova pomáhá najít řádky k projití. */
.suggest--weak { color: var(--c-soon-ink); background: var(--c-soon-soft); border-color: var(--c-soon-line); }

/* --- Hodnota ke spárování (E9 krok 5, design/e9/e9.css) ---------------
   Datagrid by z „hodnota · počet řádků · nabídka · vysvětlení" udělal
   čtyři sloupce, ve kterých se špatně míří na select a vysvětlující věta
   by neměla kam. Tři sloupce a věta přes celou šířku. */
.pair {
    display: grid; grid-template-columns: minmax(0, 200px) 92px minmax(0, 1fr);
    gap: var(--space-3); align-items: center;
    padding: 7px var(--space-2);
    border-block-end: 1px solid var(--c-border-hair);
    font-size: var(--fs-control);
}
.pair:last-child { border-block-end: 0; }
.pair__value { font-weight: 600; overflow-wrap: anywhere; }
.pair__n { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); overflow-wrap: anywhere; }
.pair__ctl { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.pair__ctl .select { min-inline-size: 200px; flex: 1; }
.pair__note { grid-column: 1 / -1; margin: 0; font-size: var(--fs-meta); color: var(--c-ink-mute); }

/* Pod 720 px se sloupce staví pod sebe — do 200 px vedle sebe se select
   ani hodnota nevejdou (totéž pravidlo jako u tabulky mapování). */
@media (max-width: 720px) { .pair { grid-template-columns: 1fr; gap: var(--space-2); } }

/* --- Odvozený tarifní stupeň (E9 krok 15, design/e9/e9.css) ----------------
   Není to číselníkové spárování, takže to není `.pair`: sazba se **měnit
   nesmí** (je to hodnota, na které lidé v souboru sedí, M3-P21) a vedle ní
   stojí počet lidí — podle něj se pozná, co je stupeň a co překlep v
   účetnictví. */
.grade {
    display: grid; grid-template-columns: minmax(0, 160px) 110px minmax(0, 1fr);
    gap: var(--space-3); align-items: center;
    padding: 6px var(--space-2);
    border-block-end: 1px solid var(--c-border-hair);
    font-size: var(--fs-control);
}
.grade:last-child { border-block-end: 0; }
.grade__rate { font-family: var(--font-mono); font-weight: 600; overflow-wrap: anywhere; }
.grade__n { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Pod 720 px totéž jako u `.pair`: tři sloupce se do šířky telefonu
   nevejdou a sazba by se zalomila uprostřed čísla. */
@media (max-width: 720px) { .grade { grid-template-columns: 1fr; gap: 2px; } }

/* Sekce průvodce. Vidět je vždy jedna (`card-sections`), takže odsazení
   nese sekce sama — bez něj se nadpis lepí na obsah té předchozí, která je
   jen skrytá, ne smazaná. */
.sec { margin-block-end: var(--space-5); }
.sec:last-child { margin-block-end: 0; }

/* --- Pruh průběhu -----------------------------------------------------
   `.meter__bar` je součást karty měřidla a nemá popisek; běh importu
   potřebuje pruh s větou a živými počty vedle sebe. */
.progress { display: grid; gap: 6px; inline-size: min(420px, 100%); }
.progress__track { block-size: 10px; border-radius: 5px; background: var(--c-sunken); overflow: hidden; border: 1px solid var(--c-border-hair); }
.progress__track span { display: block; block-size: 100%; inline-size: var(--w, 0%); background: var(--c-brand); }
.progress__line { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); font-size: var(--fs-control); color: var(--c-ink-mute); }
.progress__line b { font-family: var(--font-mono); color: var(--c-ink); }

/* --- Dlaždice počtů (E9 krok 6, design/e9/e9.css) ---------------------
   `.meter` je karta s jedním velkým číslem a povinnou poznámkou — jedno
   číslo na obrazovku. Tady je dlaždic šest vedle sebe a **každá je zároveň
   ovladač**: přepíná sekci pod sebou.

   Je to ale **odkaz, ne tlačítko** (proti mockupu): sekce návrhu změn má až
   sto tisíc osob, takže se kreslí jen ta, na kterou se člověk ptá — a pak
   je sekce adresa (§ 6.2), kterou jde poslat kolegovi. Aktivní dlaždice
   proto nese `aria-current`, ne `aria-pressed`; `aria-pressed` na odkazu
   není platné. */
.counts { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: var(--space-2); }

.count {
    display: grid; gap: 2px; text-align: start;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--c-border); border-radius: var(--radius-2);
    background: var(--c-surface); color: inherit; font: inherit;
}

.count:hover { background: var(--c-sunken); text-decoration: none; }
.count:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.count--on { border-color: var(--c-brand); background: var(--c-brand-soft); box-shadow: inset 0 -2px 0 var(--c-brand); }
.count__n { font-family: var(--font-mono); font-size: 21px; font-weight: 600; line-height: 1.1; }
.count__label { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.count--warn .count__n { color: var(--c-soon-ink); }
.count--danger .count__n { color: var(--c-expired-ink); }
.count--ok .count__n { color: var(--c-ok-ink); }

/* --- Vedle sebe, pole po poli (E9 krok 6, M1 § 6.6) -------------------
   Kandidát na sloučení a rozpor mezi řádky téže osoby. **Nic není
   předvybrané** (M1-P34) a výběr je klik do buňky, proto je buňka
   `<button>` a ne řádek s přepínačem: dvě rozhodnutí na řádek by znamenala
   dvě mířidla.

   Počet sloupců nese `--cols`, protože rozpor mívá dvě hodnoty, ale může
   mít i tři — druhá třída na každý počet by znamenala, že si na ni někdo
   musí vzpomenout (`CLAUDE.md`: vzhled podle obsahu řeší komponenta).

   Slovo „vybráno" **nekreslí CSS**: obsah v `content:` by zůstal česky ve
   všech šesti jazycích (T2). Nese ho šablona. */
.cmp {
    display: grid;
    grid-template-columns: 148px repeat(var(--cols, 2), minmax(0, 1fr));
    gap: 1px; margin-block-end: var(--space-3);
    background: var(--c-border-hair);
    border: 1px solid var(--c-border-hair); border-radius: var(--radius-2);
    overflow: hidden;
}

.cmp--two { --cols: 2; }
.cmp__head { background: var(--c-sunken); padding: 6px var(--space-2); font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); }
.cmp__key { background: var(--c-surface); padding: 8px var(--space-2); font-size: var(--fs-control); color: var(--c-ink-mute); display: flex; align-items: center; }

.cmp__cell {
    background: var(--c-surface); padding: 8px var(--space-2);
    font: inherit; font-size: var(--fs-control); text-align: start;
    border: 0; border-inline-start: 3px solid transparent;
    min-inline-size: 0; overflow-wrap: anywhere;
}

button.cmp__cell { cursor: pointer; }
button.cmp__cell:hover { background: var(--c-brand-soft); }
button.cmp__cell:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
.cmp__cell[aria-pressed="true"] { background: var(--c-brand-soft); border-inline-start-color: var(--c-brand); font-weight: 600; }
.cmp__cell--muted { background: var(--c-sunken); color: var(--c-ink-mute); }
.cmp__note { font-size: var(--fs-micro); color: var(--c-brand-ink); display: block; }

@media (max-width: 720px) {
    /* Sloupce pod sebe; stranu nese `data-side`, jinak by se nepoznalo,
       která hodnota odkud je. */
    .cmp { grid-template-columns: 1fr; }
    .cmp__head { display: none; }
    .cmp__key { background: var(--c-sunken); font-weight: 600; color: var(--c-ink); }
    .cmp__cell::before { content: attr(data-side) ": "; color: var(--c-ink-mute); font-weight: 400; }
}

/* --- Rozbalený řádek datagridu (E9 krok 6) ---------------------------
   Detail osoby se otvírá **v místě řádku**, ne v dialogu: rozhoduje se
   o něm v kontextu ostatních. Buňka přes celou šířku nesmí dědit ořez ani
   výšku běžné buňky. Rozbalení drží nativní `<details>`, takže funguje bez
   JavaScriptu. */
.rowx > td { block-size: auto; max-inline-size: none; white-space: normal; padding: var(--space-3); background: var(--c-sunken); }
.rowx__summary { cursor: pointer; font-size: var(--fs-control); color: var(--c-ink-mute); }
.rowx__summary:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.rowx__body { display: grid; gap: var(--space-3); padding-block-start: var(--space-2); }
.rowx__body .facts { margin-block-end: 0; }
.rowx__reasons { margin: 0; padding-inline-start: 18px; font-size: var(--fs-control); }

/* --- Spodní lišta s potvrzením (E9 krok 6, § 6.2) --------------------
   „Nic se nezapíše bez posledního potvrzení s větou, co se stane."
   `.form-actions` je linka **pod** formulářem — na obrazovce se šesti
   sekcemi a stovkami řádků by ji nikdo neviděl. */
.actbar {
    position: sticky; inset-block-end: 0; z-index: 5;
    display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    background: var(--c-surface); border-block-start: 1px solid var(--c-border);
    box-shadow: 0 -2px 8px oklch(0.30 0.02 250 / 0.06);
}

.actbar__what { flex: 1 1 240px; min-inline-size: 0; font-size: var(--fs-control); margin: 0; text-wrap: pretty; }
.actbar__acts { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* Na telefonu jen hlavní věta. Doplňující počty (připojí se, už v kartotéce,
   vyřazeno) stojí o kus výš v dlaždicích — tady by z lišty udělaly pruh přes
   pětinu obrazovky a zakryly by to, o čem se rozhoduje. */
@media (max-width: 720px) { .actbar__more { display: none; } }

/* --- Dvojice „otázka → odpověď" v kartě -------------------------------
   Seznam faktů, u kterého je popisek úzký a odpověď dlouhá věta. `.facts`
   staví hodnoty do mřížky stejné šířky, což u vět nefunguje. */
.way__rows { display: grid; gap: 1px; margin: var(--space-1) 0 0; }
.way__row {
    display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: var(--space-2);
    font-size: var(--fs-control); padding-block: 4px;
    border-block-start: 1px solid var(--c-border-hair);
}
.way__row dt { color: var(--c-ink-mute); margin: 0; }
.way__row dd { margin: 0; }

@media (max-width: 560px) { .way__row { grid-template-columns: 1fr; gap: 2px; } }

/* --- Drobnosti --------------------------------------------------------- */
.notice__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* Banner s akcí se na telefonu láme pod větu. `.notice` je flex v jednom
   řádku, takže tlačítko vedle textu zmáčkne větu do sloupce o dvou
   slovech — nalezeno u „V souboru chybí" v reportu importu (E9 krok 10).
   Rozhoduje **obsah** (`:has()`), ne druhá třída: platí to i pro bannery
   s akcí, které teprve vzniknou (`CLAUDE.md`). */
@media (max-width: 720px) {
  .notice:has(.notice__actions) { flex-wrap: wrap; align-items: flex-start; }
  .notice:has(.notice__actions) .notice__actions { flex-basis: 100%; }
}

/* Technický zápis uvnitř věty (přípona, kód). Jediné místo, kde se do UI
   píše řetězec, který je hodnota, ne popisek. */
.key { font-family: var(--font-mono); font-size: var(--fs-micro); }

/* Ikona v zóně pro soubor je inline SVG (ikonový font designový systém
   zakazuje), takže se musí zvětšit z 16px na velikost ikony zóny. */
.drop__icon .app__nav-icon { inline-size: 22px; block-size: 22px; color: var(--c-ink-mute); }

/* Popisek nad nativním výběrem souboru, ne vedle něj: nativní prvek je
   široký a v centrovaném gridu by se s popiskem přetahoval o řádek. */
.drop .field { display: grid; gap: 4px; justify-items: center; margin: 0; }

/* --- Druhý řádek v buňce tabulky (E9 krok 8) ---------------------------
   Odmítnutý a opuštěný běh nese v přehledu rovnou důvod, ne jen stav.
   Věta patří pod štítek, ne vedle něj: vedle by z ní zůstala první dvě
   slova a zbytek by tabulku roztáhl do strany.

   `white-space: normal` je tu to podstatné: buňky tabulky se nelámou
   (`nowrap`), takže věta dlouhá dva řádky se v buňce **uřízne uprostřed** —
   přesně ta vada, kterou zelená brána nechytí. Strop šířky drží sloupec
   v rozumné míře, aby se kvůli jedné větě neroztáhla celá tabulka. */
.table__note {
    display: block; margin-block-start: 2px;
    font-size: var(--fs-micro); color: var(--c-ink-mute);
    white-space: normal; min-inline-size: 26ch; max-inline-size: 34ch;
}

/* --- Sada polí na API klíči (E9 krok 17, M1-P44) ----------------------
   `.matrix` je „něco × něco" (role × oprávnění). Tohle je **jeden seznam
   po skupinách**: co klíč smí vydat. Citlivá pole stojí odděleně, ve
   výchozím stavu vypnutá a s varováním — barva sama by informace nebyla
   (člověk s poruchou barvocitu), proto nese skupina i nadpis a větu.

   `auto-fit` s dolní mezí 190 px proto, že agentura se čtyřiceti vlastními
   poli má seznam na tři sloupce a agentura bez nich na jeden; pevný počet
   sloupců by v jednom z těch dvou případů byl špatně. */
.fieldset-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-3); margin-block-end: var(--space-4); }
.fieldgroup { display: grid; gap: 4px; align-content: start; }
.fieldgroup__title { font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--c-ink-mute); }
.fieldgroup--sensitive { border: 1px solid var(--c-soon-line); background: var(--c-soon-soft); border-radius: var(--radius-2); padding: var(--space-2); }
.fieldgroup--sensitive .fieldgroup__title { color: var(--c-soon-ink); }

/* --- Jednorázově zobrazený klíč (E9 krok 17, § 8) ---------------------
   Klíč se ukáže jednou a musí být poznat, že je to **hodnota ke
   zkopírování**, ne popisek. `overflow-wrap: anywhere` je tu to
   podstatné: klíč je 72 znaků bez mezery a bez zalomení by na telefonu
   vyhnal stránku do strany. */
.secret {
    display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
    font-family: var(--font-mono); font-size: var(--fs-control);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--c-brand-line); background: var(--c-brand-soft);
    border-radius: var(--radius-2); overflow-wrap: anywhere;
}
.secret__value { overflow-wrap: anywhere; min-inline-size: 0; }
/* --- zauceni cteni vykazu (design/e13-cteni, #163) --------------------------
   Platno o dvou polovinach: vlevo nahrany vykaz, vpravo data, ktera jsme
   z nej precetli. Cte se zleva doprava a dokument je predloha, data jsou
   tvrzeni o ni.

   Kazda polovina se roluje sama za sebe a stranka jako celek ne. Bez toho by
   posun v dokumentu odsunul data — a cele „divat se misto pamatovat si" by
   padlo u prvniho vykazu delsiho nez obrazovka, tedy u kazdeho. */

.rd-canvas {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 430px;
    block-size: calc(100dvh - var(--topbar-h) - 128px);
    min-block-size: 420px;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-3) var(--radius-3) 0 0;
    background: var(--c-surface);
    overflow: hidden;
}

.rd-side {
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.rd-side + .rd-side { border-inline-start: 1px solid var(--c-border); }

.rd-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 7px var(--space-3);
    border-block-end: 1px solid var(--c-border-hair);
    background: var(--c-sunken);
    min-block-size: 38px;
    flex: none;
}

.rd-head__title { font-weight: 600; font-size: var(--fs-control); white-space: nowrap; }
.rd-head__spacer { flex: 1; }

/* Tohle je ta oprava, o kterou jde: vlastni posuvnik v kazde polovine. */
.rd-scroll { flex: 1; overflow: auto; min-block-size: 0; }

/* Kam se v dokumentu ukazalo. Bez znacky clovek nevi, jestli se klik
   chytil a kam — a pise poznamku k mistu, ktere model nedostane. */
.rd-scroll--sheet { position: relative; }

.rd-mark {
    position: absolute;
    inline-size: 26px;
    block-size: 26px;
    margin: -13px 0 0 -13px;
    border: 2px solid var(--c-danger);
    border-radius: 50%;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-danger) 25%, transparent);
    pointer-events: none;
}

.rd-foot {
    flex: none;
    padding: 7px var(--space-3);
    border-block-start: 1px solid var(--c-border-hair);
    font-size: var(--fs-meta);
    color: var(--c-ink-mute);
    background: var(--c-surface);
}

/* --- ovladani dokumentu ---------------------------------------------------
   Priblizeni ma tri stupne a nic mezi tim. Plynuly zoom by znamenal, ze si
   ho kazdy nastavi jinak a nikdo pak nevi, na co se druhy diva. */

.rd-zoom { display: flex; }

.rd-zoom__btn {
    block-size: 22px;
    padding-inline: 7px;
    border: 1px solid var(--c-border);
    background: var(--c-surface);
    font: inherit;
    font-size: var(--fs-micro);
    color: var(--c-ink-mute);
    cursor: pointer;
}

.rd-zoom__btn + .rd-zoom__btn { border-inline-start: none; }
.rd-zoom__btn:first-child { border-start-start-radius: var(--radius-2); border-end-start-radius: var(--radius-2); }
.rd-zoom__btn:last-child { border-start-end-radius: var(--radius-2); border-end-end-radius: var(--radius-2); }

.rd-zoom__btn[aria-pressed="true"] {
    background: var(--c-brand-soft);
    border-color: var(--c-brand-line);
    color: var(--c-brand-ink);
    font-weight: 600;
}

.rd-pages { display: flex; align-items: center; gap: 2px; }

.rd-pages__btn {
    inline-size: 22px;
    block-size: 22px;
    border: 1px solid var(--c-border);
    background: var(--c-surface);
    border-radius: var(--radius-2);
    cursor: pointer;
    font: inherit;
    font-size: 11px;
    color: var(--c-ink-mute);
    line-height: 1;
}

.rd-pages__pos {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    color: var(--c-ink-mute);
    padding-inline: 3px;
    white-space: nowrap;
}

/* --- papir ----------------------------------------------------------------
   Skutecna A4. Kliknutim se ukazuje, proto kurzor kriz — a proto se obrazek
   nesmi tahnout jako odkaz. */

.rd-paper {
    display: block;
    margin: var(--space-3) auto;
    max-inline-size: 100%;
    box-shadow: var(--shadow-1);
    border: 1px solid var(--c-border);
    cursor: crosshair;
    -webkit-user-drag: none;
    user-select: none;
}

.rd-paper--fit { max-block-size: none; }
.rd-paper--wide { inline-size: 100%; }
.rd-paper--zoom { inline-size: 150%; max-inline-size: none; }

/* --- prepinac lidi ve vzorku ----------------------------------------------
   Nestaci „1/3". Musi byt videt, ze ostatni dva jsou v poradku — jinak se
   k nim nikdo neproklikne a trojclenny vzorek ztraci smysl. */

.rd-who { display: flex; gap: 2px; flex-wrap: wrap; }

.rd-who__tab {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    block-size: 24px;
    padding-inline: 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-2);
    background: none;
    font: inherit;
    font-size: var(--fs-micro);
    color: var(--c-ink-mute);
    cursor: pointer;
    white-space: nowrap;
}

.rd-who__tab:hover { background: var(--c-surface); }

.rd-who__tab[aria-current="true"] {
    background: var(--c-surface);
    border-color: var(--c-border);
    color: var(--c-ink);
    font-weight: 600;
}

.rd-who__st { font-family: var(--font-mono); font-weight: 700; }
.rd-who__st--warn { color: var(--c-soon-ink); }
.rd-who__st--ok { color: var(--c-ok-ink); }

/* --- kontrolky ------------------------------------------------------------
   Prilepene nahore: jsou to jedina tri meritka, podle kterych clovek pozna,
   jestli se hybe dopredu. Nesmi odrolovat pryc ani pri otevrene oprave. */

.rd-checks {
    flex: none;
    display: grid;
    gap: 1px;
    background: var(--c-border-hair);
    border-block-end: 1px solid var(--c-border);
}

.rd-check {
    display: grid;
    grid-template-columns: 58px 78px 1fr;
    align-items: center;
    gap: var(--space-2);
    background: var(--c-surface);
    padding: 6px var(--space-3);
    font-size: var(--fs-control);
}

.rd-check__key { color: var(--c-ink-mute); font-size: var(--fs-meta); }
.rd-check__val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.rd-check--warn { background: var(--c-soon-soft); }
.rd-check--warn .rd-check__val { color: var(--c-soon-ink); font-weight: 600; }
.rd-check--none .rd-check__val { color: var(--c-ink-faint); }
/* Součet jde opravit — tlačítko na konci řádku, ať kontrolka zůstane čitelná. */
.rd-check--fixable { grid-template-columns: 58px 78px 1fr auto; }
.rd-check__fix { height: auto; padding: 2px var(--space-2); font-size: var(--fs-meta); }
/* Věta kontrolky se zalomí, neuřízne. Rozpor bývá dlouhá věta s dvěma čísly
   a bez zalomení z ní na obrazovce zbylo „Model uvedl vlastní součet 195,00 h,
   ale z vyps…" (Lukáš 23. 9. 2026). `min-width: 0` je nutné: položka mřížky
   se jinak nezúží pod šířku svého textu. */
.rd-check > * { min-width: 0; }
.rd-check > .status { white-space: normal; height: auto; line-height: 1.35; padding-block: 2px; }

/* --- vypis dnu ------------------------------------------------------------ */

.rd-days { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-control); }

.rd-days th {
    text-align: start;
    font-size: var(--fs-micro);
    font-weight: 500;
    color: var(--c-ink-mute);
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 5px var(--space-3);
    border-block-end: 1px solid var(--c-border-hair);
    background: var(--c-surface);
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
}

.rd-days td {
    padding: 3px var(--space-3);
    border-block-end: 1px solid var(--c-border-hair);
    block-size: 26px;
}

.rd-days__date {
    color: var(--c-ink-mute);
    font-family: var(--font-mono);
    inline-size: 78px;
    white-space: nowrap;
}

.rd-days__val {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    text-align: end;
    inline-size: 58px;
}

.rd-days__note { color: var(--c-ink-mute); font-size: var(--fs-meta); }
.rd-days tbody tr { cursor: pointer; }
.rd-days tbody tr:hover { background: var(--c-sunken); }
.rd-days tr[data-state="warn"] { background: var(--c-soon-soft); }
.rd-days tr[data-state="warn"] .rd-days__val { color: var(--c-soon-ink); font-weight: 600; }

.rd-days tr[aria-selected="true"] {
    background: var(--c-brand-soft);
    box-shadow: inset 3px 0 0 var(--c-brand);
}

.rd-days__empty { color: var(--c-ink-faint); }

/* Den, ktery se od minuleho precteni pohnul. Prouzek, ne barva pozadi —
   ta patri nesouhlasu a dva vyznamy jedne barvy by se pletly. */
.rd-days tr[data-moved="true"] { box-shadow: inset 3px 0 0 var(--c-brand-line); }
.rd-days tr[data-moved="true"] .rd-days__date { color: var(--c-ink); font-weight: 600; }

/* --- panel opravy ---------------------------------------------------------
   Prisspendleny dole. Kdyby stal pod vypisem, po klepnuti na den by byl
   u jednatricetidenniho mesice pod ohybem a clovek by nevedel, ze se ho
   aplikace na neco pta. */

.rd-fix {
    flex: none;
    border-block-start: 1px solid var(--c-border);
    background: oklch(0.982 0.003 250);
    padding: var(--space-3);
    display: grid;
    gap: var(--space-2);
    box-shadow: 0 -4px 12px oklch(0.30 0.02 250 / 0.05);
}

.rd-fix__q { font-size: var(--fs-base); font-weight: 600; margin: 0; }
.rd-fix__opts { display: flex; flex-wrap: wrap; gap: 5px; }

.rd-fix__opts .choice {
    block-size: 25px;
    padding-inline: 8px;
    font-size: var(--fs-meta);
    background: var(--c-surface);
}

.rd-fix__pointed {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--fs-meta);
    color: var(--c-brand-ink);
    background: var(--c-brand-soft);
    border: 1px solid var(--c-brand-line);
    border-radius: var(--radius-2);
    padding: 3px 8px;
}

.rd-fix__actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.rd-fix__price { font-size: var(--fs-meta); color: var(--c-ink-mute); margin-inline-start: auto; }

/* --- pruh „co se zmenilo" ------------------------------------------------- */

.rd-changed {
    flex: none;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    padding: 6px var(--space-3);
    background: var(--c-ok-soft);
    border-block-end: 1px solid var(--c-ok-line);
    font-size: var(--fs-meta);
    color: var(--c-ok-ink);
}

/* --- pruh s pokynem pod platnem -------------------------------------------
   Pokyn je to, co se tady vyrabi. Ukazat ho az u ukladani znamena ladit
   naslepo, proto je pod platnem po celou dobu. */

.rd-hint {
    border: 1px solid var(--c-border);
    border-block-start: none;
    border-end-start-radius: var(--radius-3);
    border-end-end-radius: var(--radius-3);
    background: var(--c-surface);
}

.rd-hint__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    inline-size: 100%;
    padding: 8px var(--space-3);
    background: var(--c-sunken);
    border: none;
    font: inherit;
    font-size: var(--fs-control);
    text-align: start;
    cursor: pointer;
}

.rd-hint__head::-webkit-details-marker { display: none; }
.rd-hint__name { font-weight: 600; }
.rd-hint__meta { color: var(--c-ink-mute); font-size: var(--fs-meta); }
.rd-hint__spacer { flex: 1; }
.rd-hint__body { padding: var(--space-3); display: grid; gap: var(--space-3); }

.rd-diff {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    line-height: 1.65;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-2);
    background: var(--c-surface);
    padding: var(--space-3);
    white-space: pre-wrap;
}

.rd-diff del { background: var(--c-danger-soft); color: var(--c-danger); }
.rd-diff ins { background: var(--c-ok-soft); color: var(--c-ok-ink); text-decoration: none; }

/* --- pod 1024 px se poloviny skladaji a ukazovani se vypne ---------------- */

.rd-narrow { display: none; }

@media (max-width: 1023px) {
    .rd-narrow { display: flex; }
    .rd-canvas { grid-template-columns: 1fr; block-size: auto; }
    .rd-side + .rd-side { border-inline-start: none; border-block-start: 1px solid var(--c-border); }
    .rd-scroll { max-block-size: 420px; }
    .rd-paper { cursor: default; }
}

/* --- Checklisty a úkoly (E10, design/e10-checklisty) ------------------
   Nové vzory etapy, schválené Jakubem 23. 9. 2026; zdůvodnění, proč
   nestačí stávající, je v README návrhu. Všechno přes tokeny.

   Stav úkolu nese vždy ikonu **i** slovo (M1-P23). `status` má pět barev
   pro platnost; úkol potřebuje ještě šedou pro „naplánováno" a
   „přeskočeno / zrušeno". */
.status--inactive { background: var(--c-inactive-soft); border-color: var(--c-inactive-line); color: var(--c-inactive-ink); }
.status--inactive::before { content: "…"; }
.status--skipped { background: var(--c-inactive-soft); border-color: var(--c-inactive-line); color: var(--c-inactive-ink); }
.status--skipped::before { content: "↷"; }

/* Počet v nabídce sekcí karty (Checklist: k vyřešení, ✕ když po termínu). */
.section-nav__n { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.section-nav__item--active .section-nav__n { color: inherit; }
.section-nav__n--danger, .section-nav__item--active .section-nav__n--danger { color: var(--c-expired-ink); font-weight: 600; }

/* Souhrn checklistu: prstenec + čísla. Procento dává smysl jen tady —
   v seznamu osob by to byl šum, tam je jen počet k vyřešení. */
.cl-summary { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; padding: var(--space-3) var(--space-4); background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-3); }
.ring { --p: 0; width: 64px; height: 64px; border-radius: 50%; flex: none; display: grid; place-items: center; background: conic-gradient(var(--c-brand) calc(var(--p) * 1%), var(--c-sunken) 0); }
.ring__in { width: 50px; height: 50px; border-radius: 50%; background: var(--c-surface); display: flex; align-items: baseline; justify-content: center; padding-top: 16px; font-family: var(--font-mono); font-weight: 600; font-size: 14px; }
.ring__in small { font-size: 10px; color: var(--c-ink-mute); font-weight: 400; }
.cl-nums { display: flex; gap: var(--space-4); flex-wrap: wrap; }
.cl-num { display: grid; gap: 1px; }
.cl-num__n { font-family: var(--font-mono); font-size: 20px; font-weight: 600; line-height: 1.1; }
.cl-num__l { font-size: var(--fs-micro); color: var(--c-ink-mute); text-transform: uppercase; letter-spacing: .05em; }
.cl-num--ok .cl-num__n { color: var(--c-ok-ink); }
.cl-num--danger .cl-num__n { color: var(--c-expired-ink); }
.cl-num--soon .cl-num__n { color: var(--c-soon-ink); }
.cl-num--mute .cl-num__n { color: var(--c-ink-mute); }
.cl-bar { margin-top: var(--space-3); }

/* Filtr checklistu je odkaz s adresou, ne tlačítko — vybraná položka
   se proto pozná podle `aria-current`, ne `aria-pressed`. */
.cl-bar .seg__item { display: inline-flex; align-items: center; gap: 6px; }
.cl-bar .seg__item + .seg__item { border-left: 1px solid var(--c-border); }
.cl-bar .seg__item[aria-current="true"] { background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600; }
.seg__n { font-family: var(--font-mono); font-size: var(--fs-micro); }

/* Skupina úkolů (Před nástupem, …, Jednorázové). */
.tgroup { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-3); margin-top: var(--space-3); }
/* Bez `overflow: hidden` na skupině: nabídka ⋯ visí z řádku ven a uřízla
   by se. Zaoblení proto nese hlavička a poslední řádek. */
.tgroup__head { border-radius: var(--radius-3) var(--radius-3) 0 0; display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--c-sunken); border-bottom: 1px solid var(--c-border-hair); }
.tgroup__title { font-size: var(--fs-body, inherit); font-weight: 600; margin: 0; }
.tgroup__sub { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.tgroup__progress { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-control); color: var(--c-ink-mute); white-space: nowrap; }
.tgroup__bar { width: 120px; height: 6px; border-radius: 3px; background: var(--c-border-hair); overflow: hidden; }
.tgroup__bar span { display: block; height: 100%; width: var(--w, 0%); background: var(--c-brand); }
.tgroup__list { list-style: none; margin: 0; padding: 0; }
.tgroup__empty { padding: var(--space-3) var(--space-4); font-size: var(--fs-control); color: var(--c-ink-mute); }
@media (max-width: 640px) { .tgroup__bar { display: none; } }

/* Řádek úkolu. Na telefonu se akce zalomí pod text a jsou na celou
   šířku — koordinátor odškrtává na hale (§ 6.2). Po termínu je
   podbarvený celý řádek, ne jen štítek (README návrhu, bod 3). */
.task { display: flex; gap: var(--space-3); align-items: flex-start; padding: var(--space-3) var(--space-4); }
.task + .task { border-top: 1px solid var(--c-border-hair); }
.task:last-child { border-radius: 0 0 var(--radius-3) var(--radius-3); }
.task__mark { width: 26px; height: 26px; border-radius: 50%; flex: none; display: grid; place-items: center; font-family: var(--font-mono); font-size: 13px; font-weight: 700; border: 1.5px dashed var(--c-border); color: var(--c-ink-faint); margin-top: 1px; }
.task--done .task__mark { border: 0; background: var(--c-ok-soft); color: var(--c-ok-ink); }
.task--overdue .task__mark { border: 0; background: var(--c-expired-soft); color: var(--c-expired-ink); }
.task--soon .task__mark { border: 0; background: var(--c-soon-soft); color: var(--c-soon-ink); }
.task--planned .task__mark, .task--skipped .task__mark { border-style: solid; }
.task--overdue { background: var(--c-danger-soft); }
.task__body { flex: 1; min-width: 0; display: grid; gap: 4px; }
.task__title { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--space-2); font-weight: 500; }
.task__name { overflow-wrap: anywhere; }
.task--done .task__name, .task--skipped .task__name { color: var(--c-ink-mute); }
.task__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-3); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.task__meta b { font-weight: 600; color: var(--c-ink); }
.task__acts { display: flex; gap: var(--space-2); flex: none; align-items: center; }
.task__acts form { display: contents; }
.task__note { font-size: var(--fs-micro); color: var(--c-ink-mute); font-style: italic; overflow-wrap: anywhere; }
.task__menu { display: grid; padding: var(--space-1); min-width: 220px; }
.task__menu-item { display: block; padding: 6px var(--space-3); border-radius: var(--radius-1); color: var(--c-ink); text-decoration: none; font-size: var(--fs-control); }
.task__menu-item:hover, .task__menu-item:focus-visible { background: var(--c-brand-soft); text-decoration: none; }
@media (max-width: 640px) {
  .task { flex-wrap: wrap; }
  .task__acts { width: 100%; padding-left: 38px; }
  /* Roztažené tlačítko smí popisek zalomit. `.btn` má `nowrap` (šířka roste
     s textem) a jako položka flexu `min-width: auto`, takže se nezmenší pod
     délku popisku: „Doplnit Datum poslední lékařské prohlídky →" vytlačilo
     ⋯ o 72 px za okraj a stránka měla 411 px místo 375. Délku popisku dává
     pole karty a jazyk, ne název úkolu — proto to drží tlačítko, ne pole.
     Každé roztažené tlačítko to musí mít (`StretchedButtonTest`). */
  .task__acts .btn:not(.btn--icon) {
    flex: 1; justify-content: center;
    min-width: 0; white-space: normal; overflow-wrap: anywhere; text-align: center;
    height: auto; min-height: var(--control-h); padding-top: 4px; padding-bottom: 4px;
  }
  /* Když je ⋯ v liště samo (naplánovaný úkol), stojí vlevo a panel
     zarovnaný doprava by visel 100 px za levým okrajem, kam se nedá
     dorolovat. Panel se pak zarovná k levému okraji tlačítka. */
  .task__acts > .popover:first-child .popover__panel { left: 0; right: auto; }
}

/* Způsob splnění. Automatický se liší plnou tečkou: uživatel musí na
   první pohled vědět, jestli má klikat, nebo vyplnit data (C-P2). */
.how { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-micro); font-weight: 400; padding: 0 6px; line-height: 18px; border-radius: var(--radius-1); background: var(--c-sunken); color: var(--c-ink-mute); border: 1px solid var(--c-border); white-space: nowrap; }
.how--auto { background: var(--c-pending-soft); border-color: var(--c-pending-line); color: var(--c-pending-ink); }

/* Počet „K vyřešení" v seznamu osob. Po termínu červeně s ✕ a slovem. */
.todo { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-mono); font-size: var(--fs-control); color: var(--c-ink); text-decoration: none; }
.todo--overdue { color: var(--c-expired-ink); font-weight: 600; }
.todo--overdue::before { content: "✕"; font-size: 11px; }
.todo--none { color: var(--c-ink-faint); }
.todo__sub { font-family: var(--font-sans); font-size: var(--fs-micro); color: var(--c-ink-mute); white-space: nowrap; }

/* Rychlé volby termínu (dnes, zítra, za týden, konec měsíce). */
.quick { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.quick .chip { cursor: pointer; padding: 0 10px; }
.quick .chip[aria-pressed="true"] { border-color: var(--c-brand); font-weight: 600; }

/* --- Obrazovka Úkoly (E10 F3, design/e10-checklisty/3-ukoly) ------------
   Skupiny podle naléhavosti jsou řádky tabulky, ne čtyři tabulky pod sebou:
   jedna tabulka drží jedno záhlaví s řazením a jeden výběr. */
.table__group td { background: var(--c-sunken); font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--c-ink-mute); padding-top: 6px; padding-bottom: 6px; height: auto; }
.table__group--danger td { color: var(--c-expired-ink); }
.table__group a { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: var(--space-2); }
/* Po termínu: proužek na kraji řádku vedle štítku se slovem — barva
   sama nestačí (M1-P23). */
tr.row--overdue td:first-child { box-shadow: inset 3px 0 0 var(--c-expired-ink); }
.table td .task__origin { display: flex; flex-wrap: wrap; gap: 4px var(--space-2); align-items: center; margin-top: 2px; }
/* Název úkolu a provozovna se zalamují, neuřezávají — „Kontrola čipu po
   týdn…" je jiný úkol než „po týdnu". */
.table td.queue__task, .table td.queue__site { white-space: normal; max-width: 340px; min-width: 200px; }
.table td.queue__site { min-width: 140px; max-width: 220px; }
.queue__title { font-weight: 500; overflow-wrap: anywhere; }
.queue__notified { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.table__actions-group form { display: contents; }
/* Odznak Úkolů v menu: moje úkoly po termínu, ✕ a barva (C19). */
.app__nav-count--danger { color: var(--c-expired-ink); background: var(--c-expired-soft); font-weight: 600; }
/* Nabídka ⋯ řádku úkolu je nativní popover (tabulka by ji uřízla) — stojí
   uprostřed obrazovky a nese název úkolu, aby bylo jasné, ke kterému patří. */
.task__menu[popover] { inset: 0; margin: auto; height: fit-content; width: min(340px, calc(100vw - 32px)); }

@media (max-width: 720px) {
  /* Šířky sloupců z tabulky na kartě neplatí — jinak by popisek u
     provozovny stál jinde než u ostatních údajů. */
  .table td.queue__task, .table td.queue__site { min-width: 0; max-width: none; }
  /* Na telefonu je skupina nadpis nad kartami, ne další karta. */
  .table tr.table__group { background: none; border: 0; box-shadow: none; padding: var(--space-2) 0 0; margin: 0; }
  .table tr.table__group td { display: block; background: none; padding: 0; border: 0; }
  .table tr.table__group td::before { content: none; }
  tr.row--overdue { border-left: 3px solid var(--c-expired-ink); }
  tr.row--overdue td:first-child { box-shadow: none; }
  /* Nadpisem karty úkolu je jeho **název**, ne stav: „po termínu 2 dny"
     tučně nahoře se čte jako jméno karty. Stav zůstává prvním údajem. */
  .table tr.queue-row { display: flex; flex-direction: column; }
  .table tbody tr.queue-row td.queue__task {
    order: -1; 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 tr.queue-row td.queue__task::before { content: none; }
  .table tbody tr.queue-row td.queue__state {
    display: grid; font-size: inherit; font-weight: 400;
    padding: 3px 0; margin: 0; border-bottom: 0;
  }
  .table tbody tr.queue-row td.queue__state::before { content: attr(data-label); }
  /* Akce se na kartě úkolu roztáhnou pod údaje — koordinátor odškrtává
     na hale palcem (README návrhu, bod 4). Roh karty drží zaškrtávátko. */
  .table tr.queue-row .table__actions:has(.btn, button, a, input, select) { position: static; margin-top: var(--space-2); }
  .table tr.queue-row .table__actions-group { display: flex; width: 100%; }
  /* Zalomení popisku jako u řádku úkolu na kartě: tlačítko má tu z
     `.table__actions .btn` pevnou šířku ikony, takže dlouhý popisek
     přetékal přes ⋯. */
  .table tr.queue-row .table__actions-group > .btn:not(.btn--icon),
  .table tr.queue-row .table__actions-group > form > .btn {
    flex: 1; justify-content: center;
    min-width: 0; white-space: normal; overflow-wrap: anywhere; text-align: center;
    height: auto; min-height: 26px; padding-top: 3px; padding-bottom: 3px;
  }
}

/* Prázdný stav uvnitř sekce karty — s rámečkem, aby se nerozlil do
   plochy karty. */
.state--boxed { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-3); min-height: 0; }

/* --- Šablony checklistů (E10 F2, design/e10-checklisty/5-editor-sablony) ---
   Editor: vlevo šablona, vpravo náhled dopadu, který se drží při rolování.
   Pod 960 px se náhled staví pod šablonu. `.impact` už v systému znamená
   výčet dopadů akce (seznam řádků), proto má náhled vlastní `cl-impact`. */
.editor { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--space-4); align-items: start; }
.editor__aside { position: sticky; top: calc(var(--topbar-h, 52px) + var(--space-3)); display: grid; gap: var(--space-3); }
@media (max-width: 960px) { .editor { grid-template-columns: 1fr; } .editor__aside { position: static; } }
.fgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-3); }
.cl-gap { margin-top: var(--space-3); }
.cl-impact { display: grid; gap: var(--space-2); padding: var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-surface); }
.cl-impact__n { font-family: var(--font-mono); font-size: 24px; font-weight: 600; }
.cl-impact__l { font-size: var(--fs-control); color: var(--c-ink-mute); }
.cl-impact__list { margin: 0; padding-left: var(--space-4); font-size: var(--fs-control); display: grid; gap: 2px; }
.cl-danger { color: var(--c-expired-ink); }

/* Položka šablony: sbalená hlavička s pravidlem, rozbalená s poli.
   `details`, ne skript — rozbalí ji i klávesnice a funguje bez JS. */
.item { border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); }
.item + .item { margin-top: var(--space-2); }
.item[open] { border-color: var(--c-brand-line); box-shadow: 0 0 0 1px var(--c-brand-line); }
.item__head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); padding: var(--space-2) var(--space-3); cursor: pointer; list-style: none; }
.item__head::-webkit-details-marker { display: none; }
.item__head::after { content: "▾"; margin-left: auto; color: var(--c-ink-mute); }
.item[open] > .item__head::after { content: "▴"; }
.item__order { color: var(--c-ink-faint); font-family: var(--font-mono); font-size: var(--fs-micro); min-width: 1.5em; }
.item__name { font-weight: 500; flex: 1 1 240px; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; overflow-wrap: anywhere; }
.item__rule { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.item__body { border-top: 1px solid var(--c-border-hair); padding: var(--space-3); display: grid; gap: var(--space-3); background: var(--c-canvas); }
.item__acts { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.rule { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.rule .input, .rule .select { width: auto; max-width: 100%; }
.rule .input--num { width: 80px; }

/* Volba s popisem (radio/checkbox + co udělá). Vybraná se pozná podle
   obsahu — `:has(:checked)` —, ne podle druhé třídy (`CLAUDE.md`). */
.opt { display: flex; gap: var(--space-2); align-items: flex-start; padding: var(--space-2) var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius-2); background: var(--c-surface); cursor: pointer; }
.opt + .opt { margin-top: var(--space-2); }
.opt > input { margin-top: 3px; accent-color: var(--c-brand); flex: none; }
.opt:has(> input:checked) { border-color: var(--c-brand); background: var(--c-brand-soft); }
.opt__t { font-weight: 500; }
.opt__d { font-size: var(--fs-micro); color: var(--c-ink-mute); }
/* Seznam poboček / provozoven patří jen k vybranému rozsahu. */
.cl-choices { margin-top: var(--space-2); }
.opt:not(:has(> input:checked)) .cl-choices { display: none; }
.cl-picker > summary { cursor: pointer; font-size: var(--fs-control); color: var(--c-brand-ink); }
.cl-apply { display: grid; gap: var(--space-2); }

/* Typ šablony jako segment z přepínačů: vybraný podle `:has(:checked)`. */
.cl-seg { flex-wrap: wrap; }
.cl-seg .seg__item { display: inline-flex; align-items: center; gap: 6px; }
.cl-seg .seg__item + .seg__item { border-left: 1px solid var(--c-border); }
.cl-seg .seg__item input { position: absolute; opacity: 0; pointer-events: none; }
.cl-seg .seg__item:has(input:checked) { background: var(--c-brand-soft); color: var(--c-brand-ink); font-weight: 600; }
.cl-seg .seg__item:has(input:focus-visible) { outline: 2px solid var(--c-brand); outline-offset: -2px; }

/* Původ úkolu ze šablony na kartě („ze šablony Nástup — agentura"). */
.task__origin { font-size: var(--fs-micro); font-weight: 400; color: var(--c-ink-mute); }
.cl-summary__where { flex-basis: 100%; margin: 0; font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Legenda skupiny polí v editoru bez rámečku prohlížeče. */
fieldset.field { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
fieldset.field > legend { padding: 0; }
/* Pole, která platí jen pro jednu volbu, se ukáží podle obsahu položky
   (`:has`, ne třída navíc — `CLAUDE.md`). Bez podpory `:has` zůstanou
   vidět a server je u jiné volby ignoruje. */
.item__body:has(select[name$="[completion]"] option[value="checkbox"]:checked) .cl-field-pick { display: none; }
.item__body:has(select[name$="[repeat]"] option[value=""]:checked) .cl-repeat-months { display: none; }
.item__body:not(:has(select[name$="[assignee]"] option[value="user"]:checked)) .cl-assignee-user { display: none; }
/* Hlídat platnost (E10 C23) jen u datumového pole: jiné pole volbu skryje
   a ukáže důvod. Zvolené pravidlo nahradí pravidlo termínu i předstih —
   termín plyne z data karty (C25). Rozhoduje obsah položky, ne třída. */
.item__body:not(:has(select[name$="[field]"] option[data-date]:checked)) :is(.cl-validity__pick, .cl-validity__hint) { display: none; }
.item__body:has(select[name$="[field]"] option[data-date]:checked) .cl-validity__reason { display: none; }
.item__body:has(select[name$="[validity]"] :is(option[value=""], option[value="in_past"]):checked) .cl-validity-days { display: none; }
.cl-due-validity { display: none; margin: 0; }
.item__body:has(select[name$="[completion]"] option[value="card_field"]:checked):has(select[name$="[field]"] option[data-date]:checked):has(select[name$="[validity]"] option:not([value=""]):checked) :is(.cl-due-rule, .cl-lead) { display: none; }
.item__body:has(select[name$="[completion]"] option[value="card_field"]:checked):has(select[name$="[field]"] option[data-date]:checked):has(select[name$="[validity]"] option:not([value=""]):checked) .cl-due-validity { display: block; }
/* Co se u úkolu hlídá („Platnost povolení končí 12. 10. 2026 — za 18 dní"). */
.task__watch { font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* ==============================================================
   Daňové slevy — prohlášení poplatníka (zadání 29, schválený mockup
   design/e16-danove-slevy/, vzory zdůvodněné v jeho README).

   Pás měsíců `.months`, prohlášení `.decl`, řádek slevy či dítěte `.rl`,
   stav dokladu `.proof` (znak i slovo), volba slevy `.opt-relief`.
   ===================================================================== */
/* --- Pás měsíců roku: které měsíce kryje které prohlášení ------------------ */
.months { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 2px; margin: 0 0 var(--space-2); }
.months__m { position: relative; display: grid; gap: 1px; justify-items: center; padding: 5px 0 4px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-1, 3px); background: var(--c-surface); font-size: var(--fs-micro); color: var(--c-ink-faint); }
.months__m b { font-family: var(--font-mono); font-weight: 500; }
.months__m small { font-size: 9.5px; line-height: 1; min-height: 10px; }
.months__m--on { background: var(--c-brand-soft); border-color: var(--c-brand-line); color: var(--c-brand-ink); }
.months__m--draft { background: repeating-linear-gradient(135deg, var(--c-brand-soft) 0 4px, var(--c-surface) 4px 8px); border-color: var(--c-brand-line); color: var(--c-brand-ink); }
.months__m--taken { background: var(--c-inactive-soft); border-color: var(--c-inactive-line); color: var(--c-inactive-ink); }
.months__m--clash { background: var(--c-expired-soft); border-color: var(--c-expired-line); color: var(--c-expired-ink); }
.months__m--now::after { content: ""; position: absolute; left: 50%; bottom: -5px; width: 6px; height: 6px; margin-left: -3px; border-radius: 50%; background: var(--c-ink); }
.months__legend { display: flex; flex-wrap: wrap; gap: var(--space-3); font-size: var(--fs-micro); color: var(--c-ink-mute); margin-bottom: var(--space-3); }
.months__legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; border: 1px solid var(--c-border); vertical-align: -1px; margin-right: 4px; }
.months__legend .l-on { background: var(--c-brand-soft); border-color: var(--c-brand-line); }
.months__legend .l-draft { background: repeating-linear-gradient(135deg, var(--c-brand-soft) 0 3px, var(--c-surface) 3px 6px); border-color: var(--c-brand-line); }
.months__legend .l-taken { background: var(--c-inactive-soft); border-color: var(--c-inactive-line); }
.months__legend .l-clash { background: var(--c-expired-soft); border-color: var(--c-expired-line); }

/* --- Hlavička jednoho prohlášení ------------------------------------------ */
.decl { border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-surface); margin-bottom: var(--space-4); }
.decl__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--c-border-hair); }
.decl__title { font-size: var(--fs-section); font-weight: 600; margin: 0; }
.decl__meta { display: flex; flex-wrap: wrap; gap: 4px var(--space-4); font-size: var(--fs-control); color: var(--c-ink-mute); width: 100%; }
.decl__meta b { color: var(--c-ink); font-weight: 500; }
.decl__acts { margin-left: auto; display: flex; gap: var(--space-2); flex-wrap: wrap; }
.decl__part { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--c-border-hair); }
.decl__part:last-child { border-bottom: none; }
.decl__part > .section-title { display: flex; gap: var(--space-2); align-items: baseline; }
.decl__part > .section-title small { text-transform: none; letter-spacing: 0; font-weight: 400; }
.decl--past { background: var(--c-canvas); }
.decl--past .decl__head { border-bottom: none; }

/* --- Řádek slevy / dítěte / dokladu --------------------------------------- */
.rl { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--space-3); align-items: center; padding: 8px 0; border-top: 1px dashed var(--c-border-hair); }
.rl:first-of-type { border-top: none; }
.rl__name { font-weight: 500; }
.rl__law { font-family: var(--font-mono); font-size: 10.5px; color: var(--c-ink-faint); margin-left: 4px; }
.rl__meta { grid-column: 1; display: flex; flex-wrap: wrap; gap: 3px var(--space-3); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.rl__meta b { color: var(--c-ink); font-weight: 500; }
.rl__amt { grid-row: 1 / span 2; grid-column: 2; text-align: right; font-family: var(--font-mono); font-size: var(--fs-control); }
.rl__amt small { display: block; font-family: var(--font-sans); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.rl__acts { grid-column: 1 / -1; display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: 4px; }
.rl--attn { background: linear-gradient(90deg, var(--c-soon-soft), transparent 70%); margin: 0 calc(-1 * var(--space-4)); padding-left: var(--space-4); padding-right: var(--space-4); }

/* Doklad jako drobný štítek s ikonou — stav nese znak i slovo, ne jen barva. */
.proof { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-micro); padding: 1px 7px; border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-surface); color: var(--c-ink-mute); white-space: nowrap; }
.proof::before { font-family: var(--font-mono); }
.proof--ok { border-color: var(--c-ok-line); background: var(--c-ok-soft); color: var(--c-ok-ink); }
.proof--ok::before { content: "✓"; }
.proof--missing { border-color: var(--c-soon-line); background: var(--c-soon-soft); color: var(--c-soon-ink); }
.proof--missing::before { content: "△"; }
.proof--expired { border-color: var(--c-expired-line); background: var(--c-expired-soft); color: var(--c-expired-ink); }
.proof--expired::before { content: "✕"; }
.proof--none::before { content: "—"; }
a.proof { text-decoration: none; }
a.proof:hover { text-decoration: underline; }

/* Informativní součet (skutečný výpočet dělá mzda). */
.sum { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); align-items: baseline; padding: var(--space-2) var(--space-4); background: var(--c-sunken); border-top: 1px solid var(--c-border-hair); font-size: var(--fs-control); border-radius: 0 0 var(--radius-3) var(--radius-3); }
.sum b { font-family: var(--font-mono); font-weight: 600; }
.sum__note { font-size: var(--fs-micro); color: var(--c-ink-mute); flex-basis: 100%; }

/* --- Formulář prohlášení --------------------------------------------------- */
.form-sec { border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-surface); padding: var(--space-4); margin-bottom: var(--space-4); display: grid; gap: var(--space-3); }
.form-sec__title { margin: 0; font-size: var(--fs-section); font-weight: 600; display: flex; gap: var(--space-2); align-items: baseline; }
.form-sec__title .step-num { flex: none; }
.form-sec__lead { margin: 0; font-size: var(--fs-control); color: var(--c-ink-mute); text-wrap: pretty; }
.period { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; }
.period .field { min-width: 140px; }

/* Volba slevy: zaškrtávátko + částka + co zákon žádá doložit. */
.opt-relief { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 2px var(--space-3); align-items: start; padding: var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius-2); }
.opt-relief:has(> input:checked) { border-color: var(--c-brand); background: var(--c-brand-soft); }
.opt-relief:has(> input:disabled) { background: var(--c-canvas); color: var(--c-ink-faint); }
.opt-relief input[type="checkbox"], .opt-relief input[type="radio"] { width: 15px; height: 15px; margin-top: 2px; accent-color: var(--c-brand); }
.opt-relief__name { font-weight: 500; }
.opt-relief__desc { grid-column: 2; font-size: var(--fs-micro); color: var(--c-ink-mute); text-wrap: pretty; }
.opt-relief:has(> input:disabled) .opt-relief__desc { color: var(--c-ink-mute); }
.opt-relief__amt { font-family: var(--font-mono); font-size: var(--fs-control); text-align: right; white-space: nowrap; }
.opt-relief__amt small { display: block; font-family: var(--font-sans); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.opt-relief__extra { grid-column: 2 / -1; display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); align-items: center; margin-top: var(--space-2); }
.opt-relief__why { grid-column: 2 / -1; font-size: var(--fs-micro); color: var(--c-ink-mute); margin-top: 2px; }
.opt-relief__why::before { content: "⊘ "; }
.reliefs { display: grid; gap: var(--space-2); }

.tax-upload { display: inline-flex; align-items: center; gap: var(--space-2); padding: 4px 10px; border: 1px dashed var(--c-border); border-radius: var(--radius-2); font-size: var(--fs-micro); color: var(--c-ink-mute); background: var(--c-surface); }

/* Tabulka dětí ve formuláři: vstupy v buňkách. */
.kids td { vertical-align: middle; }
.kids .input, .kids .select { height: 28px; }
.kids td.kids__proof { white-space: normal; min-width: 180px; }
.kids-wrap { overflow-x: auto; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); }

.small-months { display: inline-flex; gap: 4px; align-items: center; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.small-months .select { height: 26px; width: auto; font-size: var(--fs-micro); padding-right: 22px; }


.choices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.table-wrap--inline { flex: none; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); }
.decl__acts form { display: contents; }
@media (max-width: 640px) {
  .months { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .rl { grid-template-columns: minmax(0, 1fr); }
  .rl__amt { grid-row: auto; grid-column: 1; text-align: left; }
  .opt-relief { grid-template-columns: auto minmax(0, 1fr); }
  .opt-relief__amt { grid-column: 2; text-align: left; }
}

/* Výplata zálohy s podpisem (M5 řez 4, `design/m5-pokladna/4-vyplata.html`).
   Nejdřív telefon: pokladník ho podává zaměstnanci, takže karta je úzká,
   tlačítko potvrzení přes celou šířku a plátno dost vysoké na prst. */
.payout-sign__card { max-width: 560px; margin-inline: auto; display: grid; gap: var(--space-3); }
.payout-sign__amount { display: grid; gap: 2px; padding: var(--space-3); border-radius: var(--radius-2); background: var(--c-brand-soft); }
.payout-sign__value { font-size: 1.75rem; font-weight: 700; color: var(--c-brand-ink); }
.payout-sign__langs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.payout-sign__lang {
  display: inline-flex; align-items: center; height: var(--control-h); padding: 0 10px;
  border: 1px solid var(--c-border); border-radius: var(--radius-2); font-size: var(--fs-control);
  color: var(--c-ink); text-decoration: none;
}
.payout-sign__lang[aria-current="true"] { background: var(--c-brand); border-color: var(--c-brand); color: var(--c-on-brand); font-weight: 600; }
.payout-sign__confirm { margin: 0; padding: var(--space-3); border-left: 3px solid var(--c-brand); background: var(--c-surface); font-size: 1.05rem; }
.payout-sign__pad-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.payout-sign__pad {
  display: block; width: 100%; height: 220px; touch-action: none;
  border: 1px dashed var(--c-border); border-radius: var(--radius-2); background: #fff; cursor: crosshair;
}
.payout-sign__pad[aria-invalid="true"] { border-color: var(--c-expired-line); }
.payout-sign__actions { display: grid; gap: var(--space-2); }
.btn--block { width: 100%; justify-content: center; }
.payout-proof__rows { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px var(--space-3); margin: 0 0 var(--space-3); }
.payout-proof__rows dt { color: var(--c-ink-mute); margin: 0; }
.payout-proof__rows dd { margin: 0; overflow-wrap: anywhere; }
.payout-proof img { display: block; max-width: 100%; max-height: 320px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); background: #fff; }

/* Seznam k výplatě na telefonu: řádek je karta a tlačítka jsou vidět bez
   posouvání do strany — pokladník vyplácí z telefonu v ruce. */
@media (max-width: 720px) {
  .payout-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .payout-table, .payout-table tbody, .payout-table tr, .payout-table td { display: block; width: 100%; }
  .payout-table tr { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-border-hair); }
  .payout-table td { padding: 2px 0; border: 0; text-align: left; max-width: none; white-space: normal; }
  .payout-table td[data-label]::before { content: attr(data-label) ": "; color: var(--c-ink-mute); font-size: var(--fs-micro); }
  .payout-table td:first-child { font-weight: 600; }
  .payout-table td:first-child::before { content: none; }
  .payout-table .table__actions { display: flex; flex-wrap: wrap; gap: var(--space-1); padding-top: var(--space-2); }
  /* Tady tlačítka nesou text, ne ikonu — ikonový tvar akcí tabulky by je ořízl. */
  .payout-table .table__actions .btn { width: auto; height: var(--control-h); padding: 0 var(--space-3); }
}

/* ---------------------------------------------------------------------------
   Mapa obsazenosti (M6, design/m6-ubytovani/2-mapa-a-zapis.html).
   Pokoj nese řádky lůžek a volné lůžko je samo tlačítko (zápis na dvě
   kliknutí). .kcard nese jeden záznam a tažení; tabulka by se na třicet
   pokojů nevešla a na telefonu nerozpadla do karet.
   --------------------------------------------------------------------------- */
.room { padding: 0; display: grid; align-content: start; overflow: hidden; }
.room__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--c-border-hair); }
.room__name { font-weight: 600; }
.room__meta { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.room--off { background: var(--c-sunken); color: var(--c-ink-mute); }
.bed { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; gap: 2px 8px; align-items: center; min-height: var(--control-h); padding: 4px var(--space-3); border-top: 1px solid var(--c-border-hair); font-size: var(--fs-control); }
.room__head + .bed { border-top: 0; }
.bed__note { grid-column: 2 / -1; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.bed--free { width: 100%; background: none; border: 0; border-top: 1px dashed var(--c-border); color: var(--c-brand-ink); font: inherit; font-size: var(--fs-control); text-align: left; cursor: pointer; text-decoration: none; }
.bed--free:hover { background: var(--c-brand-soft); }
.bed--blocked { background: var(--c-pending-soft); }

/* ---------------------------------------------------------------------------
   Zablokovaný účet (zadání 30, B6; návrh E30 `4-zablokovany-ucet.html`).

   Skořápka bez modulů: lišta nese jen logo, přepínač agentur a uživatele,
   obsah je jedna úzká kolona uprostřed. Barvy jsou tokeny stavů — blokace
   je „vypršelý" stav (červená), čekání na spárování „čeká" (modrošedá).
   --------------------------------------------------------------------------- */
.app__topbar--bare .app__logo { border-right: 1px solid var(--c-border); }
.lock-menu { position: relative; }
.lock-menu > summary { display: inline-flex; align-items: center; gap: var(--space-2); }
/* V liště nabídka visí dolů a zarovnaná vpravo — v navigaci vyjíždí nahoru. */
.lock-menu > .account__menu { top: calc(100% + var(--space-1)); bottom: auto; left: auto; right: 0; width: min(272px, calc(100vw - 32px)); }

.lock { max-width: 720px; margin: 0 auto; padding: var(--space-6) var(--space-4); display: grid; gap: var(--space-4); width: 100%; min-width: 0; }
.lock__icon {
  width: 44px; height: 44px; border-radius: var(--radius-3);
  border: 1px solid var(--c-expired-line); background: var(--c-expired-soft); color: var(--c-expired-ink);
  display: grid; place-items: center; font-family: var(--font-mono); font-size: 20px; font-weight: 700;
}
.lock__icon--wait { border-color: var(--c-pending-line); background: var(--c-pending-soft); color: var(--c-pending-ink); }
.lock__title { font-size: var(--fs-page); font-weight: 600; margin: 0; letter-spacing: -.015em; overflow-wrap: anywhere; }
.lock__text { margin: 0; font-size: var(--fs-base); color: var(--c-ink-mute); text-wrap: pretty; }
.lock__text strong { color: var(--c-ink); }
/* Věta o datech se znakem i slovem — barva sama informace není. */
.lock__safe { display: flex; gap: var(--space-2); align-items: center; margin: 0; font-size: var(--fs-control); color: var(--c-ok-ink); font-weight: 500; }
.lock__safe::before { content: "✓"; font-family: var(--font-mono); font-weight: 700; }
.lock__list { margin: 0; padding-left: 18px; font-size: var(--fs-control); color: var(--c-ink-mute); display: grid; gap: 2px; }
.lock__total { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); padding: var(--space-3) 0 0; border-top: 1px solid var(--c-border); flex-wrap: wrap; }
.lock__sum { font-family: var(--font-mono); font-size: 22px; font-weight: 600; }
.lock__table { flex: none; border: 0; }
.lock__transfer { display: grid; gap: var(--space-2); }
.lock__transfer > summary { cursor: pointer; }
/* Jediná karta pod sebou (čeká na spárování) nemá stát v půlce šířky. */
.lock .split:not(:has(> :nth-child(2))) { grid-template-columns: 1fr; }

.people { margin: 0; padding: var(--space-3); list-style: none; display: grid; gap: var(--space-2); }
.people li { display: flex; gap: var(--space-3); align-items: baseline; flex-wrap: wrap; font-size: var(--fs-control); }
.people b { font-weight: 600; }
.people a { overflow-wrap: anywhere; }

/* Faktury: číslo dokladu neproporcionálně, částky doprava, druhý řádek v buňce. */
.inv-num { font-family: var(--font-mono); font-size: var(--fs-control); white-space: nowrap; }
.table__cell--amount { text-align: right; font-family: var(--font-mono); white-space: nowrap; }
.table__sub { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); line-height: 1.3; }

/* Platební údaje k okopírování: popisek, hodnota, (částka), Kopírovat. */
.bank { display: grid; gap: var(--space-2); }
.bank__row { display: grid; grid-template-columns: minmax(120px, max-content) minmax(0, 1fr) auto auto; gap: var(--space-2); align-items: center; }
.bank__k { font-size: var(--fs-control); color: var(--c-ink-mute); }
.bank__v { font-family: var(--font-mono); min-width: 0; }
.bank__amount { font-family: var(--font-mono); font-size: var(--fs-control); white-space: nowrap; }
.bank__row:not(:has(.bank__amount)) .bank__copy { grid-column: 4; }

@media (max-width: 720px) {
  .lock { padding: var(--space-4); }
  /* Na telefonu je faktura karta: popisek nad hodnotou, nic nejede do strany. */
  .lock__table .table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .lock__table .table, .lock__table .table tbody, .lock__table .table tr, .lock__table .table td { display: block; width: 100%; }
  .lock__table .table tr { padding: var(--space-2) 0; border-bottom: 1px solid var(--c-border-hair); }
  .lock__table .table td { padding: 2px 0; border: 0; text-align: left; max-width: none; white-space: normal; }
  .lock__table .table td[data-label]::before { content: attr(data-label) ": "; color: var(--c-ink-mute); font-size: var(--fs-micro); font-family: var(--font-sans); }
  .bank__row { grid-template-columns: minmax(0, 1fr) auto; }
  .bank__row .bank__k { grid-column: 1 / -1; }
  .bank__row:not(:has(.bank__amount)) .bank__copy { grid-column: auto; }
  .bank__row .bank__amount { grid-column: 1 / -1; order: 1; }

  /* Pás stavu na telefonu: tlačítko pod text, jinak se text zúží na tři
     slova na řádek (návrh E30, README „Nové vzory"). */
  .plan-strip { flex-wrap: wrap; }
  .plan-strip > .btn { flex: 1 1 100%; justify-content: center; white-space: normal; min-width: 0; }
}

/* ---------------------------------------------------------------------------
   Účet a předplatné — faktury, Zaplatit, způsob platby (zadání 30, F6a;
   návrh E30 `1-ucet-a-predplatne.html`, `2-zaplatit.html`, nové vzory
   z `e30.css`, zdůvodněné v README návrhu).
   --------------------------------------------------------------------------- */

/* Dva nové stavy faktury, oba se znakem — barva sama informace není.
   Dobropis ↺, čeká na vystavení … (doklad ještě neexistuje). */
.status--credit { background: var(--c-inactive-soft); border-color: var(--c-inactive-line); color: var(--c-inactive-ink); }
.status--credit::before { content: "↺"; }
.status--draft { background: var(--c-surface); border-style: dashed; border-color: var(--c-soon-line); color: var(--c-soon-ink); }
.status--draft::before { content: "…"; }

/* Faktura bez čísla (čeká na vystavení) a číslo jako odkaz do detailu. */
.inv-num--none { color: var(--c-ink-faint); font-family: var(--font-sans); font-style: italic; }
a.inv-num { font-weight: 500; }
.table th.table__cell--amount { text-align: right; }

/* Tabulka faktur se na 1440 px nesmí schovat za vodorovný posun (v mockupu
   se to jednou stalo). Rozhoduje obsah, ne nová třída: buňka se stavem nebo
   s druhým řádkem (`.table__sub`) se smí zalomit, ostatní zůstávají
   jednořádkové. Na telefonu platí datagrid s posunem doprava jako všude. */
.table td:has(> .table__sub), .table td:has(> .status) { white-space: normal; height: auto; padding-top: 6px; padding-bottom: 6px; }
.table td:has(> .status) .status { white-space: normal; }

/* Detail faktury: položky a součet. Vlastní malá tabulka, ne `.table` —
   řádků je pár a na telefonu se mají zalomit, ne posouvat. */
.inv-lines { width: 100%; border-collapse: collapse; font-size: var(--fs-control); }
.inv-lines th { text-align: left; font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); padding: 6px 0; border-bottom: 1px solid var(--c-border); }
.inv-lines td { padding: 7px 0; border-bottom: 1px solid var(--c-border-hair); vertical-align: top; }
.inv-lines td + td, .inv-lines th + th { padding-left: var(--space-3); }
.inv-lines .num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.inv-lines tfoot td { border-bottom: none; font-weight: 600; padding-top: var(--space-2); font-size: var(--fs-base); }
.inv-lines__kind { display: block; font-size: var(--fs-micro); color: var(--c-ink-mute); }

/* Daňové zacházení — věta, kterou nese faktura, proto doslovně a v rámečku. */
.tax { display: flex; gap: var(--space-2); align-items: flex-start; padding: var(--space-2) var(--space-3); border-left: 3px solid var(--c-pending-line); background: var(--c-pending-soft); font-size: var(--fs-control); border-radius: 0 var(--radius-2) var(--radius-2) 0; }
.tax__k { font-weight: 600; white-space: nowrap; }

/* Zmrazené údaje odběratele (a dodavatel vedle nich). */
.frozen { border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); padding: var(--space-2) var(--space-3); font-size: var(--fs-control); background: var(--c-canvas); min-width: 0; overflow-wrap: anywhere; }
.frozen__k { font-size: var(--fs-micro); color: var(--c-ink-mute); display: flex; gap: 6px; align-items: center; margin-bottom: 2px; }
.frozen--snapshot .frozen__k::before { content: "❄"; font-size: 10px; }

/* Uložená karta: značka, poslední čtyři číslice a platnost. Nic víc (B14). */
.paycard { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; padding: var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius-3); background: var(--c-surface); }
.paycard__brand { width: 44px; height: 30px; border-radius: var(--radius-2); border: 1px solid var(--c-border); background: var(--c-sunken); display: grid; place-items: center; font-size: 10px; font-weight: 700; letter-spacing: .04em; color: var(--c-pending-ink); flex: none; text-transform: uppercase; }
.paycard__num { font-family: var(--font-mono); font-size: 15px; font-weight: 600; }
.paycard__meta { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.paycard__acts { margin-left: auto; display: flex; gap: var(--space-2); flex-wrap: wrap; }
/* Karta, jejíž stržení selhalo, se pozná podle stavu v ní — ne podle třídy. */
.paycard:has(.status--expired) { border-color: var(--c-expired-line); box-shadow: inset 3px 0 0 var(--c-expired-ink); }
@media (max-width: 520px) { .paycard__acts { margin-left: 0; width: 100%; } }

/* Dialog Zaplatit: dvě rovnocenné cesty platby, karta vlevo, převod vpravo;
   na telefonu pod sebou. Převod není „méně" platba. */
.pay-dialog { max-width: 820px; }
/* Dvě cesty platby vedle sebe, jen když se obě vejdou: sloupec pod ~22 rem
   usekává číslo účtu a VS v polích ke kopírování. Rozhoduje šířka dialogu,
   ne okna — vedle navigace a na tabletu je dialog užší než obrazovka. */
.paths { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr)); gap: var(--space-3); }
.path { border: 1px solid var(--c-border); border-radius: var(--radius-3); padding: var(--space-3); display: grid; gap: var(--space-3); align-content: start; background: var(--c-surface); min-width: 0; }
.path__head { display: flex; align-items: center; gap: var(--space-2); }
.path__title { font-weight: 600; font-size: var(--fs-section); }
.path__note { font-size: var(--fs-micro); color: var(--c-ink-mute); margin: 0; }
.path form { display: grid; gap: var(--space-2); }
.path .btn--primary { justify-self: stretch; justify-content: center; }
.payto { font-size: var(--fs-micro); color: var(--c-ink-mute); display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.payto__sum { font-family: var(--font-mono); font-size: 20px; font-weight: 600; color: var(--c-ink); }

/* QR platba. Kód se kreslí na serveru jako SVG; podklad je vždy bílý a moduly
   černé — banka ho musí přečíst i z tmavého režimu. */
.qr { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.qr__img { width: 132px; height: 132px; flex: none; padding: 4px; background: #fff; border: 1px solid var(--c-border); border-radius: var(--radius-2); }
.qr__img svg { width: 100%; height: 100%; display: block; }
.qr__img svg path { fill: #000; }
.qr__text { font-size: var(--fs-micro); color: var(--c-ink-mute); flex: 1 1 160px; min-width: 0; }

/* Předání podpisu na tablet QR kódem (M7-P41). Kód skenuje tablet z obrazovky
   počítače, ne telefon z papíru — proto větší než u platby a s tichou zónou.
   Na úzké obrazovce jde text pod kód. */
.handoff { display: flex; flex-direction: column; gap: var(--space-3); }
.handoff__state { margin: 0; }
.handoff__scan { display: flex; gap: var(--space-4); align-items: center; flex-wrap: wrap; }
.handoff__qr { width: 260px; height: auto; aspect-ratio: 1; max-width: 100%; padding: 12px; }
.handoff__text { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.handoff__text > p { margin: 0; }

/* =====================================================================
   PLATBY ZA JOBSON, F6b — aktivace předplatného, ukončení, nákupy
   (návrh E30 `3-aktivace.html`, `1-ucet-a-predplatne.html`; vzory
   převzaté z `design/e30-platby/e30.css`).
   ===================================================================== */

/* Formulář aktivace po krocích: tarif, odběratel, způsob platby. */
.step { display: grid; gap: var(--space-3); padding-bottom: var(--space-4); border-bottom: 1px solid var(--c-border-hair); }
.step + .step { padding-top: var(--space-4); }
.step:last-child { border-bottom: 0; }
.step__head { display: flex; align-items: center; gap: var(--space-2); }
.step__title { font-weight: 600; font-size: var(--fs-section); margin: 0; }

/* Volba tarifu je celá nabídka jako popisek radia — vybraná nese barvu
   podle stavu radia, ne podle třídy. */
.offers--pick { margin: 0; }
.offers--pick .offer { cursor: pointer; }
.offers--pick .offer:has(input:checked) { border-color: var(--c-brand); background: var(--c-brand-soft); }

/* Výsledek ověření DIČ ve VIES: znak, slovo i barva (barva sama nestačí). */
.vies { display: flex; gap: var(--space-2); align-items: flex-start; font-size: var(--fs-meta); padding: 6px var(--space-2); border-radius: var(--radius-2); }
.vies::before { font-family: var(--font-mono); font-weight: 700; }
.vies--ok { background: var(--c-ok-soft); color: var(--c-ok-ink); }
.vies--ok::before { content: "✓"; }
.vies--fail { background: var(--c-expired-soft); color: var(--c-expired-ink); }
.vies--fail::before { content: "✕"; }
.vies--wait { background: var(--c-sunken); color: var(--c-ink-mute); }
.vies--wait::before { content: "◷"; }
.vies-row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.vies-row .input { flex: 1 1 200px; }

/* Souhrn „co a kdy zaplatíte" vpravo. */
.sum { display: grid; gap: var(--space-2); }
.sum__row { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--fs-control); }
.sum__row b { font-family: var(--font-mono); font-weight: 600; white-space: nowrap; }
.sum__big { font-size: var(--fs-section); font-weight: 600; margin: 0; }
.sum__when { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; font-size: var(--fs-control); }
.sum__when li { display: grid; grid-template-columns: 64px 1fr; gap: var(--space-2); }
.sum__when time { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); padding-top: 1px; }

/* Souhrn se přepíná podle zvoleného tarifu **stavem radia** (`:has`),
   ne skriptem: bez JavaScriptu platí to, co je zaškrtnuté ze serveru. */
.editor .sum[data-tariff] { display: none; }
.editor:has(input[name="tariff"][value="start"]:checked) .sum[data-tariff="start"],
.editor:has(input[name="tariff"][value="power"]:checked) .sum[data-tariff="power"],
.editor:has(input[name="tariff"][value="power_x2"]:checked) .sum[data-tariff="power_x2"],
.editor:has(input[name="tariff"][value="power_x5"]:checked) .sum[data-tariff="power_x5"] { display: grid; }

/* Věta o kartě a souhlas se strháváním platí jen pro platbu kartou. */
.editor:has(input[name="payment"][value="transfer"]:checked) [data-when="card"] { display: none; }
.editor:has(input[name="payment"][value="card"]:checked) [data-when="transfer"] { display: none; }

/* Dialog s tabulkou vratky je širší — šířku určuje obsah (`CLAUDE.md`). */
@media (min-width: 721px) {
  .dialog:has(.inv-lines) { width: min(640px, calc(100vw - 2 * var(--space-4))); }
}

/* Nabídka tarifu s formulářem akce: tlačítko a věta o dopadu pod sebou,
   stejně jako přímé potomky nabídky. */
.offer > form { display: grid; gap: var(--space-2); justify-items: start; }

/* ===================================================================== */
/* Správa provozovatele (/admin, zadání 30 B12; návrh E30
   `5-admin-provozovatel.html`, `6-admin-agentury.html`, README bod 17).
   Jiná zóna, jiná skořápka: tmavý pruh nad lištou, aby nikdo nezaměnil
   superadmin za agenturu. Barvy jsou tokeny inkoustu a plochy, jen
   obrácené — žádná nová barva. Převzaté z `e30.css` beze změny. */
.op-band { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; padding: 6px var(--space-4); background: var(--c-ink); color: var(--c-surface); font-size: var(--fs-control); position: sticky; top: 0; z-index: 21; height: 30px; white-space: nowrap; overflow: hidden; }
.op-band__name { font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-size: var(--fs-micro); }
.op-band__who { margin-left: auto; opacity: .8; font-size: var(--fs-micro); }
.op-band ~ .app .app__topbar { top: 30px; }
.op-band ~ .app .detail__aside--sticky { top: calc(var(--topbar-h) + 30px); }
@media (max-width: 720px) { .op-band__what, .op-band__who { display: none; } }
.app__nav--op .app__nav-item[aria-current="page"] { background: var(--c-sunken); color: var(--c-ink); box-shadow: inset 3px 0 0 var(--c-ink); }

/* Každý ruční zásah superadmina se zapíše do auditu — a říká to předem. */
.audit { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-micro); color: var(--c-ink-mute); }
.audit::before { content: "⎘"; font-family: var(--font-mono); }

/* Stav spojení se službou (Fakturoid, Stripe). */
.conn { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1px; background: var(--c-border-hair); border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); overflow: hidden; margin-bottom: var(--space-3); }
.conn__item { background: var(--c-surface); padding: var(--space-2) var(--space-3); display: grid; gap: 2px; min-width: 0; }
.conn__k { font-size: var(--fs-micro); color: var(--c-ink-mute); }
.conn__v { overflow-wrap: anywhere; }

/* Změny v auditu: pole · stará → nová, pod sebou. */
.changes { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; font-size: var(--fs-micro); }
.changes li { overflow-wrap: anywhere; }
.changes b { font-weight: 600; }

/* Důsledek změny daňového režimu platí jen pro zvolený režim — stav
   výběru (`:has`), ne skript: bez JavaScriptu platí, co je vybrané ze
   serveru. */
[data-when-regime] { display: none; }
form:has(select[name="regime"] option[value="vat_payer"]:checked) [data-when-regime="vat_payer"],
form:has(select[name="regime"] option[value="identified_person"]:checked) [data-when-regime="identified_person"],
form:has(select[name="regime"] option[value="non_payer"]:checked) [data-when-regime="non_payer"] { display: flex; }

/* Návrh od osoby (zadání 29 § 9, DS22) — modře odlišený od toho, co agentura
   už vede; nic z něj není zapsané, dokud ho člověk nepřijme. */
.decl--proposal { border-color: var(--c-brand-line); }
.decl--proposal > .decl__head { background: var(--c-brand-soft); border-radius: var(--radius-3) var(--radius-3) 0 0; }
.decl__reject { display: grid; gap: var(--space-2); background: var(--c-canvas); border-radius: 0 0 var(--radius-3) var(--radius-3); }
.select--inline { width: auto; height: 26px; font-size: var(--fs-micro); padding-block: 0; }
.field--narrow { max-width: 320px; }

/* =====================================================================
   E17 · Přehledy — nástěnka, rám boxu, režim úprav, katalog
   (zadání 31, návrh design/e17-prehledy; proč nestačí existující vzory
   stojí v README návrhu).
   ===================================================================== */


/* ---------------------------------------------------------------------
   Nástěnka: tok s pořadím (P2). Sloupce řídí šířka nástěnky, ne okna —
   container query, takže se chová stejně se sbalenou i rozbalenou navigací.
   Box, který se do zbytku řádku nevejde, začne na dalším řádku: pořadí
   uživatele má přednost před zaplněním mezery (žádné `dense`).
   --------------------------------------------------------------------- */
.dash-wrap { container-type: inline-size; padding: var(--space-4); }
.dash { display: grid; gap: var(--space-4); grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: 132px; }
.box { grid-column: span 1; grid-row: span 2; }
.box--m  { grid-column: span 2; }
.box--l  { grid-column: span 3; }
.box--xl { grid-column: span 4; }
.box--tall { grid-row: span 4; }

@container (max-width: 900px) {
  .dash { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .box--l, .box--xl { grid-column: span 2; }
}
@container (max-width: 520px) {
  .dash { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .box, .box--m, .box--l, .box--xl { grid-column: span 1; }
  .box, .box--tall { grid-row: auto; }
  .box__body { max-height: 420px; }
}

/* Rám boxu — kreslí nástěnka, tělo dodává modul (§ 9). */
.box { display: flex; flex-direction: column; min-width: 0; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-3); box-shadow: var(--shadow-1); overflow: hidden; }
.box__head { display: flex; align-items: center; gap: var(--space-2); padding: 9px var(--space-3) 7px; border-bottom: 1px solid var(--c-border-hair); min-height: 40px; }
.box__icon { width: 16px; height: 16px; flex: none; color: var(--c-ink-mute); }
.box__title { margin: 0; font-size: var(--fs-control); font-weight: 600; line-height: var(--lh-tight); color: var(--c-ink); text-wrap: balance; }
.box__title a { color: inherit; text-decoration: none; }
.box__title a:hover { text-decoration: underline; }
.box__count { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--c-ink-mute); }
.box__count--danger { color: var(--c-expired-ink); font-weight: 600; }
.box__spacer { flex: 1; }
.box__tool { width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent; border-radius: var(--radius-1); background: none; color: var(--c-ink-mute); cursor: pointer; font: inherit; }
.box__tool:hover { background: var(--c-sunken); color: var(--c-ink); }
.box__tool:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.box__body { flex: 1; min-height: 0; overflow: auto; padding: var(--space-3); }
.box__body:has(> .mini-list), .box__body:has(> .table) { padding: 0; }
.box__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: 7px var(--space-3); border-top: 1px solid var(--c-border-hair); font-size: var(--fs-meta); }
.box__foot a { color: var(--c-brand-ink); text-decoration: none; font-weight: 500; }
.box__foot a:hover { text-decoration: underline; }
.box__meta { color: var(--c-ink-faint); }

/* Stavy boxu (§ 7.2). Stav obsahu se pozná podle obsahu (`:has`), ne třídou. */
.box__state { display: grid; gap: 6px; justify-items: center; align-content: center; text-align: center; height: 100%; min-height: 120px; padding: var(--space-3); }
.box__state-icon { width: 34px; height: 34px; 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: 16px; color: var(--c-ink-mute); }
.box__state-title { font-size: var(--fs-control); font-weight: 600; }
.box__state-text { font-size: var(--fs-meta); color: var(--c-ink-mute); max-width: 36ch; text-wrap: pretty; }
.box__state--ok .box__state-icon { color: var(--c-ok-ink); border-color: var(--c-ok-line); background: var(--c-ok-soft); }
.box__state--error .box__state-icon { color: var(--c-expired-ink); border-color: var(--c-expired-line); background: var(--c-expired-soft); }
.box__state--settings .box__state-icon { color: var(--c-soon-ink); border-color: var(--c-soon-line); background: var(--c-soon-soft); }
.box:has(.box__state--error) { border-color: var(--c-expired-line); }
.box__skel { display: grid; gap: 9px; }
.box__skel .skeleton:nth-child(2n) { width: 78%; }
.box__skel .skeleton:nth-child(3n) { width: 62%; }

/* Režim úprav (P14). */
.dash--editing .box { box-shadow: none; border-style: dashed; border-color: var(--c-brand-line); }
.dash--editing .box__body { pointer-events: none; opacity: .72; }
.box__handle { cursor: grab; letter-spacing: -2px; font-family: var(--font-mono); }
.box__resize { position: absolute; right: 3px; bottom: 3px; width: 14px; height: 14px; cursor: nwse-resize; color: var(--c-brand); }
.dash--editing .box { position: relative; }
.box--dragging { opacity: .45; }
.box--drop-before { box-shadow: -4px 0 0 0 var(--c-brand) !important; }
.box--new { border-color: var(--c-brand) !important; border-style: solid !important; box-shadow: 0 0 0 3px var(--c-brand-soft) !important; }
.box--hidden { background: var(--c-canvas); }
.box--hidden .box__title { color: var(--c-ink-mute); }
.box__hidden-note { font-size: var(--fs-meta); color: var(--c-ink-mute); }
.box__size { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-brand-ink); background: var(--c-brand-soft); border: 1px solid var(--c-brand-line); border-radius: var(--radius-1); padding: 0 5px; }

.edit-bar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: var(--space-3) var(--space-4) 0; padding: 8px var(--space-3); border: 1px solid var(--c-brand-line); background: var(--c-brand-soft); border-radius: var(--radius-2); font-size: var(--fs-control); }
.edit-bar__text { color: var(--c-brand-ink); flex: 1; min-width: 20ch; }

/* Menu boxu ⋯ — otevřené jen v mockupu staticky. */
.box-menu { position: absolute; top: 38px; right: 8px; z-index: 5; width: 232px; padding: 6px; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-2); box-shadow: var(--shadow-2); display: grid; gap: 1px; font-size: var(--fs-control); }
.box-menu__label { padding: 6px 8px 2px; font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); text-transform: uppercase; letter-spacing: .04em; }
.box-menu__item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 0; background: none; border-radius: var(--radius-1); text-align: left; font: inherit; color: var(--c-ink); cursor: pointer; }
.box-menu__item:hover { background: var(--c-sunken); }
.box-menu__item--danger { color: var(--c-expired-ink); }
.box-menu__item[aria-disabled="true"] { color: var(--c-ink-faint); cursor: not-allowed; }
.box-menu__sep { height: 1px; background: var(--c-border-hair); margin: 4px 0; }
.box-menu__sizes { display: flex; gap: 4px; padding: 2px 8px 6px; }
.box-menu__sizes .btn { height: 26px; padding: 0 8px; font-family: var(--font-mono); font-size: var(--fs-meta); }
.box-menu__sizes .btn[aria-pressed="true"] { background: var(--c-brand); border-color: var(--c-brand); color: var(--c-on-brand); }

/* Katalog boxů — boční panel. */
.catalog { position: fixed; top: var(--topbar-h); right: 0; bottom: 0; z-index: 20; width: min(420px, 100vw); display: flex; flex-direction: column; background: var(--c-surface); border-left: 1px solid var(--c-border); box-shadow: var(--shadow-2); }
.catalog__head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--c-border); }
.catalog__title { margin: 0; font-size: var(--fs-section); font-weight: 600; flex: 1; }
.catalog__search { padding: var(--space-3) var(--space-4) 0; }
.catalog__body { flex: 1; overflow: auto; padding: var(--space-2) var(--space-4) var(--space-4); }
.catalog__cat { margin: var(--space-4) 0 var(--space-2); font-size: var(--fs-micro); font-weight: 600; color: var(--c-ink-mute); text-transform: uppercase; letter-spacing: .05em; }
.catalog__item { display: grid; grid-template-columns: 32px 1fr auto; gap: 4px var(--space-3); align-items: start; padding: 10px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); margin-bottom: 6px; }
.catalog__item:hover { border-color: var(--c-brand-line); background: var(--c-brand-soft); }
.catalog__item-icon { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-2); background: var(--c-sunken); color: var(--c-ink-mute); }
.catalog__item-name { font-weight: 600; font-size: var(--fs-control); }
.catalog__item-desc { grid-column: 2; font-size: var(--fs-meta); color: var(--c-ink-mute); text-wrap: pretty; }
.catalog__item-sizes { grid-column: 2; font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-faint); }
.catalog__item .btn { grid-row: 1 / span 2; grid-column: 3; align-self: center; }
.catalog__item-on { grid-column: 3; font-size: var(--fs-micro); color: var(--c-ok-ink); }
.catalog__foot { padding: var(--space-3) var(--space-4); border-top: 1px solid var(--c-border); font-size: var(--fs-meta); color: var(--c-ink-mute); }

/* Lišta „Box odebrán · Vrátit“. */
.undo { position: fixed; left: 50%; bottom: var(--space-5); transform: translateX(-50%); z-index: 30; display: flex; align-items: center; gap: var(--space-3); padding: 8px 8px 8px var(--space-4); background: var(--c-ink); color: var(--c-surface); border-radius: var(--radius-2); box-shadow: var(--shadow-2); font-size: var(--fs-control); }
.undo .btn { background: transparent; border-color: oklch(1 0 0 / .35); color: var(--c-surface); }
.undo__timer { font-family: var(--font-mono); font-size: var(--fs-micro); opacity: .7; }


/* ---------------------------------------------------------------------
   Obsah těl boxů — vzory, ze kterých si moduly skládají šablony těla.
   --------------------------------------------------------------------- */
/* Seznam s řádky: osoba · co · termín. */
.mini-list { list-style: none; margin: 0; padding: 0; }
.mini-list__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--space-2); align-items: center; padding: 7px var(--space-3); border-bottom: 1px solid var(--c-border-hair); font-size: var(--fs-control); }
.mini-list__row:last-child { border-bottom: 0; }
.mini-list__row:hover { background: var(--c-sunken); }
.mini-list__main { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-list__main a { color: var(--c-ink); font-weight: 500; text-decoration: none; }
.mini-list__main a:hover { text-decoration: underline; }
.mini-list__sub { grid-column: 1; font-size: var(--fs-meta); color: var(--c-ink-mute); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-list__side { grid-row: 1 / span 2; grid-column: 2; display: flex; align-items: center; gap: 6px; }
.mini-list__group { padding: 6px var(--space-3) 4px; font-size: var(--fs-micro); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--c-ink-mute); background: var(--c-canvas); border-bottom: 1px solid var(--c-border-hair); }
.mini-list__group--danger { color: var(--c-expired-ink); background: var(--c-expired-soft); }
.mini-list__check { width: 22px; height: 22px; border: 1px solid var(--c-border); border-radius: var(--radius-1); background: var(--c-surface); cursor: pointer; font-size: 12px; color: var(--c-ok-ink); }
.mini-list__check:hover { border-color: var(--c-ok-line); background: var(--c-ok-soft); }

/* Sekce fronty s počty (box Co vyřešit). */
.sections { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; padding: var(--space-3); border-bottom: 1px solid var(--c-border-hair); }
.sections__item { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; padding: 6px 9px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); text-decoration: none; color: var(--c-ink); font-size: var(--fs-meta); }
.sections__item:hover { border-color: var(--c-brand-line); background: var(--c-brand-soft); }
.sections__n { font-family: var(--font-mono); font-weight: 600; font-size: var(--fs-control); }
.sections__item:has(.sections__n--danger) { border-color: var(--c-expired-line); background: var(--c-expired-soft); }
.sections__n--danger { color: var(--c-expired-ink); }

/* Metriky: velké číslo + popisek + srovnání. */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: var(--space-3); }
.metric { display: grid; gap: 2px; align-content: start; text-decoration: none; color: inherit; }
.metric__value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 24px; font-weight: 600; letter-spacing: -.02em; line-height: 1.1; color: var(--c-ink); }
.metric__label { font-size: var(--fs-meta); color: var(--c-ink-mute); text-wrap: pretty; }
.metric__delta { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--c-ink-mute); }
.metric__delta--up { color: var(--c-ok-ink); }
.metric__delta--down { color: var(--c-expired-ink); }

/* Počítadlo — jedno číslo přes celý box (S). */
.counter { display: grid; align-content: center; justify-items: start; gap: 4px; height: 100%; text-decoration: none; color: inherit; }
.counter__value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 44px; font-weight: 600; line-height: 1; letter-spacing: -.03em; }
.counter__value--danger { color: var(--c-expired-ink); }
.counter__label { font-size: var(--fs-control); color: var(--c-ink-mute); text-wrap: pretty; }

/* Vodorovné pruhy (trychtýř, zdroje). */
.bars { display: grid; gap: 7px; }
.bars__row { display: grid; grid-template-columns: minmax(80px, 30%) 1fr 5ch; gap: var(--space-2); align-items: center; font-size: var(--fs-meta); }
.bars__label { color: var(--c-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bars__track { height: 10px; background: var(--c-sunken); border-radius: 5px; overflow: hidden; }
.bars__fill { display: block; height: 100%; background: var(--c-brand); border-radius: 5px; }
.bars__n { font-family: var(--font-mono); text-align: right; color: var(--c-ink-mute); }

/* Tabulka uvnitř boxu je kompaktnější než na obrazovce. */
.box .table td { height: 34px; }
.box .table th { height: 30px; }

/* Průběh — pruh v boxu První kroky. */
.progress { height: 6px; background: var(--c-sunken); border-radius: 3px; overflow: hidden; margin-bottom: var(--space-3); }
.progress__fill { display: block; height: 100%; background: var(--c-ok-line); }
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-2); }
.step { display: grid; grid-template-columns: 24px 1fr; gap: 2px 8px; padding: 9px; border: 1px solid var(--c-border-hair); border-radius: var(--radius-2); font-size: var(--fs-meta); }
.step__n { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: var(--fs-micro); border: 1px solid var(--c-border); color: var(--c-ink-mute); }
.step__title { font-weight: 600; font-size: var(--fs-control); color: var(--c-ink); }
.step__text { grid-column: 2; color: var(--c-ink-mute); }
.step__action { grid-column: 2; margin-top: 4px; }
.step:has(.step__n--done) { background: var(--c-ok-soft); border-color: var(--c-ok-line); }
.step:has(.step__n--done) .step__title { text-decoration: line-through; text-decoration-color: var(--c-ok-line); }
.step__n--done { background: var(--c-ok-line); border-color: var(--c-ok-line); color: var(--c-surface); }

/* Rychlé akce. */
.quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--space-2); }
.quick .btn { justify-content: flex-start; width: 100%; }


/* Rám boxu je Turbo Frame uvnitř sekce — musí se roztáhnout jako sekce. */
.box__frame { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.box__head .app__nav-icon { width: 16px; height: 16px; flex: none; color: var(--c-ink-mute); }
.box__state-title, .box__state-text { margin: 0; }
.dash-notices { padding: 0 var(--space-4); }
.dash-notices:empty { display: none; }
.dash-notices .notice { margin: var(--space-3) 0 0; }
.dash-notices .notice form { margin-left: auto; }
.edit-bar__text { margin: 0; }

/* Menu ⋯ je nativní <details>, aby se otevřelo i bez JavaScriptu. */
.box-menu-wrap { position: relative; }
.box-menu-wrap > summary { list-style: none; }
.box-menu-wrap > summary::-webkit-details-marker { display: none; }
.box-menu-wrap .box-menu { top: 30px; right: 0; }
.box-menu form { display: contents; }
.box-menu form.box-menu__sizes { display: flex; }
a.box-menu__item { text-decoration: none; }

/* Katalog na telefonu přes celou šířku, pod ním nic neujíždí. */
.catalog__item[hidden], .catalog__cat[hidden] { display: none; }
.undo form { display: contents; }
.dash--editing .box { overflow: visible; }
.step__help { margin: var(--space-3) 0 0; font-size: var(--fs-meta); color: var(--c-ink-mute); }
.mini-list__side form { display: contents; }
.perf { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-4); }
.perf__title { margin: 0 0 var(--space-2); font-size: var(--fs-meta); font-weight: 600; color: var(--c-ink-mute); }
/* Měřidla statistik v boxu: menší číslo, bez definic navíc pod sebou. */
.box .meters { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

/* --- Co teď: další krok podpisu (M7-P44, M7-ux-návrh § 11) ---------------
   Notice oznamuje stav; tohle říká, co udělat — jedna věta a tlačítka, první
   je hlavní. Značková barva, protože je to výzva k akci, ne varování. Hotový
   dokument přepne na rodinu „ok". Na úzké obrazovce se tlačítka lámou pod
   větu na celou šířku, ne vedle ní do sloupce o dvou slovech. */
.next-step { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3) var(--space-4); padding: var(--space-3) var(--space-4); border: 1px solid var(--c-brand-line); background: var(--c-brand-soft); border-radius: var(--radius-2); margin-bottom: var(--space-2); }
.next-step--done { border-color: var(--c-ok-line); background: var(--c-ok-soft); }
.next-step__body { flex: 1 1 320px; min-width: 0; display: grid; gap: 2px; }
.next-step__label { margin: 0; font-size: var(--fs-micro); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--c-brand-ink); }
.next-step--done .next-step__label { color: var(--c-ok-ink); }
.next-step__text { margin: 0; font-size: var(--fs-section); }
.next-step__why { margin: 0; font-size: var(--fs-meta); color: var(--c-ink-mute); }
.next-step__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.next-step__path { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-size: var(--fs-meta); color: var(--c-ink-mute); margin-bottom: var(--space-4); }
@media (max-width: 640px) {
    .next-step__actions { width: 100%; }
    .next-step__actions > .btn, .next-step__actions > form, .next-step__actions > form .btn { flex: 1 1 100%; width: 100%; white-space: normal; min-width: 0; }
}

/* Technické údaje důkazu podpisu (zařízení, IP) — sbalené pod shrnutím, ať
   syrový řetězec prohlížeče nezakrývá, kdo a jak podepsal (M7-P2). */
.evidence-tech { margin: var(--space-2) 0 var(--space-3); font-size: var(--fs-meta); }
.evidence-tech > summary { cursor: pointer; color: var(--c-ink-mute); }
.evidence-tech > summary:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.evidence-tech__line { margin: var(--space-1) 0 0; color: var(--c-ink-mute); }
