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

  --accent: #1d6a4c;
  --accent-strong: #175840;
  --accent-text: #ffffff;
  --accent-soft: #e9f1ec;
  --accent-soft-text: #1d5b41;
  --nav-active-bg: #1d6a4c;
  --nav-active-text: #ffffff;

  --error: #b3261e;
  --error-soft: #f3e8e8;
  --error-soft-text: #7c2b26;
  --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: #1d6a4c;
  --link-hover: #175840;
  --input-border: #d3d8db;
  --input-placeholder: #8b949b;
  --focus-ring: 0 0 0 3px rgba(29, 106, 76, 0.18);
  --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);
  /* Žlutá se po přechodu používá už jen na hvězdičky hodnocení; jejich systém
     na to má jantarovou `--warning`. Tlačítko `.btn-accent` nikde v aplikaci
     není, takže se barva nikam jinam nepropíše. */
  --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);

  /* Zelený akcent nese i úspěch - mít vedle sebe dvě zelené by znamenalo
     rozlišovat odstíny, které od sebe nikdo nepozná. */
  --color-success: var(--accent);
  --color-success-bg: var(--accent-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řehled tipů má
     deset sloupců a v užší stránce se nevejde 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: #3e9b71;
  --accent-strong: #57b187;
  --accent-text: #0f1214;
  --accent-soft: #1b3328;
  --accent-soft-text: #7ed1a6;
  --nav-active-bg: #235b43;
  --nav-active-text: #e9f5ee;

  --error: #e5675e;
  --error-soft: #34211f;
  --error-soft-text: #e5675e;
  --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(62, 155, 113, 0.28);
  --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);
}
/* 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 jejich tmavého režimu (#0f1214, #171b1e) a záře je zelený
     akcent. Do 5. 10. 2026 tu byl modrý přechod po předchůdci, který se se zelenou
     akcentovou barvou tloukl. */
  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%, #1b3328 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);
  color: var(--text-tertiary);
}

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

@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-4 { width: 33.3333%; }
  .col-lg-5 { width: 41.6667%; }
  .col-lg-6 { width: 50%; }
  .col-lg-7 { width: 58.3333%; }
}

/* ---------- Hvězdičkové hodnocení (rozhodnutí H1) ---------- */

.stars {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--color-accent);
}
/* Dvě vrstvy přes sebe: spodní obrysy, horní vyplněná a oříznutá na šířku hodnoty.
   Půlka hvězdy je pak přesně polovina té samé ikony, ne zvláštní obrázek. */
.stars-track {
  position: relative;
  display: inline-flex;
  line-height: 0;
}
.stars-fill {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  overflow: hidden;
}
/* Bez tohohle se hvězdy do zúžené vrstvy zmáčknou (flex-shrink), místo aby se ořízly,
   a půlhvězda by nesedla na obrys pod sebou. */
.stars-track svg {
  flex: none;
}
.stars-count {
  color: var(--text-secondary);
}

/* Žádost o smazání se rozbaluje pod komentářem, ke kterému patří. Pruh a podklad ji
   oddělují od formuláře vlastního hodnocení, který v kartě může být hned pod ní - dva
   formuláře za sebou by jinak splynuly v jeden. */
.rating-removal {
  margin-top: var(--sp-3);
  padding: var(--sp-4);
  border-left: 3px solid var(--color-primary);
  background: var(--bg-muted);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.rating-removal .form-actions-end {
  margin-bottom: 0;
}

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

/* Fronta moderace: karty pod sebou, ne mřížka - rozhoduje se tu o textu, který je
   potřeba přečíst celý. */
.rating-queue {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Citovaný komentář musí být na první pohled cizí text, ne popisek stránky. */
.rating-quote {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--color-primary);
  background: var(--bg-muted);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.rating-queue-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--sp-2) var(--sp-4);
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-sm);
}
.rating-queue-meta dt {
  color: var(--text-secondary);
}
.rating-queue-meta dd {
  margin: 0;
}

