/* ============================================================================
   Administrace (backoffice) — vlastní vizuální vrstva NAD Bootstrapem 5.3.

   Tenhle soubor je čistě adminní: načítá ho `assets/app.js`, tedy jen
   `base.html.twig` (přihlášená administrace) a `security_base.html.twig`
   (přihlášení / obnova hesla). Veřejné weby zákazníků si linkují svou šablonu
   a `webotron-blocks.css` a `app` entrypoint vůbec nemají — pravidla odsud se
   k nim nedostanou, proto se tu smí psát i na holé `body`.

   Pravidla barev: ŽÁDNÝ hex ani rgb() natvrdo. Celá paleta se odvozuje
   z Bootstrapových proměnných (`--bs-body-bg`, `--bs-border-color`,
   `--bs-emphasis-color-rgb`, `--bs-primary-rgb`, …) přes `color-mix()`
   a `rgba(var(--…-rgb), α)`. Admin tak automaticky sedí na Bootstrapovu
   světlou/tmavou paletu a nemá vlastní, druhou pravdu o barvách.
   ========================================================================= */

/* --------------------------------------------------------------------------
   Písmo. Tělo administrace nese platformní `--font-platform-body` (Inter jako
   rodina `InterAdmin`), wordmark `--font-wordmark` (Audiowide) — obojí i s
   `@font-face` deklaracemi dodává `templates/components/_platform_fonts.html.twig`
   z `App\Service\PlatformFontRegistry` (GH #121). Deklarace tady schválně NEJSOU:
   interní panel `/admin` `app.css` záměrně nenačítá (viz `Admin\DashboardController`)
   a marketingový web platformy jede přes zákaznickou šablonu — druhá kopie
   `@font-face` v tomhle souboru by tedy identitu pokrývala jen na části povrchů
   a rozešla by se s registrem při první změně řezu.

   Záložní stack za `var()` je pojistka, ne nosná větev: partial se vkládá do obou
   šablon, které `app.css` načítají (`base`, `security_base`).
   -------------------------------------------------------------------------- */

:root {
    /* Poloměry: Bootstrap míchá 6 px (`.btn`) a 4 px (`.btn-sm`, `.form-control-sm`),
       takže vedle sebe stojící ovládací prvky mají různý tvar. Admin sjednocuje
       obojí na 8 px a kartám dává 12 px — jeden tvarový jazyk pro celý backoffice. */
    --bs-border-radius: 0.5rem;
    --bs-border-radius-sm: 0.5rem;
    --bs-border-radius-lg: 0.75rem;
    --bs-border-radius-xl: 1rem;

    /* Odvozená paleta administrace. */
    --wa-canvas: color-mix(in srgb, var(--bs-tertiary-bg) 55%, var(--bs-secondary-bg));
    --wa-panel: var(--bs-body-bg);
    --wa-line: var(--bs-border-color);
    --wa-line-soft: color-mix(in srgb, var(--bs-border-color) 55%, var(--bs-body-bg));
    --wa-ink: var(--bs-emphasis-color);
    --wa-ink-muted: var(--bs-secondary-color);
    --wa-hover: rgba(var(--bs-emphasis-color-rgb), 0.045);
    --wa-hover-strong: rgba(var(--bs-emphasis-color-rgb), 0.075);
    --wa-accent-tint: rgba(var(--bs-primary-rgb), 0.09);
    --wa-danger-tint: rgba(var(--bs-danger-rgb), 0.09);
    --wa-shadow-xs: 0 1px 2px rgba(var(--bs-emphasis-color-rgb), 0.05);
    --wa-shadow-sm: 0 1px 2px rgba(var(--bs-emphasis-color-rgb), 0.04), 0 1px 3px rgba(var(--bs-emphasis-color-rgb), 0.06);
    --wa-shadow-md: 0 1px 2px rgba(var(--bs-emphasis-color-rgb), 0.04), 0 12px 28px -14px rgba(var(--bs-emphasis-color-rgb), 0.28);

    --wa-sidebar-width: 15.5rem;
    --wa-content-max: 76rem;
    --wa-gutter: 2rem;

    /* Velikost dialogu výběru obrázku (GH #564). Pevná, ne podle obsahu: nativní
       <dialog> se bez ní roztáhne podle toho, co je v něm právě vidět, takže dialog
       při každém přepnutí záložky skočil do jiné velikosti. Knihovna médií je mřížka –
       chce se v ní vidět co nejvíc dlaždic naráz, proto „téměř celá obrazovka“ (přání
       majitele produktu), s horní hranicí, aby na širokém monitoru nebyla mřížka
       roztažená přes celou šířku. Na úzkém viewportu vyhraje procentní část a dialog
       zabere prakticky celou plochu. */
    --wa-media-picker-width: min(92vw, 72rem);
    --wa-media-picker-height: min(88vh, 48rem);

    /* Odsazení úrovně stromu stránek nástěnky (GH #84, vlna 1 bod 2) – NAMĚŘENO
       v prototypu (docs/superpowers/specs/2026-08-27-hierarchie-stranek-prototyp.html,
       spec §9.3), ne odhadnuto: 24 px je jediná hodnota, která ve všech třech
       rozvrženích výpisu nepřidá zalomený řádek. Na telefonu (@media níž) klesá
       na 16 px ze stejného důvodu. */
    --wa-tree-indent: 24px;
}

body {
    font-family: var(--font-platform-body, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);
    -webkit-font-smoothing: antialiased;
}

/* Nadpisy: Bootstrap dává všem `font-weight: 500` a lineární škálu, takže
   „nadpis stránky" a „nadpis karty" vedle sebe neznějí jinak. Admin má tři
   hlasitosti a drží je pevně. */
.dashboard-shell h1,
.dashboard-shell h2,
.dashboard-shell h3,
.dashboard-shell h4,
.dashboard-shell h5,
.dashboard-shell h6 {
    font-weight: 600;
    letter-spacing: -0.011em;
    color: var(--wa-ink);
}

/* ==========================================================================
   1. Skořápka: postranní panel + horní lišta + obsah
   ========================================================================== */

.dashboard-shell {
    display: flex;
    min-height: 100vh;
    background-color: var(--wa-canvas);
    /* 15px místo 16px — hustota, na kterou jsou administrace zvyklé. Bootstrap
       z téhle proměnné počítá i `.form-control` a `.btn`, takže se zmenší
       konzistentně celá sada ovládacích prvků, ne jen text. */
    --bs-body-font-size: 0.9375rem;
    font-size: var(--bs-body-font-size);
}

/* -------- Postranní panel -------- */

.dashboard-sidebar {
    width: var(--wa-sidebar-width);
    flex-shrink: 0;
    /* Panel plave nad `--wa-canvas` (tip 22) jako každá jiná karta v adminu
       (`.dashboard-shell .card` níž) – odsazení + zaoblení + stín ho vizuálně
       odlepí od okrajů obrazovky, kde dřív splýval s podkladem. `top`/`max-height`
       počítají s odsazením shora i zdola, jinak by se sticky panel při scrollu
       zaříznul o dolní hranu okna. Mobilní větev (níž v @media) tohle všechno
       ruší – tam se panel vysouvá přes obsah přes celou šířku. */
    background-color: var(--wa-panel);
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--wa-shadow-xs);
    position: sticky;
    top: 1rem;
    margin: 1rem 0 1rem 1rem;
    align-self: flex-start;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
    padding: 1.25rem 0.875rem 1rem;
    gap: 0.25rem;
}

.dashboard-brand {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.25rem 0.5rem 0;
    margin-bottom: 1.5rem;
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: -0.02em;
    color: var(--wa-ink);
    text-decoration: none;
}

/* Nápis „Webotron" (GH #121). Samotné `font-family: var(--font-wordmark)` sedí
   v `components/_platform_fonts.html.twig` (spolu se zrušením prostrkání, které
   wordmark dědí z `.dashboard-brand`), aby ho měly i povrchy bez `app.css` – interní
   panel a marketingový web. Tady zůstává jen adminní doladění velikosti: displayové
   řezy mají menší optický dojem tloušťky než grotesk ve stejné velikosti bodu. */
.wordmark {
    font-size: 1.05em;
}

/* Značka vedle nápisu je TÁŽ dlaždice jako favikona platformy (GH #658):
   modrý čtverec `--bs-primary` se zaoblením 8/28 plochy a bílé „W". Do #658 v ní
   ale stálo „W" v tělovém písmu, takže po zavedení skutečné favikony by měl uživatel
   vedle sebe dvě různá „W" – v záložce jedno, v postranním panelu druhé. Řez se proto
   bere ze stejného zdroje jako nápis vedle ní. Audiowide je širší než grotesk, takže
   se stejné optické váhy dosáhne o stupeň níž a bez `font-weight` (řez má jedinou
   váhu, 400 – `700` by prohlížeč jen uměle ztučnil). */
.dashboard-brand__mark {
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    flex-shrink: 0;
    border-radius: 0.5rem;
    background-color: var(--bs-primary);
    color: var(--bs-white);
    font-family: var(--font-wordmark);
    font-size: 0.75rem;
}

.dashboard-nav__section {
    padding: 0.5rem 0.625rem 0.25rem;
    margin-top: 0.75rem;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--wa-ink-muted);
}

.dashboard-nav__section:first-child {
    margin-top: 0;
}

/* Skupina panelu schovaná za rolí – GH #570, dnes jedině „Staff". Nadpis skupiny
   odděluje sám, linka nad ním navíc říká, že tady začíná blok, který má jiné
   publikum než skupiny nad ním. Neslibuje, že je to konec zákaznické části panelu:
   za skupinami je ještě neskupinová sekce „Tato stránka", kterou vidí každý.
   Vlasová linka a odsazení, ne barva ani odznak: je to hranice v pořadí, ne stav,
   na který by měl staff koukat. Jméno kopíruje podmínku, která třídu nasazuje
   (`group.role is defined`), ne význam „interní" – viz komentář v `base.html.twig`. */
.dashboard-nav__section--role-gated {
    margin-top: 1.25rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--wa-line-soft);
}

.dashboard-nav .nav-link {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.4375rem 0.625rem;
    margin-bottom: 0.0625rem;
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink);
    font-size: 0.9375rem;
    font-weight: 500;
    line-height: 1.4;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.dashboard-nav .nav-link:hover,
.dashboard-nav .nav-link:focus-visible {
    background-color: var(--wa-hover);
    color: var(--wa-ink);
}

.dashboard-nav .nav-link.active {
    background-color: var(--wa-accent-tint);
    color: var(--bs-primary);
    font-weight: 600;
}

/* Položka „Průvodce zatím není k dispozici" (GH #371) – vypadá jako
   `.nav-link`, ale je to `<span>` bez `tabindex`, ne odkaz ani tlačítko:
   kliknout ani najet fokusem se na ni nedá, proto tu není `:focus-visible`.
   `cursor: default` a ztlumená barva to potvrzují i vizuálně, ne jen
   sémanticky. Selektor musí být `.dashboard-nav .nav-link.dashboard-nav__link--disabled`
   (specificita 0,3,0), ne jen `.dashboard-nav__link--disabled` (0,1,0) –
   jinak prohraje proti `.dashboard-nav .nav-link` (0,2,0) výš a položka se
   vykreslí plnou barvou. */
.dashboard-nav .nav-link.dashboard-nav__link--disabled {
    color: var(--wa-ink-muted);
    cursor: default;
}

.dashboard-nav .nav-link.dashboard-nav__link--disabled:hover {
    background-color: transparent;
    color: var(--wa-ink-muted);
}

.dashboard-nav__link--disabled .dashboard-nav__icon {
    opacity: 0.4;
}

.dashboard-nav__icon {
    flex-shrink: 0;
    width: 1.0625rem;
    height: 1.0625rem;
    opacity: 0.7;
}

.dashboard-nav .nav-link.active .dashboard-nav__icon {
    opacity: 1;
}

/* Ikony NA opakujících se tlačítkách (uložit/zpět/přidat/smazat), ne v panelu.
   `.dashboard-nav__icon` je zmatelá s `opacity: .7` (vybledlá vedle plného
   textu `.btn-primary`) a `1.0625rem` (velká vedle `.btn-sm`) – obojí je
   naladěné na ztlumené odkazy v postranním panelu, ne na tlačítka. */
