/* ==========================================================================
   Design systém projektu — jediný zdroj pravdy pro vzhled.
   --------------------------------------------------------------------------
   Načítají ho obě vstupní stránky (front i administrace). Vzniklo sloučením
   front.css a portal.css poté, co administrace přestala používat Bootstrap;
   díky tomu vypadá celá aplikace stejně.

   Obsah:
     1. proměnné (barvy, typografie, rozestupy) + tmavý režim
     2. reset a základní typografie
     3. layout (container, sekce) a tlačítka
     4. hlavička, hero a patička frontu
     5. komponenty administrace (grid, formuláře, karty, tabulky, navbar)

   Pravidlo: nové opakující se prvky patří sem, ne do jednotlivých komponent.
   Ukázky použití jsou v administraci pod Design system.
   ========================================================================== */

:root {
  /* --------------------------------------------------------------------
     Tokeny převzaté z design systému provoz.polyweb.cz (5. 10. 2026).
     Hodnoty jsou odečtené z jeho sestaveného stylopisu; dokumentační
     stránka `/settings/docs-design` je za přihlášením, takže psaná
     pravidla k nim nemáme a odvozují se z kódu.
     -------------------------------------------------------------------- */
  --font-ui: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Archivo", "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --radius-tag: 4px;
  --radius-control: 6px;
  --radius-card: 8px;
  --radius-block: 10px;
  --radius-pill: 999px;

  --bg: #f5f6f7;
  --surface: #ffffff;
  --surface-sunken: #fbfcfc;
  --surface-zebra: #fafbfb;
  --border: #d5dadd;
  --border-soft: #e6eaec;
  --text: #14181b;
  --muted: #626b72;
  --hover: #edf0f1;

  /* Akcent PolyRentu je indigo (9. 10. 2026). Převzatý systém z provoz.polyweb.cz
     měl zelený akcent, který zároveň nesl úspěch; kostra má vlastní barvu, a proto
     má úspěch vlastní zelené tokeny (--success*) níž. Indigo je zvolené tak, aby se
     nepletlo s žádnou stavovou barvou: zelená = úspěch, jantarová = varování,
     červená = chyba, tmavě modrá = informace. */
  --accent: #4338ca;
  --accent-strong: #3730a3;
  --accent-text: #ffffff;
  --accent-soft: #ecebfa;
  --accent-soft-text: #3730a3;
  --nav-active-bg: #4338ca;
  --nav-active-text: #ffffff;

  --success: #1d6a4c;
  --success-soft: #e9f1ec;
  --success-soft-text: #1d5b41;
  /* Text na plné zelené (toast). V tmavém režimu je zelená světlejší a bílý text na ní
     měl kontrast kolem 3:1 - audit ho neviděl, protože toast po čtyřech vteřinách zmizí. */
  --on-success: #ffffff;

  --error: #b3261e;
  --error-soft: #f3e8e8;
  --error-soft-text: #7c2b26;
  /* Text na plné chybové barvě (tlačítko „Deaktivovat"). V tmavém režimu je --error
     světlejší a bílý text na něm neprojde kontrastem, proto se tam překlápí na tmavý. */
  --on-error: #ffffff;
  --warning: #a66a00;
  --warning-soft: #f3ede3;
  --warning-soft-text: #7a5518;
  --info: #1d4e8f;
  --info-soft: #e6eef3;
  --info-soft-text: #234d66;
  --neutral-soft: #edf0f1;
  --neutral-soft-text: #46505a;

  --link: #4338ca;
  --link-hover: #3730a3;
  --input-border: #d3d8db;
  --input-placeholder: #8b949b;
  --focus-ring: 0 0 0 3px rgba(67, 56, 202, 0.2);
  --shadow: 0 8px 28px rgba(20, 24, 27, 0.14);
  --container-width: 1080px;

  /* --------------------------------------------------------------------
     Starší názvosloví projektu. Zůstává jako **alias**, ne jako druhá sada
     hodnot: tenhle stylopis má přes tři sta tříd a přejmenovat je všechny
     by znamenalo sáhnout do šedesáti React komponent bez jediné vizuální
     změny navíc. Nové pravidlo piš rovnou s tokeny výš.
     -------------------------------------------------------------------- */
  --color-primary: var(--accent);
  --color-primary-hover: var(--accent-strong);
  --color-primary-light: var(--accent-soft);
  /* Akcentová barva je jantarová `--warning`. Tlačítko `.btn-accent` je připravené,
     ale aplikace ho zatím nepoužívá. */
  --color-accent: var(--warning);
  --color-accent-soft: var(--warning-soft);

  --text-primary: var(--text);
  --text-secondary: var(--muted);
  --text-tertiary: var(--input-placeholder);
  --text-inverse: var(--surface);
  --text-on-primary: var(--accent-text);
  --text-on-accent: var(--warning-soft-text);

  --bg-page: var(--bg);
  --bg-surface: var(--surface);
  --bg-muted: var(--surface-sunken);
  --bg-input: var(--hover);

  --border-default: var(--border-soft);
  --border-strong: var(--border);

  /* Úspěch má vlastní zelenou, nezávislou na akcentu - jinak by změna barvy značky
     přebarvila i „aktivní" štítky a potvrzení uložení. */
  --color-success: var(--success);
  --color-success-bg: var(--success-soft);
  --color-warning: var(--warning);
  --color-warning-bg: var(--warning-soft);
  --color-danger: var(--error);
  --color-danger-bg: var(--error-soft);
  --color-info: var(--info);
  --color-info-bg: var(--info-soft);

  --font-base: var(--font-ui);

  --fs-xs: 12px;
  --fs-sm: 14px;
  --fs-base: 16px;
  --fs-lg: 18px;
  --fs-xl: 20px;
  --fs-2xl: 24px;
  --fs-3xl: 30px;
  --fs-4xl: 36px;
  --fs-5xl: 48px;
  --lh-base: 1.5;
  --lh-heading: 1.2;

  --radius-sm: var(--radius-control);
  --radius-md: var(--radius-card);
  --radius-lg: var(--radius-block);
  --radius-xl: var(--radius-block);
  --radius-full: var(--radius-pill);

  --shadow-card: inset 0 0 0 1px var(--border-soft);
  --shadow-sm: 0 1px 2px rgba(20, 24, 27, 0.06);
  --shadow-md: 0 4px 12px rgba(20, 24, 27, 0.08);
  --shadow-lg: var(--shadow);

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  --header-height: 60px;
  --banner-height: 36px;
  --content-max-width: 1280px;
  /* Administrace je širší než veřejný web i než jejich 1080 px: přehledy mívají
     deset a víc sloupců a v užší stránce se nevejdou ani při nejlepší vůli. */
  --portal-max-width: 1600px;
  --transition: 150ms ease;
}

[data-theme="dark"] {
  --bg: #0f1214;
  --surface: #171b1e;
  --surface-sunken: #13171a;
  --surface-zebra: #1a1f22;
  --border: #363d43;
  --border-soft: #2b3237;
  --text: #e8ebed;
  --muted: #98a1a8;
  --hover: #232a2e;

  --accent: #8b8ff5;
  --accent-strong: #a5a8f8;
  --accent-text: #0f1214;
  --accent-soft: #24264a;
  --accent-soft-text: #b4b7fb;
  --nav-active-bg: #34378a;
  --nav-active-text: #eef0ff;

  --success: #3e9b71;
  --success-soft: #1b3328;
  --success-soft-text: #7ed1a6;
  --on-success: #0f1214;

  --error: #e5675e;
  --error-soft: #34211f;
  --error-soft-text: #e5675e;
  --on-error: #0f1214;
  --warning: #d79a2b;
  --warning-soft: #33291a;
  --warning-soft-text: #d79a2b;
  --info: #6fa8e8;
  --info-soft: #1c2a37;
  --info-soft-text: #6fa8e8;
  --neutral-soft: #262c31;
  --neutral-soft-text: #c9d1d6;

  --link: #6fa8e8;
  --link-hover: #92bfef;
  --input-border: #3a4452;
  --input-placeholder: #7c858c;
  --focus-ring: 0 0 0 3px rgba(139, 143, 245, 0.3);
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.5);

  /* Jediný alias, který v tmavém režimu nestačí odvodit: text na barevné ploše
     je tu tmavý, ne bílý. */
  --text-inverse: var(--text);
}