/* Seznam hodnocení u tipu: oddělovač místo rámečků, ať karta nevypadá jako tabulka. */
.rating-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.rating-item + .rating-item {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-default);
}

/* Posuvník s náhledem hvězd vedle: člověk vidí, co těch 80 bodů znamená. */
.rating-input {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
.rating-input input[type='range'] {
  flex: 1 1 auto;
  accent-color: var(--color-primary);
}
.rating-input-value {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  white-space: nowrap;
}

/* Oprava bodů rovnou v buňce gridu (rozhodnutí H2). Pole je úzké schválně - jsou to
   nejvýš tři číslice a širší by roztáhlo sloupec i mimo editaci. */
.score-edit {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  white-space: nowrap;
}
.score-edit input[type='number'] {
  width: 5rem;
}

/* ---------- 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);
  color: var(--text-tertiary);
}
/* 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);
}
.alert-danger { background: var(--color-danger-bg); color: var(--color-danger); }
.alert-success { background: var(--color-success-bg); color: var(--color-success); }
.alert-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.alert-info { background: var(--color-info-bg); color: var(--color-info); }

/* ---------- 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(--color-success); }
.text-bg-secondary { background: var(--bg-muted); color: var(--text-secondary); }
.text-bg-primary { background: var(--color-primary-light); color: var(--color-primary); }
.text-bg-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.text-bg-danger { background: var(--color-danger-bg); color: var(--color-danger); }

/* 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 tipů 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 všech tipů má
   dvanáct sloupců a 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
   „Opravit body" a „Tip" se dotýkaly a vypadaly 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: #ffffff;
}
.btn-danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--error) 85%, black);
  color: #ffffff;
}
.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; }
/* `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 zvoneček,
   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);
}

/* Pruh filtrů nad tabulkou. Flex místo dvanáctisloupcové mřížky: filtrů bývá různý
   počet a v mřížce po `col-lg-2` už šestý vytlačil tlačítko „Zrušit filtry" na druhý
   řádek. Takhle se o místo dělí rovným dílem a tlačítko drží u nich. */
/* 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 (rozhodnutí A22). */
.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: #fff;
  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;
}

/* ---------- Párovací kód ---------- */
/* QR drží bílý podklad i v tmavém režimu - čtečka potřebuje kontrast, ne barvu tématu. */
.pairing-qr {
  display: block;
  margin: 0 auto var(--sp-4);
  background: #fff;
  border-radius: var(--radius-md);
}
/* Kód se diktuje a opisuje, proto neproporcionální písmo a rozpal mezi znaky. */
.pairing-code {
  font-family: var(--font-mono);
  font-size: var(--fs-2xl);
  font-weight: 600;
  letter-spacing: 3px;
  color: var(--text-primary);
}
.pairing-input {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  letter-spacing: 3px;
  text-align: center;
  text-transform: uppercase;
}

/* ---------- Souhrnné dlaždice a audit tipu ---------- */
.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);
}

/* ---------- Výběr z více možností ---------- */
/* Zaškrtávátka do sloupců, ať se čtrnáct krajů ani šest typů nerozlije do sloupce
   dlouhého přes celou obrazovku. Šířka sloupce je na nejdelší název kraje. */
.choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: var(--sp-1) var(--sp-3);
}
/* Typů tipů je šestatřicet - bez omezení výšky by formulář narostl na tři obrazovky.
   Spodní odsazení je větší než horní schválně: poslední řádek se tak neslepí s hranou
   a je na první pohled vidět, že seznam pokračuje. */
/* Náznak, že seznam pokračuje. Bez něj vypadá useknutý řádek na spodní hraně jako
   chyba vykreslení, ne jako scroll. Gradient nereaguje na dojetí na konec - to by
   chtělo sledovat scroll a kvůli dvěma pixelům to nestojí za to. */
.choice-scroll-wrap {
  position: relative;
}
.choice-scroll-wrap::after {
  content: '';
  position: absolute;
  right: 1px;
  bottom: 1px;
  left: 1px;
  height: var(--sp-6);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  background: linear-gradient(to bottom, transparent, var(--bg-muted));
  pointer-events: none;
}
.choice-scroll {
  max-height: 280px;
  overflow-y: auto;
  padding: var(--sp-3) var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-muted);
}