.admin-btn__icon {
    flex-shrink: 0;
    width: 0.9375rem;
    height: 0.9375rem;
}

.dashboard-user {
    margin-top: auto;
    padding: 0.875rem 0.625rem 0;
    border-top: 1px solid var(--wa-line-soft);
}

.dashboard-user__email {
    display: block;
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
    margin-bottom: 0.375rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-decoration: none;
}

.dashboard-user__email:hover {
    color: var(--bs-primary);
    text-decoration: underline;
}

.dashboard-user__logout {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--wa-ink-muted);
    text-decoration: none;
}

.dashboard-user__logout:hover {
    color: var(--bs-danger);
}

/* Přepínač motivu administrace (GH #601): tři volby vedle sebe (světlý / tmavý /
   automaticky), ne jedno cyklující tlačítko. Popisek „Motiv" vlevo, segmentovaná
   trojice ikon vpravo – do panelu širokého `--wa-sidebar-width` se to vejde
   s rezervou, protože jsou volby jen ikonové (jméno nese `aria-label`/`title`).

   Dřív tu bylo jedno tlačítko s `.btn.btn-link` a celý blok pravidel na to, jak
   přebít Bootstrapův `.btn` (specificita `.dashboard-shell .btn` je (0,2,0),
   takže scope selektor sám nestačil). Segmenty `.btn` vůbec nenosí, takže ta
   válka o specificitu odpadla i s ní – styluje se holé `<button>`. */
.dashboard-nav__theme {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.dashboard-nav__theme-caption {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--wa-ink-muted);
}

/* Podklad skupiny je `--wa-canvas`, panel kolem ní `--wa-panel` – aktivní segment
   se pak zvýrazní tím, že se z něj „vynoří" zpět na barvu panelu, bez akcentní
   barvy navíc. */
.dashboard-nav__theme-options {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
    padding: 0.1875rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.dashboard-nav__theme-option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.875rem;
    height: 1.625rem;
    padding: 0;
    border: 0;
    border-radius: calc(var(--bs-border-radius) - 0.1875rem);
    background-color: transparent;
    color: var(--wa-ink-muted);
}

.dashboard-nav__theme-option:hover {
    color: var(--wa-ink);
    background-color: var(--wa-hover);
}

/* Prstenec explicitně: segmenty jsou tři sousední tlačítka bez vlastního
   rámečku, takže by po nich klávesnice putovala neviditelně. `outline-offset`
   je záporný, aby se prstenec vešel dovnitř skupiny a nepřelezl přes sousedy. */
.dashboard-nav__theme-option:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

/* Vlastní velikost, ne `.dashboard-nav__icon`: ten má `opacity: 0.7` naladěnou na
   ztlumené odkazy panelu a rozdíl mezi aktivní a neaktivní volbou by tím zeslábl
   na půl. Tady nese stav barva, ne průhlednost. */
.dashboard-nav__theme-icon {
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
}

/* Aktivní volbu vybírá `data-wa-theme-choice` na `<html>` (VOLBA uživatele), ne
   `data-bs-theme` (výsledná barva): u automatiky se ty dva liší a zvýraznit se má
   „Automaticky", ne „Tmavý". Atribut sází blokující skript v <head>, takže je
   zvýraznění správné hned při prvním vykreslení.

   Poslední selektor je pojistka pro případ, že skript v <head> vůbec neproběhne
   (chyba, blokované skripty): výchozí stav je automatika, tak ať je zvýrazněná
   i bez atributu. */
[data-wa-theme-choice="light"] .dashboard-nav__theme-option--light,
[data-wa-theme-choice="dark"] .dashboard-nav__theme-option--dark,
[data-wa-theme-choice="auto"] .dashboard-nav__theme-option--auto,
:root:not([data-wa-theme-choice]) .dashboard-nav__theme-option--auto {
    color: var(--wa-ink);
    background-color: var(--wa-panel);
    box-shadow: var(--wa-shadow-xs);
}

/* -------- Hlavní sloupec + horní lišta -------- */

.dashboard-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.dashboard-topbar {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 3.25rem;
    padding: 0.5rem 1.25rem;
    background-color: color-mix(in srgb, var(--wa-panel) 88%, transparent);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--wa-line-soft);
}

.dashboard-topbar__burger {
    display: inline-grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 1px solid var(--wa-line);
    border-radius: var(--bs-border-radius);
    background-color: transparent;
    color: var(--wa-ink);
}

.dashboard-topbar__spacer {
    flex: 1 1 auto;
}

/* Lišta bez obsahu (jediný web, vypnutá zpětná vazba) se na desktopu nekreslí —
   prázdný 52px pruh nad každou stránkou je jen mrtvé místo. Na mobilu zůstává,
   protože nese tlačítko navigace. */
@media (min-width: 992px) {
    .dashboard-topbar--bare {
        display: none;
    }
}

/* Přepínač webů (tip 20) – dropdown v postranním panelu, ne pilulky v topbaru
   (nahrazená podoba, viz historie base.html.twig). Tlačítko vypadá jako
   `.dashboard-nav .nav-link` výš, aby v panelu nepůsobilo jako cizí prvek. */
/* Přepínač webů (GH #258): jeden řádek, dvě podoby. S jedním webem je vlevo
   popisek (`__current`), s víc rozbalovací tlačítko (`__toggle`) – obojí má
   schválně identický box, aby se panel při založení druhého webu vizuálně
   nepohnul. Vpravo `+` na nový web, protože zakládání patří k volbě webu. */
.dashboard-site-switcher {
    display: flex;
    align-items: stretch;
    gap: 0.375rem;
    margin-bottom: 1rem;
}

.dashboard-site-switcher__picker {
    flex: 1 1 auto;
    min-width: 0;
}

.dashboard-site-switcher__toggle,
.dashboard-site-switcher__current {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4375rem 0.625rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-hover);
    color: var(--wa-ink);
    font-size: 0.875rem;
    font-weight: 600;
}

/* Jen `__toggle`: popisek jediného webu se nikam neklikne, takže ani nesmí
   reagovat na najetí myší – jinak slibuje akci, která neexistuje. */
.dashboard-site-switcher__toggle:hover,
.dashboard-site-switcher__toggle:focus-visible {
    background-color: var(--wa-hover-strong);
}

.dashboard-site-switcher__add {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2.125rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink-muted);
    text-decoration: none;
}

.dashboard-site-switcher__add:hover,
.dashboard-site-switcher__add:focus-visible {
    background-color: var(--wa-hover-strong);
    color: var(--wa-ink);
}

.dashboard-site-switcher__add svg {
    width: 1rem;
    height: 1rem;
}

.dashboard-site-switcher__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}

.dashboard-site-switcher .dropdown-menu {
    width: 100%;
}

.dashboard-site-switcher__item {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0 0.25rem;
}

.dashboard-site-switcher__item form,
.dashboard-site-switcher__item .dropdown-item {
    flex: 1 1 auto;
    min-width: 0;
}

/* Odznak PRO u položek panelu, které tarif skutečně zamyká (odvozeno z
   `App\Enum\Feature`, viz base.html.twig). `margin-left: auto` ho drží při
   pravém okraji řádku bez ohledu na délku popisku vlevo. */
.dashboard-nav__pro-badge {
    margin-left: auto;
    padding: 0.0625rem 0.375rem;
    border-radius: 999px;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    background-color: var(--wa-accent-tint);
    color: var(--bs-primary);
}

/* -------- Obsah -------- */

.dashboard-content {
    flex: 1 1 auto;
    min-width: 0;
    padding: 1.75rem var(--wa-gutter) 4rem;
}

.dashboard-content__inner {
    max-width: var(--wa-content-max);
    margin-inline: auto;
}

/* Flash zprávy patří nad obsah stránky, ne nad celou skořápku (dřív visely
   ještě nad postranním panelem). */
.admin-flash {
    border: 1px solid transparent;
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--wa-shadow-xs);
    font-size: 0.9375rem;
}

/* ==========================================================================
   2. Hlavička stránky, drobečky, prázdné stavy
   ========================================================================== */

.admin-page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem 1.5rem;
    margin-bottom: 1.125rem;
}

.admin-page-title {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 650;
    line-height: 1.25;
    letter-spacing: -0.02em;
}

/* GH #598: `max-width: 62ch` vynucovalo čitelnou délku řádku na ODSTAVCI, jenže karta
   ani hlavička kolem něj žádnou takovou šířku nemá — drží se stropu celého obsahu
   (`--wa-content-max: 76rem`). Na širokém monitoru tak vpravo zbyla prázdná plocha přes
   půl šířky a vypadalo to jako rozbitý layout (nahlásil majitel produktu na
   `/nastaveni-mcp`). Strop řádku proto od 75rem výš drží `.dashboard-content__inner`,
   tedy jediné místo, kde je i vizuálně vidět. Totéž u `.admin-card-hint`.

   Pod 75rem `ch`-strop zůstává: tam je kontejner stejně užší než 62ch, takže se
   vizuálně neprojevuje, ale drží flex základ hlavičky malý (viz níž). */
.admin-page-lead {
    margin: 0.375rem 0 0;
    max-width: 62ch;
    font-size: 0.9375rem;
    color: var(--wa-ink-muted);
}

@media (min-width: 75rem) {
    .admin-page-lead {
        max-width: none;
    }

    /* Textový sloupec hlavičky (nadpis + lead) si bere zbylé místo, ale do zalomení
       vstupuje se základem 24rem, ne se šířkou svého nejdelšího řádku. Bez toho by
       nezúžený lead nafoukl svůj flex základ přes celou hlavičku a tlačítka vpravo by
       spadla na druhý řádek — naměřeno na /eshop, /eshop/objednavky, /eshop/poukazy,
       /kariera, /rezervace a /socialni-site. Opačným směrem (že by se zalomilo něco, co
       se dřív vešlo — krátký lead měl základ i pod 24rem) pravidlo neuškodí právě proto,
       že platí až od 75rem: přeměřeno na všech 42 bezparametrových obrazovkách adminu
       ve 14 šířkách od 390 do 1920 px, žádná hlavička nepřibrala řádek. */
    .admin-page-header > :first-child {
        flex: 1 1 24rem;
        min-width: 0;
    }
}

/* Tip 49: prstenec obsazenosti úložiště, jen obrys – `conic-gradient` udělá výseč,
   `mask` z ní vykousne střed, takže zbyde tenký kruh, ne vyplněný koláčový graf
   („decentní… jen border", přesně jak chtěl uživatel). `--wa-storage-percent` nese
   Twig hodnotu 0-100 (média/index.html.twig), CSS ji nepočítá, jen vykresluje. */
.media-storage-ring {
    display: inline-block;
    width: 1.125rem;
    height: 1.125rem;
    margin-right: 0.375rem;
    vertical-align: -0.2em;
    border-radius: 50%;
    background: conic-gradient(var(--bs-primary) calc(var(--wa-storage-percent) * 1%), var(--wa-line-soft) 0);
    /* `black`/`transparent`, ne hex: masce jde jen o alfa kanál (plně/vůbec), nikdy
       se nevykreslí jako barva – ale projektové pravidlo „žádný hex v CSS" je psané
       bez výjimky pro masky, tak radši klíčové slovo než literál. */
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), black calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 3px), black calc(100% - 3px));
}

/* Stejný práh jako DashboardAttentionBuilder (`storagePercent() >= 80`) – barva se
   shoduje s `.badge.text-bg-warning`, kterým nástěnka to samé číslo hlásí jako
   upozornění. */
.media-storage-ring--warning {
    background: conic-gradient(var(--bs-warning) calc(var(--wa-storage-percent) * 1%), var(--wa-line-soft) 0);
}

.admin-page-header__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* Vysvětlení, proč tu chybí tlačítko „Smazat stránku" (editor domovské stránky,
   tip 43) – ticho na tomhle místě by vypadalo jako chyba, ne jako pravidlo. */
.admin-page-header__hint {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

.admin-page-header__hint .admin-btn__icon {
    width: 1rem;
    height: 1rem;
}

/* Nadpis sekce uvnitř stránky — mezistupeň mezi H1 a nadpisem karty. */
.admin-section-title {
    margin: 0 0 0.75rem;
    font-size: 1.0625rem;
    font-weight: 600;
}

.admin-subtitle {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--wa-ink-muted);
}