/* ---------- Reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-height) + var(--banner-height));
}
body {
  font-family: var(--font-base);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--text-primary);
  background: var(--bg-page);
  -webkit-font-smoothing: antialiased;
}
img {
  max-width: 100%;
  display: block;
}
a {
  color: var(--color-primary);
  text-decoration: none;
  transition: color var(--transition);
}
a:hover {
  color: var(--color-primary-hover);
}
/* Odkaz uprostřed textu se nesmí poznat jen barvou (WCAG 1.4.1) - kdo barvy nerozliší,
   by ho v odstavci nenašel. Navigace, tlačítka a samostatné odkazy podtržení nemají. */
p a:not(.btn),
li a:not(.btn, .nav-link),
.form-check-label a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* Nadpisy a čísla nese Archivo, zbytek IBM Plex Sans - tak to má jejich systém.
   Prostrkání se s velikostí zmenšuje: velký nadpis v Archivu bez stažení působí
   rozsypaně, drobný s ním naopak zhoustne. */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.2;
  color: var(--text);
  text-wrap: balance;
}
h1 { font-size: 1.9rem; letter-spacing: -0.02em; }
h2 { font-size: 1.35rem; letter-spacing: -0.015em; }
h3 { font-size: 1.1rem; letter-spacing: -0.01em; }
h4 { font-size: 1rem; }
button {
  font-family: inherit;
  cursor: pointer;
}
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ---------- Layout ---------- */
.container {
  /* width: 100% je nutná - jako flex item (viz sticky patička níž) by se jinak
     kontejner scvrkl na šířku obsahu místo na šířku stránky. */
  width: 100%;
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: 0 var(--sp-6);
}
@media (max-width: 720px) {
  .container {
    padding: 0 var(--sp-5);
  }
}
.section {
  padding: var(--sp-16) 0;
  border-bottom: 1px solid var(--border-default);
}
@media (max-width: 720px) {
  .section {
    padding: var(--sp-12) 0;
  }
}
.section-head {
  text-align: center;
  max-width: 640px;
  margin: 0 auto var(--sp-12);
}
.section-head h2 {
  font-size: var(--fs-4xl);
  font-weight: 700;
  margin-bottom: var(--sp-3);
}
@media (max-width: 720px) {
  .section-head h2 {
    font-size: var(--fs-3xl);
  }
}
.section-head p {
  color: var(--text-secondary);
  font-size: var(--fs-lg);
}
.section-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-bottom: var(--sp-3);
}
.section-foot {
  text-align: center;
  margin-top: var(--sp-10);
}

/* ---------- Tlačítka ---------- */
/* Velikost drží odsazení, ne pevná výška - tak to má jejich systém a hlavně díky tomu
   sedí tlačítko vedle vstupního pole na stejnou výšku, protože obojí má stejný svislý
   padding. S pevnými výškami se to muselo ladit zvlášť a rozcházelo se to při každé
   změně velikosti písma. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.55rem 0.9rem;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.3;
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
  white-space: nowrap;
  text-decoration: none;
}
.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.btn-lg {
  padding: 0.75rem 1.3rem;
  font-size: 1rem;
}
.btn-primary {
  background: var(--color-primary);
  color: var(--text-on-primary);
}
.btn-primary:hover {
  background: var(--color-primary-hover);
  color: var(--text-on-primary);
}
.btn-secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--input-border);
}
.btn-secondary:hover:not(:disabled) {
  background: var(--hover);
  color: var(--text);
}
/* Tlačítko v hlavičce - dřív inline styl v Latte layoutu, teď regulérní třída. */
.btn-header {
  height: 36px;
  font-size: 13px;
  padding: 0 14px;
}
.btn-ghost {
  background: transparent;
  color: var(--muted);
  border-color: transparent;
}
.btn-ghost:hover:not(:disabled) {
  background: var(--hover);
  color: var(--text);
}
.btn-accent {
  background: var(--color-accent);
  color: var(--text-on-accent);
}
.btn-accent:hover {
  background: var(--color-accent-soft);
  color: var(--text-on-accent);
}
/* Obrysové tlačítko na tmavé scéně (hero). Bílá je tu natvrdo schválně: podklad je
   tmavý v obou režimech, takže se nemá podle čeho překlápět. */
.btn-outline {
  background: transparent;
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.4);
}
.btn-outline:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
}
.btn-link {
  background: transparent;
  color: var(--text-primary);
  padding: 0 4px;
  border-bottom: 1px solid var(--text-primary);
  border-radius: 0;
  height: auto;
}

/* ---------- Hlavička ---------- */
.site-header {
  position: sticky;
  top: var(--banner-height);
  z-index: 100;
  height: var(--header-height);
  background: color-mix(in srgb, var(--bg-page) 80%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-default);
}
.site-header .container {
  height: 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-8);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--text-primary);
  letter-spacing: -0.01em;
}
.brand:hover {
  color: var(--text-primary);
}
.logo-mark {
  width: 28px;
  height: 28px;
  object-fit: contain;
  display: block;
  flex: none;
}
.main-nav {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-left: auto;
}
.main-nav .nav-link {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-secondary);
  border-radius: var(--radius-md);
}
.main-nav .nav-link:hover {
  color: var(--text-primary);
  background: var(--bg-muted);
}
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: transparent;
  color: var(--text-secondary);
  border-radius: var(--radius-md);
  border: none;
}
.theme-toggle:hover {
  background: var(--bg-muted);
  color: var(--text-primary);
}
.theme-toggle svg {
  width: 18px;
  height: 18px;
}
[data-theme="dark"] .icon-moon {
  display: none;
}
:root:not([data-theme="dark"]) .icon-sun {
  display: none;
}
/* Burger patří jen na úzkou obrazovku; zapíná ho media query níž. */
.nav-burger {
  display: none;
}
@media (max-width: 860px) {
  .main-nav .nav-link {
    display: none;
  }
}
@media (max-width: 720px) {
  .nav-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: var(--radius-md);
  }
  .nav-burger svg {
    width: 22px;
    height: 22px;
  }
  .main-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
  }
  .main-nav.open {
    display: flex;
  }
  .main-nav.open .nav-link {
    display: inline-flex;
  }
}

