html, body {
    /*font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;*/
}

@media (hover: none) and (pointer: coarse) {
    html,
    body {
        touch-action: pan-x pan-y; /* Zakaze browserovy zoom gesty, ale necha bezny scroll. */
        overscroll-behavior: none;
    }
}

/*a, .btn-link {*/
/*    color: #006bb7;*/
/*}*/

/*.btn-primary {*/
/*    color: #fff;*/
/*    background-color: #1b6ec2;*/
/*    border-color: #1861ac;*/
/*}*/

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

/*.content {*/
/*    padding-top: 1.1rem;*/
/*}*/

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* Na mobilu skryjeme hero upload input — brání interakci s hero obrázkem */
@media (max-width: 640px) {
    .hero-upload-input {
        display: none !important;
    }
}

/* Minimální výška kořenového feed kontejneru – brání zkrácení stránky při přepínání záložek.
   Výslovně vyloučeny vnořené .feed-tree (složky uvnitř složek). */
.feed-tree:not(.feed-tree .feed-tree),
.feed-timeline {
    min-height: 80vh;
}

/* Světlé téma potřebuje kontrastní rub navrstvených fotografií; proměnné se dědí i do izolovaného CSS komponenty. */
[data-bs-theme=light] {
    --photo-variant-layer-back: #bcc2c9;
    --photo-variant-layer-front: #d9dde1;
    --photo-variant-layer-back-shadow: 0 -1px 2px rgba(0, 0, 0, 0.18);
    --photo-variant-layer-front-shadow: 0 -1px 2px rgba(0, 0, 0, 0.14);
}

/* Feed toolbar — odsazení mezi ikonami */
.feed-toolbar {
    gap: 20px !important;
}

/* Feed toolbar — neutrální barva ikon (přebíjí btn-link fialovou) */
.feed-toolbar a.btn-link,
.feed-toolbar button.btn-link {
    color: var(--bs-body-color) !important;
    opacity: 0.85;
    font-size: 1.35rem;
    padding: 0;
    line-height: 1;
    display: inline-flex !important;
    align-items: center;
    transition: opacity 0.15s;
}

.feed-toolbar a.btn-link i,
.feed-toolbar button.btn-link i {
    font-size: 1.35rem;
    line-height: 1;
}

.feed-toolbar .feed-toolbar-dots {
    display: inline-flex;
    align-items: center;
}

.feed-toolbar a.btn-link:hover,
.feed-toolbar button.btn-link:hover {
    color: var(--bs-body-color) !important;
    opacity: 1;
}

/* Aktivní stav poznámek */
.feed-toolbar a.btn-primary,
.feed-toolbar button.btn-primary {
    color: var(--bs-primary) !important;
    opacity: 1;
}

/* Tři tečky */
.feed-toolbar .feed-toolbar-dots {
    color: var(--bs-body-color);
    opacity: 0.85;
    cursor: pointer;
    transition: opacity 0.15s;
}

.feed-toolbar .feed-toolbar-dots:hover {
    opacity: 1;
}

/* FeedAppearancePanel — panel se otevírá doleva (zarovnání k pravému okraji ikony) */
.fap-panel {
    left: auto !important;
    right: 0 !important;
}

/* bars-filter je opticky výš — vizuální korekce */
.feed-toolbar .fap-wrapper button i.fa-bars-filter {
    position: relative;
    top: 2px;
}

/* Foto zpětná vazba nad PhotoSwipe: navrstvení panelu řeší PhotoCommentsPanel.razor.css (z-index 100001),
   zúžení samotného lightboxu řeší PhotoSwipe paddingFn v JS (photoswipe.blazor.js). */
.pswp .pswp__button--close {
    /* Křížek držíme mimo pravý panel a dostupný i po skrytí ostatních ovládacích prvků. */
    position: absolute;
    top: max(6px, env(safe-area-inset-top));
    right: auto;
    left: max(6px, env(safe-area-inset-left));
    /* Stejný rozměr jako --feedback a --more, aby všechna tři kulatá tlačítka lišty seděla
       na jedné ose. Výchozích 50x60 z photoswipe.css by křížek posunulo o 6 px níž než ostatní. */
    width: 44px;
    height: 44px;
    margin: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0.9;
    pointer-events: auto;
}

/* Viz --more/--feedback: .pswp__icn má v photoswipe.css pevné top/left naladěné na tlačítko 50x60,
   po zmenšení na 44x44 by ikona nesedla do středu. */