/* Drobečky: záměrně tiché a přisazené k nadpisu, ne plovoucí pruh. */
.dashboard-shell .breadcrumb {
    --bs-breadcrumb-divider-color: var(--wa-ink-muted);
    --bs-breadcrumb-item-padding-x: 0.4375rem;
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
}

.dashboard-shell .breadcrumb-item + .breadcrumb-item::before {
    /* Bootstrap's own rule floats the separator left ("suppress inline spacings and
       underlining"), which drops it out of the line box and top-aligns it to the
       line instead of sitting on the text baseline – fine for a slash, visible as
       an offset "zobáček" for a tall glyph like `›`. Un-floating puts it back into
       normal inline flow so it shares the same baseline as the labels around it. */
    float: none;
    content: '›';
    font-size: 1em;
    line-height: 1;
}

.dashboard-shell .breadcrumb-item a {
    color: var(--wa-ink-muted);
    text-decoration: none;
    border-radius: 0.25rem;
}

.dashboard-shell .breadcrumb-item a:hover {
    color: var(--bs-primary);
    text-decoration: underline;
}

.dashboard-shell .breadcrumb-item.active {
    color: var(--wa-ink);
    font-weight: 500;
}

/* Pozn.: `:empty` by tu bylo k ničemu — Twig do kontejnerů vypisuje odsazení,
   takže uzel „bez obsahu" má v DOMu textový uzel a `:empty` na něj nesedne.
   Proto všude `:not(:has(…))`. */

/* Prázdný stav — ne holý odstavec. Tip 13: uživatel chtěl u CTA na založení
   záznamu (kariéra bez nabídek a spol.) výraznější, „modernější" dashed rámeček –
   `2px`, stejná síla jako `.admin-dropzone` (obrázkové pole, viz níž). Bere se jen
   vzhled, ne ovladač: `.admin-empty` není drag&drop cíl, takže žádný hover/drop
   stav sem nepatří, jen samotná síla čáry. */
.admin-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2rem 1.5rem;
    text-align: center;
    border: 2px dashed var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-panel);
    color: var(--wa-ink-muted);
}

.admin-empty__title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* ==========================================================================
   3. Karty, tabulky, formuláře, tlačítka
   ========================================================================== */

.dashboard-shell .card {
    --bs-card-border-color: var(--wa-line-soft);
    --bs-card-border-radius: var(--bs-border-radius-lg);
    --bs-card-inner-border-radius: calc(var(--bs-border-radius-lg) - 1px);
    --bs-card-cap-bg: transparent;
    --bs-card-spacer-y: 1rem;
    --bs-card-spacer-x: 1.25rem;
    box-shadow: var(--wa-shadow-sm);
}

.dashboard-shell .card > .card-header {
    padding: 0.75rem 1.25rem;
    border-bottom-color: var(--wa-line-soft);
    font-weight: 600;
}

/* Dlouhé formuláře (nastavení webu) dělí obsah do karet a mezeru mezi
   nimi nechávají na Bootstrapí `.mb-3` – to je `!important` utilita, ne
   proměnná, takže bez vlastního `!important` by přepis nezabral. */
.dashboard-shell .card.mb-3 {
    margin-bottom: 0.75rem !important;
}

/* Karta jako „sekce nastavení": nadpis + vysvětlení + pole. */
.admin-card-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}

/* Bez `max-width` schválně, ze stejného důvodu jako `.admin-page-lead` (GH #598) —
   šířku řádku tady drží samotná karta, ne odstavec v ní. */
.admin-card-hint {
    margin: 0.25rem 0 0;
    font-size: 0.875rem;
    color: var(--wa-ink-muted);
}

/* Hledání v seznamu administrace (GH #554, #606) – `/blog`, nástěnka, `/eshop`
   a `/reality`. Pole je omezené šířkou, ne roztažené přes celou kartu: dotaz bývá
   jedno až tři slova a pole na šířku obrazovky by vypadalo jako místo na odstavec.
   Stejný odstup zdola jako `.card.mb-4`, aby seznam pod ním nezačínal jinak vysoko
   než bez hledání. */
.admin-search-form {
    max-width: 32rem;
    margin-bottom: 1.5rem;
}

/* Dlaždice s popiskem POD dlaždicí (volba kompozice na „Nový příspěvek", GH #543).

   Dlaždice je `<label class="btn … h-100">`, popisek je její sourozenec. V Bootstrapí
   mřížce je sloupec flexový prvek, který se roztáhne na výšku řádku – `h-100` pak
   spotřebuje CELOU tu výšku, takže popisek skončí až pod dolní hranou sloupce, přes
   prvek, který tam už stojí (u kompozice „Fotka" panel s nahráním obrázku). Nebyla to
   chyba pozicování ani přetečení textu: popisek se normálně zalomí, jen se vykreslí
   mimo box svého sloupce.

   Subgrid o dvou řádcích to řeší výškou řádku, ne krácením textu: dlaždice dostanou
   první řádek, popisky druhý. Výška prvního řádku roste podle nejvyšší dlaždice,
   druhého podle nejdelšího popisku, dlaždice zůstávají stejně vysoké a celá skupina
   si svoji výšku poctivě nárokuje. Bez podpory subgridu pravidlo propadne na obyčejný
   grid: dlaždice pak nemají stejnou výšku, ale popisek pořád nikam nepřeteče. */
.admin-choice-tiles {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    gap: 0.5rem;
}

/* Od `sm` výš tři dlaždice na řádek, jako předtím `col-sm-4`. `auto-fit` místo
   pevného počtu proto, že kompozic může přibýt. */
@media (min-width: 576px) {
    .admin-choice-tiles {
        grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    }
}

.admin-choice-tiles__option {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: span 2;
}

/* Editor vlastního CSS (tip 19, custom_css_editor_controller.js). Rámeček je zdejší,
   samotné podbarvení textu dělá CodeMirror přes svůj EditorView.theme() – ten čte
   stejné --wa-* proměnné, takže drží krok s přepínáním motivu. */
.admin-css-editor {
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    overflow: hidden;
}

.admin-css-editor__mount .cm-editor {
    height: 100%;
}

.admin-css-editor__mount .cm-scroller {
    min-height: 12rem;
    max-height: 28rem;
    font-family: var(--bs-font-monospace, ui-monospace, monospace);
    font-size: 0.8125rem;
}

/* Nebezpečná zóna (tip 24) – jemně červený rámeček, žádný natvrdo hex (`--wa-danger-tint`
   i "danger" Bootstrap proměnná jsou obojí odvozené z tématu). */
.admin-danger-zone {
    border-color: rgba(var(--bs-danger-rgb), 0.35);
    background-color: var(--wa-danger-tint);
}

.admin-danger-zone__row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 0;
}

.admin-danger-zone__title {
    margin: 0;
    font-weight: 600;
}

.admin-danger-zone__text {
    margin: 0.125rem 0 0;
    max-width: 46ch;
    font-size: 0.875rem;
    color: var(--wa-ink-muted);
}

.admin-danger-zone__delete-form {
    min-width: 16rem;
}

/* FAQ akordeon (Nápověda, GH #377) – nativní `<details>/<summary>`, aby fungoval
   bez JS i bez Stimulus controlleru, jen obalený do stejného tvarového jazyka
   jako `.admin-danger-zone` (rámeček + `--wa-*` proměnné, žádný natvrdo hex). */
.admin-faq {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.admin-faq__item {
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-panel);
}

.admin-faq__item[open] {
    background-color: var(--wa-canvas);
}

.admin-faq__question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    font-weight: 500;
    color: var(--wa-ink);
    cursor: pointer;
    list-style: none;
}

.admin-faq__question::-webkit-details-marker {
    display: none;
}

.admin-faq__question:hover {
    background-color: var(--wa-hover);
}

.admin-faq__chevron {
    flex-shrink: 0;
    width: 0.9375rem;
    height: 0.9375rem;
    color: var(--wa-ink-muted);
    transition: transform 0.15s ease;
}

.admin-faq__item[open] .admin-faq__chevron {
    transform: rotate(180deg);
}

.admin-faq__answer {
    padding: 0.75rem 1rem 0.875rem;
    border-top: 1px solid var(--wa-line-soft);
}

/* Ukázka tvaru vstupu uvnitř nápovědy (vlna C migrace, `/presmerovani`).

   `overflow-x: auto` je celý smysl téhle třídy: ukázka mapy stránek nese plné
   adresy starého webu, takže je delší než karta, a bez vlastního posuvníku by
   vodorovný posuvník dostala celá stránka. Barvy jen proměnnými – nový odstín
   se sem nezavádí, je to táž plocha jako u `.admin-empty`. */
.admin-code-sample {
    margin: 0.5rem 0 0.75rem;
    padding: 0.625rem 0.75rem;
    overflow-x: auto;
    font-size: 0.8125rem;
    background-color: var(--wa-canvas);
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink-muted);
}

/* -------- Postranní navigace sekcí (nastavení webu, GH #367) --------

   Deset karet jednoho formuláře dřív nešlo najít jinak než scrollováním.
   Kotvy, ne záložky/samostatné routy – formulář má jedno tlačítko „Uložit"
   na konci a rozdělení do routů by ho muselo rozštěpit na deset submitů. */

.settings-layout {
    display: flex;
    align-items: flex-start;
    gap: 1.5rem;
}

.settings-toc {
    flex: 0 0 12.5rem;
    position: sticky;
    /* Offset o výšku `.dashboard-topbar` (sticky top: 0) + mezera, jinak by
       panel při scrollu zajel pod ni. */
    top: calc(3.25rem + 1rem);
    max-height: calc(100vh - 3.25rem - 2rem);
    overflow-y: auto;
}

.settings-toc__list {
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
    margin: 0;
    padding: 0;
    list-style: none;
    border-left: 1px solid var(--wa-line-soft);
}

.settings-toc__link {
    display: block;
    padding: 0.375rem 0.75rem;
    margin-left: -1px;
    border-left: 2px solid transparent;
    font-size: 0.875rem;
    color: var(--wa-ink-muted);
    text-decoration: none;
    transition: border-color 0.12s ease, color 0.12s ease;
}

.settings-toc__link:hover,
.settings-toc__link:focus-visible {
    color: var(--wa-ink);
}

.settings-toc__link.active {
    border-left-color: var(--bs-primary);
    color: var(--bs-primary);
    font-weight: 600;
}

.settings-layout__content {
    flex: 1 1 auto;
    min-width: 0;
}

/* Cíl kotvy nesmí přistát pod stejnou sticky lištou, kterou musí obejít i
   `.settings-toc` výš. */
[data-settings-toc-target="section"] {
    scroll-margin-top: calc(3.25rem + 1rem);
}

/* -------- Tabulky -------- */

.admin-table {
    --bs-table-bg: transparent;
    margin-bottom: 0;
}

.admin-table > thead > tr > th {
    padding: 0.625rem 1rem;
    border-bottom: 1px solid var(--wa-line-soft);
    background-color: color-mix(in srgb, var(--wa-canvas) 60%, var(--wa-panel));
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.045em;
    text-transform: uppercase;
    color: var(--wa-ink-muted);
    white-space: nowrap;
}

.admin-table > tbody > tr > td {
    padding: 0.75rem 1rem;
    border-bottom-color: var(--wa-line-soft);
    vertical-align: middle;
}

.admin-table > tbody > tr:last-child > td {
    border-bottom-width: 0;
}

.admin-table__primary {
    font-weight: 600;
    color: var(--wa-ink);
    text-decoration: none;
}

.admin-table__primary:hover {
    color: var(--bs-primary);
    text-decoration: underline;
}

