/* Chování značky: kde je málo místa, zůstane jen znak; kde je místo, vysune
   se k němu i slovo.

   Animuje se grid-template-columns z 0fr na 1fr. Šířka textu se tím nemusí
   nikde měřit ani natvrdo psát — prohlížeč ji spočítá sám a přechod je
   plynulý. Kdyby se animovala width, muselo by se počítat v JS a při změně
   jazyka nebo velikosti písma by to přestalo sedět. */

.brand-word {
    display: grid;
    grid-template-columns: 0fr;
    transition: grid-template-columns .18s cubic-bezier(.32, .72, 0, 1),
                opacity .12s ease;
    opacity: 0;
}



.brand-word > span {
    overflow: hidden;
    min-width: 0;
    white-space: nowrap;
}

.brand.is-open .brand-word {
    grid-template-columns: 1fr;
    opacity: 1;
}

/* Kde je místo, je celý název vidět rovnou — ne až po doběhnutí skriptu.
 *
 * Otevíral ho JS třídou `is-open`, jenže ten běží až po prvním vykreslení:
 * při každém přechodu na jinou záložku „.d" viditelně vyjelo na „.datum".
 * Výchozí stav proto říká CSS, které platí dřív než jakýkoliv skript.
 * Skript už jen zavírá, když se odscrolluje — a to je pohyb, který si
 * člověk vyvolal sám, ne něco, co appka udělá pod rukama. */
@media (min-width: 1024px) {
    .brand[data-collapsible] .brand-word {
        grid-template-columns: 1fr;
        opacity: 1;
    }
}

/* Jediný důvod sevřít nápis: scrollování. Jsem někde v půlce stránky,
   značka ustoupí obsahu. Kvůli místu v liště se nesevře nikdy — nahoře na
   stránce má stát „.datum"; když se záložky nevejdou, lišta se posune. */
.brand[data-collapsible].is-shut .brand-word {
    grid-template-columns: 0fr;
    opacity: 0;
}

/* Během načítání se značka nastaví skokem, ne přechodem. Po refreshi
 * obnoví prohlížeč odscrollování až po prvním vykreslení, takže „.datum"
 * stihlo bliknout a teprve pak zajelo na „.d". Příznak sází base.html
 * ve <head> a odstraňuje po `load`. */
html.is-booting .brand-word,
html.is-booting .topbar-shell {
    transition: none;
}

/* Celý nápis je jedna sazba, takže „atum" navazuje na „d" bez jakékoli
   mezery — jinak by se to četlo jako dvě slova. */
.brand-word > span {
    padding-left: 0;
}

/* --- listování dlaždic ---
 *
 * Neaktivní pruh měl `bg-white/15`, což je na světlém motivu neviditelné —
 * nešlo poznat, kolik stránek dlaždice vůbec má. Barva se proto bere
 * z textu, ne z bílé, a funguje v obou motivech. */
.page-dot {
    height: 3px;
    width: 26px;
    background: currentColor;
    opacity: .18;
    color: inherit;
    transition: opacity .2s ease, background-color .2s ease;
    cursor: pointer;
}

.page-dot:hover {
    opacity: .4;
}

.page-dot.is-active {
    background: var(--accent);
    opacity: 1;
}

.page-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    opacity: .45;
    transition: opacity .2s ease;
    cursor: pointer;
}

.page-nav:hover {
    opacity: 1;
    color: var(--accent);
}

/* Na kraji se šipka nezhasne, jen zešedne — zmizelé tlačítko posune
   sousedy a lišta pod dlaždicí by při listování poskakovala. */
.page-nav[disabled] {
    opacity: .12;
    cursor: default;
}

.page-dot:focus-visible,
.page-nav:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Značka lícuje se sloupcem obsahu, i když lišta jde přes celou šířku.
 *
 * Lišta se roztáhla proto, aby se do ní vešly záložky — jenže s ní odjela
 * ke kraji okna i značka a přestala stát nad kartami. Odsazení vlevo se
 * proto počítá tak, aby `.datum` začínalo přesně tam, kde začínají karty:
 * půlka rozdílu mezi oknem a sloupcem obsahu, plus jeho vnitřní okraj.
 * Na užším okně `max()` spadne na běžné odsazení.
 *
 * Vpravo se nic nedopočítává schválně — ikony mají zůstat u kraje, aby
 * záložky měly co nejvíc místa. */
.topbar-shell {
    position: relative;
    transition: padding .3s ease;
    padding-left: max(1rem, calc((100% - 64rem) / 2 + 1rem));
}

@media (min-width: 640px) {
    .topbar-shell {
        padding-left: max(1.5rem, calc((100% - 64rem) / 2 + 1.5rem));
    }
}

@media (prefers-reduced-motion: reduce) {
    .brand-word,
    .brand svg,
    .topbar-shell,
    .assistant-slide {
        transition: none;
    }
}

/* --- navigace na úzkém okně --------------------------------------------
 *
 * Do lišty na telefonu se vejde jedna záložka, sotva dvě. Vodorovné
 * posouvání to řešilo jen naoko: kdo neví, že se s lištou dá hýbat, vidí
 * appku o třech obrazovkách a o zbytku se nedozví.
 *
 * Pod 640 px proto zbydou v liště tři čárky a nabídka vyjede od levé hrany.
 * Jméno záložky v liště bylo dřív, ale opakovalo nadpis stránky pod ní —
 * a rozbalovátko u textu vypadá jako výběr hodnoty, ne jako navigace.
 * Nad 640 px se nabídka schová a vrátí se běžný pruh záložek. */
.nav-toggle {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 1px;
    height: 1px;
}

.nav-button {
    display: none;
    align-items: center;
    justify-content: center;
    /* Čtverec 44 px: ťukací plocha podle Applu, bez dalšího dolaďování. */
    width: 44px;
    height: 44px;
    color: var(--c-muted);
    cursor: pointer;
}

/* Tři čárky, které se při otevření přehnou do křížku. Kreslí se z prvků,
 * ne z SVG: přechod mezi oběma stavy je pak jedna transformace a nemusí
 * se překreslovat cesta. */
.nav-burger {
    position: relative;
    display: block;
    width: 18px;
    height: 12px;
}

.nav-burger i {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform .22s cubic-bezier(.4, 0, .2, 1), opacity .16s ease;
}

.nav-burger i:nth-child(1) { top: 0; }
.nav-burger i:nth-child(2) { top: 5px; }
.nav-burger i:nth-child(3) { top: 10px; }

.nav-toggle:checked ~ header .nav-button { color: var(--accent); }
.nav-toggle:checked ~ header .nav-burger i:nth-child(1) {
    transform: translateY(5px) rotate(45deg);
}
.nav-toggle:checked ~ header .nav-burger i:nth-child(2) { opacity: 0; }
.nav-toggle:checked ~ header .nav-burger i:nth-child(3) {
    transform: translateY(-5px) rotate(-45deg);
}

.nav-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    /* Nad jazýčkem asistenta (40), pod jeho panelem (50) — otevřená
       nabídka má překrýt všechno, co je pod ní, včetně toho jazýčku. */
    z-index: 41;
    background: rgb(0 0 0 / .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s ease;
}

/* Nabídka vyjede od pravé hrany, ne shora pod lištou.
 *
 * POZOR: panel stojí v šabloně **vedle** <header>, ne v něm. Lišta má
 * `backdrop-blur` a `backdrop-filter` z prvku dělá containing block pro
 * potomky s `position: fixed` — fixed se pak nepočítá od okraje obrazovky,
 * ale od lišty. Panel se tím scvrkl na její výšku a schoval za obsah
 * stránky. Rozbalovátko přes
 * celou šířku zakrývalo obsah a končilo v polovině obrazovky, takže nebylo
 * poznat, jestli je seznam celý. Panel od hrany je na telefonu dohodnutý
 * tvar navigace: přijde odtamtud, kam se ťuklo, a zabere celou výšku,
 * takže se v něm nemá kde schovat zbytek.
 *
 * `fixed`, ne `absolute`: panel má jít od horní hrany obrazovky až ke
 * spodní, a to by uvnitř lišty nešlo. */