/* ---------- Hero (tmavá scéna, split layout) ---------- */
.hero {
  position: relative;
  overflow: hidden;
  /* Podklad je tmavý v obou režimech, proto si sekce přepisuje proměnné odvozené
     od pozadí. Bez toho kreslí .btn-secondary ve světlém režimu tmavý text na tmavý
     gradient a .lead je sotva čitelný. Přepisují se rovnou základní tokeny, ne jejich
     starší aliasy - ty se od nich odvozují, takže se srovná všechno pod nimi. */
  --text: #e8ebed;
  --muted: #98a1a8;
  --surface: rgba(255, 255, 255, 0.08);
  --input-border: rgba(255, 255, 255, 0.38);
  --border: rgba(255, 255, 255, 0.38);
  --hover: rgba(255, 255, 255, 0.14);
  /* Tmavé tóny jsou ty z tmavého režimu (#0f1214, #171b1e), záře i dojezd přechodu
     se odvozují z akcentu - při změně barvy značky se hero přebarví samo. */
  background:
    radial-gradient(900px 500px at 78% 30%, color-mix(in srgb, var(--accent) 48%, transparent), transparent 70%),
    linear-gradient(135deg, #0f1214 0%, #171b1e 55%, color-mix(in srgb, var(--accent) 22%, #0f1214) 100%);
  color: var(--text);
}
.hero h1 {
  font-size: var(--fs-5xl);
  font-weight: 700;
  line-height: 1.1;
  /* `--text`, ne `--text-on-primary`: hero si ho přepisuje na světlý a platí to
     v obou režimech. `--accent-text` se naopak v tmavém režimu překlápí na tmavý,
     protože je to text *na akcentu* - na tmavém pozadí hera by zmizel. */
  color: var(--text);
  margin-bottom: var(--sp-5);
}
/* Mřížka `1fr 1fr` tu zbyla po předchůdci, kde vpravo stál obrázek certifikátu
   (třídy `.cert*` níž). Od té doby je pravá půlka prázdná, tak drží šířku řádku
   `.hero-copy` - vyjde to nastejno a odpadne sloupec, který nic neobsahuje. */
.hero-split {
  display: grid;
  gap: var(--sp-10);
  align-items: center;
  min-height: 520px;
  padding: var(--sp-16) 0;
}
.hero-copy {
  max-width: 36rem;
}
/* Kresba certifikátu po projektu „ověřená osoba" tady byla do 5. 10. 2026. Žádná
   komponenta ji nepoužívala a držela starou paletu (modrá #2E83FB, zelená #0DAF04),
   takže po přechodu na design systém z provoz.polyweb.cz zmizela i s ní. */

@media (max-width: 900px) {
  .hero-split {
    min-height: 0;
    padding: var(--sp-12) 0;
  }
  .hero h1 {
    font-size: var(--fs-4xl);
  }
  .hero .hero-visual {
    margin-top: var(--sp-6);
    max-width: 380px;
    margin-left: auto;
    margin-right: auto;
  }
}
@media (max-width: 720px) {
  .hero h1 {
    font-size: var(--fs-3xl);
  }
  .hero .hero-lead {
    font-size: var(--fs-base);
  }
}

/* ---------- Patička ---------- */
.site-footer {
  background: var(--bg-muted);
  border-top: 1px solid var(--border-default);
  padding: var(--sp-16) 0 var(--sp-8);
}
@media (max-width: 860px) {
  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 480px) {
  .footer-grid {
    grid-template-columns: 1fr;
  }
}
.footer-bottom {
  padding-top: var(--sp-6);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  /* --muted, ne --text-tertiary: tertiary má na bílé kontrast 3,1:1 a WCAG chce 4,5:1. */
  color: var(--muted);
}

/* ==========================================================================
   Komponenty administrace
   --------------------------------------------------------------------------
   Náhrada Bootstrapu. Stojí na proměnných z první části app.css, takže
   administrace vypadá jako front — jedny barvy, jedna typografie, jeden
   tmavý režim. Názvy tříd zůstaly bootstrapové (.card, .form-control, .row),
   aby se nemusel přepisovat každý JSX; chování je ale jen to, co používáme.
   ========================================================================== */

/* ---------- Grid ---------- */
.row {
  display: flex;
  flex-wrap: wrap;
  margin-left: calc(var(--sp-3) * -1);
  margin-right: calc(var(--sp-3) * -1);
}
.row > * {
  /* Bez flex-basis by se sloupec ve flexu smrskl na obsah a width by neplatila. */
  flex: 0 0 auto;
  padding-left: var(--sp-3);
  padding-right: var(--sp-3);
  width: 100%;
}
.g-2 { gap: var(--sp-2) 0; }
.g-3 { gap: var(--sp-4) 0; }
.g-4 { gap: var(--sp-6) 0; }

/* Mřížka obsahuje jen šířky, které se opravdu používají. Přibývá do ní se šablonou,
   která ji potřebuje - a když se zapomene, třída v JSX tiše nedělá nic a řádek se zalomí
   (stalo se u `col-8`/`col-4` na nástěnce a u `col-sm-*` na objednávce služby). */
.col { flex: 1 0 0%; }
.col-4 { width: 33.3333%; }
.col-5 { width: 41.6667%; }
.col-6 { width: 50%; }
.col-7 { width: 58.3333%; }
.col-8 { width: 66.6667%; }
.col-12 { width: 100%; }

@media (min-width: 768px) {
  .col-md-5 { width: 41.6667%; }
}
@media (min-width: 576px) {
  .col-sm-5 { width: 41.6667%; }
  .col-sm-6 { width: 50%; }
  .col-sm-7 { width: 58.3333%; }
}
@media (min-width: 992px) {
  .col-lg-2 { width: 16.6667%; }
  .col-lg-3 { width: 25%; }
  .col-lg-4 { width: 33.3333%; }
  .col-lg-5 { width: 41.6667%; }
  .col-lg-6 { width: 50%; }
  .col-lg-7 { width: 58.3333%; }
}

/* Zásady soukromí: odstavce uvnitř pasáže potřebují mezeru, jinak se slijí v blok. */
.privacy-passage p + p {
  margin-top: var(--sp-3);
}

/* ---------- Utility ---------- */
.d-flex { display: flex; }
.d-block { display: block; }
.flex-column { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.justify-content-between { justify-content: space-between; }
.justify-content-center { justify-content: center; }
.justify-content-end { justify-content: flex-end; }
.align-items-center { align-items: center; }
.align-items-end { align-items: flex-end; }
.mx-auto { margin-left: auto; margin-right: auto; }
.ms-auto { margin-left: auto; }
.me-auto { margin-right: auto; }
.mt-auto { margin-top: auto; }
.text-center { text-align: center; }
.text-end { text-align: right; }
.text-nowrap { white-space: nowrap; }
.text-muted { color: var(--text-secondary); }
.small { font-size: var(--fs-sm); }
.fw-normal { font-weight: 400; }
.fw-semibold { font-weight: 600; }
.w-100 { width: 100%; }
.w-auto { width: auto; }
.h-100 { height: 100%; }
.position-relative { position: relative; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--sp-1); }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-4); }
.mb-4 { margin-bottom: var(--sp-6); }
.mb-5 { margin-bottom: var(--sp-10); }
.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-4); }
.mt-4 { margin-top: var(--sp-6); }
.mt-5 { margin-top: var(--sp-10); }
.me-3 { margin-right: var(--sp-4); }
.py-2 { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
.py-4 { padding-top: var(--sp-6); padding-bottom: var(--sp-6); }
.py-5 { padding-top: var(--sp-10); padding-bottom: var(--sp-10); }
.pt-3 { padding-top: var(--sp-4); }
.p-0 { padding: 0; }
.p-4 { padding: var(--sp-6); }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-4); }
.border-bottom { border-bottom: 1px solid var(--border-default); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Dlouhá hodnota v seznamu údajů - e-mail, IBAN, telefon - je pro prohlížeč jedno slovo
   a bez tohohle vyleze ze svého sloupce ven. Hledá se to mizerně: `getBoundingClientRect()`
   prvku zůstane v pořádku, protože přetéká až text uvnitř, takže na profilu jen tiše
   rozšiřovala stránku o 20 px (18. 9. 2026). */
dd {
  overflow-wrap: anywhere;
}

/* ---------- Nadpisy ----------
   Třídy `.h3` až `.h6` nesou v kódu velikost nadpisu nezávisle na úrovni značky
   (nadpis karty je `h2.h6`, aby osnova stránky seděla a velikost taky). Po přechodu
   na jejich systém je i tady Archivo a stupnice je jeho, ne naše původní. */
.h3,
.h4,
.h5,
.h6 {
  font-family: var(--font-display);
  letter-spacing: -0.01em;
}
.h3 { font-size: 1.9rem; font-weight: 600; letter-spacing: -0.02em; }
.h4 { font-size: 1.35rem; font-weight: 600; letter-spacing: -0.015em; }
.h5 { font-size: 1.1rem; font-weight: 600; }
.h6 { font-size: 0.95rem; font-weight: 600; }
.lead { font-size: var(--fs-lg); color: var(--muted); }

/* ---------- Karta ---------- */
.card {
  background: var(--bg-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.card-body { padding: var(--sp-6); }
.card-title { margin-bottom: var(--sp-4); }
.shadow-sm { box-shadow: var(--shadow-card), var(--shadow-sm); }

/* ---------- Formuláře ---------- */
.form-label {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-secondary);
}
/* Stejný svislý padding jako tlačítko, takže obojí vedle sebe sedí na stejnou výšku
   bez dolaďování. Pevná výška tu dřív byla a při každé změně písma se rozešla. */
.form-control,
.form-select {
  display: block;
  width: 100%;
  padding: 0.55rem 0.7rem;
  font-family: inherit;
  font-size: 0.95rem;
  line-height: 1.3;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-control);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.form-control::placeholder {
  color: var(--input-placeholder);
}
.form-control:focus,
.form-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
/* Víceřádkové pole se neřídí výškou jednořádkových: tu určuje atribut `rows`, jinak
   by se druhý řádek schoval za posuvník. Svislé odsazení už řeší `.form-control`
   samo - od přechodu na jejich systém je padding na obou osách. */
textarea.form-control {
  height: auto;
  padding-top: 0.55rem;
  padding-bottom: var(--sp-2);
  line-height: 1.5;
  resize: vertical;
}

/* Odsazení i písmo jako u `.btn-sm`, ať malé pole a malé tlačítko vedle sebe sedí.
   Pevná výška tu dřív byla, ale nikdy neplatila: společné pravidlo `.form-control,
   .form-select` je o kus níž a stejnou specifičností ji přebíjelo. */
.form-control-sm,
.form-select-sm {
  font-size: 0.85rem;
  padding: 0.35rem 0.65rem;
}

/* Select potřebuje vpravo místo na šipku, vstupní pole ne - společné odsazení by
   v něm nechalo prázdný pruh. */
.form-select-sm {
  padding-right: 1.8rem;
}

/* `w-auto` je o dvě stě řádků výš než `.form-select { width: 100% }`, takže ho při
   stejné specifičnosti prohrávalo a výběr počtu na stránku se roztahoval přes celou
   řádku patičky - „25" v poli širokém 400 px. */
.form-select.w-auto,
.form-control.w-auto {
  width: auto;
}
.form-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2364748B' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  background-size: 14px;
  padding-right: var(--sp-8);
}
.form-text {
  margin-top: var(--sp-1);
  font-size: var(--fs-xs);
  /* Nápověda se čte, není to dekorace - --text-tertiary (3,1:1) byl pod hranicí WCAG. */
  color: var(--muted);
}
/* Skupina polí. Prohlížeč kreslí kolem `fieldset` rámeček se zapuštěnou legendou -
   vzhled, který ve zbytku formulářů není, a do kterého se navíc lepil text nápovědy.
   Sekce se odděluje odstupem a popiskem, stejně jako kterékoli jiné pole. */
fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
legend {
  display: block;
  width: 100%;
  padding: 0;
  margin-bottom: var(--sp-2);
}

/* `flex-start`, ne `center`: dlouhý popisek se zalomí a při centrování by čtverec
   zaškrtávátka odplul doprostřed dvou řádků. Dvoupixelový posun ho vrátí na účaří
   prvního řádku. */
.form-check {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
/* Popisek si bere zbytek řádku a zalamuje se sám v sobě. Bez `min-width: 0` by ho
   flex nenechal zúžit pod délku nejdelšího slova a text by přetekl ven. */
.form-check-label {
  flex: 1 1 0;
  min-width: 0;
}
/* Hláška patří pod celý řádek, ne vedle popisku: jako třetí flex prvek by si vzala
   část šířky a text u zaškrtávátka by se rozlámal do sloupce. */
.form-check .invalid-feedback {
  flex-basis: 100%;
}
.form-check-input {
  width: 16px;
  height: 16px;
  margin-top: 2px;
  flex: none;
  accent-color: var(--color-primary);
  cursor: pointer;
}
.form-check-label {
  font-size: var(--fs-sm);
  cursor: pointer;
}
/* Vypnuté zaškrtávátko musí být poznat i bez najetí myší — jinak člověk klika do
   políčka, které nereaguje, a hledá chybu v aplikaci. Popisek bledne s ním; sám
   o sobě by v plné barvě vypadal jako aktivní volba. */
.form-check-input:disabled,
.form-check-input:disabled + .form-check-label {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Chybové stavy. .invalid-feedback je skrytá, dokud pole nemá .is-invalid —
   stejná logika jako v Bootstrapu, na kterou spoléhá React Hook Form.

   Výjimka .d-block je nutná pro prvky, u kterých se .is-invalid nedává na samotné
   pole (zaškrtávátka). Musí být v selektoru, ne jen jako utilita: .d-block stojí
   v souboru dřív, takže by při stejné specificitě prohrálo s display: none a hláška
   by zůstala neviditelná v DOMu. */
.is-invalid {
  border-color: var(--color-danger);
}
.is-invalid:focus {
  box-shadow: 0 0 0 3px var(--color-danger-bg);
}
.invalid-feedback:not(.d-block) {
  display: none;
}
.invalid-feedback {
  margin-top: var(--sp-1);
  font-size: var(--fs-xs);
  color: var(--color-danger);
}
.is-invalid ~ .invalid-feedback {
  display: block;
}

/* Odrážkový seznam v běžném textu. Reset nuluje padding, takže bez odsazení by
   odrážky visely mimo text; ostatní seznamy v projektu jsou navigace a mají
   list-style: none. */
.list-bulleted {
  padding-left: var(--sp-5);
  list-style: disc;
}
.list-bulleted li + li {
  margin-top: var(--sp-2);
}

/* ---------- Hlášky ---------- */
.alert {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
}
/* Text na jemné ploše bere `*-soft-text`, ne plnou barvu: jantarová --warning nebo zelená
   --accent mají na své jemné ploše kontrast pod 4,5:1 (našel audit přístupnosti). */
.alert-danger { background: var(--color-danger-bg); color: var(--error-soft-text); }
.alert-success { background: var(--color-success-bg); color: var(--success-soft-text); }
.alert-warning { background: var(--color-warning-bg); color: var(--warning-soft-text); }
.alert-info { background: var(--color-info-bg); color: var(--info-soft-text); }

/* ---------- Odznaky ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  border-radius: var(--radius-full);
}
.text-bg-success { background: var(--color-success-bg); color: var(--success-soft-text); }
.text-bg-secondary { background: var(--neutral-soft); color: var(--neutral-soft-text); }
.text-bg-primary { background: var(--color-primary-light); color: var(--accent-soft-text); }
.text-bg-warning { background: var(--color-warning-bg); color: var(--warning-soft-text); }
.text-bg-danger { background: var(--color-danger-bg); color: var(--error-soft-text); }

/* Dlouhý volný text v buňce tabulky - typicky adresa. Bez omezení jeden takový údaj
   roztáhne sloupec a ukradne šířku sousedním: „Náměstí Svobody 1234/56b, budova C, 4.
   patro…" z řádku udělá odstavec a adresa bez mezer (231 znaků) natáhla tabulku na
   2498 px, takže se k ostatním sloupcům šlo dostat jen vodorovným posunem.

   `anywhere`, ne `break-word`: jen ono ovlivňuje i min-content šířku, takže se sloupec
   smí zúžit. `break-word` by zalomil až uvnitř už roztažené buňky, což je pozdě. */
.cell-address {
  display: inline-block;
  /* Spodní mez je tam proto, že `anywhere` sráží i min-content šířku skoro na nulu -
     bez ní by se sloupec s adresou smrskl užší, než je potřeba, a lámal se po slabikách
     i u běžného „Praha 4". */
  min-width: 11rem;
  max-width: 18rem;
  overflow-wrap: anywhere;
}

/* ---------- Tabulka ---------- */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.table th,
.table td {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  border-bottom: 1px solid var(--border-default);
}
.table th {
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
}
.table-light th {
  background: var(--bg-muted);
}
.table tbody tr:last-child td {
  border-bottom: none;
}
.table-hover tbody tr:hover {
  background: var(--bg-muted);
}
.align-middle th,
.align-middle td {
  vertical-align: middle;
}
.table-responsive {
  overflow-x: auto;
}
/* Na užších obrazovkách se buňky stáhnou o 4 px z každé strany. U deseti sloupců
   přehledu je to 80 px, přesně tolik, o kolik se tabulka na 1280px displeji
   nevešla - a vodorovný posun uvnitř karty je horší než o kousek hustší řádek.
   Nad 1400 px zůstává pohodlnější odsazení, tam je místa dost. */
@media (max-width: 1400px) {
  .table th,
  .table td {
    padding: var(--sp-3);
  }
}
/* Hustší sazba pro tabulky s hodně sloupci (`<DataGrid dense>`). Přehled s dvanácti
   sloupci by s běžným odsazením přeteče kartu i na široké obrazovce - tabulka se
   pak posouvá uvnitř karty a půlka sloupců je za okrajem. Je to totéž odsazení, jaké
   všechny tabulky dostávají pod 1400 px, jen bez ohledu na šířku okna. */
.table-dense th,
.table-dense td {
  padding-left: var(--sp-3);
  padding-right: var(--sp-3);
}
/* Buňka s akcemi řádku.
   `.text-end` tu nestačilo: `.table td { text-align: left }` má vyšší specificitu, takže
   zarovnání vpravo nikdy neplatilo. Řádek, ve kterém jedno tlačítko chybí (přepnout se
   pod cizí účet jde jen u aktivního a aktivovaného), pak posunul „Upravit" doleva
   a sloupec vypadal jako roztřepený okraj.
   `nowrap` drží dvojici tlačítek na jednom řádku - v úzkém sloupci se lámala pod sebe
   a řádek tabulky kvůli tomu povyrostl. */
.table td.datagrid-actions,
.table th.datagrid-actions {
  text-align: right;
  white-space: nowrap;
}

/* Mezera mezi akcemi. JSX mezi prvky na samostatných řádcích žádnou nevloží, takže
   dvě sousední tlačítka se dotýkala a vypadala jako jedno rozdělené tlačítko.

   > ⚠️ Flex patří sem, na obal uvnitř buňky - **ne na samotné `td`**. Tím se buňka
   > přestane chovat jako `table-cell`, přestane držet výšku řádku a spodní linka se
   > vykreslí jinde než u ostatních sloupců (17. 9. 2026: poslední sloupec vypadal
   > utržený od tabulky). */
.datagrid-actions-inner {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

/* Aby utilita fungovala i uvnitř tabulky - bez tohohle ji `.table td` přebije a v buňce
   nedělá nic, což se těžko hledá. */
.table th.text-end,
.table td.text-end {
  text-align: right;
}

/* Řazení je v hlavičce tlačítko, ale nesmí se tak chovat při zarovnání: `.btn-sm` mu
   dává vnitřní odsazení 12 px, takže nadpis uskakoval oproti obsahu sloupce a lícoval
   jen ten, podle kterého se řadit nedá. Selektor je záměrně přes `.table th`, aby
   přebil `.btn-sm` bez ohledu na pořadí pravidel v souboru. */
.table th .btn-link {
  padding: 0;
  height: auto;
  justify-content: flex-start;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  text-align: left;
}

/* ---------- Tlačítka: doplňky pro administraci ---------- */
.btn-sm {
  padding: 0.35rem 0.65rem;
  font-size: 0.85rem;
}
.btn-danger {
  background: var(--error);
  color: var(--on-error);
}
.btn-danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--error) 85%, black);
  color: var(--on-error);
}
.btn-outline-primary {
  background: var(--surface);
  color: var(--accent);
  border-color: var(--accent);
}
.btn-outline-primary:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent-soft-text);
}
.btn-outline-secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--input-border);
}
.btn-outline-secondary:hover:not(:disabled) {
  background: var(--hover);
  color: var(--text);
}
/* Nevratná akce, kterou ale nechceme na obrazovce křičet - plné .btn-danger patří
   až potvrzovacímu kroku. */