.admin-table__meta {
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

/* Strom stránek na nástěnce (GH #84, vlna 1 bod 2), náhrada plochého seznamu.
   Jeden „rail" span na úroveň hloubky, ne jediné `padding-left` – tak je vidět
   svislice KAŽDÉ úrovně, ne jen odsazení té poslední (spec §9.3 bod 4: svislice
   je povinná, na telefonu při 16 px je to jediné, co úroveň vůbec drží).
   `.page-tree-item__body` nikdy nedostane `text-overflow`/`white-space: nowrap` –
   plná cesta pod titulkem se nesmí zkracovat (spec §9.3 bod 5). */
.page-tree-item {
    display: flex;
    align-items: flex-start;
}

.page-tree-item__rail {
    flex: 0 0 var(--wa-tree-indent);
    width: var(--wa-tree-indent);
    align-self: stretch;
    position: relative;
}

.page-tree-item__rail::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    border-left: 1px solid var(--wa-line-soft);
}

.page-tree-item__body {
    min-width: 0;
    flex: 1 1 auto;
}

/* Akce v řádku se drží pohromadě vpravo a nezalamují se do schodů. */
.admin-row-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.375rem;
}

/* -------- Kalendář obsazenosti (rezervace) -------- */

.admin-calendar-nav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.admin-calendar-nav__label {
    min-width: 9rem;
    text-align: center;
    font-weight: 600;
}

.admin-calendar-grid {
    margin-bottom: 0;
    font-size: 0.8125rem;
}

.admin-calendar-grid > thead > tr > th,
.admin-calendar-grid > tbody > tr > td,
.admin-calendar-grid > tbody > tr > th {
    padding: 0.25rem 0.375rem;
    text-align: center;
    vertical-align: middle;
}

.admin-calendar-grid > thead > tr > th:first-child,
.admin-calendar-grid > tbody > tr > th {
    text-align: left;
    white-space: nowrap;
}

.admin-calendar-grid__day--weekend {
    background-color: var(--wa-hover-strong);
}

.admin-calendar-grid__cell {
    min-width: 1.75rem;
}

.admin-calendar-grid__cell--blocked {
    background-color: var(--wa-danger-tint);
}

/* -------- Odznaky stavu -------- */

.dashboard-shell .badge {
    --bs-badge-font-weight: 600;
    --bs-badge-padding-x: 0.5rem;
    --bs-badge-padding-y: 0.3em;
    --bs-badge-font-size: 0.75em;
    letter-spacing: 0.01em;
}

/* Měkčí varianta plných `text-bg-*` odznaků: v seznamu jich je desítky vedle
   sebe a plná plocha z nich dělá barevný šum. */
.admin-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    padding: 0.25rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.25;
    background-color: var(--wa-hover-strong);
    color: var(--wa-ink-muted);
}

.admin-badge::before {
    content: '';
    width: 0.4375rem;
    height: 0.4375rem;
    border-radius: 50%;
    background-color: currentcolor;
    opacity: 0.85;
}

.admin-badge--success {
    background-color: rgba(var(--bs-success-rgb), 0.12);
    color: color-mix(in srgb, var(--bs-success) 78%, var(--wa-ink));
}

.admin-badge--info {
    background-color: rgba(var(--bs-info-rgb), 0.16);
    color: color-mix(in srgb, var(--bs-info) 62%, var(--wa-ink));
}

.admin-badge--danger {
    background-color: var(--wa-danger-tint);
    color: color-mix(in srgb, var(--bs-danger) 78%, var(--wa-ink));
}

.admin-badge--warning {
    background-color: rgba(var(--bs-warning-rgb), 0.2);
    color: color-mix(in srgb, var(--bs-warning) 45%, var(--wa-ink));
}

.admin-badge--dark {
    background-color: rgba(var(--bs-emphasis-color-rgb), 0.1);
    color: var(--wa-ink);
}

/* -------- Tlačítka -------- */

.dashboard-shell .btn {
    --bs-btn-font-weight: 500;
    --bs-btn-padding-y: 0.4375rem;
    --bs-btn-padding-x: 0.875rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    white-space: nowrap;
}

.dashboard-shell .btn-sm {
    --bs-btn-padding-y: 0.3125rem;
    --bs-btn-padding-x: 0.625rem;
    --bs-btn-font-size: 0.8125rem;
}

.dashboard-shell .btn-outline-secondary {
    --bs-btn-color: var(--wa-ink);
    --bs-btn-border-color: var(--wa-line);
    --bs-btn-hover-bg: var(--wa-hover);
    --bs-btn-hover-color: var(--wa-ink);
    --bs-btn-hover-border-color: var(--wa-line);
    --bs-btn-active-bg: var(--wa-hover-strong);
    --bs-btn-active-color: var(--wa-ink);
    --bs-btn-active-border-color: var(--wa-line);
    background-color: var(--wa-panel);
}

/* Přepínač zobrazení dlaždic na /media (vyplnit/zachovat proporce,
   media_gallery_controller.js) – pravidlo výš dává aktivnímu stavu
   `--bs-btn-active-bg: var(--wa-hover-strong)`, tón na 7,5 % krytí míněný pro
   krátký hover, ne pro trvalé „tohle zobrazení je teď zapnuté": aktivní
   a neaktivní tlačítko byla skoro k nerozeznání (nahlásil majitel produktu).
   Plná `--bs-primary` místo tónu jako u `.dashboard-nav .nav-link.active`/
   `.settings-toc__link.active` výš, protože jde o dvojici přepínacích
   tlačítek se vzájemně vylučujícím výběrem, ne o položku v delším seznamu –
   tam stačí tón, tady musí být „stisknuto" jednoznačné na první pohled. */
.media-view-toggle .btn.active {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
    color: var(--bs-white);
}

/* Ničivá akce, která se opakuje na každém řádku (odebrat blok, odebrat
   položku): dokud na ni uživatel nemíří, nemá křičet červeně. */
.btn-quiet-danger {
    --bs-btn-color: var(--wa-ink-muted);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--bs-danger);
    --bs-btn-hover-bg: var(--wa-danger-tint);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-color: var(--bs-danger);
    --bs-btn-active-bg: var(--wa-danger-tint);
    --bs-btn-active-border-color: transparent;
    --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

/* -------- Formuláře -------- */

.dashboard-shell .form-label {
    margin-bottom: 0.3125rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* Povinné pole. Symfony na popisek povinného pole dává třídu `required` už roky,
   Bootstrapí form theme s ní ale nic nedělá — nikde v administraci tedy nešlo poznat,
   co se MUSÍ vyplnit, dokud formulář nespadl na validaci.

   Značka sedí jen tam, kde uživatel opravdu může nechat prázdno — u textových
   polí a zaškrtávátek. `<select>` má vždycky nějakou hodnotu vybranou, takže by
   u něj hvězdička nic nenaučila, jen přidala červenou tam, kde nejde nic udělat
   špatně. (Pravidlo se proto píše kladně, ne jako výjimka pro `<select>`:
   `:has()` se podle specifikace nesmí zanořovat do `:has()`.) */
.dashboard-shell :has(> input.form-control, > textarea.form-control) > .form-label.required::after,
.dashboard-shell .form-check-label.required::after {
    content: ' *';
    color: var(--bs-danger);
}

.dashboard-shell .form-control,
.dashboard-shell .form-select {
    border-color: var(--wa-line);
    background-color: var(--wa-panel);
}

.dashboard-shell .form-control:hover:not(:focus),
.dashboard-shell .form-select:hover:not(:focus) {
    border-color: color-mix(in srgb, var(--bs-border-color) 65%, var(--wa-ink));
}

.dashboard-shell .form-text,
.dashboard-shell .help-text {
    margin-top: 0.3125rem;
    margin-bottom: 0;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--wa-ink-muted);
}

.dashboard-shell fieldset > legend {
    float: none;
    width: auto;
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* Segmentovaný přepínač z `btn-check` — používá ho „Plocha sekce" v editoru
   bloků i jazyk/tvar rozbalení v editoru menu. */
.admin-seg {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.1875rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.admin-seg .btn {
    --bs-btn-border-color: transparent;
    --bs-btn-bg: transparent;
    --bs-btn-color: var(--wa-ink-muted);
    --bs-btn-hover-bg: var(--wa-hover);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-hover-color: var(--wa-ink);
    --bs-btn-active-bg: var(--wa-panel);
    --bs-btn-active-border-color: var(--wa-line-soft);
    --bs-btn-active-color: var(--wa-ink);
    --bs-btn-padding-y: 0.1875rem;
    --bs-btn-padding-x: 0.5rem;
    --bs-btn-font-size: 0.8125rem;
    font-weight: 500;
}

.admin-seg .btn-check:checked + .btn {
    box-shadow: var(--wa-shadow-xs);
    font-weight: 600;
}

/* Popisek před segmentovaným přepínačem/řádkem ovládání. */
.admin-field-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.admin-field-row__label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* Textový filtr nad dlouhým seznamem zaškrtávátek (`checkbox_filter_controller.js`,
   WS-6 tip 12) – nabídka cílených stránek popupu je první místo, které to
   potřebuje, ale jméno je obecné: kdo příště dostane do formuláře dalších sto
   zaškrtávátek, sáhne po týhle třídě, ne po nové kopii stejného pravidla.
   Omezená výška se scrollem, ne celá dlouhá řada – karta formuláře tak
   nenarůstá do nekonečna s počtem položek webu. */
.admin-filterable-list {
    max-height: 16rem;
    overflow-y: auto;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

/* ==========================================================================
   4. Editor stránky (bloky)
   ========================================================================== */

.page-editor__panel {
    display: flex;
    flex-direction: column;
}

/* Pruh se stavem publikace — samostatná karta nad seznamem bloků, aby
   „publikovat" nebylo osamocené modré tlačítko bez kontextu. */
.page-editor__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
    padding: 0.75rem 1.125rem;
    margin-bottom: 1rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-panel);
    box-shadow: var(--wa-shadow-sm);
}

.page-editor__status {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--wa-ink-muted);
}

.page-editor-blocks {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1.125rem;
}

/* -------- Řádek bloku -------- */

.block-row {
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-panel);
    box-shadow: var(--wa-shadow-xs);
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.block-row:hover {
    border-color: var(--wa-line);
}

/* Duch globálního bloku (spec globálních bloků #101 §4.7) — na první pohled se
   musí lišit od bloku, co v editoru doopravdy jde upravit: přerušovaný rámeček,
   ne plná čára, a bez stínu/hoveru, který by naznačoval interaktivitu. */
.block-row--ghost {
    border-style: dashed;
    box-shadow: none;
    background-color: var(--wa-hover);
}

.block-row--ghost:hover {
    border-color: var(--wa-line-soft);
}

.block-row__handle--ghost {
    cursor: default;
}

/* Rozbalený blok se musí poznat na první pohled — to je přesně to „nevím,
   kde vlastně jsem". Barevný pruh vlevo + stín + výraznější rámeček. */
.block-row:has(.block-row__toggle[aria-expanded='true']) {
    border-color: color-mix(in srgb, var(--bs-primary) 35%, var(--wa-line));
    box-shadow: var(--wa-shadow-md);
}

.block-row__header {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.375rem 0.5rem 0.375rem 0.25rem;
    border-radius: inherit;
}

.block-row:has(.block-row__toggle[aria-expanded='true']) .block-row__header {
    border-bottom: 1px solid var(--wa-line-soft);
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    background-color: color-mix(in srgb, var(--bs-primary) 4%, var(--wa-panel));
}

/* Úchyt pro přetažení: skutečný cíl pro myš (28 px) a hlavně kurzor, podle
   kterého se pozná, že se dá chytit. Bez `cursor: grab` na něm nikdo
   nepoznal, že je řádek přetažitelný. */
.block-row__handle,
.menu-row__handle,
.global-block-row__handle {
    display: inline-grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    flex-shrink: 0;
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink-muted);
    cursor: grab;
    user-select: none;
    line-height: 1;
}

.block-row__handle:hover,
.menu-row__handle:hover,
.global-block-row__handle:hover {
    background-color: var(--wa-hover);
    color: var(--wa-ink);
}

.block-row__handle:active,
.menu-row__handle:active,
.global-block-row__handle:active,
.page-editor-blocks.is-dragging .block-row__handle {
    cursor: grabbing;
}

.block-row__handle svg,
.menu-row__handle svg,
.global-block-row__handle svg {
    width: 1rem;
    height: 1rem;
    pointer-events: none;
}

/* Zatímco se přetahuje, seznam nesmí animovat sbalování — jinak by se cíle
   pro upuštění hýbaly pod kurzorem. */