.nav-sheet {
    display: none;
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    width: min(19rem, 82vw);
    z-index: 42;
    flex-direction: column;
    background: var(--surface);
    border-left: 1px solid var(--line);
    overflow-y: auto;
    /* Pod výřezem a nad čárkou gesta — panel sahá přes celou výšku, takže
     * si odsazení musí řešit sám. */
    padding: calc(env(safe-area-inset-top) + .5rem) 0 calc(env(safe-area-inset-bottom) + .5rem);
    transform: translateX(100%);
    pointer-events: none;
    transition: transform .26s cubic-bezier(.32, .72, 0, 1);
}

.nav-sheet-link {
    padding: .8125rem 1.25rem;
    font-size: 17px;
    font-weight: 500;
    letter-spacing: -.025em;
}

/* Oddělovač odsazený od levé hrany, jako v iOS seznamech. Linka přes celou
 * šířku rozsekne panel na pruhy; odsazená drží položky pohromadě jako
 * jeden seznam. */
.nav-sheet-link + .nav-sheet-link {
    box-shadow: inset 0 1px 0 var(--line);
}

.nav-sheet-link.is-active {
    color: var(--accent);
}

@media (max-width: 639px) {
    .nav-rail { display: none; }

    .nav-button { display: flex; }
    .nav-sheet { display: flex; }
    .nav-backdrop { display: block; }

    .nav-toggle:checked ~ .nav-sheet {
        transform: translateX(0);
        pointer-events: auto;
    }

    .nav-toggle:checked ~ .nav-backdrop {
        opacity: 1;
        pointer-events: auto;
    }
}

/* Obal grafu. V šablonách byl od začátku, v CSS nikdy — takže široký
 * graf netlačil sám sebe do posuvníku, ale celou stránku: na displeji
 * 320 px šlo appku posouvat o 55 px do prázdna.
 *
 * Graf, který se nevejde, má rolovat uvnitř svého rámečku. `contain`
 * navíc zaručí, že se s ním do šířky dokumentu nepočítá vůbec. */
.chart-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    max-width: 100%;
    /* `min-width: 0` je tu kvůli mřížce a flexu: jejich prvky se ve
     * výchozím stavu nezmenší pod šířku svého obsahu, takže graf o šesti
     * stech pixelech roztáhl celý sloupec a s ním stránku. Tohle jim
     * dovolí se zúžit a graf pak roluje uvnitř sebe, jak má. */
    min-width: 0;
    contain: paint;
}

/* Totéž o úroveň výš. Obal grafu bývá v mřížce zabalený ještě v jednom
 * <div>, a ten se musí umět zúžit taky — jinak se `min-width: 0` výš
 * nemá o co opřít. */
.chart-cell {
    min-width: 0;
}

/* Grafy se do úzkého okna vejdou zmenšením, ne posunem — `viewBox` je
 * na to udělaný. Minimální šířku si nastavuje jen ten graf, u kterého by
 * zmenšení slepilo popisky. */
.chart-scroll > svg {
    max-width: 100%;
    height: auto;
}

/* --- význam v textu ---
 *
 * Zelená a cihlová se berou ze stejného zdroje jako grafy. Dřív měl text
 * vlastní `text-emerald-400` a grafy vlastní šalvějovou; bylo to dvakrát
 * „dobře", pokaždé jinou barvou. Cihlová schválně není accent — ten
 * označuje odkazy a tlačítka, takže záporné číslo v accentu by se četlo
 * jako výzva něco udělat, ne jako údaj. */
.text-good { color: var(--c-good); }
.text-bad { color: var(--c-bad); }
.bg-good { background-color: var(--c-good); }
.bg-good-soft { background-color: color-mix(in srgb, var(--c-good) 12%, transparent); }
.border-good { border-color: color-mix(in srgb, var(--c-good) 40%, transparent); }

/* --- rám stránky ---
 *
 * Hlavička, sekce a tlačítka byly rozepsané jako utility v každé šabloně
 * zvlášť. Dokud se nic nemění, funguje to; jakmile se doladí odsazení,
 * rozejde se to, protože se místa hledají grepem. Tady jsou jednou.
 *
 * Nejsou to komponenty — každá záložka si dál dělá své ovládání. Tohle je
 * jen rám, který je kolem toho všude stejný. */
/* Nadpis stránky nese systémovou barvu. Je na stránce jediný, takže se
   accent neroztříští — a zároveň je hned poznat, že barva appky není jen
   v liště a v odkazech, ale drží celý vzhled pohromadě. */
.page-title {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -.025em;
    line-height: 1.15;
    color: var(--accent);
}

.page-lede {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .75rem;
    color: var(--c-muted);
    margin-top: .25rem;
}

/* Tři velikosti, ne čtyři náhodné. `btn` je výchozí, `btn-sm` do řádku
   tabulky, `btn-lg` na hlavní akci stránky. */
/* Schované tlačítko musí zmizet i tady. `[hidden] { display: none }` z
 * Tailwindu má stejnou specificitu jako `.btn`, a protože se tenhle soubor
 * načítá později, vyhrávalo `inline-flex` — takže `button.hidden = true`
 * ze skriptu nedělalo nic a „Uložit" zůstávalo viset pod každým formulářem,
 * který se ukládá sám. */
.btn[hidden],
.btn-sm[hidden],
.btn-lg[hidden] {
    display: none;
}

.btn,
.btn-sm,
.btn-lg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    background: var(--accent);
    color: #fff;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .75rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    transition: background-color .15s ease;
    cursor: pointer;
}

/* Druhotné akce. Do téhle chvíle se psaly inline a rozešly se: dvě
 * rodiny lišící se jen odstínem textu a velikostí písma, dohromady
 * devětadvacet podob tlačítka napříč appkou. Rozdíl mezi
 * `text-neutral-300` a `text-neutral-400` nikdo nezamýšlel, jen se to
 * někde opsalo jinak — a přesně z toho vzniká pocit, že je appka
 * poskládaná z kousků.
 *
 * `btn-tichy` je akce s rámečkem (Uložit u řádku, Dorovnat, Přidat),
 * `btn-mini` je akce bez rámečku (Zpátky na návrh, Schovat),
 * `btn-x` je mazací křížek. Víc podob druhotného tlačítka appka
 * nepotřebuje. */
.btn-tichy,
.btn-mini,
.btn-x {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: .08em;
    text-transform: uppercase;
    transition: color .15s ease, border-color .15s ease;
    cursor: pointer;
}

.btn-tichy {
    border: 1px solid color-mix(in srgb, var(--line) 85%, transparent);
    color: var(--c-muted);
    font-size: .625rem;
    padding: .25rem .5rem;
}

.btn-tichy:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.btn-tichy[disabled] {
    border-color: color-mix(in srgb, var(--line) 45%, transparent);
    color: color-mix(in srgb, var(--c-muted) 55%, transparent);
    cursor: not-allowed;
}

.btn-mini {
    color: var(--c-muted);
    font-size: .625rem;
}

.btn-mini:hover { color: var(--accent); }

/* Na telefonu o pixel výš. Deset pixelů je na monitoru drobný popisek,
 * na displeji v ruce hádanka — Apple chce u čitelného textu aspoň 11.
 * Je to uppercase mono s prostrkáním, takže se tím nic nerozsype;
 * měřeno v prohlížeči na devíti šířkách, přetečení nikde.
 *
 * Patří to sem, a ne do theme.css k ostatním mobilním úpravám: brand.css
 * se načítá později, takže by přepis v theme.css tahle definice přebila.
 * Media query specificitu nepřidává. */