/* ---------- Pozvánky ---------- */
/* Odkaz a jeho akce na jednom řádku. Tlačítka si drží šířku textu, aby se
   „Zkopírováno" nezalomilo; v úzké kartě se řádek zalomí a pole zůstane čitelné. */
.invite-link {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
}
.invite-link .form-control {
  /* Dlouhý odkaz nesmí roztáhnout kartu, ale ani se scvrknout na pár znaků -
     pod 12rem se radši zalomí celý řádek. */
  flex: 1 1 12rem;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}
.invite-link .btn {
  flex: none;
  white-space: nowrap;
}
.invite-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border-default);
}
.invite-item {
  display: flex;
  gap: var(--sp-3);
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-default);
  font-size: var(--fs-sm);
}

/* ---------- Ikona tipu ---------- */
/* Ikona a text vedle sebe - ve výpisu i v hlavičce detailu. Ikona se nesmí zmenšit
   pod svou velikost (flex: none), jinak by ji dlouhý název typu stlačil. */
.tip-cell {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
/* Seznam posledních tipů na nástěnce. Není to tabulka - sloupce by tu nic nepřidaly
   a na telefonu by se stejně sesypaly pod sebe. Celý řádek je odkaz, protože mířit
   na tříslovný text je zbytečná práce navíc. */
.tip-feed {
  list-style: none;
  margin: 0;
  padding: 0;
}
.tip-feed-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-default);
  color: var(--text-primary);
  text-decoration: none;
}
.tip-feed li:last-child .tip-feed-item {
  border-bottom: 0;
  padding-bottom: 0;
}
.tip-feed-item:hover {
  color: var(--color-primary);
}
.tip-feed-text {
  flex: 1;
  min-width: 0;
}
.tip-feed-title {
  display: block;
  font-weight: 500;
}
/* Lokalita bývá dlouhá adresa - jedno slovo bez mezery by jinak roztáhlo kartu. */
.tip-feed-meta {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.tip-icon {
  flex: none;
  object-fit: contain;
  /* Podklady jsou kreslené v jedné modré. V tmavém režimu by na tmavém podkladu
     zanikly, proto se v něm rozjasní. */
  display: block;
}
:root[data-theme='dark'] .tip-icon {
  filter: brightness(1.35);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .tip-icon {
    filter: brightness(1.35);
  }
}

/* Historie stavů: svislá linka se záznamy, nejstarší nahoře. */
.tip-timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--sp-4);
  border-left: 2px solid var(--border-default);
}
.tip-event {
  position: relative;
  padding-bottom: var(--sp-4);
}
.tip-event:last-child {
  padding-bottom: 0;
}
.tip-event::before {
  content: '';
  position: absolute;
  left: calc(-1 * var(--sp-4) - 5px);
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--border-strong);
}

/* ---------- Profil a výchozí provize ---------- */
/* Jméno je jeden údaj rozdělený do čtyř polí (rozhodnutí A9 a A13), 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;
}
/* Pole jednoho účtu patří na jeden řádek - je to jeden údaj, ne čtyři. Měna je užší
   než zbytek: je to trojpísmenný kód ze selectu, ne psaná hodnota. */
.bank-account-row {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr 1fr;
  gap: var(--sp-3);
  align-items: start;
}
.bank-account-row .mb-3 {
  margin-bottom: 0;
}
/* IBAN a SWIFT na vlastním řádku. IBAN má dvacet čtyři znaků a do čtvrtiny šířky se
   nevejde, takže dostává dvě třetiny a SWIFT zbytek. */
.iban-row {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--sp-3);
  align-items: start;
}
.iban-row .mb-3 {
  margin-bottom: 0;
}