.page-editor-blocks.is-dragging .collapse,
.page-editor-blocks.is-dragging .collapsing {
    transition: none !important;
}

/* Přenášený řádek (tip 1, sortable_controller.js a collection_controller.js) —
   zvýraznění a stín, aby „plaval" nad ostatními. Platí pro bloky, řádky
   galerie i položky kolekce (odrážky, karty, plány) – tři různí řadiči,
   jedna sdílená třída. */
.block-row.is-dragged,
.media-field__row.is-dragged,
.config-item.is-dragged,
.admin-table tr.is-dragged {
    position: relative;
    z-index: 2;
    box-shadow: var(--wa-shadow-md);
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

.block-row__toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.375rem 0.5rem;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: none;
    text-align: start;
    color: var(--wa-ink);
}

.block-row__toggle:hover {
    background-color: var(--wa-hover);
}

.block-row__toggle:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

/* Šipka rozbalení. Bootstrapí `.accordion-button::after` tady NIKDY nefungovala:
   ikonu bere z `--bs-accordion-btn-icon`, kterou definuje až rodičovský
   `.accordion` — a ten v editoru nikdy neexistoval, takže se pseudoprvek
   kreslil 0 × 0 px bez obrázku. Řádky bloků tedy neměly žádný náznak, že se
   dají rozbalit. Vlastní šipka z `border` je na kontejneru nezávislá. */
.block-row__chevron {
    display: inline-block;
    flex-shrink: 0;
    width: 0.4375rem;
    height: 0.4375rem;
    margin-inline: 0.125rem 0.125rem;
    border-right: 1.5px solid currentcolor;
    border-bottom: 1.5px solid currentcolor;
    transform: rotate(-45deg);
    transition: transform 0.18s ease;
    color: var(--wa-ink-muted);
}

.block-row__toggle[aria-expanded='true'] .block-row__chevron {
    transform: rotate(45deg);
    color: var(--bs-primary);
}

.block-row__title {
    font-weight: 600;
    white-space: nowrap;
}

.block-row__summary {
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.875rem;
    color: var(--wa-ink-muted);
}

.block-row__body {
    padding: 0.875rem;
}

/* -------- Konfigurační formulář bloku -------- */

/* Pole se skládají do 12sloupcové mřížky (`.row.g-3`), takže krátká pole
   nezabírají celý řádek. `form_row()` z Bootstrapového tématu si ale s sebou
   nese `mb-3`, což je v Bootstrapu `!important` — bez téhle nulace by se
   k mezerám mřížky přičítal ještě spodní margin a rytmus by se rozjel.
   (Stejná past, jakou u simble zabila „mrtvá" pravidla přebitá `!important`.) */
.config-grid > .mb-3 {
    margin-bottom: 0 !important;
}

/* Číselné pole: široký sloupec (aby se nápověda pod ním nelámala do pěti řádků),
   ale úzký vstup — do „počtu dní" ani „počtu sloupců" se nic dlouhého nevejde. */
.field-narrow .form-control,
.field-narrow .form-select {
    max-width: 10rem;
}

/* Svislý gutter mřížky polí (`row g-3`) je z Bootstrapu stejný jako
   vodorovný – 1 rem. Administrace potřebuje zhustit jen svislý rytmus
   mezi řádky formuláře, ne mezeru mezi sloupci vedle sebe, proto se
   přepisuje jen `--bs-gutter-y`. */
.dashboard-shell .config-grid {
    --bs-gutter-y: 0.625rem;
}

.config-section {
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.config-section__label {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.045em;
    text-transform: uppercase;
    color: var(--wa-ink-muted);
}

/* Vnořená skupina polí (třeba „Otevírací doba → týden"). */
.config-fieldset {
    padding: 0.75rem 1rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.config-fieldset > legend {
    font-size: 0.75rem !important; /* přebíjí obecné pravidlo pro legendu výš */
    letter-spacing: 0.045em;
    text-transform: uppercase;
    color: var(--wa-ink-muted) !important;
}

/* Sbalitelné skupiny formuláře bloku (GH #359, hero: Obsah / Rozvržení /
   Fotka / Tlačítka) — nativní `<details>`, žádný JS na sbalení/rozbalení
   navíc. */
.config-form__group {
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
}

.config-form__group:last-child {
    margin-bottom: 0;
}

.config-form__group > .config-grid {
    margin-top: 0.75rem;
}

.config-form__group-title {
    cursor: pointer;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.045em;
    text-transform: uppercase;
    color: var(--wa-ink-muted);
}

/* -------- Opakovaná kolekce (položky) -------- */

.config-collection {
    counter-reset: wa-repeater;
}

.config-collection__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.4375rem;
}

.config-collection__label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* „2 / 2" vedle nadpisu kolekce (GH #227). Strop kolekce byl do téhle opravy
   vidět jedině jako chybová hláška PO uložení — tady je vidět dřív, než na něj
   uživatel narazí. */
.config-collection__count {
    flex-shrink: 0;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--wa-ink-muted);
}

/* Vysvětlení k odkazu „přidat", který po dosažení limitu zhasl. Zhasnuté
   tlačítko bez věty vedle sebe je hádanka, ne prevence. */
.config-collection__limit {
    margin-top: 0.375rem;
    margin-bottom: 0;
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

.config-collection__items {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.config-collection__items:not(:has(> *)) {
    margin-bottom: 0;
}

/* Jedna položka kolekce = jedna ohraničená karta s vlastním číslem a vlastním
   „Odebrat" v záhlaví. Dřív to byl jen tenký rámeček a tlačítko „Odebrat"
   viselo POD ním, takže vypadalo, že patří k následující položce — přesně
   proto nešlo poznat, kde jedna položka končí a druhá začíná. */
.config-item {
    position: relative;
    padding: 0.625rem 0.875rem 0.75rem;
    border: 1px solid var(--wa-line);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-panel);
    counter-increment: wa-repeater;
}

.config-item__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

/* „Odebrat" zůstává vpravo, i když mezi ním a číslem přibyla skupina pro
   pořadí – `space-between` by teď se třemi dětmi roztáhlo mezery rovnoměrně
   a prostřední skupina by opticky „plavala" uprostřed hlavičky. */
.config-item__head > .btn-quiet-danger {
    margin-inline-start: auto;
}

/* -------- Pořadí položky kolekce (tip 5): šipky + úchyt pro myš -------- */

.config-item__order {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
}

.config-item__move {
    display: inline-grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    color: var(--wa-ink-muted);
}

.config-item__move svg {
    width: 0.875rem;
    height: 0.875rem;
    pointer-events: none;
}

.config-item__move:disabled {
    opacity: 0.35;
    cursor: default;
}

.config-item__handle {
    display: inline-grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink-muted);
    cursor: grab;
    user-select: none;
}

.config-item__handle:hover {
    background-color: var(--wa-hover);
    color: var(--wa-ink);
}

.config-item__handle svg {
    width: 1rem;
    height: 1rem;
    pointer-events: none;
}

.config-item__badge {
    display: inline-grid;
    place-items: center;
    min-width: 1.5rem;
    height: 1.5rem;
    padding-inline: 0.375rem;
    border-radius: 999px;
    background-color: var(--wa-hover-strong);
    color: var(--wa-ink-muted);
    font-size: 0.75rem;
    font-weight: 600;
}

.config-item__badge::before {
    content: counter(wa-repeater);
}

/* Patička dlouhého formuláře (nastavení webu, nabídka práce): uložení se drží
   při odscrollování dole u okna, aby zákazník po třiceti polích nemusel hledat,
   kam vlastně kliknout. `margin-bottom` je záměrně stejně velký jako
   `margin-top`: patička je poslední prvek uvnitř `<form>` a bez něj by se na
   stránkách, které mají obsah i po `form_end()` (nebezpečná zóna u nastavení
   webu, doklady u fakturace), doscrollováním dolů dostala plovoucí lišta do
   dotyku s tím obsahem, protože po ukotvení na dně okna už není vidět žádná
   mezera pod ní. */
.admin-form-footer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.875rem 1.25rem;
    margin-top: 0.5rem;
    margin-bottom: 0.5rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--wa-panel) 92%, transparent);
    backdrop-filter: blur(8px);
    box-shadow: var(--wa-shadow-md);
}

/* Tlačítko „přidat řádek" přes celou šířku a čárkovaně: čitelný cíl na konci
   seznamu položek, ne drobné tlačítko schované vlevo dole. */
.config-collection__add {
    width: 100%;
    border-style: dashed;
    --bs-btn-color: var(--wa-ink-muted);
    --bs-btn-border-color: var(--wa-line);
    --bs-btn-bg: transparent;
    --bs-btn-hover-color: var(--bs-primary);
    --bs-btn-hover-bg: var(--wa-accent-tint);
    --bs-btn-hover-border-color: var(--bs-primary);
    --bs-btn-active-color: var(--bs-primary);
    --bs-btn-active-bg: var(--wa-accent-tint);
    --bs-btn-active-border-color: var(--bs-primary);
    font-weight: 500;
}

/* Patička formuláře bloku: uložení je hlavní akce, tak ať je vidět. */
.config-form__footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--wa-line-soft);
}

.config-form__hint {
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

/* Souhrn chyb NAD tlačítkem (GH #227). Pod tlačítkem končil u každého delšího
   bloku pod hranou obrazovky — uživatel klikl na „Uložit blok", nic viditelného
   se nestalo a odešel s tím, že je uloženo. */
.config-form__errors {
    margin-top: 1rem;
    margin-bottom: 0;
}

.config-form__errors-title {
    margin-bottom: 0.375rem;
    font-weight: 600;
}

.config-form__errors:focus-visible {
    outline: 2px solid var(--bs-danger);
    outline-offset: 2px;
}

/* Upozornění na cookies u bloku HTML/snippet (GH #486) – informativní, ne chybové,
   proto stejný odstup jako .config-form__errors, ale ne alert-danger. */
.config-form__notice {
    margin-top: 1rem;
    margin-bottom: 0;
}

/* Blok, jehož uložení právě selhalo. Sám se rozbalí (šablona) a tímhle je
   i vidět v seznamu sbalených bloků, takže se dá najít bez rolování naslepo. */
.block-row--invalid {
    border-color: var(--bs-danger);
    box-shadow: 0 0 0 1px var(--wa-danger-tint);
}

/* -------- Nabídka bloků k přidání -------- */

.block-picker {
    padding: 1.125rem 1.25rem 1.25rem;
    border: 1px dashed var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--wa-canvas) 55%, var(--wa-panel));
}

/* Kategorie nabídky (GH #360, BlockTypeCatalog): „Text a obsah", „Prodej"… */
.block-picker__group {
    margin-bottom: 1rem;
}

.block-picker__group:last-child {
    margin-bottom: 0;
}

.block-picker__group-title {
    margin: 0 0 0.5rem;
}

.block-picker__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.block-picker__item {
    display: flex;
    align-items: flex-start;
    width: 100%;
    gap: 0.5rem;
    padding: 0.5rem 0.625rem;
    text-align: left;
    --bs-btn-color: var(--wa-ink);
    --bs-btn-bg: var(--wa-panel);
    --bs-btn-border-color: var(--wa-line);
    --bs-btn-hover-color: var(--bs-primary);
    --bs-btn-hover-bg: var(--wa-panel);
    --bs-btn-hover-border-color: var(--bs-primary);
    --bs-btn-active-color: var(--bs-primary);
    --bs-btn-active-bg: var(--wa-accent-tint);
    --bs-btn-active-border-color: var(--bs-primary);
}

/* `.dashboard-shell .btn` výš („Tlačítka") dává tlačítkům `white-space: nowrap`
   se specificitou (0,2,0) — víc, než má samotné `.block-picker__item` (0,1,0),
   takže by ho přebilo bez ohledu na pořadí v souboru (do GH #601 se stejná past
   řešila i u přepínače motivu, než přestal být `.btn`). Tlačítka bez
   ikony/popisku (výběr stránky,
   modulu i kotvy na blok v `MenuEditor.html.twig`) mají label přímo v textu
   tlačítka — beze zlomu řádku dlouhý popisek přetekl přes hranici dlaždice
   v CSS gridu a vykreslil se přes sousední tlačítko. Selektor tady je `.btn`
   spojený s `.block-picker__item` (ne přes mezeru) plus `.dashboard-shell`,
   aby specificita (0,3,0) vyhrála bez ohledu na pořadí v souboru. */