.pswp .pswp__button--close .pswp__icn {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.pswp .pswp__button--close:hover,
.pswp .pswp__button--close:active,
.pswp .pswp__button--close:focus {
    background: rgba(0, 0, 0, 0.75);
    opacity: 1;
}

/* Vestavěné zoom tlačítko PhotoSwipe nepoužíváme - zoom jde i tak přes kolečko myši/pinch, tlačítko
   navíc zabíralo místo v horní liště vedle download/⋯ menu. */
.pswp .pswp__button--zoom {
    display: none !important;
}

/* Potvrzovací dialog mazání (Blazored.Modal .bm-container, z-index 1300) by jinak zůstal schovaný
   za PhotoSwipe (.pswp má z-index 100000, viz photoswipe.css --pswp-root-z-index) - uživatel by klikl
   na "Smazat" a nic viditelného by se nestalo. Zvyšujeme z-index jen dokud je lightbox otevřený. */
body:has(.pswp--open) .bm-container {
    z-index: 100001 !important;
}

/* Bílá ikona "⋯" splývá se světlými fotkami. Jemný tmavý podklad (slabší než u zavíracího tlačítka,
   které musí být vidět vždy) drží kontrast, aniž by z ovládacího prvku dělal dominantu nad fotkou. */
.pswp .pswp__button--more {
    /* Výchozí tlačítko je 50x60 (viz photoswipe.css), z border-radius by proto vznikl ovál. */
    width: 44px;
    height: 44px;
    /* Horní margin drží stejnou osu jako absolutně umístěný křížek/counter vlevo (safe-area + 22px).
       Bez něj lišta sedí o 2 px níž a ikony vpravo se opticky rozejdou s křížkem. */
    margin: 6px 6px 0 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
}

/* .pswp__icn má v photoswipe.css pevné absolutní top/left (14px/9px), naladěné na výchozí tlačítko
   50x60. Protože je toto tlačítko zmenšené na 44x44, ten offset už ikonu nedrží ve středu a tečky
   se opticky posunou doprava dolů. Centrujeme proto ikonu vůči skutečné velikosti tlačítka.
   Kruhy v path leží na y=14 (viewBox 32x32), tedy 2px nad středem - dorovnáno posunem ikony o 2px dolů. */
.pswp .pswp__button--more .pswp__icn {
    top: 50%;
    left: 50%;
    transform: translate(-50%, calc(-50% + 2px));
}

.pswp .pswp__button--more:hover,
.pswp .pswp__button--more:active,
.pswp .pswp__button--more:focus {
    background: rgba(0, 0, 0, 0.6);
}

/* Mobilní přepínač panelu komentářů - stejný kruhový tvar jako "⋯", aby lišta držela jednu vizuální
   řadu. Vykresluje se jen na mobilu (viz photoswipe.blazor.js, registruje se pod isMobileUi):
   na desktopu se panel otevírá automaticky a tlačítko by nemělo co přepínat. */
.pswp .pswp__button--feedback {
    width: 44px;
    height: 44px;
    /* Horní margin drží stejnou osu jako absolutně umístěný křížek/counter vlevo (safe-area + 22px).
       Bez něj lišta sedí o 2 px níž a ikony vpravo se opticky rozejdou s křížkem. */
    margin: 6px 6px 0 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
}

/* Lajk vedle komentářů; stejný kruhový tvar, aby lišta držela jednu vizuální řadu. */
.pswp .pswp__button--like {
    width: 44px;
    height: 44px;
    margin: 6px 6px 0 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
}

.pswp .pswp__button--like:hover,
.pswp .pswp__button--like:active,
.pswp .pswp__button--like:focus {
    background: rgba(0, 0, 0, 0.6);
}

/* Font Awesome ikony uvnitř tlačítek lišty. PhotoSwipe počítá s vlastním .pswp__icn (absolutně
   umístěné SVG), takže pro <i> element žádné pravidlo nemá a bez tohoto by ikona zůstala v levém
   horním rohu tlačítka v základní velikosti textu. */
.pswp .pswp__button--like i,
.pswp .pswp__button--feedback i {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 19px;
    line-height: 1;
    color: #fff;
}

/* Stisknutý stav odlišuje, že panel je otevřený - jinak tlačítko po otevření sheetu nic nesignalizuje.
   Plnou ikonu (fas) přepíná JS; podklad je druhý, méně nápadný signál téhož. */
.pswp .pswp__button--feedback[aria-pressed="true"],
.pswp .pswp__button--like[aria-pressed="true"] {
    background: rgba(255, 255, 255, 0.28);
}

.pswp .pswp__button--feedback:hover,
.pswp .pswp__button--feedback:active,
.pswp .pswp__button--feedback:focus {
    background: rgba(0, 0, 0, 0.6);
}

/* Menu sekundárních akcí za "⋯" (viz photoswipe.blazor.js buildMoreActionsMenu). Leží v kořeni .pswp,
   ne v top-baru, který má vlastní stacking a menu by v něm bylo oříznuté. */
.pswp__more-menu {
    position: absolute;
    z-index: 20;
    min-width: 200px;
    padding: 0.25rem;
    border-radius: 0.5rem;
    background: rgba(30, 30, 30, 0.97);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}

.pswp__more-menu[hidden] {
    display: none;
}

.pswp__more-menu-item {
    display: block;
    width: 100%;
    padding: 0.55rem 0.75rem;
    border: 0;
    border-radius: 0.35rem;
    background: transparent;
    color: #fff;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}

.pswp__more-menu-item:hover,
.pswp__more-menu-item:focus-visible {
    background: rgba(255, 255, 255, 0.14);
}

/* Položka menu, která je ve skutečnosti nativní input[type=file] překrytý přes text.
   Musí být pozicovací kontext, aby se input roztáhl přesně přes ni. */
.pswp__more-menu-item--file {
    position: relative;
}

/* Průhledný input přes celou plochu položky. Nesmí se skrývat přes display:none ani
   pointer-events:none - právě jeho nativní klik otevírá dialog, což je jediný způsob,
   jak ho Safari otevře (programový click() mimo user gesture zahodí). */
.pswp__more-menu-file-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* Safari kreslí u input[type=file] vlastní tlačítko "Choose file" s pevnou šířkou; bez
   roztažení by klikatelná plocha nepokryla celou položku a její okraje by nereagovaly. */
.pswp__more-menu-file-input::-webkit-file-upload-button {
    width: 100%;
    height: 100%;
    cursor: pointer;
}

/* Smazání je nevratné, proto ho odlišíme barvou už v menu, ne až v potvrzovacím dialogu. */
.pswp__more-menu-item--danger {
    color: #ff8b96;
}

.pswp__more-menu-item--danger:hover,
.pswp__more-menu-item--danger:focus-visible {
    background: rgba(220, 53, 69, 0.85);
    color: #fff;
}

.pswp .pswp__counter {
    /* Výchozí PhotoSwipe counter začíná vlevo a po přesunutí zavíracího tlačítka do stejného
       rohu by se oba prvky překrývaly. Držíme ho proto hned za 44px křížkem a respektujeme
       stejné safe-area odsazení, aby se sestava nerozpadla ani na telefonu s výřezem.
       Svisle ho centrujeme na stejnou osu jako kulatá tlačítka (jejich střed = safe-area + 22px),
       aby lišta nebyla rozházená na tři různé výšky. */
    position: absolute;
    top: calc(max(6px, env(safe-area-inset-top)) + 22px);
    left: calc(max(6px, env(safe-area-inset-left)) + 52px);
    transform: translateY(-50%);
    margin: 0;
}

/* Odsazení pro desktopový boční panel; negace .pswp--mobile-ui místo @media (min-width: 641px) -
   telefon na šířku přesahuje 641 px, takže by si pod media query odsadil šipku i top-bar o 390 px,
   přestože na mobilu se panel otevírá jako bottom sheet a vpravo nic nerezervuje. */
.pswp:not(.pswp--mobile-ui) {
    /* PhotoSwipe padding neovlivňuje absolutně umístěné šipky, proto pravou držíme před bočním panelem. */
    &.pswp--feedback-panel-open .pswp__button--arrow--next {
        right: 390px;
    }

    /* Top-bar (zoom/download/delete/close) je také absolutně umístěný přes celou šířku (width: 100%,
       viz photoswipe.css .pswp__top-bar) - bez odsazení by tlačítka zůstala schovaná pod panelem
       zpětné vazby, který se na desktopu otevírá automaticky hned po otevření lightboxu. */
    &.pswp--feedback-panel-open .pswp__top-bar {
        width: calc(100% - 390px);
    }
}

/* Vlastní popisek fotky pod PhotoSwipe viewerem - jádro caption nemá vestavěný (viz photoswipe.blazor.js). */
.pswp__custom-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    padding: 8px 16px max(8px, env(safe-area-inset-bottom));
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.6));
    color: #fff;
    font-size: 0.85rem;
    text-align: center;
    pointer-events: none;
    /* Pevná výška (ne auto), aby na ní mohl stackovat variant-switcher (viz --pswp-caption-height níže) -
       jednořádkový text je vždy stejně vysoký, takže žádný obsah neuřízne. */
    height: var(--pswp-caption-height, 36px);
    box-sizing: border-box;
}