.btn-outline-danger {
  background: transparent;
  color: var(--color-danger);
  box-shadow: inset 0 0 0 1px var(--color-danger);
}
.btn-outline-danger:hover:not(:disabled) {
  background: var(--color-danger-bg);
}
.btn:disabled,
.btn.disabled {
  opacity: 0.55;
  cursor: default;
}
.btn-group {
  display: inline-flex;
}
.btn-group > .btn {
  border-radius: 0;
}
.btn-group > .btn:first-child { border-radius: var(--radius-control) 0 0 var(--radius-control); }
.btn-group > .btn:last-child { border-radius: 0 var(--radius-control) var(--radius-control) 0; }
.btn-group > .btn + .btn { margin-left: -1px; }
/* Ukazatel „1 / 3" mezi šipkami stránkování. Není to vypnuté tlačítko - dřív nesl
   .disabled a s jeho průhledností neprošel kontrastem. */
.datagrid-page-indicator {
  pointer-events: none;
  color: var(--text);
}
/* `btn-group-sm` se v DataGridu používá od začátku, ale pravidlo k němu nikdy nebylo:
   stránkování tak bylo o sedm pixelů vyšší než výběr počtu na stránku vedle něj. */
.btn-group-sm > .btn {
  padding: 0.35rem 0.65rem;
  font-size: 0.85rem;
}
.btn-link {
  background: transparent;
  border: none;
  color: inherit;
}