.dashboard-shell .btn.block-picker__item {
    white-space: normal;
}

/* Ikona typu bloku (BlockTypeIcons): stejná tažená čára jako zbytek admin
   sady, jen o chlup menší, aby nepřebila text vedle sebe v úzké dlaždici. */
.block-picker__icon {
    width: 1.125rem;
    height: 1.125rem;
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--wa-ink-muted);
}

.block-picker__item:hover .block-picker__icon,
.block-picker__item:active .block-picker__icon {
    color: inherit;
}

.block-picker__item-body {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 0.125rem;
}

.block-picker__item-label {
    font-weight: 500;
}

/* Jednořádkový popis pod názvem dlaždice (GH #360) — „ROI kalkulačka" a
   „RSVP" cílovému zákazníkovi samy o sobě nic neřeknou. */
.block-picker__item-description {
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--wa-ink-muted);
    white-space: normal;
}

/* Varovná věta nad mřížkou (GH #566): u bloku na více stránkách je volba typu
   NEVRATNÁ, takže to musí být vidět tam, kde se vybírá, ne jen v úvodu stránky. */
.block-picker__note {
    margin: 0 0 0.75rem;
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

/* Filtr nad dlaždicemi (GH #566, block_picker_controller.js). Nabídka je dost
   velká na to, aby se v ní rolovalo — tímhle se nahradilo vyhledávání zrušeného
   `searchable_choice_widget`. */
.block-picker__search {
    margin-bottom: 1rem;
}

.block-picker__empty {
    margin: 0 0 1rem;
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

/* Radio pod dlaždicí ve formuláři (GH #566) je Bootstrapův `btn-check`, takže
   zaškrtnutý i zaostřený stav kreslí Bootstrap sám z `--bs-btn-active-*`
   proměnných, které `.block-picker__item` výš už definuje. Zbývá jen zvýraznit
   VYBRANOU dlaždici o chlup víc než tu, nad kterou je zrovna myš — bez toho se
   po výběru nedá poznat, co je vybrané, a to je u nevratné volby málo. */
.block-picker__radio:checked + .block-picker__item {
    box-shadow: inset 0 0 0 1px var(--bs-primary);
}

.block-picker__radio:checked + .block-picker__item .block-picker__icon {
    color: inherit;
}

/* -------- Textový blok: lišta nástrojů nad Tiptap editorem (GH #193) --------

   Lišta, dialog odkazu a plocha editoru jsou jeden svislý celek se společným
   rámečkem – vizuálně tedy jedno pole formuláře, ne tři nesouvisející prvky
   nad sebou. Tlačítka jsou Bootstrapovy `.btn-outline-secondary` ve skupinách,
   takže stav `.active` (rozsvícené podle pozice kurzoru) i focus ring nastavuje
   Bootstrap sám a nemá tu druhou pravdu.                                    */

.rich-text-editor {
    border: 1px solid var(--wa-line);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-panel);
    overflow: hidden;
}

.rich-text-editor__toolbar {
    gap: 0.375rem;
    padding: 0.375rem;
    border-bottom: 1px solid var(--wa-line-soft);
    background-color: var(--wa-canvas);
}

.rich-text-editor__button {
    --bs-btn-color: var(--wa-ink-muted);
    --bs-btn-border-color: var(--wa-line);
    --bs-btn-hover-color: var(--wa-ink);
    --bs-btn-hover-bg: var(--wa-hover);
    --bs-btn-hover-border-color: var(--wa-line);
    --bs-btn-active-color: var(--bs-primary);
    --bs-btn-active-bg: var(--wa-accent-tint);
    --bs-btn-active-border-color: var(--bs-primary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.3125rem 0.5rem;
    background-color: var(--wa-panel);
}

.rich-text-editor__icon {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
}

.rich-text-editor__link {
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid var(--wa-line-soft);
    background-color: var(--wa-canvas);
}

.rich-text-editor__link-label {
    margin-bottom: 0.25rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--wa-ink-muted);
}

.rich-text-editor__link-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
}

.rich-text-editor__link-row .form-control {
    flex: 1 1 14rem;
    min-width: 0;
}

.rich-text-editor__link-hint {
    margin-bottom: 0;
    font-size: 0.75rem;
}

/* Plocha editoru: `.ProseMirror` je element, který si Tiptap sám udělá
   contenteditable, takže výška i vnitřní odsazení musí sedět na něm, ne na
   obalu – jinak zůstane klikatelná jen výška napsaného textu. */
/* Výchozí devítirem plocha stačí popisu produktu nebo poznámkám k epizodě; pole,
   kde se píše dlouhý text (tělo newsletterové kampaně), si vyšší plochu předá
   vlastní vlastností přes `min_height` v `_rich_text_field.html.twig`. */
.rich-text-editor__surface .ProseMirror {
    min-height: var(--rich-text-editor-surface-min-height, 9rem);
    padding: 0.625rem 0.75rem;
    color: var(--wa-ink);
    outline: none;
}

.rich-text-editor__surface .ProseMirror > :last-child {
    margin-bottom: 0;
}

/* Tiptap balí obsah položky seznamu do `<p>`, takže mezi odrážkami vyroste
   Bootstrapův odstavcový `margin-bottom` a seznam se roztrhá. Ve veřejném
   výstupu ten `<p>` zůstává (sanitizer ho povoluje), tady jde jen o to, aby
   editor ukazoval seznam jako seznam. */
.rich-text-editor__surface .ProseMirror li > p {
    margin-bottom: 0;
}

/* Bootstrapovy výchozí 2rem/1.75rem jsou uvnitř výchozí devítirem plochy editoru
   nepoužitelně velké; menší rozdíl mezi nadpisem a podnadpisem stačí, aby
   zákazník viděl, kterou úroveň zrovna má. */
.rich-text-editor__surface .ProseMirror h2 {
    font-size: 1.25rem;
    font-weight: 650;
}

.rich-text-editor__surface .ProseMirror h3 {
    font-size: 1.0625rem;
    font-weight: 650;
}

.rich-text-editor__surface .ProseMirror a {
    color: var(--bs-primary);
    text-decoration: underline;
}

/* ==========================================================================
   5. Obrázková pole (knihovna médií)
   ========================================================================== */

.media-field {
    padding: 0.625rem 0.875rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.media-field__label {
    margin-bottom: 0.375rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--wa-ink);
}

.media-field__preview {
    margin-bottom: 0.5rem;
}

/* `:not(.admin-dropzone)` obojí: pole s dropzone prázdným stavem (tip 15b, dnes jen
   logo webu) má vlastní, výraznější prázdný stav o kus níž – bez tý výjimky by se obě
   pravidla přetahovala o `height`/`border` na tomtéž prvku. */
.media-field__preview:not(:has(img)):not(.admin-dropzone) {
    display: grid;
    place-items: center;
    height: 4.25rem;
    margin-bottom: 0.5rem;
    border: 1px dashed var(--wa-line);
    border-radius: var(--bs-border-radius);
    color: var(--wa-ink-muted);
    font-size: 0.8125rem;
}

.media-field__preview:not(:has(img)):not(.admin-dropzone)::before {
    content: 'Zatím bez obrázku';
}

.media-field__preview img,
.media-field__preview .media-field__video {
    width: 4.25rem;
    height: 4.25rem;
    object-fit: cover;
    border-radius: var(--bs-border-radius);
    border: 1px solid var(--wa-line-soft);
    background-color: var(--wa-panel);
}

.media-field__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-top: 0.5rem;
}

/* Prázdný stav obrázkového pole. Dashed rámeček nese informaci „sem se dá
   pustit soubor" – proto je výraznější než okolní pole, ne slabší.

   `:not(:has(img))` na hlavním pravidlu: `.admin-dropzone` teď žije napořád na
   `.media-field__preview` (tip 15b), i po výběru obrázku – jakmile media_field_controller.js
   vloží <img>, tohle pravidlo přestane platit samo a náhled vypadá jako běžné kompaktní
   pole, bez reloadu stránky. `:has(video)` stejně (GH #383): video na pozadí hera do
   téhle dlaždice vkládá `<video>`, ne `<img>`. */
.admin-dropzone:not(:has(img)):not(:has(video)) {
    display: grid;
    place-items: center;
    gap: 0.5rem;
    min-height: 8rem;
    padding: 1.25rem;
    border: 2px dashed var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    color: var(--wa-ink-muted);
    background: var(--wa-panel);
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.admin-dropzone:not(:has(img)):not(:has(video)):hover,
.admin-dropzone:not(:has(img)):not(:has(video)):focus-visible {
    border-color: rgba(var(--bs-primary-rgb), 0.55);
    background: var(--wa-accent-tint);
}

.admin-dropzone__icon {
    width: 1.75rem;
    height: 1.75rem;
    color: var(--wa-ink-muted);
}

/* Ikona i výzva zůstávají v DOMu i s vybraným obrázkem a schovává je tohle pravidlo,
   ne JavaScript (GH #287). Dřív je vypisovala jen prázdná větev šablony, takže když
   `media_field_controller.js` po „Odebrat" obsah náhledu vyprázdnil, zbyla ohraničená
   krabice bez jediného slova a bez cesty zpátky. Složit je v JS by znamenalo mít inline
   SVG ikonu ve dvou souborech naráz. Stejná úvaha jako u `:not(:has(img))` výš:
   o tom, co je v kterém stavu vidět, rozhoduje CSS. */
.admin-dropzone:has(img) .admin-dropzone__icon,
.admin-dropzone:has(img) .admin-dropzone__hint,
.admin-dropzone:has(video) .admin-dropzone__icon,
.admin-dropzone:has(video) .admin-dropzone__hint {
    display: none;
}

.admin-dropzone__hint {
    margin: 0;
    font-size: 0.8125rem;
    text-align: center;
}

.admin-dropzone.is-dragover {
    border-color: rgba(var(--bs-primary-rgb), 0.9);
    background: var(--wa-accent-tint);
}

.admin-dropzone.is-uploading {
    opacity: 0.6;
    pointer-events: none;
}

/* Tip 46: bez tohohle vypadalo nahrání velkého souboru, že se nic neděje. Pruh je
   skrytý, dokud `media_upload_controller.js` neoznačí zónu jako `is-uploading` –
   `display` na třídě rodiče, ne na samotném pruhu, aby JS neřešil dvě věci
   (viditelnost i šířku výplně) najednou. */
.admin-dropzone__progress {
    display: none;
    width: 100%;
    max-width: 16rem;
    height: 0.25rem;
    border-radius: 999px;
    background: var(--wa-line-soft);
    overflow: hidden;
}

.admin-dropzone.is-uploading .admin-dropzone__progress {
    display: block;
}

.admin-dropzone__progress-fill {
    height: 100%;
    width: 0;
    background: var(--bs-primary);
    transition: width 0.2s ease;
}

.admin-dropzone.is-error {
    border-color: rgba(var(--bs-danger-rgb), 0.7);
}

.admin-dropzone__error {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--bs-danger);
}

/* Dialog výběru obrázku (GH #564). Do téhle issue nemělo `.media-picker-dialog`
   v CSS jediné pravidlo, takže o velikosti rozhodovalo výchozí chování <dialog>:
   šířka podle obsahu, tedy jiná na každé záložce. Proměnné jsou v `:root` nahoře. */
.media-picker-dialog {
    width: var(--wa-media-picker-width);
    max-width: none;
    height: var(--wa-media-picker-height);
    max-height: none;
    /* Odsazení má na starosti `.card-body`; UA stylesheet dává <dialog> vlastní
       `padding: 1em`, které by se s ním sčítalo. */
    padding: 0;
    overflow: hidden;
    box-shadow: var(--wa-shadow-md);
}

.media-picker-dialog::backdrop {
    background-color: rgba(var(--bs-emphasis-color-rgb), 0.32);
}

.media-picker-dialog__body {
    display: flex;
    flex-direction: column;
    /* `min-height: 0` na sloupci i na posuvné části níž: bez něj flexový prvek
       nikdy neklesne pod výšku svého obsahu a posuvník by dostal dialog, ne mřížka. */
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.media-picker-dialog__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.media-picker-dialog__title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--wa-ink);
}