.pswp--has-thumbnail-strip {
    --pswp-thumbnail-rail-height: 92px;
}

.pswp--has-thumbnail-strip .pswp__custom-caption {
    bottom: var(--pswp-thumbnail-rail-height, 92px);
}

/* Scrollovací pás miniatur je vlastní PhotoSwipe UI; aktivní fotku udržuje vycentrovanou photoswipe.blazor.js. */
.pswp__thumbnail-strip {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 12;
    display: flex;
    align-items: center;
    gap: 8px;
    height: var(--pswp-thumbnail-rail-height);
    padding: 12px max(16px, env(safe-area-inset-right)) 12px max(16px, env(safe-area-inset-left));
    overflow-x: auto;
    overflow-y: hidden;
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(8px);
    overscroll-behavior-x: contain;
    scrollbar-color: rgba(255, 255, 255, 0.35) transparent;
    scrollbar-width: thin;
    touch-action: pan-x;
    transition: right 0.2s ease;
}

.pswp__thumbnail {
    flex: 0 0 64px;
    width: 64px;
    height: 64px;
    padding: 0;
    overflow: hidden;
    border: 2px solid transparent;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.08);
    cursor: pointer;
    opacity: 0.62;
    transition: border-color 0.15s ease, opacity 0.15s ease, transform 0.15s ease;
}

.pswp__thumbnail:hover {
    opacity: 0.9;
}

.pswp__thumbnail--active {
    border-color: var(--bs-primary, #7c5cff);
    opacity: 1;
    transform: scale(1.06);
}

.pswp__thumbnail img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
}

/* Miniatura videa v pásu. Bez značky je k nerozeznání od fotky, protože poster je obyčejný
   obrázek - uživatel by nevěděl, že ho čeká přehrávač. */
.pswp__thumbnail {
    position: relative;
}

.pswp__thumbnail-video-badge {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 13px;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
    pointer-events: none;
}

/* Video jako slide. PhotoSwipe u typu 'html' nedává obsahu žádné rozměry, takže se musí
   roztáhnout sám - jinak by se vykreslil ve své přirozené velikosti mimo střed plochy. */
.pswp__video-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.pswp__video {
    /* max-* místo width/height: video si drží vlastní poměr stran a nesmí se deformovat
       na poměr slidu, který jádro odhaduje z posteru nebo výchozích 16:9. */
    max-width: 100%;
    max-height: 100%;
    outline: none;
}

/* Jen desktop: na mobilu je panel bottom sheet a pás s popiskem se místo odsazení skrývají úplně
   (viz .pswp--mobile-ui níže), takže odsazení o šířku bočního panelu by tam bylo chybné. */
.pswp:not(.pswp--mobile-ui).pswp--feedback-panel-open .pswp__thumbnail-strip,
.pswp:not(.pswp--mobile-ui).pswp--feedback-panel-open .pswp__custom-caption {
    right: 390px;
}

/* Přepínač variant dole uprostřed, těsně NAD popiskem a spodním pásem miniatur hlavní osy - ne
   samostatná lišta nahoře. Svisle stackuje: [fotka] -> variant-switcher -> caption -> thumbnail-strip,
   všechny tři dolní vrstvy jsou ukotvené na bottom podle výšky vrstev pod nimi (viz --pswp-caption-height
   a --pswp-thumbnail-rail-height). Druhá, nezávislá osa vůči swipe/šipkám/spodnímu pásu (ty se pohybují
   jen mezi motivy). Kontejner má VŽDY stejnou výšku (viz --pswp-variant-switcher-height), i pro fotky
   bez variant, kde zůstává prázdný a neviditelný (opacity, ne display:none) - s variantou na zhruba
   každé druhé fotce by jinak lišta při každém druhém swipu problikávala dovnitř a ven. Pozadí (gradient)
   i obsah se objevují jen společně s --visible, aby na fotkách bez variant nezůstal viset ani prázdný
   pruh přes obrázek. Náhledy místo teček - tečka neřekne, čím se varianta liší.
   Kořenový kontejner drží pointer-events: none NATRVALO, i když je --visible - je full-width přes
   celý lightbox (kvůli center-aligned obsahu na libovolně široké obrazovce), ale PhotoSwipe by jinak
   klikům pod ním bránil ve fullscreen gridu. Klikatelné jsou proto jen samotné náhledy
   (.pswp__variant-switcher-thumb), viz níže. !important je nutný: registerElement přidává vlastní třídu
   .pswp__hide-on-close a vendorované photoswipe.css má pravidlo
   `.pswp--ui-visible .pswp__hide-on-close { pointer-events: auto }' se specificitou dvou tříd, které
   by jinak naše jednořádkové pravidlo přebilo v běžném stavu s viditelným UI. */
.pswp__variant-switcher {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(var(--pswp-thumbnail-rail-height, 0px) + var(--pswp-caption-height, 36px));
    z-index: 11;
    height: var(--pswp-variant-switcher-height, 104px);
    padding-bottom: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    pointer-events: none !important;
    opacity: 0;
    transition: opacity 0.15s ease;
}

/* Gradient patří jen ke stavu s náhledy. V základním pravidle by se kreslil i pro fotky bez variant:
   opacity: 0 sice skryje obsah, ale samotný přechod na fotku bez variant nechal nad pásem miniatur
   viset tmavý pruh, dokud doběhla animace přechodu. */