/* Řádek nastavení provize: název typu, částka, měna. */
.provision-row {
  display: grid;
  grid-template-columns: 1fr 140px 90px;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--border-default);
}
.provision-row:last-child {
  border-bottom: none;
}
.provision-label {
  font-size: var(--fs-sm);
  color: var(--text-primary);
}
@media (max-width: 575px) {
  .name-row,
  .bank-account-row,
  .iban-row,
  .provision-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,
  .bank-account-row .mb-3,
  .iban-row .mb-3 {
    margin-bottom: var(--sp-4);
  }
}

/* ---------- Schránka upozornění ---------- */
.notification-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  line-height: 1;
}
.notification-icon {
  display: block;
}
/* Odznak s počtem nepřečtených - sedí na rohu zvonečku, ne vedle něj. */
.notification-badge {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 18px;
  padding: 0 4px;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  color: var(--text-on-primary);
  background: var(--color-danger);
  border-radius: var(--radius-full);
}
.notification-menu {
  left: auto;
  right: 0;
  width: 340px;
  max-height: 420px;
  overflow-y: auto;
}
.notification-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}
.notification-empty {
  padding: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.notification-item {
  display: block;
  width: 100%;
  padding: var(--sp-3);
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--text-primary);
}
.notification-item:hover {
  background: var(--bg-muted);
}
/* Nepřečtené drží proužek vlevo - barva textu by v tmavém režimu nestačila. */
.notification-item.is-unread {
  border-left: 3px solid var(--color-primary);
}
/* Hlášení aplikace drží proužek pořád, ne jen dokud je nepřečtené: otevření schránky
   označí všechno přečtené naráz, takže proužek vázaný na `is-unread` by se nikdy
   neukázal. Barva odlišuje typ zprávy, ne její stav - modrá „někdo ti píše",
   oranžová „tohle udělala aplikace, případně to vyřiď". */
.notification-item.is-system {
  border-left: 3px solid var(--color-warning);
}
.notification-tag {
  display: inline-block;
  margin-right: var(--sp-2);
  padding: 0 var(--sp-1);
  border-radius: var(--radius-sm);
  background: var(--color-warning-bg);
  color: var(--color-warning);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  vertical-align: 1px;
}
.notification-title {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.notification-text {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.notification-time {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-tertiary);
}

/* ---------- Veřejný katalog makléřů (rozhodnutí A18) ---------- */
/* Karty, ne tabulka: katalog se prochází očima a čte na mobilu, kdežto DataGrid je
   nástroj administrace - řazení podle sloupců a stránkování po padesáti tady nikomu
   nepomůže. */
.catalogue-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-4);
  margin-bottom: var(--sp-8);
}
.catalogue-filter {
  flex: 1 1 220px;
  min-width: 0;
}
.catalogue-filter .form-label {
  margin-bottom: var(--sp-1);
}
/* Tlačítko lícuje s poli, ne s jejich popisky - proto vlastní odsazení místo align. */
.catalogue-filters-reset {
  flex: 0 0 auto;
}
.catalogue-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--sp-5);
}
.catalogue-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  height: 100%;
  padding: var(--sp-5);
  background: var(--bg-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card), var(--shadow-sm);
  transition: box-shadow var(--transition);
}
.catalogue-card:hover {
  box-shadow: var(--shadow-card), var(--shadow-md);
}
.catalogue-card-head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  color: var(--text-primary);
}
.catalogue-card-head:hover h3 {
  color: var(--color-primary);
}
.catalogue-card-title {
  min-width: 0;
}
.catalogue-card-title h3 {
  font-size: var(--fs-lg);
  font-weight: 600;
  margin-bottom: var(--sp-1);
}
/* Hvězdičky drží pravý okraj hlavičky a nesmí se zalomit pod jméno. */
.catalogue-card-rating {
  margin-left: auto;
  flex: none;
  align-self: flex-start;
}
/* Tlačítko vlevo, logo vpravo. `margin-top: auto` sráží patu ke spodku karty, takže
   mřížka drží tlačítka na jedné lince i u karet s různě dlouhým výčtem typů. */