/* Tiché ✕ v rohu, ne obrysové tlačítko „Zavřít“ nad záložkami: zavírání je pořád
   nativní <form method="dialog">, jen přestalo být nejvýraznějším prvkem dialogu. */
.media-picker-dialog__close {
    --bs-btn-color: var(--wa-ink-muted);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--wa-ink);
    --bs-btn-hover-bg: var(--wa-hover);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-color: var(--wa-ink);
    --bs-btn-active-bg: var(--wa-hover-strong);
    --bs-btn-active-border-color: transparent;
    display: inline-flex;
    align-items: center;
    padding: 0.3125rem;
}

.media-picker {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.media-picker__tabs {
    margin-bottom: 1rem;
}

/* Posuvník patří obsahu, ne dialogu – dialog má pevnou velikost a nesmí se hýbat
   podle toho, kolik obrázků web má. Vodorovné odsazení dává prostor obrysu fokusu
   dlaždic, který by se u kraje posuvné oblasti jinak seřízl. */
.media-picker__panel {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0.125rem;
}

.media-picker__dropzone {
    margin-bottom: 1rem;
}

.media-field__list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin: 0 0 0.75rem;
    padding: 0;
    list-style: none;
}

.media-field__row {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-panel);
    cursor: grab;
}

.media-field__row:active {
    cursor: grabbing;
}

.media-field__row img {
    width: 4.5rem;
    height: 4.5rem;
    object-fit: cover;
    border-radius: calc(var(--bs-border-radius) - 2px);
}

/* Knihovna médií jako mřížka dlaždic (tip 10), ne centrovaný seznam karet.
   `auto-fill` + `minmax`, ne Bootstrapovy `row-cols-*`: se stovkami obrázků má
   sloupců přibývat plynule podle šířky, ne v pevných krocích po zlomech. */
.media-page-upload {
    margin-bottom: 1.25rem;
}

.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.875rem;
}

/* WS-J: `transform` v tomhle seznamu je pro FLIP přechod mezi „vyplnit"/„zachovat
   proporce" (media_gallery_controller.js#applyModeAnimated) – JS jen na dlaždici
   spočítá posun/změnu velikosti oproti stavu před přeskládáním a rovnou ho zruší,
   tahle deklarace pak dojezd odanimuje na kompozitoru. Nativní View Transitions API
   byl původní kandidát (přesně na tenhle případ vznikl), ale změřeno na knihovně
   s ~650 položkami: `document.startViewTransition` trvalo 2-9 s (snímkuje celou
   stránku se stovkami velkých <img>, bez ohledu na počet pojmenovaných elementů),
   zatímco FLIP na stejné knihovně ~20 ms – proto tahle cesta. */
.media-tile {
    display: block;
    padding: 0;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    background: none;
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.32s ease;
}

.media-tile:hover,
.media-tile:focus-visible {
    border-color: rgba(var(--bs-primary-rgb), 0.55);
    box-shadow: var(--wa-shadow-xs);
}

/* Výchozí je „vyplnit dlaždici" (čtvercový výřez) – `.media-grid--fit` ho
   přepíná na skutečné zachování poměru stran, stejné rozhodnutí jako ve
   Fotkách na iPhonu (tip 48). Nejde jen o `object-fit`: zdrojový náhled `thumb`
   je na Glide úrovni oříznutý na čtverec, takže portrét by čtvercový zůstal
   i s `contain` (viz media_gallery_controller.js#applyMode, přepíná i `src`
   na derivát `grid`, který poměr zachovává). Beze čtvercového `aspect-ratio`
   proto dlaždice v „fit" mají různou výšku podle skutečné fotky – normální
   mřížka (`grid-template-rows` implicitně stejně vysoké) by mezi nimi nechala
   otrhané mezery. Řešení je sloupcové rozvržení (`columns`), ne JS masonry
   knihovna, kterou AssetMapper prostředí nemá důvod tahat dovnitř: dlaždice
   plynou shora dolů po sloupcích a každý sloupec si drží vlastní výšku. */
.media-tile__thumb {
    display: block;
    width: 100%;
    /* `height: auto`, ne prázdné: `<img>` teď nese SKUTEČNÉ rozměry obrázku v HTML
       atributech `width`/`height` (kvůli „fit" módu níž), a ty by se jako prezentační
       nápověda prohlížeče chovaly jako pevná výška v pixelech – `aspect-ratio` se
       použije jen tam, kde je aspoň jeden rozměr `auto`. Bez tohohle by ve „vyplnit"
       zůstal portrét vysoký přesně tak, jak byl nahraný, místo aby ho `aspect-ratio: 1/1`
       oříznul na čtverec. */
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    /* Šachovnice (`--wa-canvas`/`--wa-panel`, ne natvrdo šedá) prosvítá skrz
       průhledná místa PNG – bez ní splývala průhlednost s podkladem stránky
       a nešlo poznat, že obrázek nemá pozadí. */
    background-image:
        linear-gradient(45deg, var(--wa-canvas) 25%, transparent 25%),
        linear-gradient(-45deg, var(--wa-canvas) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--wa-canvas) 75%),
        linear-gradient(-45deg, transparent 75%, var(--wa-canvas) 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
    background-color: var(--wa-panel);
    /* WS-J: protiškálování k FLIP přechodu dlaždice (media_gallery_controller.js#applyModeAnimated)
       – stejná doba/křivka jako `.media-tile`, aby oba transformy doběhly současně. */
    transition: transform 0.32s ease;
}

.media-grid--fit {
    display: block;
    column-width: 9rem;
    column-gap: 0.875rem;
}

.media-grid--fit .media-tile {
    display: block;
    width: 100%;
    margin-bottom: 0.875rem;
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
}

.media-grid--fit .media-tile__thumb {
    aspect-ratio: auto;
    object-fit: contain;
    padding: 0;
}

/* Dlaždice dokumentu (PDF/Word, GH #378): žádný náhled, jen ikona podle typu a jméno
   souboru – na rozdíl od `.media-tile__thumb` zůstává čtvercová i v režimu „zachovat
   proporce": dokument nemá vlastní poměr stran, který by šlo zachovávat. */
.media-tile__doc {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    aspect-ratio: 1 / 1;
    padding: 0.75rem;
    background-color: var(--wa-canvas);
}

.media-tile__doc-icon {
    width: 2.25rem;
    height: 2.25rem;
    color: var(--wa-ink-muted);
}

.media-tile__doc-name {
    max-width: 100%;
    overflow: hidden;
    font-size: 0.75rem;
    color: var(--wa-ink-muted);
    text-align: center;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.media-grid--fit .media-grid__empty-hint {
    column-span: all;
}

.media-grid__empty-hint {
    grid-column: 1 / -1;
    margin: 0;
    padding: 2rem 1.5rem;
    text-align: center;
    color: var(--wa-ink-muted);
    border: 1px dashed var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-panel);
}

/* Lightbox: prostý <dialog>, žádná knihovna (AssetMapper nemá build krok).
   Podklad kreslí `::backdrop`, ne vlastní overlay div. */
.media-lightbox {
    max-width: min(90vw, 62rem);
    max-height: 90vh;
    padding: 1rem;
    border: none;
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-canvas);
    box-shadow: var(--wa-shadow-md);
}

.media-lightbox::backdrop {
    /* Úklid natvrdo barev (WS-13): jediný natvrdo zapsaný `rgba()` v souboru, zbytek
       už čte `rgba(var(--bs-*-rgb), α)`, viz vzor výš. */
    background-color: rgba(var(--bs-black-rgb), 0.55);
}

.media-lightbox__close {
    display: flex;
    justify-content: flex-end;
}

.media-lightbox__close button {
    padding: 0.25rem;
    border: none;
    background: none;
    color: var(--wa-ink-muted);
    cursor: pointer;
}

.media-lightbox__image {
    display: block;
    max-width: 100%;
    max-height: 55vh;
    margin: 0 auto;
    object-fit: contain;
}

/* Náhrada `.media-lightbox__image` pro dokument (PDF/Word, GH #378): žádná fotka
   k zobrazení, jen velká ikona podle typu. */
.media-lightbox__document-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 30vh;
}

.media-lightbox__document-svg {
    width: 4.5rem;
    height: 4.5rem;
    color: var(--wa-ink-muted);
}

.media-lightbox__document-link {
    display: flex;
    flex: 1 1 100%;
    flex-direction: column;
    gap: 0.25rem;
}

.media-lightbox__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px dashed var(--wa-line-soft);
}

.media-lightbox__filename {
    flex: 1 1 100%;
    margin: 0;
    font-weight: 600;
    color: var(--wa-ink);
}

.media-lightbox__alt-form {
    display: flex;
    flex: 1 1 16rem;
    align-items: center;
    gap: 0.375rem;
}

/* ==========================================================================
   6. Editor menu
   ========================================================================== */

.menu-editor__items {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-bottom: 1.5rem;
    padding: 0;
    list-style: none;
}

.menu-row {
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--wa-panel);
    box-shadow: var(--wa-shadow-xs);
}

.menu-row--child {
    border-radius: var(--bs-border-radius);
    background-color: color-mix(in srgb, var(--wa-canvas) 60%, var(--wa-panel));
    box-shadow: none;
}

.menu-row__inner {
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    padding: 0.5rem 0.75rem;
}

.menu-row__body {
    flex: 1 1 auto;
    min-width: 0;
}

.menu-row__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    min-height: 1.75rem;
}

/* Sbalení/rozbalení větve (`menu_collapse_controller.js`) – stejná šipka jako
   `.block-row__chevron` u panelu bloků stránky, jen přesměrovaná na tenhle
   přepínač: čistě klientský stav si zaslouží stejný vizuální jazyk, ne druhou
   sadu ikon. */
.menu-row__toggle {
    display: inline-grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
    padding: 0;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: none;
    color: var(--wa-ink-muted);
}

.menu-row__toggle:hover {
    background-color: var(--wa-hover);
    color: var(--wa-ink);
}

.menu-row__toggle:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: -2px;
}

.menu-row__toggle .block-row__chevron {
    margin-inline: 0;
}

.menu-row__toggle[aria-expanded='true'] .block-row__chevron {
    transform: rotate(45deg);
    color: var(--bs-primary);
}

.menu-row__label {
    font-weight: 600;
    color: var(--wa-ink);
}

.menu-row__target {
    font-size: 0.8125rem;
    color: var(--wa-ink-muted);
}

.menu-row__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-inline-start: auto;
}

/* Druhotné ovládání řádku (kategorie, tvar rozbalení) — jeden tichý pruh, ne
   fieldsety pod sebou s vlastními nadpisy. Jazyk už tu není, ten se od GH #219
   nabízí až v panelu „Upravit". */
.menu-row__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem 1rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px dashed var(--wa-line-soft);
}

/* Po odchodu jazyka (GH #219) je pruh u většiny řádků prázdný — a prázdný by
   z sebe kreslil jen čárkovanou linku a dva odsazovací kroky navíc. Nepodmiňuje
   se to v šabloně: obsah pruhu je několik nezávislých `{% if %}` a jejich
   souhrnná podmínka by se musela udržovat dvakrát. */
.menu-row__meta:not(:has(> *)) {
    display: none;
}

/* Odznak jazyka u názvu položky (GH #219) — nese ho jen nevýchozí hodnota,
   takže je na obrazovce skoro nikdy a nemá strhávat pozornost od názvu. */
.menu-row__locale {
    flex: 0 0 auto;
}

.menu-row__children {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 0 0.75rem 0.75rem 2.25rem;
    padding: 0;
    list-style: none;
}

.menu-row__children:not(:has(> *)) {
    min-height: 0.5rem;
    margin-bottom: 0.5rem;
}

/* `menu_collapse_controller.js` sbaluje větev přes IDL `hidden`, ne přes vlastní
   třídu – ale `display: flex` výš má na `[hidden]`u prohlížeče (uživatelský
   agent, ne autorský původ CSS) stejnou specificitu 0-1-0 a autorský původ
   v kaskádě vždycky vyhrává, takže by beze zvlášť napsaného pravidla zůstala
   sbalená větev viditelná. Vyšší specificita (třída + atribut) tohle řeší bez
   `!important`. */