.pswp__variant-switcher--visible {
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.55));
}

/* Zobrazí se jen když má fotka varianty (--visible) A ZÁROVEŇ je vidět ovládání. Tap na fotku tak
   schová i tento přepínač (fullscreen jako v Google Photos) - nepoužíváme pro něj pswp__hide-on-close
   jako u captionu a pásu miniatur, protože ta třída také řídí opacity a prala by se s --visible,
   které tady navíc rozlišuje fotky s variantami a bez nich. */
.pswp--ui-visible .pswp__variant-switcher--visible {
    opacity: 1;
}

.pswp__variant-switcher-label {
    color: #fff;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

.pswp__variant-switcher-thumbs {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.pswp__variant-switcher-thumb {
    flex: 0 0 64px;
    width: 64px;
    height: 64px;
    padding: 0;
    overflow: hidden;
    border: 2px solid rgba(255, 255, 255, 0.5);
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.08);
    cursor: pointer;
    opacity: 0.7;
    /* Rodič má natrvalo pointer-events: none !important (viz výše) - tohle je jediný klikatelný prvek
       uvnitř, proto musí mít vlastní !important, aby se přes zákaz na rodiči dostal. */
    pointer-events: auto !important;
    transition: border-color 0.15s ease, opacity 0.15s ease, transform 0.15s ease;
}

.pswp__variant-switcher-thumb:hover {
    opacity: 0.95;
}

.pswp__variant-switcher-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
}

.pswp__variant-switcher-thumb--active {
    border-color: var(--bs-primary, #7c5cff);
    opacity: 1;
    transform: scale(1.06);
}

/* Mobilní rozměry vieweru se řídí třídou z Blazoru (viewer.isMobileUi v photoswipe.blazor.js),
   NE media query na šířku okna. Telefon otočený na šířku má přes 640 px, takže by pod media query
   spadl do desktopových hodnot (92px pás, 390px boční panel) - přestože o mobil pořád jde.
   Server telefon od úzkého desktopového okna rozliší (IsPhoneApp), šířka sama o sobě ne.
   Selektory uvnitř musí zůstat v sync s .pswp--mobile-ui na kořeni .pswp. */
.pswp--mobile-ui {
    &.pswp--has-thumbnail-strip {
        --pswp-thumbnail-rail-height: 76px;
    }

    .pswp__thumbnail-strip {
        gap: 6px;
        padding-top: 8px;
        padding-bottom: 8px;
    }

    .pswp__thumbnail {
        flex-basis: 52px;
        width: 52px;
        height: 52px;
    }

    /* Mobilní panel komentářů je bottom sheet přes ~68 % výšky obrazovky - pás miniatur a caption jsou
       dole a sheet by je stejně zakryl, proto zmizí úplně. Přepínač variant je jediný z dolního trojlístku,
       který na mobilu s otevřeným panelem NEmizí (viz níže) - je to jediné místo, kde uživatel pozná,
       že fotka, kterou zrovna komentuje, má varianty. */
    &.pswp--feedback-panel-open .pswp__thumbnail-strip,
    &.pswp--feedback-panel-open .pswp__custom-caption {
        display: none !important;
    }

    .pswp__variant-switcher {
        /* Výška počítá s 56px touch targetem (viz .pswp__variant-switcher-thumb níže) - pořád nad
           minimální doporučenou velikostí dotykového cíle (44px), jen o něco menší než na desktopu. */
        --pswp-variant-switcher-height: 84px;
        padding-bottom: 8px;
    }

    .pswp__variant-switcher-label {
        font-size: 0.72rem;
    }

    .pswp__variant-switcher-thumb {
        flex-basis: 56px;
        width: 56px;
        height: 56px;
    }

    /* S otevřeným bottom sheetem není dole místo (viz výše) - přepínač se přesune nahoru pod topbar,
       jediné volné místo, a zmenší na minimum: menší náhledy, bez labelu (na úzkém pruhu nahoře
       by kolidoval s "N / total" counterem a Download/Zoom ikonami). Miniaturní, ale pořád jasně
       čitelné a klikatelné - to je záměr, ne kompromis navíc. */
    &.pswp--feedback-panel-open .pswp__variant-switcher {
        top: max(48px, env(safe-area-inset-top));
        bottom: auto;
        justify-content: center;
        padding-bottom: 0;
        --pswp-variant-switcher-height: 56px;
        background: none;
    }

    &.pswp--feedback-panel-open .pswp__variant-switcher-label {
        display: none;
    }

    &.pswp--feedback-panel-open .pswp__variant-switcher-thumb {
        flex-basis: 40px;
        width: 40px;
        height: 40px;
    }
}

/* ==========================================================================
   ContextDropdown (design v2) – sdílený skelet kontextových menu v topbaru.

   Tyto styly jsou ZÁMĚRNĚ globální, ne scoped (.razor.css): obsah panelu dodávají
   volající komponenty přes ChildContent (WorkspaceContextMenu, ProjectContextMenu),
   takže jejich markup nese cizí scope atribut a scoped pravidla ContextDropdownu
   by se na něj nikdy nenavázala.
   ========================================================================== */

/* Kontejner musí být pozicovací kontext pro absolutně umístěný panel. */
.ctxd {
    position: relative;
    display: inline-flex;
}

/* Spouštěč se tváří jako segment breadcrumbu: bez vlastního pozadí, aby splynul
   s topbarem; jemné zvýraznění jen na hoveru/otevřeném stavu. */
.ctxd-trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    line-height: 1;
    transition: background-color 0.12s ease;
}

.ctxd-trigger:hover,
.ctxd-trigger.active {
    background: rgb(161 161 161 / 12%);
}

[data-bs-theme=light] .ctxd-trigger:hover,
[data-bs-theme=light] .ctxd-trigger.active {
    background: rgb(32 32 32 / 6%);
}

/* Průhledný backdrop přes celý viewport: klik kamkoli mimo panel ho zavře. */
.ctxd-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 1040;
}

/* Panel se otevírá DOLŮ (spouštěč je nahoře v topbaru).
   overflow: visible (ne auto) – scroll je na .ctxd-scroll uvnitř, aby ořezávající
   kontejner nemohl oříznout flyout vysouvající se absolutně vedle panelu. */