/* Tlačítko vpravo, logo vlevo. `row-reverse` místo přeházení v JSX: hlavní akce má
   v pořadí dokumentu zůstat první, jen se vykreslí na druhé straně. */
.catalogue-card-foot {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  margin-top: auto;
}
/* Logo v patě je značka firmy, ne ikonka - v grafickém návrhu zabírá vedle tlačítka
   celý zbytek řádku. `max-width` v procentech mu nedovolí tlačítko vytlačit. */
.catalogue-card-logo {
  max-width: 45%;
  max-height: 32px;
  width: auto;
  object-fit: contain;
  object-position: left center;
  flex: 0 1 auto;
}
.catalogue-card-regions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
}
/* Popisek typů se nesmí roztáhnout do několika řádků a rozhodit výšku karet v mřížce. */
.catalogue-card-types {
  margin-bottom: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.catalogue-avatar {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: var(--radius-full);
  /* cover, ne contain: fotky se neořezávají při nahrání (bradu by usekl server
     naslepo), takže je na čtverec srovná až tohle - a je to vratné. */
  object-fit: cover;
  background: var(--bg-muted);
}
.catalogue-avatar-empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: var(--fs-xl);
  color: var(--text-tertiary);
}
.catalogue-avatar-lg {
  width: 112px;
  height: 112px;
  font-size: var(--fs-3xl);
}
.catalogue-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}
.catalogue-detail-head {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  margin-bottom: var(--sp-8);
}
.catalogue-detail-head h1 {
  font-size: var(--fs-3xl);
  font-weight: 700;
  margin-bottom: var(--sp-2);
}
.catalogue-detail-logo {
  max-width: 160px;
  max-height: 80px;
  object-fit: contain;
  margin-left: auto;
}
/* Popisek je prostý text, ale uživatel v něm odřádkoval - bez tohohle by se slil. */
.catalogue-detail-bio {
  white-space: pre-line;
}
@media (max-width: 720px) {
  .catalogue-detail-head {
    flex-wrap: wrap;
    gap: var(--sp-4);
  }
  .catalogue-detail-logo {
    margin-left: 0;
  }
}

/* ---------- Číselník zdrojů registrace (rozhodnutí A24) ---------- */
/* Seznam, ne tabulka: položek jsou jednotky, mají tři údaje a nejčastější úkon je
   zkopírovat odkaz - na to je řádek s tlačítky po pravé straně lepší než sloupce. */
.source-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.source-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-default);
}
.source-list li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
/* Vypnutý kód zůstává čitelný, jen ustoupí - staré registrace na něj pořád ukazují. */
.source-inactive {
  opacity: 0.6;
}
/* Adresa je jedno dlouhé slovo; bez zalomení roztáhne kartu na mobilu. */
.source-url {
  font-family: var(--font-mono);
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

/* ---------- Urgence tipu (zadání „Urgence a důvod u tipu") ---------- */
/* Vlastní prvek, ne varianta `.badge`: barva stavového štítku je vyhrazená koncům
   cesty tipu (B10), a kdyby urgenci nesla taky barva, přestala by znamenat výsledek.
   Odznak je proto obtažený, ne vyplněný - na první pohled patří k jiné kategorii. */
.urgent-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin-left: var(--sp-2);
  padding: 0 var(--sp-2);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-sm);
  color: var(--color-warning);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  vertical-align: middle;
}

/* ---------- Příloha tipu (zadání „Příloha u tipu") ---------- */
/* Pole pro výběr sdílí vzhled s nahráním obrázku v profilu - je to tentýž úkon.
   Vlastní jsou jen dvě věci: značka typu tam, kde náhled nedává smysl (PDF), a
   náhled v detailu. */
.attachment-kind {
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
}
/* Náhled se drží v rozumné výšce: fotka na výšku by jinak vytlačila zbytek karty
   mimo obrazovku. Obrázek se nikdy neořezává - příloha má něco doložit. */