.menu-row__children[hidden] {
    display: none;
}

.menu-row__edit {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem;
    margin-top: 0.125rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

.menu-add {
    padding: 1.125rem 1.25rem 1.25rem;
    border: 1px dashed var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    background-color: color-mix(in srgb, var(--wa-canvas) 55%, var(--wa-panel));
}

/* Kotva na blok stránky (GH #423) — bez vlastního rámečku splývala s plochým
   seznamem „Přidat stránku" o pár řádků výš. Plná (ne přerušovaná) barevně
   zvýrazněná karta ji na první pohled odliší od zbytku panelu. */
.menu-add__anchor-panel {
    padding: 0.875rem 1rem 1rem;
    border: 1px solid color-mix(in srgb, var(--bs-primary) 35%, var(--wa-line));
    border-radius: var(--bs-border-radius);
    background-color: color-mix(in srgb, var(--bs-primary) 4%, var(--wa-panel));
}

/* ==========================================================================
   6b. Zpětná vazba („Moje hlášení")
   ========================================================================== */

/* `white-space: pre-line` u popisu a `object-fit`/`width`/`height` u snímku
   zůstávají INLINE v šabloně, ne tady: přesně tyhle deklarace drží opravu
   MSLCK-24 („Nejde vidět celý popis hlášení") a hlídá je statický test
   `FeedbackListReadabilityTest`, který čte `templates/feedback/index.html.twig`.
   Tady se doplňuje jen rámování, které s tou opravou nesouvisí. */
.feedback-list__description {
    margin-bottom: 0;
}

.feedback-list__screenshot {
    display: block;
    max-height: 12rem;
    margin-top: 0.875rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-canvas);
}

/* ==========================================================================
   7. Dialog výběru média
   ========================================================================== */

dialog:not([open]) {
    display: none;
}

/* ==========================================================================
   8. Výběr barvy (form/color_choice.html.twig)
   ========================================================================== */

.admin-color__row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Nativní kolečko dostává stejný rám jako sousední textové pole, aby ve
   dvojici vypadalo jako jeden ovládací prvek, ne jako cizí widget vedle inputu.
   `::-webkit-color-swatch`/`::-moz-color-swatch` mají vlastní výchozí rám,
   který je potřeba smazat, jinak by uvnitř vznikl druhý, menší obdélník. */
.admin-color__wheel {
    flex-shrink: 0;
    width: 2.375rem;
    height: 2.375rem;
    padding: 0.1875rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: var(--bs-border-radius);
    background-color: var(--wa-panel);
    cursor: pointer;
}

.admin-color__wheel::-webkit-color-swatch-wrapper {
    padding: 0;
}

.admin-color__wheel::-webkit-color-swatch {
    border: none;
    border-radius: calc(var(--bs-border-radius) - 3px);
}

.admin-color__wheel::-moz-color-swatch {
    border: none;
    border-radius: calc(var(--bs-border-radius) - 3px);
}

.admin-color__presets {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.625rem;
}

/* `--wa-swatch` chodí z inline `style` v šabloně – je to zákazníkova barva
   z databáze (data), ne barva z designu projektu, proto se do CSS pravidla
   nepíše natvrdo. Samo pravidlo čte jen proměnnou. */
.admin-color__swatch {
    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid var(--wa-line-soft);
    border-radius: 999px;
    background: var(--wa-swatch);
    transition: transform 0.12s ease;
}

.admin-color__swatch:hover {
    transform: scale(1.12);
}

.admin-color__swatch:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

/* Aktivní předvolba: prsten z platformní `--bs-primary`, ne z barvy samotné
   předvolby – ta je jedna z dvanácti, takže si nemůže „zvýraznit sama sebe"
   bez rizika, že na určitých odstínech prsten zmizí v ploše, kterou obepisuje. */
.admin-color__swatch.is-active {
    box-shadow: 0 0 0 2px var(--wa-panel), 0 0 0 4px var(--bs-primary);
}

/* ==========================================================================
   9. Responzivita
   ========================================================================== */

@media (max-width: 991.98px) {
    .dashboard-shell {
        flex-direction: column;
        --wa-gutter: 1rem;
    }

    /* Panel je na mobilu sbalený (`.collapse`) a rozbaluje se z horní lišty.
       Bez toho začínala každá stránka na telefonu zdí jedenácti odkazů
       a skutečný obsah byl až pod ní.

       Rozbalený panel překrývá obsah (`position: fixed`), ne aby ho odsouval:
       v toku dokumentu sedí PŘED horní lištou, takže by se tlačítko, kterým ho
       uživatel právě otevřel, odsunulo o půl obrazovky níž a nešlo by jím
       zavřít. Horní lišta má vyšší `z-index`, takže zůstane nad panelem. */
    .dashboard-topbar {
        z-index: 6;
    }

    .dashboard-sidebar {
        position: fixed;
        inset: 0 0 auto 0;
        z-index: 5;
        width: 100%;
        /* Odsazení, zaoblení a rámeček zavedené výš (tip 22) jsou pro plovoucí
           desktopový panel – tady se panel vysouvá přes celý obsah přes celou
           šířku, takže by mu `margin`/`border-radius` ubraly místo a nechaly
           kolem něj vykukovat podklad. */
        margin: 0;
        border-radius: 0;
        max-height: 100dvh;
        overflow-y: auto;
        border: 0;
        border-bottom: 1px solid var(--wa-line-soft);
        box-shadow: var(--wa-shadow-md);
        padding: 3.75rem 1rem 1rem;
    }

    .dashboard-sidebar.collapse.show {
        display: flex;
    }

    .dashboard-brand {
        display: none;
    }

    .dashboard-user {
        margin-top: 1rem;
    }

    .dashboard-content {
        padding: 1.25rem var(--wa-gutter) 3rem;
    }

    .admin-page-title {
        font-size: 1.3125rem;
    }

    /* Postranní panel sekcí (`.settings-toc`) se na mobilu zplošťuje na
       vodorovný pruh nad formulářem – svislý sloupec by ukrajoval šířku,
       na kterou telefon nemá. */
    .settings-layout {
        flex-direction: column;
    }

    .settings-toc {
        position: static;
        max-height: none;
        width: 100%;
        overflow-x: auto;
    }

    .settings-toc__list {
        flex-direction: row;
        border-left: 0;
        border-bottom: 1px solid var(--wa-line-soft);
        padding-bottom: 0.25rem;
    }

    .settings-toc__link {
        flex: 0 0 auto;
        margin-left: 0;
        border-left: 0;
        border-bottom: 2px solid transparent;
        white-space: nowrap;
    }

    .settings-toc__link.active {
        border-bottom-color: var(--bs-primary);
    }
}

@media (max-width: 575.98px) {
    /* Strom stránek: 16 px místo 24 px (spec §9.3 bod 3) – NAMĚŘENO, ne odhadnuto,
       viz komentář u `--wa-tree-indent` v `:root` výš. */
    :root {
        --wa-tree-indent: 16px;
    }

    .block-row__summary {
        display: none;
    }

    .block-row__body {
        padding: 1rem 0.875rem;
    }

    .admin-row-actions {
        justify-content: flex-start;
    }

    /* Na telefonu se ze čtyřsloupcové tabulky stane sloupec karet. Vodorovné
       posouvání (`.admin-table-scroll` níž) drží tabulku uvnitř karty, ale číst
       se stránky, stavy a tři akce v pruhu 375 px stejně nedají. */
    .admin-table,
    .admin-table > tbody,
    .admin-table > tbody > tr,
    .admin-table > tbody > tr > td {
        display: block;
        width: 100%;
    }

    .admin-table > thead {
        display: none;
    }

    .admin-table > tbody > tr {
        padding: 0.875rem 1rem;
        border-bottom: 1px solid var(--wa-line-soft);
    }

    .admin-table > tbody > tr:last-child {
        border-bottom: 0;
    }

    .admin-table > tbody > tr > td {
        padding: 0;
        border: 0;
    }

    .admin-table > tbody > tr > td + td {
        margin-top: 0.5rem;
    }

    .admin-table > tbody > tr > td.text-end {
        text-align: start !important;
    }
}

/* Široké tabulky se na tabletu posouvají uvnitř své karty, ne celou stránkou
   do strany. Na telefonu se místo toho rozloží na karty (výš). */
@media (max-width: 991.98px) {
    .admin-table-scroll {
        overflow-x: auto;
    }
}

/* WS-J: `.media-tile`/`.media-tile__thumb` tu jsou pojistka pro FLIP přechod
   knihovny médií – JS (applyModeAnimated) tenhle případ sám přeskakuje na obyčejné
   přeskládání bez FLIP, tohle platí i kdyby se dlaždice transformovala jinou cestou. */
@media (prefers-reduced-motion: reduce) {
    .block-row__chevron,
    .dashboard-nav .nav-link,
    .block-row,
    .admin-color__swatch,
    .media-tile,
    .media-tile__thumb {
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   Průvodce (driver.js, Task 15/17). Knihovna staví `.driver-popover` na
   `all: unset` a pak mu natvrdo dává bílé pozadí a tmavý text – v tmavém
   režimu (tip 22) by tak zůstal bílý flek nečitelný na vlastním textu.

   Každý selektor tu má navíc element `body` na začátku: `driver.js/dist/driver.css`
   se natahuje AŽ z `onboarding_controller.js` (lazy Stimulus controller), tedy
   fyzicky PO tomhle souboru – bez toho `body` navíc by měl při shodné
   specificitě vyhrát on, ne my, jen díky pořadí v <head>. `body` selektor
   specificitu zvedne bez nutnosti `!important`.

   Žádný hex/rgb natvrdo – jen `var(--wa-*)` a Bootstrapovy proměnné (viz
   hlavička souboru), aby popover seděl na obě barevná témata automaticky.
   -------------------------------------------------------------------------- */
body .driver-popover {
    /* Platformní tělové písmo, ne opsaný stack: driver.js kreslí popover mimo
       `.dashboard-shell`, takže `font-family` z `body` nedědí sám. Token, ne
       `'InterAdmin'` natvrdo – druhá kopie by se s `PlatformFontRegistry` rozešla
       při první výměně řezu (GH #121). */
    font-family: var(--font-platform-body, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);
    color: var(--wa-ink);
    background-color: var(--wa-panel);
    border: 1px solid var(--wa-line);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--wa-shadow-md);
}

body .driver-popover-title {
    color: var(--wa-ink);
}

body .driver-popover-description {
    color: var(--wa-ink-muted);
}

body .driver-popover-close-btn {
    color: var(--wa-ink-muted);
}

body .driver-popover-close-btn:hover,
body .driver-popover-close-btn:focus {
    color: var(--wa-ink);
}

body .driver-popover-progress-text {
    color: var(--wa-ink-muted);
}

body .driver-popover-footer-btn {
    color: var(--wa-ink);
    background-color: var(--wa-panel);
    border: 1px solid var(--wa-line);
    border-radius: var(--bs-border-radius-sm);
}

body .driver-popover-footer-btn:hover,
body .driver-popover-footer-btn:focus {
    background-color: var(--wa-hover);
}

body .driver-popover-arrow {
    border-color: var(--wa-panel);
}

/* --------------------------------------------------------------------------
   Právní dokumenty (`templates/legal/document.html.twig`) — Markdown vykreslený
   filtrem `markdown_to_html`. Tabulky umí až od GH #636 (rozšíření
   `League\CommonMark\Extension\Table\TableExtension` v `config/services.yaml`)
   a CommonMark je vypisuje jako holé `<table>` bez jediné třídy, protože do
   vygenerovaného markupu nejde z Markdownu sáhnout. Bootstrap holou tabulku
   nestyluje vůbec, takže bez těchhle pravidel by sloupce slezly na sebe.
   Ke zdrojovému textu se tu nesahá: `.table` se přidat nedá, doplňuje se
   selektorem.
   -------------------------------------------------------------------------- */

.legal-document-content table {
    width: 100%;
    margin-bottom: 1rem;
    border-collapse: collapse;
}

.legal-document-content th,
.legal-document-content td {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--bs-border-color);
    vertical-align: top;
    text-align: start;
}

.legal-document-content thead th {
    background-color: var(--bs-tertiary-bg);
}