/* ---------- Načítání ---------- */
.spinner-border {
  display: inline-block;
  width: 28px;
  height: 28px;
  border: 3px solid var(--color-primary-light);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spinner-rotate 0.7s linear infinite;
}
@keyframes spinner-rotate {
  to { transform: rotate(360deg); }
}
.text-primary { color: var(--color-primary); }

/* Hlavička stránky: nadpis vlevo, akce vpravo.
   `flex-wrap` je tu kvůli mobilu - dlouhý nadpis („Editace uživatele - dlouhy@email.cz")
   a tlačítka vedle sebe měly na 390px displeji 669 px a táhly s sebou celou stránku.
   `anywhere` láme i adresu, která je jedno slovo a jinak se nezalomí. */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.page-head h1 {
  overflow-wrap: anywhere;
}

/* ---------- Administrace: obsah stránky ---------- */
/* Poslední karta na stránce nesmí končit na hraně okna - dole stejný odstup, jaký nad
   obsahem dělá spodní okraj navbaru. Padding patří sem, ne na .container: ten používá
   i sám navbar, kde by mu rozbil výšku. */
.portal-main {
  padding-bottom: var(--sp-8);
}

/* Obsah administrace i její dva pruhy přes celou šířku drží stejnou mez - jinak by
   navigace končila jinde než tabulka pod ní. */
.portal-main,
.portal-navbar .container,
.impersonation-bar .container {
  max-width: var(--portal-max-width);
}