.ctxd-panel {
    position: absolute;
    left: 0;
    top: calc(100% + 6px);
    /* Explicitní základní váha písma: položky mají font:inherit a panel žije uvnitř
       breadcrumb segmentu (600 u prostoru, 500 u projektu) – bez tohoto resetu by menu
       dědilo tučnost triggeru a každý dropdown by vypadal jinak. 500 = kompromis mezi
       čitelností a klidem; identita (header 700) a aktivní položka (600) zůstávají silnější. */
    font-weight: 500;
    border: 1px solid rgb(161 161 161 / 14%);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bs-body-bg) 92%, #1a1a1a);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
    padding: 6px;
    z-index: 1041;
}

[data-bs-theme=light] .ctxd-panel {
    background: #fff;
    border-color: rgb(32 32 32 / 12%);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.16);
}

/* Varianta pro rail: panel se otevírá NAHORU od spouštěče. Rail dropdowny (uživatelský dock,
   Prostor) sedí u spodní hrany okna, takže dolů by neměly kam růst a ořezaly by se.
   Modifikátor jen přepíná ukotvení – zbytek vzhledu (rámeček, stín, padding) zůstává sdílený,
   aby rail menu vypadalo shodně s menu v topbaru. */
.ctxd-panel--up {
    top: auto;
    bottom: calc(100% + 6px);
}

/* Skutečný scroll kontejner položek, oddělený od .ctxd-panel kvůli flyoutu výše. */
.ctxd-scroll {
    max-height: min(80vh, 560px);
    overflow-y: auto;
}

.ctxd-divider {
    height: 1px;
    background: rgb(161 161 161 / 12%);
    margin: 5px 6px;
}

[data-bs-theme=light] .ctxd-divider {
    background: rgb(32 32 32 / 10%);
}

/* Řádek akce. position: relative kvůli flyoutu, který se z položky vysouvá
   absolutně VEDLE ní (přepnutí prostoru/projektu), ne pod ní. */
.ctxd-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    text-align: left;
    text-decoration: none;
    transition: background-color 0.1s ease;
}

.ctxd-item:hover,
.ctxd-item.active {
    background: rgb(161 161 161 / 12%);
    color: inherit;
}

[data-bs-theme=light] .ctxd-item:hover,
[data-bs-theme=light] .ctxd-item.active {
    background: rgb(32 32 32 / 6%);
}

/* Zakázaná položka: viditelná (uživatel ví, že funkce existuje), ale bez interakce. */
.ctxd-item:disabled {
    opacity: 0.45;
    cursor: default;
}

.ctxd-item:disabled:hover {
    background: transparent;
}

.ctxd-item-icon {
    width: 20px;
    text-align: center;
    opacity: 0.75;
    flex: 0 0 auto;
}

.ctxd-item-text {
    flex: 1 1 auto;
    white-space: nowrap;
}

/* Malý pomocný indikátor vpravo (external-link šipka, angle pro rozbalení). */
.ctxd-item-hint {
    font-size: 0.75em;
    opacity: 0.4;
    flex: 0 0 auto;
}

/* Nadpis sekce nad seznamem položek. */
.ctxd-label {
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 600;
    opacity: 0.45;
    padding: 8px 10px 3px;
    pointer-events: none;
}

/* Vnořené pod-menu – flyout VEDLE panelu (ne inline expand dolů), aby bylo na první
   pohled jasné, co se rozbalilo, a aby se panel nenatahoval nekontrolovatelně dolů.
   Trigger (.ctxd-item) musí mít position: relative. */
.ctxd-flyout {
    position: absolute;
    left: calc(100% + 6px);
    top: 0;
    width: 280px;
    max-height: min(70vh, 480px);
    overflow-y: auto;
    border: 1px solid rgb(161 161 161 / 14%);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bs-body-bg) 92%, #1a1a1a);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
    padding: 6px;
    z-index: 1042;
    animation: ctxd-flyout-in 0.14s ease-out;
}

[data-bs-theme=light] .ctxd-flyout {
    background: #fff;
    border-color: rgb(32 32 32 / 12%);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.16);
}

/* Flyout uvnitř panelu otevřeného nahoru (.ctxd-panel--up) se musí ukotvit ke SPODNÍ hraně
   spouštěcí položky, ne k horní: panel roste vzhůru od spodku okna, takže flyout zarovnaný
   na top by se u dolních položek vysunul pod viditelnou oblast. */
.ctxd-panel--up .ctxd-flyout {
    top: auto;
    bottom: 0;
}