@media (max-width: 430px) {
    .btn-tichy, .btn-mini, .btn-x,
    /* Názvy karet a popisky souvislostí jsou tytéž .625rem — na telefonu
     * je to většina textu, který appka ukazuje nad čísly, takže by zůstalo
     * opravené tlačítko vedle nečitelného nadpisu. */
    .card-name, .insight-source, .insight-ask, .telo-popisky { font-size: 11px; }
}

/* Mazání. Není uppercase ani mono-velké — je to křížek, ne slovo. */
.btn-x {
    color: color-mix(in srgb, var(--c-muted) 70%, transparent);
    font-size: .6875rem;
    padding: 0 .25rem;
    letter-spacing: 0;
}

.btn-x:hover { color: var(--c-bad); }

.btn { padding: .5rem 1rem; }
.btn-sm { padding: .375rem .75rem; font-size: .6875rem; }
.btn-lg { padding: .625rem 1.25rem; }

.btn:hover,
.btn-sm:hover,
.btn-lg:hover { background: var(--accent-hover); }

.btn:focus-visible,
.btn-sm:focus-visible,
.btn-lg:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Odkaz zpět na nadřazenou stránku. Podstránka neotevírá nadpisem oddílu,
   ale návratem — člověk na ni přišel odjinud a první, co potřebuje vědět,
   je kudy zpátky. */
.page-back {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .75rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--accent);
}

.page-back:hover { text-decoration: underline; }

/* --- horní lišta ---
 *
 * Ikony vpravo byly holé glyfy bez vlastní plochy. Trefit se do nich prstem
 * znamenalo mířit na dvacet pixelů; teď má každá terč 34 px, i když kresba
 * zůstala stejně velká. Podbarvení při najetí říká, že je to ovládací prvek
 * a ne popisek. */
/* Ikony mají stejnou výšku a stejný spodní ukazatel jako záložky. Profil
   ani nastavení nejsou v navigaci, takže se na nich dřív nesvítilo vůbec
   nic a stránka vypadala, jako by nikam nepatřila. */
.topbar-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Ikony v liště. Zmenšené spolu s celou lištou — dotyková plocha
     * zůstává nad 28 px, což na telefon stačí, a lišta tím ubrala
     * z výšky, kterou ukrajovala obsahu.
     *
     * Výška je stejná jako u `.nav-link` schválně. Obojí nese podtržení
     * aktivní položky na své spodní hraně, takže jakmile se výšky liší,
     * leží ta linka na notifikacích o pixel výš než na záložkách —
     * změřeno v prohlížeči: 15 px proti 14 px pod spodkem lišty. */
    width: 1.85rem;
    height: 1.9rem;
    color: rgb(115 115 115);
    border-bottom: 2px solid transparent;
    transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}

.topbar-icon:hover {
    color: #fff;
    background: rgb(255 255 255 / .08);
}

[data-theme="light"] .topbar-icon:hover {
    color: #15171a;
    background: rgb(0 0 0 / .06);
}

.topbar-icon.is-active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.topbar-icon:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Odznak s počtem. Sedí v rohu tlačítka, ale **mimo ikonu**.
 *
 * Dřív stál dva pixely od horního a pravého okraje tlačítka, které je
 * 30 × 28 px a nese ikonu 18 × 18. Změřeno v prohlížeči: u dvouciferného
 * čísla překryl 77 % zvonku — z ikony zbyl proužek a nešlo poznat, co to
 * tlačítko dělá.
 *
 * Teď je posunutý ven z tlačítka a oddělený prstencem v barvě lišty,
 * takže se čte jako štítek nad ikonou, ne jako skvrna přes ni. */
.topbar-badge {
    position: absolute;
    top: -3px;
    right: -5px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent);
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
    /* Prstenec v barvě lišty. Bez něj odznak splývá s ikonou pod sebou
     * všude, kde se dotýkají. */
    box-shadow: 0 0 0 2px rgb(0 0 0 / .9);
}

[data-theme="light"] .topbar-badge {
    box-shadow: 0 0 0 2px rgb(255 255 255 / .92);
}

/* Ikony u pravého kraje mají odznak přesahující ven — bez místa navíc
 * by se poslednímu z nich uřízl. */
.topbar-icons {
    padding-right: 5px;
}

.topbar-divider {
    width: 1px;
    height: 1.25rem;
    margin: 0 .375rem;
    background: currentColor;
    opacity: .12;
    flex-shrink: 0;
}


/* Aktivní záložka se pozná i podtržením, ne jen barvou. Accent nese v liště
   víc rolí najednou (odznaky, značka) a u světlejších systémových barev je
   rozdíl proti šedé menší, než by měl být. */
/* Ukazatel aktivní záložky má být zarovnaný se spodkem nápisu .datum, ne
   s textem záložky. Text proto zůstává vystředěný a podtržení se odděluje:
   odkaz dostane pevnou výšku shodnou s výškou značky, takže jeho spodní
   hrana sedí tam, kde končí .datum, ať je písmo záložky jakkoli velké. */
.nav-link {
    display: inline-flex;
    align-items: center;
    /* Výška je odladěná tak, aby *spodní hrana* linky ležela na spodku
       nápisu .datum. Text záložky uvnitř zůstává vystředěný. */
    height: 1.9rem;
    padding: 0 .125rem;
    color: rgb(163 163 163);
    border-bottom: 2px solid transparent;
    transition: color .15s ease, border-color .15s ease;
}

/* Schovaná záložka musí zmizet i z rozložení.
 *
 * `[hidden] { display: none }` z Tailwindu má stejnou specificitu jako
 * `.nav-link`, a protože se tenhle soubor načítá později, vyhrálo
 * `inline-flex` — schované veličiny dál zabíraly místo. `space-between`
 * pak odsunulo poslední **viditelnou** záložku doleva a mezi ní a zvonkem
 * zela díra; navíc se kvůli tomu zabranému místu schovalo víc veličin,
 * než bylo potřeba. Stejná past už tady jednou byla u `.btn[hidden]`. */
.nav-link[hidden] {
    display: none;
}