/* ---------- Navbar administrace ---------- */
.portal-navbar {
  height: var(--header-height);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-default);
  margin-bottom: var(--sp-8);
}
.portal-navbar .container {
  height: 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-6);
}
.portal-navbar .navbar-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--text-primary);
  letter-spacing: -0.01em;
}
.portal-navbar .navbar-brand:hover {
  color: var(--text-primary);
}
.portal-logo {
  width: 28px;
  height: 28px;
  object-fit: contain;
  display: block;
  flex: none;
}
.navbar-nav {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  list-style: none;
}
.navbar-nav .nav-link {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.navbar-nav .nav-link:hover {
  color: var(--text-primary);
  background: var(--bg-muted);
}
.navbar-nav .nav-link.active {
  color: var(--text-primary);
  background: var(--bg-muted);
}
/* Administrace na mobilu.
   Dvě řady odkazů vedle sebe měly na 390px displeji 889 px a táhly s sebou celou
   stránku - obsah se posouval do boku a viewport se zmenšil na třetinu. Levá řada se
   proto schová pod tlačítko, značka nechá jen logo a v liště zůstane
   přepínač témat a odhlášení, tedy to, co člověk potřebuje po ruce.
   Pravidla jsou schválně stejná jako u veřejného webu (.main-nav), ať se menu chová
   na obou půlkách aplikace stejně. */
/* Portálová lišta nese víc než veřejná a na 720 px nedočká: běžnému uživateli
   přetékala kolem 760 px, správci kvůli nabídce „Administrace" až do 940 px -
   a vždycky s sebou táhla celou stránku, na každé obrazovce portálu. Sbaluje se proto
   dřív, a u správce ještě dřív než u ostatních. Veřejný web zůstává na 720 px, tam se
   nic nerozbíjí (ověřeno od 700 px výš). */
@media (max-width: 820px) {
  .portal-navbar .nav-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: var(--radius-md);
  }
  .portal-navbar .container {
    gap: var(--sp-3);
    position: relative;
  }
  .portal-navbar .portal-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
    z-index: 20;
  }
  .portal-navbar .portal-nav.open {
    display: flex;
  }
  .portal-navbar .portal-nav .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 var(--sp-3);
    min-width: 0;
  }
}

@media (max-width: 960px) {
  .portal-navbar:has(.admin-menu) .container {
    gap: var(--sp-3);
    position: relative;
  }
  .portal-navbar:has(.admin-menu) .nav-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: var(--radius-md);
  }
  .portal-navbar:has(.admin-menu) .portal-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
    z-index: 20;
  }
  .portal-navbar:has(.admin-menu) .portal-nav.open {
    display: flex;
  }
  /* Rozbalovací nabídka správce se v panelu nemá otevírat do strany - není kam. */
  .portal-navbar:has(.admin-menu) .portal-nav .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 var(--sp-3);
    min-width: 0;
  }
}

@media (max-width: 720px) {
  /* Název ustoupí jen tam, kde je o místo nouze - tedy když je v liště i tlačítko menu.
     Na přihlašovací obrazovce žádná navigace není a samotné logo vypadá jako nedodělek. */
  .portal-navbar:has(.nav-burger) .portal-brand-text {
    display: none;
  }
  .portal-navbar .container {
    gap: var(--sp-3);
    position: relative;
  }
  .portal-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
    z-index: 20;
  }
  .portal-nav.open {
    display: flex;
  }
  /* Rozbalovací nabídka správce se v panelu nemá otevírat do strany - není kam. */
  .portal-nav .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 var(--sp-3);
    min-width: 0;
  }
}

.portal-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: transparent;
  color: var(--text-secondary);
  border: none;
  border-radius: var(--radius-md);
}
.portal-theme-toggle:hover {
  background: var(--bg-muted);
  color: var(--text-primary);
}
.portal-theme-toggle svg {
  width: 18px;
  height: 18px;
}

/* Ikony přepínače: v světlém režimu měsíc, v tmavém slunce. */
.icon-sun,
.portal-icon-sun { display: none; }
[data-theme="dark"] .icon-moon,
[data-theme="dark"] .portal-icon-moon { display: none; }
[data-theme="dark"] .icon-sun,
[data-theme="dark"] .portal-icon-sun { display: inline-block; }

/* ---------- Rozbalovací menu ---------- */
.nav-dropdown {
  position: relative;
}
.nav-dropdown-menu {
  position: absolute;
  top: calc(100% + var(--sp-1));
  left: 0;
  min-width: 220px;
  padding: var(--sp-2);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  list-style: none;
  z-index: 50;
}
.nav-dropdown-section {
  padding: var(--sp-2) var(--sp-3) var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.nav-dropdown-menu .nav-link {
  width: 100%;
  justify-content: flex-start;
}
.nav-dropdown-toggle::after {
  content: "";
  width: 8px;
  height: 8px;
  margin-left: var(--sp-2);
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
}

/* ---------- Stránka: sticky patička ---------- */
/* Krátká stránka nesmí nechat patičku viset uprostřed okna. */
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
#root {
  display: flex;
  flex-direction: column;
  flex: 1;
}
main {
  flex: 1;
  display: flex;
  flex-direction: column;
}
/* Hero na krátké stránce vyplní zbytek výšky, ať mezi ním a patičkou nezůstane díra. */
main > .hero {
  flex: 1;
}

/* ---------- Design system: dokumentace komponent ---------- */
.design-code {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-4);
  background: var(--bg-muted);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--text-primary);
  overflow-x: auto;
}
.design-note {
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--color-primary);
  background: var(--color-primary-light);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  font-size: var(--fs-sm);
  color: var(--text-primary);
}
code {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

/* Formuláře nemají být přes celou šířku obrazovky - špatně se čtou. */
.form-row {
  max-width: 520px;
}
/* Výjimka pro formuláře s poli vedle sebe (profil): mřížky jméno+příjmení a čtyři pole
   účtu se do 520px nevejdou a v širší kartě by vpravo zůstal prázdný pruh. Šířku pak
   drží karta, ne formulář. */
.form-row-wide {
  max-width: none;
}
/* Obrazovka, která je formulář, ne tabulka.
   Administrace má mez 1600 px kvůli výpisům; formulář v ní ale zůstane 520 px široký
   a karta kolem něj se roztáhne přes celou šířku, takže vpravo zbude přes tisíc pixelů
   prázdna. Karta se proto drží obsahu. */
.form-page {
  max-width: 46rem;
}

/* Odesílací tlačítko patří vždycky doprava - v úzkém formuláři k pravému okraji polí,
   v širokém k okraji karty. Dřív se to řídilo šířkou obsahu a úzké formuláře měly akci
   vlevo; dvě pravidla vedle sebe ale znamenala jen to, že tlačítko bylo pokaždé jinde
   (18. 9. 2026). */
.form-actions-end {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
}

/* Potvrzovací dialog (components/ConfirmDialog.tsx) - náhrada window.confirm().
   Překryv přes celou stránku, karta uprostřed; na mobilu karta zabere šířku okna
   bez okrajů navíc. z-index nad toastem i nad lištou auditu design systému ne -
   ta má zůstat vidět. */
.confirm-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1090;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  background: rgba(20, 24, 27, 0.45);
}
/* Na tmavé stránce by poloprůhledná tmavá skoro nebyla vidět. */
[data-theme="dark"] .confirm-backdrop {
  background: rgba(0, 0, 0, 0.65);
}
.confirm-dialog {
  width: 100%;
  max-width: 28rem;
  padding: var(--sp-6);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
}
.confirm-body {
  display: flex;
  gap: var(--sp-4);
  margin-bottom: var(--sp-5);
}
.confirm-icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-display);
  font-weight: 700;
}
.confirm-icon-danger {
  background: var(--error-soft);
  color: var(--error);
}
.confirm-title {
  margin-bottom: var(--sp-1);
  font-size: var(--fs-lg);
}
.confirm-message {
  margin-bottom: 0;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.ds-swatch {
  width: 132px;
}
/* Vzorek barvy v živé dokumentaci (/portal/design) - barvu dosazuje JSX z tokenu. */
.ds-swatch-color {
  height: 48px;
  border-radius: var(--radius-card);
  box-shadow: inset 0 0 0 1px var(--border);
}
.ds-swatch-shape {
  background: var(--accent-soft);
}
.error-boundary-card {
  max-width: 36rem;
}

/* Vyskakovací potvrzení akce. Vpravo dole, tedy u tlačítka Uložit - tam se člověk dívá
   ve chvíli, kdy na něj klikne. Nahoře ve formuláři hláška u delších stránek skončila
   mimo obrazovku. */
.toast-stack {
  position: fixed;
  right: var(--sp-5);
  bottom: var(--sp-5);
  z-index: 1080;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-width: min(24rem, calc(100vw - 2 * var(--sp-5)));
}
.toast-item {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-md);
  background: var(--color-success);
  color: var(--on-success);
  font-size: var(--fs-sm);
  box-shadow: var(--shadow-lg);
  animation: toast-in 160ms ease-out;
}
/* Kdo má vypnuté animace, dostane hlášku rovnou - posun by ho jen rušil. */
@media (prefers-reduced-motion: reduce) {
  .toast-item {
    animation: none;
  }
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(var(--sp-3)); }
  to   { opacity: 1; transform: none; }
}
.toast-close {
  flex: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  opacity: 0.8;
  cursor: pointer;
  line-height: 1;
}
.toast-close:hover {
  opacity: 1;
}
/* Na úzké obrazovce přes celou šířku u spodní hrany - tak se mobilní hlášky chovají
   a nepřekrývají obsah jen půlkou. */