@keyframes ctxd-flyout-in {
    from {
        opacity: 0;
        transform: translateX(-4px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Search input nad rozbaleným seznamem (jen u vyššího počtu položek). */
.ctxd-search {
    position: relative;
    display: flex;
    align-items: center;
    margin: 2px 4px 6px;
}

.ctxd-search-icon {
    position: absolute;
    left: 9px;
    font-size: 0.75rem;
    opacity: 0.4;
    pointer-events: none;
}

.ctxd-search-input {
    width: 100%;
    padding: 6px 8px 6px 26px;
    border: 1px solid rgb(161 161 161 / 18%);
    border-radius: 7px;
    background: rgb(161 161 161 / 8%);
    color: inherit;
    font: inherit;
    font-size: 0.82rem;
}

.ctxd-search-input:focus {
    outline: none;
    border-color: rgb(161 161 161 / 35%);
}

[data-bs-theme=light] .ctxd-search-input {
    background: rgb(32 32 32 / 4%);
    border-color: rgb(32 32 32 / 14%);
}

[data-bs-theme=light] .ctxd-search-input:focus {
    border-color: rgb(32 32 32 / 30%);
}

.ctxd-empty {
    padding: 10px;
    text-align: center;
    font-size: 0.8rem;
    opacity: 0.5;
}

.ctxd-list {
    display: flex;
    flex-direction: column;
}

/* Řádek v seznamu pod-menu (prostor/projekt) – nižší než .ctxd-item, je jich víc pod sebou. */
.ctxd-list-item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 6px 10px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    text-align: left;
    text-decoration: none;
    transition: background-color 0.1s ease;
}

.ctxd-list-item:hover {
    background: rgb(161 161 161 / 12%);
    color: inherit;
}

[data-bs-theme=light] .ctxd-list-item:hover {
    background: rgb(32 32 32 / 6%);
}

.ctxd-list-item.active {
    font-weight: 600;
}

/* Dvouřádkový text položky: název + doplňkový kontext (vlastník prostoru, zákazník projektu). */
.ctxd-list-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.ctxd-list-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ctxd-list-sub {
    font-size: 0.76rem;
    opacity: 0.5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ctxd-list-check {
    font-size: 0.8em;
    opacity: 0.7;
    flex: 0 0 auto;
}

/* Akce "přidat" na konci menu (nový prostor). Staví na .ctxd-item, ne na .ctxd-list-item:
   sousedí přímo s položkou "Přepnout prostor", a ta je .ctxd-item (ikona 20px + gap 10px).
   Kdyby akce použila geometrii seznamu prostorů (avatar 28px + gap 9px), text by začínal
   o ~7px vpravo a obě položky by pod sebou nelícovaly.

   Barevný akcent odlišuje akci od běžných položek menu - bez něj by "Nový prostor" splynul
   s okolními řádky a v Notion-like menu se právě tahle položka hledá očima jako první. */
.ctxd-item-add {
    color: var(--bs-primary, #2f80ed);
}

.ctxd-item-add:hover {
    color: var(--bs-primary, #2f80ed);
}

/* Přebíjí výchozí ztlumení .ctxd-item-icon - u akcentované akce má ikona držet stejnou
   sytost jako text, jinak "+" vedle barevného popisku vypadá vybledle. */
.ctxd-item-add .ctxd-item-icon {
    opacity: 1;
}

/* Hlavička panelu: identita entity (avatar + název + meta).
   Levý barevný pruh (--ctxd-accent) dává hlavičce vizuální identitu shodnou s badge
   ve spouštěči, ať jsou obě části vizuálně spojené. */
.ctxd-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px 10px;
    border-left: 3px solid var(--ctxd-accent, transparent);
    border-radius: 4px;
}

.ctxd-header-text {
    min-width: 0;
}

.ctxd-header-name {
    font-weight: 700;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Drobný kontextový řádek pod názvem. Minimalistický záměrně – jen text a tečkový
   oddělovač, žádné ikony, ať hlavička nepůsobí přehlceně. */
.ctxd-header-meta {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.78rem;
    opacity: 0.6;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ctxd-header-meta-dot {
    opacity: 0.7;
}

/* Akce v pravém horním rohu hlavičky (ozubené kolo = nastavení prostoru/projektu).
   Zkratka na akci, která byla dřív až čtvrtou položkou seznamu – vzor převzatý
   z přepínače stránek v editoru profilu, kde ozubené kolo sedí přímo u názvu.
   Položka v seznamu zůstává: hlavička je zkratka pro toho, kdo ji zná, ale menu
   musí být čitelné i pro uživatele, který ikonu nenajde.

   margin-left: auto odsune ikonu doprava; hlavička je flex a text před ní má
   min-width: 0, takže se dlouhý název zkrátí elipsou místo aby ikonu vytlačil.
   Svisle je na střed hlavičky (ne u horní hrany), aby optický těžiště sedělo
   k celému bloku identity, ne jen k prvnímu řádku s názvem. */
.ctxd-header-action {
    flex: 0 0 auto;
    align-self: center;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: inherit;
    /* Znatelně viditelnější než ztlumené ikony položek menu (0.5): jde o zkratku
       k nejčastější akci, která se musí dát najít bez hledání – ale pořád ne tak
       výrazná jako pojmenované položky, ať hlavičku nepřebíjí. */
    opacity: 0.75;
    cursor: pointer;
    font-size: 1rem;
    transition: background-color 0.1s ease, opacity 0.1s ease;
}

.ctxd-header-action:hover {
    opacity: 1;
    background: rgb(161 161 161 / 16%);
}

[data-bs-theme=light] .ctxd-header-action:hover {
    background: rgb(32 32 32 / 6%);
}

/* ==========================================================================
   Prolnutí mezi veřejnými stránkami prostoru (řídí publicPageTransitions.js)
   ==========================================================================

   Proč je to tady, a ne ve scoped CSS stránky nebo v _publicTheme.scss:

   ::view-transition-* jsou pseudo-elementy DOKUMENTU, ne potomci komponenty. Scoped CSS
   připíná ke každému selektoru atribut [b-xxx], čímž by se pravidlo minulo účinkem, a
   ::deep to neřeší – ty pseudo-elementy nejsou nikde ve stromu komponenty. Zároveň sem
   nepatří styl prostoru: hodnoty (barvy, fonty, rozměry) přicházejí z DB přes
   PublicStudioDesignStyleBuilder jako CSS proměnné. Tohle je čisté PRAVIDLO chování
   navigace, které superadmin nenastavuje, takže do konfigurovatelné vrstvy nespadá.

   Bez těchto pravidel by prohlížeč použil výchozí přechod, který starý pohled odsune a
   nový přisune – u výměny celé stránky to vypadá jako posun layoutu, ne jako plynulá
   návaznost. Prolínají se proto obě vrstvy přes sebe na místě.

   Animuje se jen opacity: jediná vlastnost, kterou prohlížeč zvládne na kompozitní vrstvě
   bez překreslení, což u snímků celé stránky (hero fotka přes celé okno) rozhoduje o tom,
   jestli je přechod plynulý. */
::view-transition-old(root),
::view-transition-new(root) {
    /* Musí odpovídat TRANSITION_MS v publicPageTransitions.js. */
    animation-duration: 200ms;
    animation-timing-function: ease-out;

    /* Výchozí chování obě vrstvy skládá s mix-blend-mode, kvůli čemuž během prolnutí
       krátce prosvítá podklad a vzniká záblesk – tedy přesně to, co má přechod odstranit. */
    mix-blend-mode: normal;
}

/* Starý pohled mizí pod novým: nový obsah je to podstatné a nemá se přes něj během
   nabíhání propisovat předchozí stránka. */
::view-transition-old(root) {
    animation-name: pp-page-fade-out;
}

::view-transition-new(root) {
    animation-name: pp-page-fade-in;
}

@keyframes pp-page-fade-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}

@keyframes pp-page-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Omezení pohybu: skript přechod vůbec nespustí, tohle je pojistka pro případ, že se
   předvolba přepne až v jeho průběhu. Nulová délka přechod ukončí okamžitě, takže
   nezůstane viset snímek staré stránky. */
@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: 0.01ms;
    }
}

/* Plovoucí lišta zvýraznění pro inline editaci nadpisu ve v2 editoru stránek.

   Styl je globální, ne scoped: lištu vytváří publicHeadingInlineEdit.js a připojuje ji do
   document.body, aby ji neořízl clip-path rámce náhledu ani přetečení bloku. Tím ale ztrácí
   scope atribut komponenty, takže scoped pravidlo by se na ni nikdy neuplatnilo. */
/* Plovoucí tlačítko "Upravit s AI" u nadpisu, popisku a Tiptap textu v náhledu.

   Trvale viditelné, ne až nad výběrem jako lišta zvýraznění: označit text uživatele nemusí
   napadnout, takže by funkci nenašel. Sedí vlevo od pole, aby nepřekrývalo obsah.

   position: fixed, protože pozici přepočítává JS podle prvku – tlačítko žije v body, ne
   uvnitř náhledu, jinak by ho ořízl obal bloku s overflow. */
.pp-inline-ai-floating {
    position: fixed;
    z-index: 1080;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .18);
    background: linear-gradient(135deg, #8b7cf6, #6d5fd6);
    color: #fff;
    font-size: 13px;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
    transition: transform .12s ease, box-shadow .12s ease;
}

.pp-inline-ai-floating:hover {
    transform: scale(1.08);
    box-shadow: 0 6px 18px rgba(109, 95, 214, .5);
}

/* Lišta inline editoru v náhledu nesmí zabírat místo v toku.

   Ve výchozím stavu je position: static, takže se text při každém fokusu posune o výšku
   lišty dolů a při rozfokusu zase nahoru – v hero, kde odstavec sedí těsně pod velkým
   nadpisem, to vypadá jako poskakující obsah (naměřeno 36 px). Absolutní pozice ji položí
   nad text, takže náhled zůstane v klidu a odpovídá tomu, jak stránka skutečně vypadá. */
.pp-inline-editor {
    position: relative;
}

/* Zdvojené třídy v selektorech níž nejsou překlep: dark pravidla v tiptap.css mají
   !important a stejnou specificitu, takže o vítězi rozhodovalo pořadí souborů – a tiptap.css
   se načítá později. Zdvojení posouvá specificitu o třídu výš a dělá z výsledku pravidlo
   místo náhody (naměřeno: lišta zůstávala #23272b a hůlka šedá i přes zdejší !important). */
.pp-inline-editor .tiptap-toolbar.tiptap-toolbar {
    position: absolute;
    bottom: calc(100% + 6px);
    top: auto;
    left: 0;
    z-index: 30;
    margin: 0;
    /* Vlastní stín: lišta teď leží nad obsahem stránky, takže bez odsazení od pozadí
       splývá s textem pod sebou. */
    box-shadow: 0 4px 16px rgba(0, 0, 0, .28);
    border-radius: 8px;
    /* Vždy světlá, bez ohledu na motiv editoru: náhled veřejné stránky má vlastní barvy
       nezávislé na aplikaci a tmavá lišta na tmavé stránce prakticky zanikla. */
    background: #fff !important;
    border-color: #e5e7eb !important;
}

/* Skrytá lišta nesmí být vidět ani chytat kliky. V tiptap.css má hide jen opacity: 0
   s půlsekundovým přechodem a pointer-events zakomentované – lišta tak při rozfokusu
   půl sekundy prosvítala jako duch a neviditelná dál překrývala nadpis nad editorem,
   kterému kradla kliknutí. */
.pp-inline-editor .tiptap-toolbar.tiptap-toolbar.hide {
    visibility: hidden;
    pointer-events: none;
}

/* Barvy tlačítek proti dark pravidlům z tiptap.css: na vynucené světlé liště by tlačítka
   zůstala světle šedá (#e5e7eb) a nebyla by vidět. */
.pp-inline-editor .tt-btn.tt-btn {
    color: #343a40 !important;
}

.pp-inline-editor .tt-btn.tt-btn:hover {
    background: #f1f3f5 !important;
}

.pp-inline-editor .tt-btn.tt-btn.active {
    background: #e9ecef !important;
    border-color: #dee2e6 !important;
    color: #111 !important;
}

.pp-inline-editor .tt-sep.tt-sep {
    background: #dee2e6 !important;
}

/* TooltipB obaluje tlačítko divem; ten musí zmizet z toku, jinak by v liště rozbil
   zarovnání ostatních tlačítek. */
.tiptap-toolbar > [data-bs-toggle="tooltip"] {
    display: inline-flex;
    align-items: center;
}

.pp-heading-toolbar {
    position: fixed;
    z-index: 1080;
    display: flex;
    gap: 2px;
    padding: 4px;
    border-radius: 8px;
    /* Tmavé pozadí nezávisle na motivu editoru: lišta se objevuje nad nadpisem uvnitř
       náhledu veřejné stránky, která bývá tmavá, a světlá lišta by na ní zanikla. */
    background: #1b1b1f;
    border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: 0 6px 24px rgba(0, 0, 0, .35);
}

.pp-heading-toolbar-btn {
    border: none;
    background: transparent;
    color: #ecebe4;
    font-size: 12px;
    line-height: 1;
    padding: 7px 10px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
}

.pp-heading-toolbar-btn:hover {
    background: rgba(255, 255, 255, .1);
}

/* Aktivní stav = výběr už je zvýrazněný, takže stisk zvýraznění zruší. Akcentní barva
   odpovídá barvě samotného zvýraznění v nadpisu, aby vazba byla zřejmá. */
.pp-heading-toolbar-btn.active {
    background: rgba(232, 163, 61, .18);
    color: #e8a33d;
}

/* Editovaný nadpis nemá vlastní rámeček ani pozadí – hranici nese obrys vybraného bloku
   a text musí vypadat přesně jako vysázený, jinak náhled přestane odpovídat výsledku. */
/* outline-color, ne zkrácené `outline: none`: hover níž nastavuje jen barvu a styl, a
   zkrácený zápis by při každém překreslení resetoval i outline-style zpátky na none
   (naměřeno – outline-offset se z hoveru aplikoval, ale obrys zůstal neviditelný). */
.pp-heading-editing {
    outline: 1px dashed transparent;
    outline-offset: 6px;
    cursor: text;
}

/* Prázdný nadpis by byl neviditelný cíl. min-height ho drží klikatelný, aniž by u
   vyplněného nadpisu cokoli posouval. */
.pp-heading-editing:empty {
    min-height: 1em;
}

/* Náznak editovatelnosti při najetí myší.

   Uživatel jinak nemá jak poznat, že se nadpis dá přepsat přímo v náhledu – vypadá stejně
   jako na hotové stránce. Čárkovaný obrys se ukazuje jen na hover, takže náhled zůstává
   věrný a signál se objeví přesně tam, kde na něj uživatel míří.

   Platí i pro NEvybraný blok (třída pp-heading-editable na statickém nadpisu): právě tam
   je signál nejpotřebnější, protože uživatel teprve zvažuje, kam kliknout. Na vybraném
   bloku pokračuje na pp-heading-editing, do kterého se nadpis promění.

   outline, ne border: border by prvku změnil rozměry a text by při najetí poskočil.
   Text bloku má stejný obrys, ale řeší si ho PublicEditorialBlock.razor.css – scoped
   selektor má vyšší specificitu, takže by ho pravidlo odsud nepřebilo. */
.pp-heading-editable {
    outline: 1px dashed transparent;
    outline-offset: 6px;
    cursor: text;
}

.pp-heading-editable:hover,
.pp-heading-editing:hover {
    outline-color: rgba(127, 119, 221, .55);
    border-radius: 2px;
}

/* Během psaní obrys mizí – jeho úkolem je pozvat ke kliknutí, ne rámovat text, ve kterém
   uživatel právě pracuje. */
.pp-heading-editing:focus,
.pp-heading-editing:focus:hover {
    outline-color: transparent;
}

/* Inline editace popisku nad nadpisem (eyebrow) ve v2 editoru.

   Popisek je krátký prostrkaný štítek, takže má stejný náznak editovatelnosti jako nadpis,
   jen menší odsazení obrysu – u 11px verzálek by 6px odstup vypadal jako rámeček kolem
   prázdna. Průhledný obrys v základu a jen změna barvy na hover: zkrácený zápis by při
   překreslení resetoval outline-style zpátky na none. */
.pp-eyebrow-editable,
.pp-eyebrow-editing {
    outline: 1px dashed transparent;
    outline-offset: 4px;
    cursor: text;
}

.pp-eyebrow-editable:hover,
.pp-eyebrow-editing:hover {
    outline-color: rgba(127, 119, 221, .55);
    border-radius: 2px;
}

.pp-eyebrow-editing:focus,
.pp-eyebrow-editing:focus:hover {
    outline-color: transparent;
}

/* Blok bez popisku: místo zůstává v editoru vidět jako tlumená nápověda, aby šlo popisek
   doplnit. Na veřejné stránce se prázdný popisek nevykresluje vůbec. */
.pp-eyebrow-empty {
    opacity: .45;
    font-style: italic;
}

/* Nápověda v prázdném editovaném popisku. Kreslí ji ::before, ne textový obsah: do
   contenteditable nesmí přijít skutečný text, uložil by se jako hodnota popisku. */
.pp-eyebrow-editing:empty::before {
    content: attr(data-placeholder);
    opacity: .45;
    font-style: italic;
}

/* Prázdný popisek musí zůstat klikatelný – nulová výška by z něj udělala neviditelný cíl. */
.pp-eyebrow-editing:empty {
    min-height: 1em;
    display: block;
}

/* Inline editace polí strukturovaných bloků (karty, ceník).

   Stejný náznak jako u nadpisu a textu, jen menší odsazení obrysu – pole leží těsně vedle
   sebe uvnitř karty a 6px odstup by je slil dohromady. Průhledný obrys v základu, hover
   mění jen barvu: zkrácený zápis by při překreslení resetoval outline-style na none. */
.pp-item-field-editable,
.pp-item-field-editing {
    outline: 1px dashed transparent;
    outline-offset: 3px;
    cursor: text;
    border-radius: 2px;
}

.pp-item-field-editable:hover,
.pp-item-field-editing:hover {
    outline-color: rgba(127, 119, 221, .55);
}

.pp-item-field-editing:focus,
.pp-item-field-editing:focus:hover {
    outline-color: transparent;
}

/* Nápověda v prázdném poli. Kreslí ji ::before, ne textový obsah: do contenteditable
   nesmí přijít skutečný text, uložil by se jako hodnota. */
.pp-item-field-editing:empty::before {
    content: attr(data-placeholder);
    opacity: .45;
    font-style: italic;
}

/* Prázdné pole musí zůstat klikatelné – nulová výška by z něj udělala neviditelný cíl. */
.pp-item-field-editing:empty {
    min-height: 1em;
    display: inline-block;
    min-width: 6ch;
}

/* ==========================================================================
   Tooltipy avatarů týmu projektu (ProjectTeamAvatars)

   Bootstrap vykresluje tooltip v <body>, mimo DOM komponenty, takže její scoped CSS
   se na něj nikdy nenaváže – pravidla proto musí být tady, stejně jako u .ctxd-*.
   ========================================================================== */

/* Řádky uvnitř tooltipu jsou <span>; blokové zobrazení z nich dělá řádkovou strukturu
   (jméno / role, resp. seznam skrytých členů) bez <br> a bez závislosti na bílém znaku. */
.pta-tip-name,
.pta-tip-role,
.pta-tip-pending,
.pta-tip-line,
.pta-tip-rest {
    display: block;
    text-align: left;
    line-height: 1.3;
}

/* Stav nevyřízené pozvánky. Není potlačený jako role pod ním: je to hlavní sdělení
   tooltipu (tenhle člověk ještě není v aplikaci), ne doplňkový údaj. Jantarová barva
   navazuje na varovné odstíny jinde v aplikaci a funguje v obou motivech. */
.pta-tip-pending {
    color: #e0a63a;
    font-size: .92em;
    font-weight: 600;
}

.pta-tip-name {
    font-weight: 600;
}

/* Role je doplňková informace – nesmí soupeřit se jménem nad ní. */
.pta-tip-role {
    font-size: .92em;
    opacity: .65;
}

/* Oddělovací mezera před shrnutím "a další N", aby nesplynulo se jmény nad ním. */
.pta-tip-rest {
    margin-top: 3px;
    font-size: .92em;
    opacity: .65;
}