.attachment-preview {
  display: block;
  margin-bottom: var(--sp-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-muted);
}
.attachment-preview img {
  display: block;
  width: 100%;
  max-height: 320px;
  object-fit: contain;
}
.attachment-meta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  /* Jméno souboru je jedno slovo a bývá dlouhé. */
  overflow-wrap: anywhere;
}

/* ---------- Nahrání obrázku ve veřejném profilu ---------- */
.image-upload {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.image-upload-preview {
  width: 96px;
  height: 96px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-muted);
  color: var(--text-tertiary);
  font-size: var(--fs-xs);
  text-align: center;
  overflow: hidden;
}
.image-upload-preview img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.image-upload-actions {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

/* ---------- Propagační materiály ---------- */

/* Náhled je skutečné SVG ve své velikosti, jen zmenšené — proto se obaluje
   a škáluje, ne aby se mu měnily rozměry. Kdyby se zmenšovalo samotné SVG,
   lišil by se náhled od staženého souboru. */
.promo-nahled {
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: #fff;
}

.promo-nahled svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Náhledy se drží své skutečné velikosti, ne šířky karty: nafouknutý podpis
   svádí k tomu myslet si, že takhle velký přijde i do e-mailu. */
.promo-nahled-podpis {
  max-width: 600px;
}

/* Formáty pro sítě vedle sebe: liší se jen poměrem stran, takže se porovnávají,
   ne čtou po jednom. Šířka sloupce se řídí místem — na širokém monitoru se jich
   vejde pět, na telefonu jeden. */
.promo-mrizka {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--sp-4);
  /* Dlaždice mají různou výšku (9:16 proti 1,91:1), ale mají začínat na stejné lince. */
  align-items: start;
}

.promo-dlazdice {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* Náhled má v mřížce pevnou výšku a obrázek se do ní vepíše. Bez toho začínají
   popisky každé dlaždice jinde (9:16 je dvakrát vyšší než 1,91:1) a řádek se nedá
   přečíst jedním pohledem — přitom kvůli porovnání jsou formáty vedle sebe. */
.promo-dlazdice .promo-nahled {
  height: 20rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-2);
}

.promo-dlazdice .promo-nahled svg {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}

.promo-dlazdice figcaption {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.promo-hlavicka {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-3);
}

.promo-letaky {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.promo-letaky li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border-default);
}

.promo-letaky li:last-child {
  padding-bottom: 0;
  border-bottom: none;
}

/* Výběr barvy materiálů: tři způsoby zadání vedle sebe, na úzké obrazovce pod sebou. */
.promo-barva {
  display: grid;
  grid-template-columns: minmax(12rem, 18rem) minmax(14rem, 1fr);
  gap: var(--sp-4);
  align-items: start;
}

@media (max-width: 48rem) {
  .promo-barva {
    grid-template-columns: 1fr;
  }
}

.promo-barva-hex {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
}

/* Nativní vzorek prohlížeče: výchozí podoba má tlustý rám a jinou výšku než pole
   vedle něj, takže se srovnává ručně. */
.promo-barva-vzorek {
  width: 3rem;
  height: 2.5rem;
  padding: 2px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  cursor: pointer;
  flex: 0 0 auto;
}

.promo-barva-spektrum {
  width: 100%;
  height: 1.75rem;
  margin: 0 0 var(--sp-2) 0;
  appearance: none;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  cursor: pointer;
  /* Duha napříč celým odstínem: posuvník má ukazovat, co vybírá. */
  background: linear-gradient(
    to right,
    #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%
  );
}

.promo-barva-spektrum::-webkit-slider-thumb {
  appearance: none;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--border-strong);
  cursor: pointer;
}

.promo-barva-spektrum::-moz-range-thumb {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--border-strong);
  cursor: pointer;
}

/* Zarovnání a mezery drží `.form-actions-end`; tady se jen roztáhne přes obě
   sloupce mřížky a povolí zalomení na úzké obrazovce. */
/* Přepínač jazyka v liště. Užší než běžný select - vedle zvonečku a motivu 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á zvoneček, 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;
  }
}

.promo-barva-akce {
  grid-column: 1 / -1;
  flex-wrap: wrap;
}