@media (max-width: 576px) {
  .toast-stack {
    right: var(--sp-4);
    left: var(--sp-4);
    bottom: var(--sp-4);
    max-width: none;
  }
}

/* Pruh „jste přihlášený pod cizím účtem". Přes celou šířku a výrazný schválně -
   nenápadný odznak by se přehlédl a všechno, co se v tomhle stavu udělá, vypadá jako
   práce toho druhého člověka. */
.impersonation-bar {
  background: var(--color-warning);
  color: #fff;
  /* Navbar si nese odstup pod sebou pro obsah stránky. Pruh patří těsně pod něj, takže
     si ten odstup vezme na sebe - jinak mezi nimi zůstane bílý pás. */
  margin-top: calc(-1 * var(--sp-8));
  margin-bottom: var(--sp-8);
}
.impersonation-bar .container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  justify-content: space-between;
  padding-top: var(--sp-3);
  padding-bottom: var(--sp-3);
  font-size: var(--fs-sm);
}
.impersonation-bar .btn-outline-light {
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.7);
  color: #fff;
  background: transparent;
}
.impersonation-bar .btn-outline-light:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.15);
}

/* Řádek filtrů v hlavičce tabulky. Sdílí buňky se sloupci, takže se s nimi srovná sám -
   žádná šířka se tu nenastavuje, o tu se stará tabulka. */

/* Názvy sloupců a filtry pod nimi jsou jedna hlavička, ne dva pruhy. Linka mezi nimi
   je od sebe zbytečně dělila; oddělit se má až hlavička od dat, což dělá spodní okraj
   samotného řádku filtrů. */
thead:has(.datagrid-filter-row) tr:first-child th {
  border-bottom: 0;
  padding-bottom: var(--sp-2);
}
.datagrid-filter-row th {
  padding-top: 0;
  padding-bottom: var(--sp-2);
  border-top: 0;
  font-weight: 400;
}
.datagrid-filter-row .form-control {
  width: 100%;
  min-width: 0;
}
/* Výběr musí uživit svoji nejdelší volbu i se šipkou - u úzkého sloupce („Stav")
   se jinak zavřený select ořízne na „Vš". Sloupec se kvůli tomu radši roztáhne. */
.datagrid-filter-row .form-select {
  width: 100%;
  min-width: 7.5rem;
}
/* Křížek nemá být širší než tlačítko akce pod ním, jinak by sloupec roztáhl. */
.datagrid-filters-reset {
  padding-left: var(--sp-2);
  padding-right: var(--sp-2);
}

/* Překryv nad tabulkou při načítání, aby nepodkládal obsah skokem. */
.datagrid-loading {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  padding-top: var(--sp-6);
  background: color-mix(in srgb, var(--bg-surface) 75%, transparent);
  z-index: 1;
}

/* ---------- Souhrnné dlaždice ---------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-4);
}
.stat-tile {
  padding: var(--sp-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
}
.stat-tile .stat-value {
  font-size: var(--fs-2xl);
  font-weight: 600;
  line-height: 1.2;
  color: var(--text-primary);
}
.stat-tile .stat-label {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

/* ---------- Profil ---------- */
/* Jméno je jeden údaj rozdělený do čtyř polí takže patří na
   jeden řádek - ne pod sebe jako samostatné položky. Tituly jsou užší: „Ing." a „Ph.D."
   potřebují zlomek místa oproti jménu. */
.name-row {
  display: grid;
  grid-template-columns: 0.6fr 1fr 1fr 0.6fr;
  gap: var(--sp-3);
  align-items: start;
}
.name-row .mb-3 {
  margin-bottom: 0;
}
@media (max-width: 575px) {
  .name-row {
    grid-template-columns: 1fr;
  }
  /* Na jednom sloupci jsou z polí zase samostatné položky a potřebují odsazení,
     které jim mřížka vzala. */
  .name-row .mb-3 {
    margin-bottom: var(--sp-4);
  }
}

/* Přepínač jazyka v liště. Užší než běžný select - vedle motivu a odhlášení je o místo
   nouze a nejdelší položka („Slovenčina") se do toho vejde. */
.jazyk-prepinac {
  min-width: 7.5rem;
}

@media (max-width: 720px) {
  /* Na telefonu ustupuje: v liště zůstává motiv a odhlášení, jazyk se mění
     přes nabídku pod tlačítkem, kde je na něj místo. */
  .jazyk-prepinac {
    display: none;
  }
}

/* ---------- Kontrola pronájmů (docs/pronajmy) ---------- */
/* Odznak u položky menu - počet nespárovaných plateb. */
.nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  margin-left: var(--sp-2);
  padding: 0 var(--sp-1);
  border-radius: var(--radius-pill);
  background: var(--error);
  color: var(--on-error);
  font-size: 0.75rem;
  font-weight: 600;
}

/* Menu s částmi portfolia je nejdelší lišta portálu (sedm odkazů + nabídka portfolia).
   Název „Portál" vedle loga proto ustoupí vždycky - logo má aria-label a vrací na
   nástěnku stejně. Bez textu se běžnému uživateli lišta vejde od 1200 px (změřeno
   12. 10. 2026: 1141 px obsahu), správci s nabídkou „Administrace" od 1340 px; pod tím
   se sbalí pod tlačítko stejně jako u `admin-menu`. */
.portal-navbar:has(.portfolio-menu) .portal-brand-text {
  display: none;
}
@media (max-width: 1200px) {
  .portal-navbar:has(.portfolio-menu) .container {
    gap: var(--sp-3);
    position: relative;
  }
  .portal-navbar:has(.portfolio-menu) .nav-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: var(--radius-md);
  }
  .portal-navbar:has(.portfolio-menu) .portal-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
    z-index: 20;
  }
  .portal-navbar:has(.portfolio-menu) .portal-nav.open {
    display: flex;
  }
  .portal-navbar:has(.portfolio-menu) .portal-nav .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 var(--sp-3);
    min-width: 0;
  }
}