.nav-link:hover { color: #fff; }

[data-theme="light"] .nav-link { color: rgb(115 115 115); }
[data-theme="light"] .nav-link:hover { color: #15171a; }

.nav-link.is-active,
[data-theme="light"] .nav-link.is-active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.nav-link:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Kolejnice pod záložkami. Ukazatel na ní sedí místo aby visel v prázdnu,
   takže je vidět, po čem se posouvá — a linka zároveň ukazuje, kde je
   účaří nápisu .datum, i když je zrovna aktivní úplně jiná záložka.

   Stejná tloušťka jako ukazatel je záměr: dvě různé tloušťky by vypadaly
   jako dvě různé věci, ne jako značka a dráha, po které jede. Barva jde
   z palety, ne z `currentColor` — ten na navigaci vycházel na desetinu
   bílé a kolejnice nebyla vidět.

   Kreslí se podkladem, ne rámečkem. Navigace se na úzkém displeji posouvá
   do stran (`overflow-x: auto`), a scrollovací kontejner ořezává obsah na
   výplňový box — rámeček je až za ním. Ukazatel aktivní záložky, vtažený
   do rámečku záporným okrajem, se tím celý ořízl a na liště nebyl vidět.
   Podklad leží uvnitř výplňového boxu, takže ukazatel dosedne přesně na
   něj a přebije ho. */
/* Rail se roztáhne až k ikonám, ale záložky v něm zůstávají u sebe.
 *
 * `flex: 1 1 auto` je tu kvůli lince: kreslí se jako pozadí railu, takže
 * s ním dojde až ke zvonečku místo aby končila za poslední záložkou.
 *
 * Rozprostírat záložky po celé šířce (`space-between`) se ukázalo jako
 * slepá ulička. Rozestupy pak závisely na šířce railu, takže se měnily
 * pokaždé, když se zasunulo slovo „atum" — a všechno, čím jsem to pak
 * srovnával (pevná šířka railu, rezervované místo u značky), vyrobilo
 * jinou mezeru jinde. S pevným `gap` se rozestupy nemění nikdy a rail se
 * jen posouvá, přesně jak to dělal odjakživa. */
.nav-rail {
    background-image: linear-gradient(var(--line), var(--line));
    background-size: 100% 2px;
    background-position: 0 100%;
    background-repeat: no-repeat;
    align-items: stretch;
    flex: 1 1 auto;
}

/* Potvrzení u formuláře, který se uložil sám. Bez něj by změna proběhla
   tiše a člověk by nevěděl, jestli se něco stalo. */
.autosave-note {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .6875rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--c-good);
}

/* --- plochy podle ikony ---
 *
 * Šablony sázejí Tailwind třídy (`bg-black`, `bg-neutral-950`,
 * `border-white/10`). Přepisují se tady na proměnné, aby se pozadí tónovalo
 * do odstínu zvolené ikony — jinak vypadá appka stejně, ať si člověk vybere
 * cokoli. Přepis je tady a ne v šablonách proto, že těch tříd je přes sto
 * a měnit je po jedné by znamenalo měnit kód kvůli barvě.
 *
 * Rozvrstvení je v obou motivech obrácené: v tmavém jde stránka nejtmavší
 * a drobné prvky s okraji nahoru, ve světlém naopak. Bez toho splynou karty
 * s podkladem a zbudou z nich rámečky. */
body.bg-black { background-color: var(--ground); }

.bg-neutral-950 { background-color: var(--surface) !important; }
.bg-neutral-900 { background-color: var(--surface-2) !important; }

.border-white\/10 { border-color: var(--line) !important; }
.border-white\/15 { border-color: var(--line) !important; }

/* Lišta je průhledná s rozostřením, takže potřebuje barvu pozadí, ne plnou. */
header.bg-black\/90 { background-color: color-mix(in srgb, var(--ground) 90%, transparent) !important; }

/* Světlý motiv přepisoval tytéž třídy natvrdo v theme.css. Proměnné to
   nahrazují, ale specificita tam byla vyšší — proto ta `!important` výš. */

/* Druhé slovo názvu. Accent stejně jako tečka na začátku — obojí je
   accentové a název tím dostane rám z obou stran místo jednoho červeného
   puntíku vlevo. Drobné zůstává: „one" je součást jména, ale denně se čte
   hlavně `.datum`. */
.brand-suffix {
    font-size: .5em;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: lowercase;
    color: var(--accent);
    margin-left: .32em;
    vertical-align: baseline;
}

/* Potvrzení po akci. Neutrální plocha s barevným okrajem — hláška má být
   vidět, ale nemá tvrdit, že je něco „dobře"; to slovo patří datům. */
.flash-ok {
    border-color: var(--line);
    background: var(--surface-2);
}

/* Ztráta má i v ploše vlastní barvu, ne accent — stejný důvod jako u textu:
   accent znamená „klikni sem", ne „tady se prodělává". */
.bg-bad { background-color: var(--c-bad); }

/* Přepínač témat v souhrnech.
 *
 * Zdvojuje tečky pod dlaždicí na dashboardu a je to schválně: u dlaždice
 * stačí vědět, kolikátá stránka je vidět, u témat je potřeba vědět které.
 * Tečka to neřekne, jméno ano. Skript je obsluhuje stejně — proto nesou
 * `data-dot`, jen vypadají jinak.
 *
 * Pravidla musí přebít `[data-dot].is-active` z theme.css, které tečce sází
 * plnou accent barvu. Specificita je stejná, rozhoduje pořadí souborů:
 * brand.css se načítá později. Stejný postup jako u zbytku přepisů níž. */
.topic-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
    max-width: 14rem;
    padding: .35rem .7rem;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--c-muted);
    background: transparent;
    border: 1px solid var(--line);
    transition: color .15s, border-color .15s, background-color .15s;
}

/* Čtvereček drží barvu tématu i v neaktivním stavu — podle něj se pozná,
 * který proužek v seznamu článků patří kterému tématu. */
.topic-chip-mark {
    width: 6px;
    height: 6px;
    flex: none;
    background: var(--chip, var(--accent));
}

.topic-chip:hover {
    color: var(--accent);
    border-color: color-mix(in srgb, var(--accent) 40%, transparent);
    background: transparent;
}

.topic-chip.is-active {
    color: var(--chip, var(--accent));
    border-color: color-mix(in srgb, var(--chip) 55%, transparent);
    /* Jen náznak plochy. Plná barva by z přepínače udělala nejvýraznější
     * věc na stránce, přitom hlavní je text souhrnu nad ním. */
    background: color-mix(in srgb, var(--chip) 12%, transparent);
}

.topic-chip:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Přepínač rozsahu nad grafem. Segmentované tlačítko: volby patří k sobě
 * a je jich pár, takže rozbalovátko by přidalo klik navíc za nic. */
.horizon {
    display: inline-flex;
    border: 1px solid var(--line);
}

.horizon-btn {
    padding: .25rem .6rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
    letter-spacing: .04em;
    color: var(--c-muted);
    text-decoration: none;
    transition: color .15s, background-color .15s;
}

.horizon-btn + .horizon-btn { border-left: 1px solid var(--line); }
.horizon-btn:hover { color: var(--accent); }

.horizon-btn.is-active {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.horizon-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Postřehy nad záložkou.
 *
 * Karta jako ostatní sekce, ne volná věta. Věta bez rámu splyne s popiskem
 * pod nadpisem a nikdo ji nebere jako obsah — a přesně to se stalo, když
 * měla spočítaná varianta průhledné pozadí a šedý text. Obě varianty proto
 * vypadají stejně; liší se jen tou drobnou značkou u věty.
 *
 * Karta je schválně nízká. Je to doplněk nad stránkou, ne její obsah —
 * když zabere půl obrazovky, odsune to, kvůli čemu tam člověk přišel.
 */
.insight-pages {
    align-items: stretch;
}

.insight-page {
    /* Odsazení zprava, aby delší věta nekončila přesně na hraně další
     * stránky — při listování by z ní vykukoval kus slova. */
    padding-right: 1.5rem;
}

.insight-text {
    display: inline;
    font-size: .9375rem;
    line-height: 1.5;
    text-wrap: pretty;
}

/* Odkud věta je. Sedí na konci věty, ne pod ní: samostatný řádek by kartu
 * o řádek natáhl kvůli dvěma slovům. */
.insight-source {
    margin-left: .5rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    white-space: nowrap;
    color: color-mix(in srgb, var(--c-muted) 75%, transparent);
}

.insight-source.is-ai {
    color: var(--accent);
}

.insight-source.is-ai::before {
    /* Tečka ze značky. U věty od modelu, ne u spočítané — je to jeho podpis. */
    content: "";
    display: inline-block;
    width: .3125rem;
    height: .3125rem;
    margin-right: .3125rem;
    vertical-align: baseline;
    background: currentColor;
}

/* Doptat se na tvrzení. Sedí za značkou původu, tedy na konci věty —
 * je to nabídka, ne výzva, a tlačítko přes celou šířku by z postřehu
 * udělalo formulář. */
.insight-ask {
    margin-left: .5rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    white-space: nowrap;
    color: color-mix(in srgb, var(--c-muted) 55%, transparent);
    border-bottom: 1px solid transparent;
    transition: color .15s, border-color .15s;
}

.insight-ask:hover {
    color: var(--accent);
    border-bottom-color: color-mix(in srgb, var(--accent) 40%, transparent);
}

.insight-dots {
    display: flex;
    align-items: center;
    gap: .375rem;
    margin-top: .625rem;
}

.insight-dots .page-dot {
    width: 20px;
    height: 2px;
}

/* Upozornění pod postřehem. Nejmenší písmo v appce a nejtišší barva:
 * má být k dispozici, když si o něj člověk řekne očima, ne soutěžit
 * s větou nad ním. */
.insight-note {
    margin-top: .5rem;
    line-height: 1.4;
}

/* Když se listuje, sedí upozornění pod tečkami — jinak by se mezi větu
 * a ovládání vklínil řádek, který tam nepatří. */
.insight-dots + .insight-note {
    margin-top: .5rem;
}

/* Tažení myší přes listovací dráhu. Prst a trackpad scrollují samy, myš ne —
 * a „posunout to" je první, co člověk u karty s tečkami zkusí. */
.pages.is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
    user-select: none;
}