@media (max-width: 1340px) {
  .portal-navbar:has(.portfolio-menu):has(.admin-menu) .container {
    gap: var(--sp-3);
    position: relative;
  }
  .portal-navbar:has(.portfolio-menu):has(.admin-menu) .nav-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: var(--radius-md);
  }
  .portal-navbar:has(.portfolio-menu):has(.admin-menu) .portal-nav {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    background: var(--bg-surface);
    border-bottom: 1px solid var(--border-default);
    padding: var(--sp-4) var(--sp-6);
    box-shadow: var(--shadow-lg);
    z-index: 20;
  }
  .portal-navbar:has(.portfolio-menu):has(.admin-menu) .portal-nav.open {
    display: flex;
  }
  .portal-navbar:has(.portfolio-menu):has(.admin-menu) .portal-nav .nav-dropdown-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 var(--sp-3);
    min-width: 0;
  }
}

/* Přepínač filtru nad výpisem (stav smluv, plateb, nákladů). */
.filter-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Údaje „popisek - hodnota" v kartě detailu (smlouva, jednotka). */
.info-list {
  display: grid;
  grid-template-columns: minmax(8rem, max-content) 1fr;
  gap: var(--sp-2) var(--sp-4);
}
.info-list dt {
  color: var(--muted);
  font-weight: 500;
}
.info-list dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}
@media (max-width: 575px) {
  .info-list {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .info-list dd {
    margin-bottom: var(--sp-2);
  }
}

/* Seznam bez odrážek s odstupem mezi položkami. */
.plain-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--sp-3);
}

/* Řádek položky smlouvy: název, částka, odebrat. */
.item-row {
  display: grid;
  grid-template-columns: 1fr 12rem auto;
  gap: var(--sp-3);
  align-items: end;
}
.item-row > .btn {
  margin-bottom: var(--sp-4);
}
@media (max-width: 575px) {
  .item-row {
    grid-template-columns: 1fr auto;
  }
  .item-row > :first-child {
    grid-column: 1 / -1;
  }
}

/* Graf cashflow (SVG). Barvy z tokenů, aby graf fungoval i v tmavém režimu. */
.cashflow-chart svg {
  display: block;
  width: 100%;
  height: auto;
}
.cashflow-axis {
  stroke: var(--border);
}
.cashflow-bar-income {
  fill: var(--success);
}
.cashflow-bar-expected {
  fill: var(--success-soft);
}
.cashflow-bar-expense {
  fill: var(--error);
}
.cashflow-label {
  fill: var(--muted);
  font-size: 11px;
}
.cashflow-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.cashflow-legend span::before {
  content: "";
  display: inline-block;
  width: 0.75rem;
  height: 0.75rem;
  margin-right: var(--sp-2);
  border-radius: 2px;
  vertical-align: -1px;
}
.cashflow-legend-income::before {
  background: var(--success);
}
.cashflow-legend-expected::before {
  background: var(--success-soft);
  border: 1px solid var(--success);
}
.cashflow-legend-expense::before {
  background: var(--error);
}

/* Odkaz uprostřed textu (údaje smlouvy) se musí odlišit i jinak než barvou -
   axe: link-in-text-block. */
.info-list a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- Výběr s vyhledáváním (SearchSelect) ---------- */
/* Pole vypadá jako select (šipka z .form-select), seznam se otevře pod ním. */
.search-select {
  position: relative;
}
.search-select .form-select {
  cursor: pointer;
}
.search-select .form-select:focus {
  cursor: text;
}
/* Pozici (fixed, podle pole) dosazuje komponenta - seznam je v portálu v body. */
.search-select-list {
  z-index: 1000;
  max-height: 18rem;
  overflow-y: auto;
  margin: 0;
  padding: var(--sp-1) 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow);
}
.search-select-group {
  padding: var(--sp-2) var(--sp-3) var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.search-select-option {
  padding: var(--sp-2) var(--sp-3);
  cursor: pointer;
}
.search-select-option.grouped {
  padding-left: var(--sp-5);
}
.search-select-option.active {
  background: var(--hover);
}
.search-select-option.selected {
  font-weight: 600;
}
.search-select-empty {
  padding: var(--sp-2) var(--sp-3);
  color: var(--muted);
}
.search-select-list-sm {
  font-size: var(--fs-sm);
}

/* Náhled e-mailu upomínky - text tak, jak ho nájemník dostane (prostý text, zalomení řádků). */
.email-preview {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-control);
  background: var(--surface-sunken);
}
.email-preview-subject {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-soft);
  font-weight: 600;
}
.email-preview pre {
  margin: 0;
  padding: var(--sp-3);
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ---------- Záložky (Tabs) ---------- */
.tabs-list {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: var(--sp-4);
  overflow-x: auto;
  scrollbar-width: thin;
}
.tabs-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  cursor: pointer;
}
.tabs-tab:hover {
  color: var(--text);
}
.tabs-tab.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}
.tabs-tab:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-control) var(--radius-control) 0 0;
}
.tabs-count {
  min-width: 1.25rem;
  padding: 0 var(--sp-1);
  border-radius: var(--radius-pill);
  background: var(--neutral-soft);
  color: var(--neutral-soft-text);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-align: center;
}

/* ---------- Modální okno (Modal, nativní <dialog>) ---------- */
.modal {
  padding: 0;
  border: none;
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  width: min(32rem, calc(100vw - 2 * var(--sp-4)));
  max-height: calc(100vh - 2 * var(--sp-8));
}
.modal-lg {
  width: min(48rem, calc(100vw - 2 * var(--sp-4)));
}
.modal::backdrop {
  background: rgba(20, 24, 27, 0.45);
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-6);
  border-bottom: 1px solid var(--border-soft);
}
.modal-close {
  width: 2rem;
  height: 2rem;
  border: none;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.modal-close:hover {
  background: var(--hover);
  color: var(--text);
}
.modal-body {
  padding: var(--sp-6);
  overflow-y: auto;
}
.modal-footer {
  padding: 0 var(--sp-6) var(--sp-6);
}
.modal-footer .form-actions-end {
  margin: 0;
}

/* ---------- Prázdný stav (EmptyState) ---------- */
.empty-state {
  padding: var(--sp-10) var(--sp-6);
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.empty-state-icon {
  font-size: 2rem;
  line-height: 1;
  color: var(--border);
  margin-bottom: var(--sp-3);
}
.empty-state p {
  max-width: 34rem;
  margin: 0 auto var(--sp-4);
}

/* Řádek DescriptionList - obal dt+dd kvůli klíči v Reactu; mřížka .info-list ho přeskočí. */
.info-list-row {
  display: contents;
}

/* ---------- Menu akcí (DropdownMenu) ---------- */
.dropdown-menu-wrap {
  position: relative;
  display: inline-block;
}
.dropdown-menu-toggle {
  min-width: 2.25rem;
  font-weight: 700;
  letter-spacing: 0.1em;
}
.dropdown-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 40;
  min-width: 12rem;
  padding: var(--sp-1) 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow);
}
.dropdown-menu-item {
  display: block;
  width: 100%;
  padding: var(--sp-2) var(--sp-4);
  font: inherit;
  font-size: var(--fs-sm);
  text-align: left;
  color: var(--text);
  background: none;
  border: none;
  cursor: pointer;
}
.dropdown-menu-item:hover,
.dropdown-menu-item:focus-visible {
  background: var(--hover);
  outline: none;
}
.dropdown-menu-item.danger {
  color: var(--error);
}
.dropdown-menu-item:disabled {
  color: var(--muted);
  cursor: not-allowed;
}

/* Indikátor živých aktualizací v liště. Text na úzké obrazovce ustoupí, tečka zůstane. */
.live-indicator {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--muted);
}
.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border);
}
.live-connected .live-dot {
  background: var(--success);
  box-shadow: 0 0 0 3px var(--success-soft);
}
@media (max-width: 1340px) {
  .live-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
}