/* Ovládání karty — posunout a schovat.
 *
 * Drží se zpátky, dokud na kartu nenajedeš. Kdyby šipky svítily pořád,
 * měla by každá sekce nad sebou lištu, kterou člověk použije třikrát za
 * život, a přebila by nadpis, kvůli kterému tam kouká.
 */
.card-controls {
    display: flex;
    align-items: center;
    gap: .25rem;
    justify-content: flex-end;
    margin: -.5rem -.5rem .25rem 0;
    opacity: 0;
    transition: opacity .15s ease;
}

section:hover > .card-controls,
.card-controls:focus-within {
    opacity: 1;
}

/* Na dotykovém displeji se nenajíždí, takže se ovládání ukazuje rovnou —
 * jinak by se na telefonu ke skládání karet nešlo dostat vůbec. */
@media (hover: none) {
    .card-controls { opacity: .55; }
}

.card-name {
    margin-right: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--c-muted);
}

.card-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    color: var(--c-muted);
    transition: color .15s ease, background-color .15s ease;
}

.card-btn:hover:not(:disabled) {
    color: var(--accent);
    background: rgb(var(--accent-rgb) / .12);
}

.card-btn:disabled {
    opacity: .25;
    cursor: default;
}

/* Schované karty pod stránkou. Bez tohohle seznamu by karta zmizela
 * i s cestou, jak ji vrátit. */
.card-restore {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding-top: .75rem;
    border-top: 1px solid rgb(255 255 255 / .08);
}

[data-theme="light"] .card-restore { border-top-color: rgb(0 0 0 / .08); }

.card-chip {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .6875rem;
    padding: .25rem .5rem;
    color: var(--c-muted);
    border: 1px solid rgb(255 255 255 / .12);
    transition: color .15s ease, border-color .15s ease;
}

[data-theme="light"] .card-chip { border-color: rgb(0 0 0 / .12); }

.card-chip:hover {
    color: var(--accent);
    border-color: rgb(var(--accent-rgb) / .5);
}

/* Asistent po straně.
 *
 * Otevírá se zaškrtávátkem, ne skriptem — panel pak funguje i bez
 * JavaScriptu a stav přežije překreslení stránky. Na mobilu zabere celou
 * šířku, na monitoru pruh vpravo: otázka se má ptát nad tím, na co se
 * člověk dívá, takže obsah stránky musí zůstat vidět.
 */
/* Zaškrtávátko, které panel otevírá. Vidět být nemá, ale zmizet nesmí:
 * `display: none` by ho vyřadilo z ovládání klávesnicí a štítek by
 * přestal fungovat. Proto průhledné a odsunuté z toku.
 *
 * `position: fixed`, ne `sr-only`: to je `absolute`, takže zaškrtávátko
 * sedělo tam, kde stojí v dokumentu, a kliknutí na štítek na něj přesunulo
 * zaměření — prohlížeč k němu odroloval a stránka při každém otevření
 * panelu skočila nahoru. Fixed nahoře je místo, kde rolovat není kam. */
.assistant-toggle {
    position: fixed;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
    margin: 0;
}

/* Jazýček u levého okraje — jenom znak.
 *
 * Prošel dvěma podobami, než z něj zbylo tohle. Plný accentový obdélník
 * s nápisem vypadal jako doplněk prohlížeče přilepený přes stránku;
 * svislý popisek byl tišší, ale pořád to byl text, který se musí přečíst.
 *
 * Teď je tam jen hvězdička — tatáž, jakou nese postřeh nad každou
 * záložkou. Kdo tu značku jednou viděl nahoře, pozná ji i u kraje a
 * nemusí luštit, co na jazýčku stojí. Název zůstal v `title`.
 *
 * Plocha, vlas a rádius jsou z karet, aby to patřilo k appce a ne přes ni.
 * V rohu být nemůže: u dlouhých seznamů překrýval poslední řádek a
 * u grafů popisek osy. */
.assistant-open {
    position: fixed;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .75rem .5rem;
    background: var(--surface);
    color: var(--accent);
    border: 1px solid var(--line);
    border-left: 0;
    border-radius: 0 .5rem .5rem 0;
    cursor: pointer;
    transition: border-color .15s ease, padding-right .15s ease;
}

/* Na najetí se o kousek vysune a obtáhne accentem. Žádné zvětšení ani
 * stín: chová se jako odkaz, protože jím je. */
.assistant-open:hover,
.assistant-open:focus-within,
.assistant-toggle:focus-visible ~ .assistant-open {
    border-color: var(--accent);
    padding-right: .75rem;
}

.assistant-open:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

.assistant-backdrop {
    position: fixed;
    inset: 0;
    z-index: 45;
    background: rgb(0 0 0 / .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
}

/* Zavřený panel visí za pravým okrajem (`translateX(100%)`) a tím
 * roztahoval dokument: na displeji užším než 390 px šla stránka posouvat
 * do stran, i když tam nic nebylo. Projevilo se to jen na malých
 * telefonech, protože jinde se přetečení schovalo pod jiný obsah.
 *
 * `clip` schválně, ne `hidden`: `hidden` z prvku udělá rolovací kontejner
 * a přestala by fungovat lepivá horní lišta. `clip` jen ořízne. */
html,
main {
    /* Stránka se nesmí dát posouvat do stran. Na displeji 320 px šla
     * o 55 px do prázdna — a nezpůsobil to jeden prvek, ale několik
     * najednou: karty s tabulkou na celou šířku (`-mx-6 px-6`) trčí ven
     * z obsahového sloupce záměrně a rolovat mají uvnitř sebe.
     *
     * `clip`, ne `hidden`: `hidden` by z prvku udělal rolovací kontejner
     * a přestala by fungovat lepivá horní lišta. `clip` jen ořízne, takže
     * vodorovné rolování uvnitř karet a grafů zůstává. */
    overflow-x: clip;
}

/* Rám u pravého okraje. Sám se nehýbe, jen ořezává — proto dokument
 * neroztahuje a `pointer-events` má vypnuté, dokud je zavřený. */
.assistant-panel {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 50;
    width: var(--assistant-width, min(26rem, 100vw));
    /* `contain: paint` navrch k ořezu: samotný `overflow: clip` obsah
     * schová, ale prohlížeč s ním pořád počítá do šířky dokumentu, takže
     * na úzkém displeji šlo scrollovat do prázdna. `contain` mu řekne, že
     * ven z rámu nic nesahá — a tím to z počítání vypadne. */
    overflow: clip;
    contain: paint;
    pointer-events: none;
}

/* Tohle je to, co jezdí. Uvnitř rámu, takže se ořízne. */
.assistant-slide {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-right: 1px solid var(--line);
    transform: translateX(-100%);
    transition: transform .22s ease;
}

.assistant-toggle:checked ~ .assistant-panel { pointer-events: auto; }
.assistant-toggle:checked ~ .assistant-panel .assistant-slide { transform: translateX(0); }
.assistant-toggle:checked ~ .assistant-open { opacity: 0; pointer-events: none; }

/* Na monitoru se obsah zúží, panel nic nepřekryje.
 *
 * Ptát se nad tím, na co se člověk dívá, nedává smysl, když to zrovna
 * zakrývá odpověď — a nejčastější otázky vznikají u tabulky nebo grafu,
 * tedy u pravého okraje. Stránka proto dostane odsazení o šířku panelu
 * a přeskládá se do užšího sloupce; grafy jsou v SVG a zmenší se s ním.
 *
 * Zastínění pozadí se v tomhle režimu nezapíná: nic se nezakrývá, takže
 * ztmavit stránku by jen ubralo na čitelnosti toho, na co se ptám. */
@media (min-width: 1024px) {
    :root { --assistant-width: 24rem; }

    .assistant-toggle:checked ~ header,
    .assistant-toggle:checked ~ main,
    .assistant-toggle:checked ~ footer {
        margin-right: var(--assistant-width);
        transition: margin-right .22s ease;
    }

    header, main, footer { transition: margin-right .22s ease; }
}

/* Na telefonu se nic zužovat nedá — panel překryje obrazovku a pozadí
 * ztmavne, ať je jasné, že se stránka zatím neovládá.
 *
 * Šířka je přesně `100vw`, ne `min(26rem, 100vw)`: na užším displeji než
 * 26rem vycházel panel o kus širší než okno a uřízlo mu to křížek
 * i tlačítko Poslat u pravého okraje. Celá obrazovka je na mobilu stejně
 * to, co se od takového panelu čeká. */
@media (max-width: 1023px) {
    /* `100%`, ne `100vw`: `100vw` počítá i svislý posuvník, takže na
     * úzkém displeji vyšel panel o jeho šířku širší než okno a stránka
     * šla posouvat do stran. `100%` je u prvku s `fixed` přesně okno
     * bez posuvníku. */
    .assistant-panel { width: 100%; }
    .assistant-toggle:checked ~ .assistant-backdrop { opacity: 1; pointer-events: auto; }
}

.assistant-head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 1rem;
    border-bottom: 1px solid var(--line);
}

.assistant-close {
    color: var(--c-muted);
    cursor: pointer;
    transition: color .15s ease;
}

.assistant-close:hover { color: var(--accent); }

/* Historie roluje, formulář zůstává dole. Bez toho by se pole na psaní
 * u delší konverzace odsunulo mimo obrazovku. */
.assistant-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem;
}

.assistant-form {
    display: flex;
    gap: .5rem;
    padding: 1rem;
    border-top: 1px solid var(--line);
}

.assistant-msg-user,
.assistant-msg-ai {
    font-size: .875rem;
    line-height: 1.5;
    padding: .625rem .75rem;
    white-space: pre-wrap;
}

.assistant-msg-user {
    background: rgb(var(--accent-rgb) / .12);
    color: #fff;
    margin-left: 1.5rem;
}

[data-theme="light"] .assistant-msg-user { color: #18181b; }

.assistant-msg-ai {
    background: rgb(255 255 255 / .04);
    color: var(--c-muted);
    margin-right: 1.5rem;
}

[data-theme="light"] .assistant-msg-ai { background: rgb(0 0 0 / .04); }

/* Tisk panel nezajímá. */
@media print {
    .assistant-open, .assistant-panel, .assistant-backdrop { display: none; }
}

/* Připravená otázka v panelu. Vypadá jako odkaz, ne jako tlačítko —
 * je to nabídka, ne akce, kterou by měl člověk hledat. */
.assistant-hint {
    display: block;
    width: 100%;
    text-align: left;
    font-size: .8125rem;
    line-height: 1.4;
    padding: .5rem .625rem;
    color: var(--c-muted);
    border: 1px solid rgb(255 255 255 / .08);
    transition: color .15s ease, border-color .15s ease;
}

[data-theme="light"] .assistant-hint { border-color: rgb(0 0 0 / .08); }

.assistant-hint:hover {
    color: var(--accent);
    border-color: rgb(var(--accent-rgb) / .45);
}

/* Mapa těla se zvýrazněnými partiemi (_telo.html).
 *
 * Dvě postavy vedle sebe — zepředu a zezadu. Vedle sebe, ne pod sebou:
 * půlka partií je vidět jen z jedné strany a listovat mezi nimi by
 * znamenalo, že se celý trénink nedá přehlédnout naráz. */
/* --- kalendář: měsíční mřížka ------------------------------------------
 *
 * Vzor je Apple Kalendář: jemné linky, hodně vzduchu a událost jako
 * řádek s tečkou, ne jako barevný blok. Bloky přes celou šířku buňky
 * udělaly z měsíce pruhovanou plochu — tři pod sebou a nešlo přečíst
 * ani jeden název.
 */
.kal-bunka {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: .3rem;
    /* `<button>` centruje obsah svisle. Bez tohohle se čísla dnů
     * v prázdných buňkách posunula proti těm s událostmi a řádek se
     * viditelně roztřepil. */
    justify-content: flex-start;
    text-align: left;
    width: 100%;
    min-height: 6.75rem;
    padding: .45rem .4rem .5rem;
    border-bottom: 1px solid rgb(255 255 255 / .06);
    border-right: 1px solid rgb(255 255 255 / .06);
    transition: background-color .12s;
}

:root[data-theme="light"] .kal-bunka {
    border-color: rgb(0 0 0 / .08);
}

.kal-bunka:hover {
    background: rgb(255 255 255 / .025);
}

:root[data-theme="light"] .kal-bunka:hover {
    background: rgb(0 0 0 / .02);
}

/* Víkend jemně tónovaný. Bez toho se v mřížce nedá poznat, kde končí
 * týden, a hledá se to podle hlavičky. */
.kal-bunka-vikend {
    background: rgb(255 255 255 / .018);
}

:root[data-theme="light"] .kal-bunka-vikend {
    background: rgb(0 0 0 / .015);
}

/* Dny z okolních měsíců. Ztlumené, ne skryté — na jejich místě by byla
 * díra a týden by přestal být týden. */
.kal-bunka-mimo {
    background: rgb(0 0 0 / .25);
}

:root[data-theme="light"] .kal-bunka-mimo {
    background: rgb(0 0 0 / .035);
}

.kal-bunka-mimo .kal-cislo {
    opacity: .35;
}

/* Vybraný den. Rámeček, ne výplň: výplň by soupeřila s barvami
 * událostí uvnitř buňky. */
.kal-bunka-vybrana {
    box-shadow: inset 0 0 0 2px var(--accent);
}

.kal-cislo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: flex-start;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
    color: rgb(255 255 255 / .78);
}

:root[data-theme="light"] .kal-cislo {
    color: rgb(0 0 0 / .72);
}

.kal-cislo-dnes {
    background: var(--accent);
    color: #fff;
    font-weight: 700;
}

.kal-udalosti {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
}

/* Řádek události: tečka, čas, název. Čas je mono a tlumený, aby se dal
 * přeskočit pohledem — hledá se v něm název, ne hodina. */
.kal-udalost {
    display: flex;
    align-items: baseline;
    gap: .3rem;
    min-width: 0;
    font-size: .69rem;
    line-height: 1.35;
}

.kal-tecka {
    width: .4rem;
    height: .4rem;
    border-radius: 50%;
    flex-shrink: 0;
    /* Tečka sedí na účaří textu, ne na jeho horní hraně. */
    align-self: center;
}

.kal-cas {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .62rem;
    color: rgb(255 255 255 / .45);
    flex-shrink: 0;
}

:root[data-theme="light"] .kal-cas {
    color: rgb(0 0 0 / .45);
}

.kal-nazev {
    color: rgb(255 255 255 / .82);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

:root[data-theme="light"] .kal-nazev {
    color: rgb(0 0 0 / .78);
}

/* Celodenní událost zůstává blokem. Nemá čas, kterým by se odlišila,
 * a je to jediné, co v ten den platí celý. */
.kal-celodenni {
    padding: .05rem .3rem;
    border-radius: 3px;
    font-size: .67rem;
    line-height: 1.4;
    color: var(--kal-barva);
    background: color-mix(in srgb, var(--kal-barva) 18%, transparent);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.kal-vic {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .62rem;
    color: rgb(255 255 255 / .38);
    padding-left: .7rem;
}

/* Proužek pod číslem dne — barvy kalendářů, které v ten den něco mají.
 * Na iPhonu je to jediné, co se do buňky vejde, a stačí to: z mřížky se
 * čte „kdy něco je", ne „co to je". Detaily jsou v seznamu pod ní. */
.kal-prouzek {
    display: none;
    gap: 1px;
    height: 4px;
    margin: .2rem auto 0;
    max-width: 2.4rem;
    border-radius: 2px;
    overflow: hidden;
}

.kal-prouzek span {
    flex: 1;
    min-width: 3px;
}

/* Na úzké obrazovce se přepne na iPhonový režim: velká čísla, proužek
 * místo názvů. Názvy se do buňky široké čtyřicet pixelů stejně
 * nevejdou — vypisovat je tam znamená sedm sloupců výpustek. */
@media (max-width: 43rem) {
    .kal-bunka {
        min-height: 3.4rem;
        align-items: center;
        padding: .35rem .1rem;
        gap: 0;
    }

    .kal-cislo {
        align-self: center;
        width: 1.85rem;
        height: 1.85rem;
        font-size: 1.05rem;
    }

    .kal-udalosti {
        display: none;
    }

    .kal-prouzek {
        display: flex;
    }

    /* Víkendová čísla ztlumená, jako na iPhonu. */
    .kal-bunka-vikend .kal-cislo {
        color: rgb(255 255 255 / .42);
    }

    :root[data-theme="light"] .kal-bunka-vikend .kal-cislo {
        color: rgb(0 0 0 / .38);
    }
}

:root[data-theme="light"] .kal-vic {
    color: rgb(0 0 0 / .4);
}

/* Mřížka formuláře, která se řídí **šířkou svého místa**, ne obrazovky.
 *
 * Formulář události stojí jednou v postranním sloupci (256 px) a jednou
 * na celé šířce denní stránky. Obyčejná media query zná jen obrazovku,
 * takže na monitoru dala dva sloupce i tomu úzkému — a „02.09.2026" se
 * v poli širokém sto pixelů uřízlo na „02.09.2". Container query se ptá
 * na místo, které prvek dostal, a to je přesně ta otázka.
 */
.formular-mrizka {
    container-type: inline-size;
    display: grid;
    grid-template-columns: 1fr;
    gap: .75rem;
}

@container (min-width: 22rem) {
    .formular-mrizka {
        grid-template-columns: 1fr 1fr;
    }
}

.formular-mrizka > .col-span-full {
    grid-column: 1 / -1;
}

/* Prázdné datumové a časové pole.
 *
 * Prohlížeč do něj sám píše `dd.mm.rrrr` a `--:--` a nejde to nahradit
 * placeholderem — nativní pole ho nepodporuje. Ta zkratka pak vypadá
 * jako rozbitý text: v nepovinném poli stojí něco, co se nedá přepsat
 * ani smazat, a míchá se s vyplněnými poli vedle.
 *
 * Ztlumí se na úroveň nápovědy. Prázdnost hlídá `pole.js`, ne CSS:
 * `:placeholder-shown` u datumového pole neplatí a `:invalid` chytá jen
 * povinná, takže nepovinné prázdné pole by zůstalo plnou barvou —
 * a vyplněné povinné by se naopak ztlumilo. Změřeno na formuláři
 * události: „02.09.2026" bylo šedivé stejně jako „dd.mm.rrrr" vedle.
 */
/* Pole, které vyplnil model z věty. Musí být poznat, že to nenapsal
 * člověk — jinak by si po pár dnech nebyl jistý, odkud ta výška je.
 * Zvýraznění zmizí, jakmile do pole sáhne. */
.pole-doplneno {
    border-color: color-mix(in srgb, var(--accent) 55%, transparent) !important;
    background: color-mix(in srgb, var(--accent) 8%, transparent) !important;
}

.pole-doplneno:focus {
    background: transparent !important;
}

input.pole-prazdne:not(:focus) {
    color: rgb(255 255 255 / .3);
}

:root[data-theme="light"] /* Pole, které vyplnil model z věty. Musí být poznat, že to nenapsal
 * člověk — jinak by si po pár dnech nebyl jistý, odkud ta výška je.
 * Zvýraznění zmizí, jakmile do pole sáhne. */
.pole-doplneno {
    border-color: color-mix(in srgb, var(--accent) 55%, transparent) !important;
    background: color-mix(in srgb, var(--accent) 8%, transparent) !important;
}

.pole-doplneno:focus {
    background: transparent !important;
}

input.pole-prazdne:not(:focus) {
    color: rgb(0 0 0 / .32);
}

/* Ikona kalendáře/hodin v poli. Nativní je černá, takže na tmavém
 * podkladu mizí — invertuje se a ztlumí, ať nepřebíjí hodnotu. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
    opacity: .35;
    cursor: pointer;
    transition: opacity .15s;
}

input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator {
    opacity: .7;
}

:root[data-theme="light"] input[type="date"]::-webkit-calendar-picker-indicator,
:root[data-theme="light"] input[type="time"]::-webkit-calendar-picker-indicator,
:root[data-theme="light"] input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: none;
    opacity: .45;
}

/* Rozbalovací sekce.
 *
 * **Že se něco dá rozbalit, musí být vidět bez kliknutí.** V appce jich
 * bylo osmatřicet a jen sedm mělo šipku — u zbylých jedenatřiceti se to
 * dalo poznat leda tak, že do nich člověk ťukne. Schované nastavení,
 * o kterém se neví, je horší než nastavení, které tam není: uživatel
 * hledá funkci, kterou appka má.
 *
 * Šipka se proto kreslí ze stylu, ne z šablony. Napsaná v každé z nich
 * zvlášť se dřív nebo později někde zapomene — a přesně to se stalo.
 *
 * `list-none` v šablonách vypíná nativní trojúhelník (ten je v každém
 * prohlížeči jiný a nedá se obarvit), takže tahle šipka je jediná.
 */
summary {
    position: relative;
}

summary::after {
    content: "▾";
    display: inline-block;
    margin-left: .35rem;
    font-size: .85em;
    line-height: 1;
    opacity: .55;
    transition: transform .18s ease, opacity .15s ease;
}

summary:hover::after {
    opacity: 1;
}

details[open] > summary::after {
    transform: rotate(180deg);
}

/* Klapky, které si šipku kreslí samy nebo ji mít nemají (ikona, obrázek,
 * řádek tabulky). Přidá se jim `data-bez-sipky`. */
summary[data-bez-sipky]::after {
    content: none;
}

/* --- kalendář: seznam událostí vybraného dne -------------------------
 *
 * Sazba z iOS Kalendáře: barevný pruh vlevo nese kalendář, název je
 * největší prvek a čas stojí vpravo v jednom sloupci pod sebou. Oko
 * tak jede shora dolů po názvech a čas si najde, teprve když ho
 * potřebuje. Předchozí verze měla čas vlevo a názvy začínaly za ním —
 * tam se to čte obráceně, tedy hůř.
 */
.kal-seznam {
    display: flex;
    flex-direction: column;
}

.kal-radek {
    display: flex;
    align-items: stretch;
    gap: .7rem;
    padding: .6rem 0;
    border-bottom: 1px solid rgb(255 255 255 / .07);
}

.kal-radek:last-child {
    border-bottom: 0;
}

:root[data-theme="light"] .kal-radek {
    border-color: rgb(0 0 0 / .08);
}

/* Pruh přes celou výšku řádku — barva kalendáře, ne dekorace. */
.kal-znak-pruh {
    width: 3px;
    border-radius: 2px;
    background: var(--kal-barva);
    flex-shrink: 0;
}

/* Celodenní událost má kroužek. Je to jediný rozdíl, který v seznamu
 * potřebuje být vidět na první pohled. */
.kal-znak-kolecko {
    width: .85rem;
    height: .85rem;
    border: 2px solid var(--kal-barva);
    border-radius: 50%;
    flex-shrink: 0;
    align-self: center;
    margin-left: -1px;
}

.kal-radek-telo {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    flex: 1;
    min-width: 0;
    text-decoration: none;
}

.kal-radek-nazev {
    font-size: .95rem;
    line-height: 1.3;
    color: rgb(255 255 255 / .95);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

:root[data-theme="light"] .kal-radek-nazev {
    color: rgb(0 0 0 / .88);
}

.kal-radek:hover .kal-radek-nazev {
    color: var(--kal-barva);
}

.kal-radek-detail {
    font-size: .75rem;
    color: rgb(255 255 255 / .45);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

:root[data-theme="light"] .kal-radek-detail {
    color: rgb(0 0 0 / .45);
}

/* Čas vpravo, od nad do. Zarovnaný doprava a tabulkovými číslicemi,
 * aby dvojtečky stály nad sebou. */
.kal-radek-cas {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
    line-height: 1.3;
}

.kal-cas-od {
    font-size: .85rem;
    color: rgb(255 255 255 / .9);
}

:root[data-theme="light"] .kal-cas-od {
    color: rgb(0 0 0 / .8);
}

.kal-cas-do {
    font-size: .85rem;
    color: rgb(255 255 255 / .4);
}

:root[data-theme="light"] .kal-cas-do {
    color: rgb(0 0 0 / .4);
}

/* --- kalendář: časová osa ---------------------------------------------
 *
 * Mřížka, na které událost zabírá výšku podle délky. Pozice počítá server
 * v procentech, tady se z nich dělá jen rozvržení — osa se tím škáluje
 * s výškou, kterou jí dá stránka, bez druhého výpočtu.
 */
.kal-mrizka {
    display: grid;
    grid-template-columns: 3rem 1fr;
    gap: .5rem;
}

.kal-hodiny {
    position: relative;
}

.kal-hodina {
    position: absolute;
    right: 0;
    /* Popisek sedí na lince, ne pod ní. Bez posunu o půlku výšky by
     * „9:00" ukazovalo někam mezi devátou a desátou. */
    transform: translateY(-50%);
    white-space: nowrap;
}

.kal-osa {
    position: relative;
    border-top: 1px solid rgb(255 255 255 / .08);
    border-bottom: 1px solid rgb(255 255 255 / .08);
}

:root[data-theme="light"] .kal-osa {
    border-color: rgb(0 0 0 / .1);
}

.kal-linka {
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: rgb(255 255 255 / .06);
    pointer-events: none;
}

:root[data-theme="light"] .kal-linka {
    background: rgb(0 0 0 / .07);
}

.kal-blok {
    position: absolute;
    /* Nejkratší událost, která je ještě k přečtení. Server jí dá výšku,
     * jako by trvala dvacet minut, ale na nízké ose je i to vlásek —
     * tohle je pojistka v pixelech, nezávislá na výšce mřížky. */
    min-height: 1.15rem;
    overflow: hidden;
    border-radius: 3px;
    border-left: 2px solid var(--kal-barva);
    background: color-mix(in srgb, var(--kal-barva) 16%, transparent);
    transition: background-color .15s;
}

.kal-blok:hover {
    background: color-mix(in srgb, var(--kal-barva) 28%, transparent);
}

.kal-blok-odkaz {
    display: flex;
    flex-direction: column;
    gap: .05rem;
    height: 100%;
    padding: .15rem .35rem;
    line-height: 1.15;
    text-decoration: none;
}

.kal-blok-nazev {
    font-size: .72rem;
    font-weight: 600;
    color: var(--kal-barva);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.kal-blok-cas {
    font-size: .64rem;
    color: color-mix(in srgb, var(--kal-barva) 75%, transparent);
    white-space: nowrap;
}

/* U události kratší než čtvrthodina se název a čas nevejdou pod sebe.
 * Vedle sebe se vejde aspoň jedno z toho. */
.kal-blok-uzky .kal-blok-odkaz {
    flex-direction: row;
    align-items: center;
    gap: .3rem;
}

/* Čára „teď". Jediná věc na ose, která se hýbe sama, tak ať je vidět —
 * ale ne tak, aby přebila události. */
.kal-ted {
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: #ef4444;
    pointer-events: none;
    z-index: 5;
}

.kal-ted::before {
    content: "";
    position: absolute;
    left: -3px;
    top: -2.5px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #ef4444;
}

/* Celodenní pruh nad osou. Na ose by neměl kde být a natáhl by ji přes
 * celý den. */
.kal-celoden {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-bottom: .4rem;
}

.kal-celoden-kus {
    padding: .1rem .4rem;
    border-radius: 3px;
    font-size: .7rem;
    font-weight: 600;
    color: var(--kal-barva);
    background: color-mix(in srgb, var(--kal-barva) 16%, transparent);
    border-left: 2px solid var(--kal-barva);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.kal-celoden-uzky .kal-celoden-kus {
    font-size: .62rem;
    padding: .05rem .25rem;
}

/* Pruh drží výšku i prázdný. Bez toho by den s celodenní událostí měl
 * osu níž než ostatní a hodiny by v sloupcích neseděly. */
.kal-celoden-uzky {
    min-height: 1.05rem;
}

/* Týden: sedm sloupců na společné ose. Hodiny jsou jen jednou vlevo —
 * u každého dne by z nich byla mřížka čísel místo kalendáře. */
.kal-tyden {
    display: grid;
    grid-template-columns: 3rem repeat(7, minmax(0, 1fr));
}

/* Dny oddělené svislou linkou. Bez ní tvořilo sedm sloupců jednu plochu
 * a událost u pravého kraje úterka vypadala, že patří do středy —
 * mřížka bez svislic není mřížka. */
.kal-tyden-den {
    border-left: 1px solid rgb(255 255 255 / .07);
    padding: 0 .3rem;
}

:root[data-theme="light"] .kal-tyden-den {
    border-color: rgb(0 0 0 / .09);
}

/* Víkend jemně tónovaný, stejně jako v měsíci. */
.kal-tyden-den-vikend {
    background: rgb(255 255 255 / .022);
}

:root[data-theme="light"] .kal-tyden-den-vikend {
    background: rgb(0 0 0 / .018);
}

/* Dnešek dostane vlastní podklad — v týdnu se hledá jako první. */
.kal-tyden-den-dnes {
    background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* Hlavička dne je tlačítko. Musí vypadat jako klikatelná, ale nesmí
 * přebít mřížku pod sebou — proto jen podbarvení na najetí. */
.kal-bunka-tlacitko {
    border-radius: 4px;
    transition: background-color .12s;
}

.kal-bunka-tlacitko:hover {
    background: rgb(255 255 255 / .05);
}

:root[data-theme="light"] .kal-bunka-tlacitko:hover {
    background: rgb(0 0 0 / .04);
}

.kal-hlava-vybrana {
    background: rgb(255 255 255 / .06);
}

:root[data-theme="light"] .kal-hlava-vybrana {
    background: rgb(0 0 0 / .05);
}

.kal-tyden-hlava {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .25rem;
    padding: .1rem .1rem .4rem;
    min-height: 1.9rem;
}

.telo-mapa {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    /* Obrys těla pod svaly. Odvozený od textu, ne pevný — musí sedět
     * na tmavý i světlý motiv a měnit se s ním. Barvy svalů jsou pevné
     * (šedá → jantarová → červená), protože nesou význam, ne styl. */
    --telo-obrys: color-mix(in srgb, currentColor 7%, transparent);
    /* Nezatížená partie. Kreslí se neprůhledně, ne poloprůhledně: dva
     * svaly, které se překrývají, dělaly přes sebe světlejší flek — a ten
     * se čte jako „víc namáhané", tedy jako údaj, který v datech není. */
    --telo-klid: color-mix(in srgb, currentColor 24%, transparent);
}

.telo-postavy {
    display: flex;
    gap: .75rem;
    justify-content: center;
}

.telo-svg {
    width: auto;
    max-width: 45%;
}

.telo-popisky {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem .5rem;
    justify-content: center;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .625rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--c-muted);
}

.telo-popisky span::after {
    content: "·";
    margin-left: .5rem;
    opacity: .4;
}

.telo-popisky span:last-child::after { content: ""; }
