/* ---------------------------------------------------------------------------
   Jellyscope - vzhled

   Cely soubor stoji na jednom napadu: **barvy se nikde nepisou primo**.
   Nahore je seznam pojmenovanych promennych (--surface-1, --series-1, ...)
   a zbytek souboru pouziva jen ta jmena. Prepnuti do tmaveho rezimu je pak
   otazkou prepsani seznamu, ne prochazeni tisice radku.

   Barvy nejsou vybrane od oka. Poradi serii je sestavene tak, aby sousedni
   dvojice rozeznal i clovek s poruchou barvocitu (deuteranopie, protanopie);
   proto se poradi nemeni a devata barva se nepridava.
   --------------------------------------------------------------------------- */

:root {
    color-scheme: light;

    /* Plochy a pismo */
    --page:            #f9f9f7;
    --surface-1:       #fcfcfb;
    --surface-2:       #f2f1ed;
    --text-primary:    #0b0b0b;
    --text-secondary:  #52514e;
    --text-muted:      #898781;
    --border:          rgba(11, 11, 11, 0.10);
    --grid:            #e1e0d9;
    --axis:            #c3c2b7;

    /* Serie - pevne poradi, nikdy necyklit.

       Paleta vychazi z rozsahu Jellyfinu (modra, fialova) a pokracuje
       barvami, ktere se od nich i mezi sebou daji rozeznat. Poradi neni
       nahodne: sousedni dvojice se potkavaji nejcasteji, takze maji
       nejvetsi odstup.

       Zmerene proti puvodni palete (simulace deuteranopie a protanopie,
       rozdil v OKLab): sousedni dvojice 8,1 -> nejhorsi dvojice vubec
       se zlepsila z 1,6 na 2,2 ve svetlem a z 1,6 na 6,1 v tmavem. */
    --series-1: #1187c0;   /* modra Jellyfinu */
    --series-2: #7b3ba3;   /* fialova Jellyfinu */
    --series-3: #0f8f78;   /* tyrkysova */
    --series-4: #b8770c;   /* jantarova */
    --series-5: #c2426f;   /* ruzova  */
    --series-6: #14663f;   /* zelena  */
    --series-7: #5a62c4;   /* modrofialova */
    --series-8: #c9452b;   /* cervena */

    /* Odstupnovana skala pro teplotni mapu (svetla -> tmava) */
    --seq-250: #86b6ef;
    --seq-350: #5598e7;
    --seq-450: #2a78d6;
    --seq-550: #1c5cab;
    --seq-650: #104281;

    /* Stavove barvy - vyhrazene, nikdy se nepouzivaji jako barva serie */
    --good:     #0ca30c;
    --warning:  #fab219;
    --serious:  #ec835a;
    --critical: #d03b3b;

    /* Barva rozhrani - z loga Jellyfinu (modra #00A4DC, fialova #AA5CC3).
       Ve svetlem rezimu ztmavena, aby na bilem podkladu drzela kontrast.

       Neni to barva serie a nikdy se s nimi nemicha: serie identifikuji
       kategorie a jsou vybrane tak, aby se navzajem nepletly. Tohle je
       barva aplikace - aktivni polozka menu, vybrany chip, jednobarevny
       graf, kde zadna kategorie neni. */
    --accent:     #0b7fb0;
    --accent-2:   #8a44a8;
    --accent-ink: #ffffff;

    /* Podklad postranniho panelu - viz .sidebar. */
    --rail:       #fdfdfc;

    --linka-1: #1187c0;
    --linka-2: #7b3ba3;
    --linka-3: #11866f;

    --radius: 12px;
    --font: system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Tmavy rezim neni automaticke prevraceni svetleho. Kazdy odstin je vybrany
   znovu, pro tmavy podklad - jinak by svetle barvy zarily a tmave zmizely. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --page:           #0d0f17;
        --surface-1:      #161a26;
        --surface-2:      #1c2231;
        --text-primary:   #eef2f8;
        --text-secondary: #a9b4c6;
        --text-muted:     #7b8598;
        --border:         rgba(238, 242, 248, 0.10);
        --grid:           #232a3a;
        --axis:           #333c50;

        /* Na tmavem podkladu uz nemusi byt ztmavena - plna barva loga. */
        --accent:     #00a4dc;
        --accent-2:   #aa5cc3;
        --accent-ink: #04161d;
        --rail:       #0a0c13;

        /* Cary v grafu na Prehledu - z rozsahu Jellyfinu, ale ne primo
           z loga. Modra a fialova z loga se pri deuteranopii temer
           splyvaji (odstup 6,6 pri prahu 8). Staci ale rozejit je
           SVETLOSTI: svetlejsi modra a sytejsi fialova drzi 17,9,
           a poznaji se i tam, kde odstin sam nestaci.
        
           Plati jen tam, kde jsou dve az tri cary. Grafy s vice
           kategoriemi (jazyky) pouzivaji dal paletu serii. */
        --linka-1: #35bdf0;
        --linka-2: #9a4fc0;
        --linka-3: #2fd0b5;

        /* Stavove barvy se dosud braly ze svetleho rezimu - a tmava zelen
           #0ca30c na modrocernem podkladu skoro zmizela. Na tmavem se
           vyznam nese svetlosti smerem NAHORU, ne dolu. */
        --good:     #45c99a;
        --warning:  #ffbe4d;
        --serious:  #f0885c;
        --critical: #ef5f5f;

        --series-1: #35bdf0;
        --series-2: #9a4fc0;
        --series-3: #2fd0b5;
        --series-4: #ffb340;
        --series-5: #e5709a;
        --series-6: #1f7a4d;
        --series-7: #8b93f8;
        --series-8: #ff7a5c;

        /* Na tmavem podkladu roste vyznam smerem ke svetlejsi, ne tmavsi. */
        --seq-250: #184f95;
        --seq-350: #256abf;
        --seq-450: #3987e5;
        --seq-550: #6da7ec;
        --seq-650: #9ec5f4;
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --page:           #0d0f17;
    --surface-1:      #161a26;
    --surface-2:      #1c2231;
    --text-primary:   #eef2f8;
    --text-secondary: #a9b4c6;
    --text-muted:     #7b8598;
    --border:         rgba(238, 242, 248, 0.10);
    --grid:           #232a3a;
    --axis:           #333c50;

    --accent:     #00a4dc;
    --accent-2:   #aa5cc3;
    --accent-ink: #04161d;
    --rail:       #0a0c13;

    /* Cary v grafu na Prehledu - z rozsahu Jellyfinu, ale ne primo
       z loga. Modra a fialova z loga se pri deuteranopii temer
       splyvaji (odstup 6,6 pri prahu 8). Staci ale rozejit je
       SVETLOSTI: svetlejsi modra a sytejsi fialova drzi 17,9,
       a poznaji se i tam, kde odstin sam nestaci.
    
       Plati jen tam, kde jsou dve az tri cary. Grafy s vice
       kategoriemi (jazyky) pouzivaji dal paletu serii. */
    --linka-1: #35bdf0;
    --linka-2: #9a4fc0;
    --linka-3: #2fd0b5;

    /* Stavove barvy se dosud braly ze svetleho rezimu - a tmava zelen
       #0ca30c na modrocernem podkladu skoro zmizela. Na tmavem se
       vyznam nese svetlosti smerem NAHORU, ne dolu. */
    --good:     #45c99a;
    --warning:  #ffbe4d;
    --serious:  #f0885c;
    --critical: #ef5f5f;

    --series-1: #35bdf0;
    --series-2: #9a4fc0;
    --series-3: #2fd0b5;
    --series-4: #ffb340;
    --series-5: #e5709a;
    --series-6: #1f7a4d;
    --series-7: #8b93f8;
    --series-8: #ff7a5c;

    --seq-250: #184f95;
    --seq-350: #256abf;
    --seq-450: #3987e5;
    --seq-550: #6da7ec;
    --seq-650: #9ec5f4;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: var(--font);
    font-size: 15px;
    line-height: 1.5;
    background: var(--page);
    color: var(--text-primary);
}

a { color: inherit; }

/* --------------------------------------------------------------------- */
/* Rozvrzeni                                                              */
/* --------------------------------------------------------------------- */

.layout {
    display: grid;
    grid-template-columns: 216px 1fr;
    min-height: 100vh;
}

.sidebar {
    /* Tmavsi nez stranka, ne svetlejsi. Panel je ramec, ne obsah - kdyz
       je svetlejsi, tlaci se dopredu a karty vedle nej vypadaji ploche.
       Ve svetlem rezimu plati totez obracene: tam je o odstin svetlejsi
       nez stranka, protoze "dozadu" znamena na svetlem podkladu blize
       k bile. */
    background: var(--rail);
    border-right: 1px solid var(--border);
    padding: 20px 14px;
    display: flex;
    flex-direction: column;
    gap: 24px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 650;
    font-size: 17px;
    text-decoration: none;
    padding: 0 8px;
}

/* Značka je SVG, takže nepotřebuje barevný podklad ani vlastní barvu -
   nese si přechod v sobě a zůstane ostrá ve světlém i tmavém režimu. */
.brand-mark {
    width: 28px;
    height: 28px;
    flex: none;
    display: block;
}

.nav { display: flex; flex-direction: column; gap: 2px; }

.nav a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    border-radius: 8px;
    text-decoration: none;
    color: var(--text-secondary);
    font-size: 14px;
}

.nav a:hover { background: var(--surface-2); color: var(--text-primary); }
.nav a.active { background: var(--surface-2); color: var(--text-primary); font-weight: 600; }

/* Vybrana polozka ma u kraje panelu svisly prouzek s prechodem.
   Sama obarvena plocha nestacila: v tmavem rezimu je rozdil mezi
   --surface-1 a --surface-2 zamerne jemny, takze se aktivni polozka
   ztracela. Prouzek je videt hned a nedela z menu radu barevnych
   obdelniku. `left: -14px` je odsazeni panelu - prouzek tak sedi
   presne na jeho hrane. */
.nav a { position: relative; }

.nav a.active::before {
    content: "";
    position: absolute;
    left: -14px;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: linear-gradient(180deg, var(--accent-2), var(--accent));
}

.sidebar-foot { margin-top: auto; font-size: 12px; color: var(--text-muted); }

/* Obsah je dashboard - tabulky, mřížky plakátů, grafy. Ty šířku využijí,
   na rozdíl od článku, kde by dlouhé řádky ubíraly na čitelnosti.
   Strop je proto velkorysý a obsah se na širokých displejích centruje,
   místo aby zůstávala prázdná polovina vpravo. */
.main {
    padding: 24px 32px 56px;
    max-width: 1720px;
    margin: 0 auto;
    width: 100%;
    /* min-width: 0 je tu nutnost, ne kosmetika. Prvek v gridu ma ve
       vychozim stavu min-width: auto, takze se nesmrskne pod sirku sveho
       obsahu - a pas plakatu (.poster-strip) je vnitrne siroky 2600 px.
       Sloupec se kvuli nemu roztahl na 1720 px, stranka pretekla o 32 px
       doprava a prave odsazeni skoncilo mimo obrazovku: obsah pak vypadal
       nalepeny na posuvniku. S min-width: 0 se sloupec zuzi spravne a pas
       se posouva sam v sobe, jak ma. */
    min-width: 0;
}

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 20px;
}

h1 { font-size: 24px; margin: 0 0 4px; font-weight: 640; }
h2 { font-size: 16px; margin: 0; font-weight: 620; }
h3 { font-size: 14px; margin: 0 0 10px; font-weight: 620; color: var(--text-secondary); }
.subtitle { margin: 0; color: var(--text-secondary); font-size: 14px; }

/* --------------------------------------------------------------------- */
/* Filtr obdobi - jedna rada nad vsim, co ovlivnuje                       */
/* --------------------------------------------------------------------- */

.filters {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}

.chip {
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface-1);
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 13px;
    /* Chip je někdy odkaz a někdy tlačítko (vlastní období, rychlé volby).
       Odkaz dostane ruku od prohlížeče, <button> ne - a chip, který
       vypadá stejně jako ten vedle, se musí stejně i chovat. Font taky:
       tlačítko si jinak vezme systémový. */
    font-family: inherit;
    line-height: inherit;
    cursor: pointer;
}

/* Výběr preferovaného jazyka na stránce Jazyky.

   Vlastní třída, protože obecné pravidlo pro `select` dole roztahuje
   políčko na celou šířku - to je správné ve formulářích v Nastavení,
   ale v hlavičce karty by rozbilo řádek. */
.lang-picker {
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: flex-end;
}

.lang-picker select {
    width: auto;
    min-width: 170px;
    padding: 6px 10px;
    font-size: 13px;
    /* Ruka pri najeti. Prohlizec ji u <select> sam nedava, prestoze je
       to ovladaci prvek jako tlacitko vedle - a kdo cekal, ze na to jde
       kliknout, nemel od kurzoru zadne potvrzeni. */
    cursor: pointer;
}

.chip:hover { border-color: var(--axis); color: var(--text-primary); }

/* Vybrana volba nese barvu aplikace, ne prohozene cerne a bile.
   Prechod fialova -> modra je tentyz, jaky ma znacka v logu, takze
   filtr obdobi a menu mluvi stejnou reci. */
.chip.active {
    background: linear-gradient(135deg, var(--accent-2), var(--accent));
    color: var(--accent-ink);
    border-color: transparent;
    font-weight: 600;
}

/* Aktivní tlačítko má prohozené barvy: pozadí je barva písma a naopak.
   Obecné .chip:hover ale písmo přebarvovalo zpátky na --text-primary,
   takže po najetí myší splynulo s vlastním pozadím a text zmizel
   (bílá na bílé ve světlém režimu, černá na černé v tmavém).
   Aktivní tlačítko proto barvy při najetí nemění - jen se lehce
   projasní, ať je zpětná vazba pořád vidět. */
.chip.active:hover {
    color: var(--accent-ink);
    background: linear-gradient(135deg, var(--accent-2), var(--accent));
    border-color: transparent;
    filter: brightness(1.12);
}

/* Karta se prave prekresluje. Zesvetleni je jemne schvalne - vymena trva
   par desitek milisekund a vyrazny efekt by pusobil pomaleji, nez to je.
   Vyska se nemeni, takze stranka pod tim nepodskoci. */
.is-loading { opacity: 0.55; transition: opacity 0.12s ease; }
.is-loading .chip { pointer-events: none; }

/* --------------------------------------------------------------------- */
/* Karty a dlazdice                                                       */
/* --------------------------------------------------------------------- */



.card {
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px 20px;
    margin-bottom: 18px;
}

.card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.card-note { color: var(--text-muted); font-size: 12.5px; margin: 0; }

/* Svisly rytmus stranky drzi jedno cislo: 18 px pod kazdym blokem.
   .card si ho nese sam, ale uvnitr .grid-2 se mu vynuluje - tam mezery
   resi `gap`. Kvuli tomu musi mit spodni okraj i samotna mrizka, jinak
   se dve mrizky pod sebou (nebo mrizka a karta) slepi k sobe.
   Michat `gap` s okraji jednotlivych prvku je presne to misto, kde
   mezery mizi - proto ho tady drzi kontejner, ne jeho deti. */
.grid-2 {
    display: grid;
    /* `min(340px, 100%)`, ne holých 340 px: na úzké obrazovce by si
       sloupec o těch 340 řekl i tam, kde je k dispozici 288 - a karta
       by vylezla z obrazovky. Tohle je ta hranice, pod kterou se
       stránka dala posouvat do strany. */
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    gap: 18px;
    margin-bottom: 18px;
}
.grid-2 > .card { margin-bottom: 0; }

.kpi-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
    gap: 14px;
    margin-bottom: 18px;
}

.tile {
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
}

/* Popisek dlazdice verzalkami s prostrkanim. Cislo pod nim pak pusobi
   jako udaj, ne jako nadpis - a rada dlazdic vedle sebe drzi jednu linku,
   protoze verzalky nemaji dotahy nahoru ani dolu. */
.tile-label {
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-muted);
    margin: 0 0 6px;
}

/* Velke cislo ma proporcionalni cislice. tabular-nums (stejne siroke) je
   pro sloupce v tabulkach - u velkeho cisla vypada rozvolnene. */
.tile-value { font-size: 26px; font-weight: 650; line-height: 1.15; }

/* Bod, ktery jede po krivce pri najeti mysi. Zar kolem nej je jediny
   duvod, proc ho oko najde driv, nez precte cislo v bubline - sam kotouc
   o polomeru 3,5 px na tmavem podkladu splyva s carou. */
.sparkline .chart-hit circle,
.chart .chart-hit circle { filter: drop-shadow(0 0 6px color-mix(in oklab, var(--accent) 70%, transparent)); }

/* Ziva karta na Siti: cislo vlevo, minutova krivka vpravo.

   Tady davaji dva sloupce smysl - na rozdil od hlavniho cisla na
   Prehledu, ktere se vratilo nad krivku. Rozdil je v tom, co krivka
   nese: mesic potrebuje sirku, aby byl videt tvar; posledni hodina je
   kratky pohled a hlavni sdeleni je cislo vedle ni. */
.zive-cislo {
    display: grid;
    grid-template-columns: minmax(min(180px, 100%), 240px) minmax(0, 1fr);
    gap: 22px;
    align-items: center;
}

.zive-cislo .hero { font-size: 40px; }
.zive-cislo .hero small { font-size: 16px; font-weight: 500; color: var(--text-secondary); }
.zive-graf { min-width: 0; }

@media (max-width: 820px) {
    .zive-cislo { grid-template-columns: 1fr; gap: 10px; }
}

/* Karta s hlavnim cislem: cislo nahore, krivka pres celou sirku pod nim.

   Zkusili jsme cislo vlevo a krivku vpravo - karta byla nizsi, ale
   krivka uzsi, a prave na ni je videt tvar mesice. Sirka je tu cennejsi
   nez usetrena vyska. */
.hero-graf { min-width: 0; margin-top: 4px; }

.hero {
    font-size: 50px;
    font-weight: 660;
    line-height: 1.05;
    letter-spacing: -0.02em;
}

/* Srovnani s predchozim obdobim. Tucne schvalne: je to jediny udaj na
   dlazdici, ktery rika, jestli cislo nad nim je hodne, nebo malo -
   a tenkym pismem se ztracel pod nim. */
.delta {
    font-size: 12.5px;
    font-weight: 650;
    margin-top: 4px;
    display: flex;
    align-items: center;
    gap: 5px;
}

.delta.flat { font-weight: 500; }
.delta.up   { color: var(--good); }
.delta.down { color: var(--critical); }
.delta.flat { color: var(--text-muted); }

/* height: auto je tu podstatné.
   SVG má viewBox 760x64 a zmenšuje se rovnoměrně (nedeformujeme tvar).
   Kdyby byla výška pevná, prohlížeč by měřítko zvolil podle ní - u výšky
   30px by z 760px šířky zbylo 356px a graf by se scvrkl doprostřed karty.
   S "auto" určuje měřítko šířka a výška se dopočítá. */
.sparkline { width: 100%; height: auto; margin-top: 10px; display: block; }

/* --------------------------------------------------------------------- */
/* Grafy                                                                  */
/* --------------------------------------------------------------------- */

/* SVG graf (uz jen carovy/plosny) se zmensi na sirku okna.
   Zadne min-width - prave to drive nutilo stranku posouvat do strany. */
.chart { width: 100%; height: auto; display: block; overflow: visible; }

/* --- vodorovne sloupce (HTML, ne SVG) ------------------------------- */

.hbars { display: flex; flex-direction: column; gap: 9px; }

.hbar-row {
    display: grid;
    /* Popisek nikdy neni sirsi nez tretina karty, drazka si vezme zbytek.
       Diky procentum se cely graf prizpusobi sirce okna sam. */
    grid-template-columns: minmax(0, 30%) 1fr max-content;
    align-items: center;
    gap: 10px;
}

/* Zebricek ma pred popiskem cislo. Rika "treti" driv, nez se to da
   odpocitat ocima - a u seznamu deseti titulu to je rozdil. */
.hbar-row.is-ranked { grid-template-columns: 18px minmax(0, 30%) 1fr max-content; }

.hbar-rank {
    font-size: 12px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.hbar-label {
    font-size: 13px;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Popisek, ktery nekam vede. Podtrzeni az pri najeti - v zebricku deseti
   radku by deset podtrzenych textu delalo z grafu seznam odkazu a odvedlo
   pozornost od sloupcu, kvuli kterym tam graf je. */
.hbar-link { text-decoration: none; color: inherit; }
.hbar-link:hover { color: var(--text-primary); text-decoration: underline; }

.hbar-track {
    /* Drážka je jen naznačená - je to pozadí, ne data. Plná --grid dělala
       z každého řádku dva pruhy vedle sebe a oko pak četlo i ten prázdný. */
    background: color-mix(in oklab, var(--grid) 55%, transparent);
    border-radius: 4px;
    /* Nizsi nez drive: sloupec nese hodnotu delkou, ne vyskou, a tlustsi
       pruh jen prida inkoustu. Deset radku pod sebou tak drzi pohromade
       jako zebricek misto rady pasu. */
    height: 10px;
    overflow: hidden;
}

.hbar-fill {
    height: 100%;
    /* Hranaty u zakladny, zaobleny na strane hodnoty - oko tak snadneji
       najde spolecnou zakladnu, od ktere se vsechny sloupce meri. */
    border-radius: 0 4px 4px 0;
    min-width: 2px;
}

.hbar-value {
    font-size: 13px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --- deleny pruh ---------------------------------------------------- */

.stack {
    display: flex;
    /* Mezera v barve podkladu oddeluje casti. Delame to mezerou, ne
       obrysem - obrys prida inkoust, ktery neni data. */
    gap: 2px;
    height: 34px;
    border-radius: 4px;
    overflow: hidden;
}

.stack-seg {
    display: grid;
    place-items: center;
    min-width: 3px;
    overflow: hidden;
}

.stack-seg span {
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
}

/* --- teplotni mapa -------------------------------------------------- */

.heatmap {
    display: grid;
    grid-template-columns: 28px 1fr;
    gap: 3px;
    align-items: center;
}

.heatmap-corner { }

.heatmap-hours,
.heatmap-cells {
    display: grid;
    grid-template-columns: repeat(24, 1fr);
    gap: 2px;
}

.heatmap-hours span {
    font-size: 10.5px;
    color: var(--text-muted);
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.heatmap-day {
    font-size: 11px;
    color: var(--text-muted);
    text-align: right;
    padding-right: 4px;
}

.heatmap-cells i {
    display: block;
    /* Pevna vyska, sirku si bunka vezme podle okna.
       Drive tu bylo aspect-ratio: 1/1 (ctvercove bunky). Na sirokem displeji
       ale 24 sloupcu znamena 64px bunky, takze mapa narostla na 485 px -
       dvakrat vic nez kterakoli jina karta, presto ze nese nejmene cisel.
       Ctverec tu zadnou informaci nenese: hodnotu ukazuje barva, ne tvar.
       Mrizka 24x7 je ze sve podstaty siroka a obdelnikove bunky jsou u
       teplotni mapy den x hodina obvykly tvar. */
    height: 26px;
    border-radius: 3px;
}

.axis-label    { fill: var(--text-muted); font-size: 11px; font-family: var(--font); font-variant-numeric: tabular-nums; }

/* --- bublina s hodnotou pri najeti mysi ------------------------------ */

/* Nativni title="" ma dve vady: objevi se az po vterine a vypada v kazdem
   prohlizeci jinak. Vlastni bublina je okamzita a drzi styl stranky.
   Hodnotu ale nikdy nenese jen ona - kazdy graf ma i tabulku nebo popisek,
   takze se ke cteni cisla nikdo nemusi trefovat mysi. */
.tooltip {
    position: fixed;
    z-index: 50;
    pointer-events: none;
    /* Kartička v barvách stránky, ne obrácené barvy.
       Dřív měla bublina pozadí --text-primary, tedy skoro bílou
       v tmavém režimu - vedle tmavého grafu svítila jako lampa
       a přebíjela to, kvůli čemu si ji člověk otevřel. */
    background: var(--surface-2);
    color: var(--text-primary);
    border: 1px solid var(--border);
    font-size: 12.5px;
    padding: 9px 12px;
    border-radius: 10px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
    max-width: 340px;
    opacity: 0;
    transition: opacity 0.08s ease;
}

/* Datum (nebo název) nad hodnotami - první, co oko potřebuje. */
.tooltip-nadpis {
    font-size: 13px;
    font-weight: 650;
    margin-bottom: 5px;
    white-space: nowrap;
}

/* Jedna hodnota = jeden řádek. Barvu nese text řádku, protože ta odpovídá
   sérii v grafu; u bubliny bez sérií zůstane běžná barva písma. */
.tooltip-radek {
    font-weight: 550;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tooltip-radek + .tooltip-radek { margin-top: 2px; }

.tooltip.visible { opacity: 1; }

/* Prvky, na kterych bublina funguje, dostanou kurzor "je tu co cist". */
[data-tip] { cursor: default; }

.hbar-row[data-tip]:hover .hbar-track { outline: 1px solid var(--axis); }
.stack-seg[data-tip]:hover { filter: brightness(1.12); }
.heatmap-cells i:hover { outline: 1.5px solid var(--text-primary); outline-offset: 1px; }

/* Svisla cara a bod v carovem grafu se ukazou az pri najeti. */
/* Výběr rozsahu tažením myši. Kurzor je svislice, protože se vybírá
   jen v čase - výška grafu se tím neomezuje. */
.chart-lze-vybirat { cursor: col-resize; touch-action: pan-y; }
.chart-vyber {
    fill: color-mix(in oklab, var(--accent) 22%, transparent);
    stroke: var(--accent);
    stroke-width: 1;
    pointer-events: none;
}
/* Během tažení nemá smysl ukazovat bubliny bodů - myš míří na rozsah,
   ne na jeden okamžik. */
.chart-tahne .chart-hit { pointer-events: none; }

.chart-hit line, .chart-hit circle { opacity: 0; transition: opacity 0.08s ease; }
.chart-hit:hover line, .chart-hit:hover circle { opacity: 1; }

.chart-empty {
    color: var(--text-muted);
    font-size: 13.5px;
    padding: 28px 0;
    text-align: center;
    margin: 0;
}

.legend {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    padding: 0;
    margin: 12px 0 0;
    font-size: 13px;
    color: var(--text-secondary);
}

.legend li { display: flex; align-items: center; gap: 7px; }

.legend-swatch {
    width: 11px; height: 11px;
    border-radius: 3px;
    display: inline-block;
    flex: none;
}

/* --------------------------------------------------------------------- */
/* Nadpis sekce na úvodní stránce                                         */
/* --------------------------------------------------------------------- */

.section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin: 30px 0 14px;
}

.section-head h2 { font-size: 20px; font-weight: 640; letter-spacing: -0.01em; }
.section-head a { text-decoration: none; }
.section-head a:hover { color: var(--text-primary); }

/* --------------------------------------------------------------------- */
/* Právě běžící přehrávání                                                */
/* --------------------------------------------------------------------- */

.sessions {
    display: grid;
    /* `min(380px, 100%)`, ne holých 380: sloupec by si o ně řekl i tam,
       kde je k dispozici 358 - a karta „právě se hraje" pak vylezla
       z obrazovky a vpravo se ořízla. */
    grid-template-columns: repeat(auto-fill, minmax(min(380px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 8px;
}

.session {
    display: grid;
    /* Plakat, obsah, pravy sloupec s tokem. Ten posledni je `auto`,
       takze si vezme jen tolik, kolik potrebuje - a kdyz na karte neni
       (u prehravani bez znameho toku), mrizka se scvrkne sama. */
    /* `minmax(0, 1fr)`, ne holé `1fr`: dráha mřížky má vlastní minimum
       podle obsahu, a to `min-width: 0` na položce neodstraní. Dlouhý
       název zařízení tak kartu roztáhl o dvacet pixelů za okraj a vpravo
       se ořezávala. */
    grid-template-columns: 78px minmax(0, 1fr) auto;
    gap: 14px;
    /* Jedina karta se zarici barvou: ta, ktera se meni po vterinach.
       Zar je v rohu, ne pres celou plochu - pres obsah by rozmazal hranu
       a sousedni karty by prestaly mit stejny podklad. */
    background:
        radial-gradient(75% 190% at 0% 0%,
                        color-mix(in oklab, var(--accent-2) 42%, transparent),
                        transparent 58%),
        radial-gradient(60% 150% at 100% 100%,
                        color-mix(in oklab, var(--accent) 20%, transparent),
                        transparent 62%),
        var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px;
}

/* Položky mřížky mají `min-width: auto`, takže se nesmrsknou pod šířku
   svého obsahu - a dlouhý název zařízení nebo výčet důvodů přepočtu pak
   roztáhne celou kartu za okraj obrazovky. */
.session > * { min-width: 0; }

.session-poster {
    display: block;
    aspect-ratio: 2 / 3;
    border-radius: 6px;
    overflow: hidden;
    /* Podklad je videt jen do doby, nez se stahne plakat - a u titulu,
       ktery zadny nema, uz navzdy. Seda plocha vypadala jako chyba
       nacitani; prechod znacky vypada jako zamer. */
    background: linear-gradient(150deg,
                color-mix(in oklab, var(--accent) 55%, var(--surface-2)),
                color-mix(in oklab, var(--accent-2) 55%, var(--surface-2)));
    box-shadow: 0 4px 14px rgb(0 0 0 / 28%);
}

.session-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }

.session-body { min-width: 0; display: flex; flex-direction: column; gap: 7px; }

.session-title { font-size: 14.5px; font-weight: 600; line-height: 1.35; }
.session-title a { text-decoration: none; }
.session-title a:hover { text-decoration: underline; }

.session-facts { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12.5px; }
.session-facts a { font-weight: 600; }

.session-tags { display: flex; flex-wrap: wrap; gap: 5px; }

.session-reason {
    margin: 0;
    font-size: 12px;
    color: var(--text-muted);
    word-break: break-word;
}

.session-progress {
    margin-top: auto;
    padding-top: 4px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.session-bar {
    height: 5px;
    border-radius: 3px;
    background: var(--grid);
    overflow: hidden;
}

/* Prechod fialova -> modra, stejny jako u vybraneho chipu a prouzku
   v menu. Byla to jedina cara na karte, ktera jeste nesla barvu serie -
   pritom zadna serie to neni, je to postup jednoho prehravani. */
.session-bar i {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: linear-gradient(90deg, var(--accent-2), var(--accent));
}

.session-time { font-size: 12px; font-variant-numeric: tabular-nums; }

.session-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    text-align: right;
    white-space: nowrap;
}

/* Tok je cislo, ne popisek - tabulkove cislice, aby pri kazde zmene
   neposkakovalo, a barva aplikace, protoze se tyka serveru. */
.session-bitrate {
    font-size: 14px;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

.session-tech { font-size: 12px; color: var(--text-muted); }

/* Na uzkem okne se pravy sloupec presune pod obsah - jinak by ukrajoval
   z nazvu titulu, ktery je dulezitejsi. */
@media (max-width: 720px) {
    .session { grid-template-columns: 78px minmax(0, 1fr); }
    .session-side {
        grid-column: 2;
        align-items: flex-start;
        text-align: left;
        flex-direction: row;
        gap: 8px;
    }
}

/* --------------------------------------------------------------------- */
/* Pás plakátů (nedávno přidané)                                          */
/* --------------------------------------------------------------------- */

/* Karta s pásem plakátů. Pás se posouvá do strany a musí sahat až na
   okraj karty - proto zápornými okraji "vystoupí" z jejího odsazení.
   Kdyby končil dřív, vypadal by useknutý plakát jako chyba místo jako
   pozvánka k posunutí. */
.recent-card { padding-bottom: 12px; }
.recent-card .poster-strip {
    margin: 0 -20px -6px;
    padding: 2px 20px 10px;
    /* Bez tohohle radku se prvni plakat lepil na ramecek karty, prestoze
       odsazeni tu bylo. Muze za to `scroll-snap`: prohlizec "pricvakne"
       prvni polozku na zacatek posouvaci oblasti a leve odsazeni tim
       odroluje pryc. `scroll-padding` mu rekne, ze zacatek je az za nim. */
    scroll-padding-left: 20px;
    scroll-padding-right: 20px;
}

.poster-strip {
    display: flex;
    gap: 14px;
    /* Dlouhý seznam se posouvá vodorovně. U mřížky médií to byla chyba
       (tam se dá zalomit), ale "nedávno přidané" je ze své podstaty
       řada seřazená podle času - a řada se posouvá. */
    overflow-x: auto;
    padding-bottom: 10px;
    scroll-snap-type: x proximity;
    /* Tenky posuvnik. Systemovy sedy pas pod pasem plakatu byl tlustsi
       nez popisky nad nim a bral pozornost necemu, co neni obsah. */
    scrollbar-width: thin;
    scrollbar-color: var(--axis) transparent;

    /* Rozměry plakátu na jednom místě. Karta po najetí roste do šířky
       (viz níž) a výška přitom musí zůstat, jinak by se posunul celý
       zbytek stránky pod pásem. */
    --poster-w: 112px;
    --poster-h: calc(var(--poster-w) * 1.5);
}

.poster-card {
    flex: 0 0 var(--poster-w);
    text-decoration: none;
    color: inherit;
    scroll-snap-align: start;
    transition: flex-basis 0.16s ease;
}

.poster-frame {
    position: relative;
    height: var(--poster-h);
    border-radius: 8px;
    overflow: hidden;
    /* Stejne jako u plakatu v "prave se hraje": nez se obrazek stahne
       (a u titulu, ktery zadny nema, navzdy) je vidět podklad. Seda
       plocha vypadala jako chyba nacitani. */
    background: linear-gradient(155deg,
                color-mix(in oklab, var(--accent) 42%, var(--surface-2)),
                color-mix(in oklab, var(--accent-2) 42%, var(--surface-2)));
    border: 1px solid var(--border);
    margin-bottom: 7px;
}

.poster-frame { display: block; }
.poster-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.poster-card:hover .poster-frame { border-color: var(--accent); }

.poster-badge {
    position: absolute;
    left: 6px;
    top: 6px;
    background: rgba(11, 11, 11, 0.82);
    color: #fff;
    font-size: 10.5px;
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 4px;
}

.poster-name {
    font-size: 12.5px;
    font-weight: 570;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
}

/* Seznam dílů, které přišly v jedné dávce.

   Leží PŘES plakát, ne pod kartou. Pás plakátů se posouvá do stran
   (overflow-x), a to podle CSS znamená, že se ořízne i to, co vyčnívá
   dolů - vysunutá nabídka pod kartou by se tedy nezobrazila celá.
   Takhle zůstane uvnitř rámečku, který si sám hlídá své hranice. */
/* Po najetí karta povyroste a teprve v ní se ukážou díly. Napřed vypadá
   jako každá jiná - jen název seriálu.

   Roste **do šířky, ne přes okolí**. Zvětšení přes `transform: scale()`
   vypadalo dobře, dokud karta nebyla u kraje: pás se posouvá do stran
   (`overflow-x: auto`), takže cokoliv, co z něj vyleze, se ořízne - a
   hrana zvětšené karty mizela za okrajem. Takhle se změní její místo
   v řádku, ostatní novinky se odsunou a ořezávat není co.

   Výška zůstává (`--poster-h`), aby se neposunul zbytek stránky pod pásem. */
.poster-card.has-episodes:hover,
.poster-card.has-episodes:focus-within {
    flex-basis: calc(var(--poster-w) * 1.75);
}

.poster-card.has-episodes .poster-frame {
    transition: border-color 0.14s ease;
}

.poster-card.has-episodes:hover .poster-frame,
.poster-card.has-episodes:focus-within .poster-frame {
    border-color: var(--accent);
}

.poster-episodes {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 8px 7px;
    background: rgba(11, 11, 11, 0.88);
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;

    /* Kolečko myši se nesmí přelít na stránku. Bez tohohle řádku se po
       dojetí seznamu na konec začne posouvat celý přehled - kurzor přitom
       sjede z karty, seznam se zavře a člověk skončí jinde, než chtěl.
       `contain` posouvání zastaví na hranici seznamu. */
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
}

/* Nesmršťovat. Ve svislém flexu se položky ve výchozím stavu zmenšují,
   aby se do rámečku vešly - u celé řady se tak řádky slisovaly na sebe
   a text se překrýval. Takhle si každý díl podrží svou výšku a seznam
   se místo toho posouvá. */
.poster-episodes-head,
.poster-episodes a { flex: 0 0 auto; }

/* `focus-within` je tu kvůli klávesnici: kdo se do seznamu dostane
   tabulátorem, musí ho taky vidět. */
.poster-card.has-episodes:hover .poster-episodes,
.poster-card.has-episodes:focus-within .poster-episodes {
    opacity: 1;
    visibility: visible;
}

.poster-episodes-head {
    /* Zůstane nahoře i při posouvání - u dlouhé řady dílů je jinak
       po pár otočkách kolečka vidět jen holý seznam bez popisku.
       `top: -8px` je odsazení seznamu, aby nadpis dosedl na okraj. */
    position: sticky;
    top: -8px;
    background: rgba(11, 11, 11, 0.95);
    padding: 3px 0 2px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #b9b8b2;
    margin-bottom: 2px;
}

.poster-episodes a {
    display: block;
    font-size: 11px;
    line-height: 1.35;
    color: #fff;
    text-decoration: none;
    padding: 3px 5px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.poster-episodes a strong { color: var(--series-1); font-weight: 700; }
.poster-episodes a:hover { background: rgba(255, 255, 255, 0.18); }

.poster-meta { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }

/* --------------------------------------------------------------------- */
/* Zalozky                                                                */
/* --------------------------------------------------------------------- */

.tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
}

/* Rozcestník sekcí jako rozbalovací seznam. Na desktopu se nekreslí -
   tam jsou záložky, ve kterých je vidět všechno naráz. */
.tabs-vyber { display: none; }

@media (max-width: 860px) {
    /* Jedenáct záložek se na 390 px zalomí do šesti řádků: 207 px odkazů,
       než člověk uvidí první nastavení. Seznam zabere jeden řádek.

       Schovají se JEN záložky, které rozbalovací seznam nahrazuje - proto
       sourozenecký selektor, ne prosté `.tabs`. Detail knihovny má taky
       záložky, jenže tři a bez seznamu; ty by prostým pravidlem zmizely
       a nebylo by se jak přepnout. */
    .tabs-vyber + .tabs { display: none; }

    .tabs-vyber {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-bottom: 18px;
    }

    .tabs-vyber label {
        font-weight: 600;
        font-size: 13.5px;
        white-space: nowrap;
    }

    .tabs-vyber select { flex: 1; min-width: 0; }
}

.tabs a {
    padding: 8px 16px;
    text-decoration: none;
    color: var(--text-secondary);
    font-size: 14px;
    font-weight: 550;
    border-radius: 8px 8px 0 0;
    /* Aktivni zalozku nese podtrzeni, ne jen barva - kdo barvy nerozlisi,
       pozna ji podle cary. */
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.tabs a:hover { color: var(--text-primary); background: var(--surface-2); }

.tabs a.active {
    color: var(--text-primary);
    border-bottom-color: var(--series-1);
    font-weight: 640;
}

/* --------------------------------------------------------------------- */
/* Dlazdice knihoven                                                      */
/* --------------------------------------------------------------------- */

.lib-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 18px;
}

.lib-card {
    display: block;
    text-decoration: none;
    color: inherit;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    transition: border-color 0.12s ease;
}

.lib-card:hover { border-color: var(--axis); }

.lib-cover {
    position: relative;
    aspect-ratio: 16 / 5;
    background: var(--surface-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}

.lib-cover img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.lib-cover-name {
    position: relative;
    font-size: clamp(28px, 5vw, 46px);
    font-weight: 700;
    color: #fff;
    /* Stin drzi nazev citelny i na svetlem obrazku. Bez nej by nazev
       na nekterych plakatech zmizel. */
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.75), 0 0 3px rgba(0, 0, 0, 0.6);
    padding: 0 16px;
    text-align: center;
}

.lib-facts { padding: 14px 18px; display: flex; flex-direction: column; gap: 7px; }

.lib-facts > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 13.5px;
}

/* --------------------------------------------------------------------- */
/* Mrizka medii                                                           */
/* --------------------------------------------------------------------- */

.media-grid {
    display: grid;
    /* auto-fill + minmax = pocet sloupcu si urci prohlizec podle sirky.
       Zadny pevny pocet, zadne posouvani do strany. */
    grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 18px;
}

.media-card { text-decoration: none; color: inherit; display: block; }

.media-poster {
    position: relative;
    aspect-ratio: 2 / 3;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 8px;
}

.media-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }

.media-card:hover .media-poster { border-color: var(--series-1); }

.media-size {
    position: absolute;
    right: 6px;
    bottom: 6px;
    background: rgba(11, 11, 11, 0.82);
    color: #fff;
    font-size: 11.5px;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 5px;
    font-variant-numeric: tabular-nums;
}

/* --- archivovana polozka ---------------------------------------------- */
/* Titul, ktery uz v Jellyfinu neni. Rozostreny plakat je videt driv, nez
   clovek stihne precist popisek - tvar nese informaci stejne jako text.
   Blur davame obrazku, ne cele kartre: popisek pod plakatem musi zustat
   citelny, jinak by slo o ozdobu, ne o sdeleni. */
.media-card.is-archived .media-poster img {
    filter: blur(3px) grayscale(0.7);
    opacity: 0.55;
}

.media-card.is-archived .media-name,
.media-card.is-archived .media-meta { opacity: 0.7; }

.media-archived {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    text-align: center;
    background: rgba(11, 11, 11, 0.72);
    color: #fff;
    font-size: 12.5px;
    font-weight: 650;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 5px 4px;
}

.media-name {
    font-size: 13px;
    font-weight: 570;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.media-meta { font-size: 12px; color: var(--text-muted); margin-top: 3px; }

/* --------------------------------------------------------------------- */
/* Detail polozky                                                         */
/* --------------------------------------------------------------------- */

.item-layout {
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: 22px;
    align-items: start;
}

/* Položka mřížky má ve výchozím stavu `min-width: auto`, takže se
   NESMRSKNE pod šířku svého obsahu. Uvnitř je řada dlaždic, která si
   říká o tři sloupce po 150 px - a sloupec se kvůli tomu roztáhl na
   520 px v rodiči širokém 358. Stránka pak na mobilu jela do strany
   a musela se oddalovat. */
.item-layout > * { min-width: 0; }

.item-poster {
    aspect-ratio: 2 / 3;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    position: sticky;
    top: 20px;
}

.item-poster img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Stejne jako u dlazdice v knihovne - archivovany titul je poznat na
   prvni pohled, ne az z popisku. */
.item-poster.is-archived { position: relative; }
.item-poster.is-archived img { filter: blur(4px) grayscale(0.7); opacity: 0.55; }

table.facts th {
    width: 160px;
    color: var(--text-secondary);
    font-weight: 550;
    vertical-align: top;
}

@media (max-width: 720px) {
    .item-layout { grid-template-columns: 1fr; }
    .item-poster { max-width: 180px; position: static; }

    /* Sloupce, které se na úzkou obrazovku nevejdou. Osmisloupcová
       historie byla v 316px okně široká 1007 px, takže byla vidět
       třetina - a řádky měly 120 px, protože se dlouhý obsah lámal.
       Zůstává kdy, kdo, co a jak dlouho; zbytek je na detailu. */
    .sloupec-navic { display: none; }
}

/* --------------------------------------------------------------------- */
/* Tabulky - kazdy graf ma mit i ctenou podobu                            */
/* --------------------------------------------------------------------- */

.table-wrap { overflow-x: auto; }

table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
}

th {
    text-align: left;
    font-weight: 600;
    color: var(--text-secondary);
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

td {
    padding: 9px 10px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}

tbody tr:hover { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: none; }

/* --------------------------------------------------------------------- */
/* Srovnání dvou období                                                   */
/* --------------------------------------------------------------------- */

/* Dva přepínače vedle sebe. Pod sebou by vypadaly jako filtr a podfiltr;
   vedle sebe je vidět, že jsou to dvě rovnocenné volby. */
.srovnani-volby {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px 24px;
}

/* První sloupec je popisek řádku, zbylé tři čísla. Bez pevné šířky by se
   popisek roztáhl a čísla by se slepila u pravého okraje. */
table.srovnani th:first-child,
table.srovnani td:first-child { width: 34%; }

/* .delta je jinak dlaždicový popisek pod číslem, takže má odsazení
   shora. V buňce tabulky by od něj řádek povyrostl. */
table.srovnani .delta {
    justify-content: flex-end;
    white-space: nowrap;
    margin-top: 0;
}

@media (max-width: 780px) {
    .srovnani-volby { grid-template-columns: minmax(0, 1fr); }

    /* Na mobilu se ze srovnání stanou bloky, ne tabulka.
       Čtyři sloupce se na 350 px nevejdou a vodorovný posuv odsune
       z obrazovky sloupec Rozdíl - tedy to jediné, kvůli čemu se člověk
       na tuhle stránku dívá. Popisek sloupce nese `data-popisek`,
       protože hlavička tabulky tady zmizí. */
    table.srovnani,
    table.srovnani tbody,
    table.srovnani tr,
    table.srovnani td { display: block; width: auto; }

    table.srovnani thead { display: none; }

    table.srovnani tr {
        padding: 10px 0;
        border-bottom: 1px solid var(--border);
    }

    table.srovnani tr:last-child { border-bottom: none; }

    table.srovnani td:first-child {
        width: auto;
        font-weight: 600;
        color: var(--text-primary);
        padding-bottom: 4px;
        border-bottom: none;
    }

    /* Hodnota vpravo, popisek vlevo - čte se to jako řádek "Období A … 753 h". */
    table.srovnani td:not(:first-child) {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 12px;
        text-align: right;
        border-bottom: none;
        padding: 3px 0;
    }

    table.srovnani td[data-popisek]::before {
        content: attr(data-popisek);
        color: var(--text-secondary);
        font-weight: 500;
        text-align: left;
    }

    table.srovnani .delta { justify-content: flex-end; }
}

.srovnani-volba .tile-label { margin: 0 0 8px; }
.srovnani-volba .filters { margin: 0; }

/* Souhrnný řádek. Bez oddělení splyne s daty a čte se jako další
   položka - jenže "Celkem 91" mezi řádky po dvou titulech mate. */
tfoot td {
    border-top: 1px solid var(--border);
    border-bottom: none;
    padding-top: 11px;
    color: var(--text-secondary);
}

.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.muted { color: var(--text-muted); }
.nowrap { white-space: nowrap; }
.strong { font-weight: 600; }

.truncate { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

details.paths summary { cursor: pointer; color: var(--text-secondary); font-size: 12.5px; }
details.paths pre {
    margin: 6px 0 0;
    font-size: 12px;
    white-space: pre-wrap;
    word-break: break-all;
    color: var(--text-muted);
}

/* --------------------------------------------------------------------- */
/* Stitky a stavy                                                         */
/* --------------------------------------------------------------------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    border: 1px solid var(--border);
    background: var(--surface-2);
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Stavova barva nikdy nestoji sama - vzdy ma vedle sebe tecku i popis,
   aby informaci nenesla jen barva. */
.badge .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.badge.good     .dot { background: var(--good); }
.badge.warning  .dot { background: var(--warning); }
.badge.serious  .dot { background: var(--serious); }
.badge.critical .dot { background: var(--critical); }
.badge.neutral  .dot { background: var(--text-muted); }
.badge.info     .dot { background: var(--accent); }

/* Odznaky na karte prehravani.

   Rozdil proti odznakum jinde v aplikaci: tady se na jednom radku sejde
   pet udaju, ktere NEMAJI stejnou vahu. "Prepocitava se" je stav serveru
   a stoji za pohled; "H264" je jen fakt o souboru. Kdyz vypadaly stejne
   (seda pilulka + barevna tecka), musel je clovek precist vsechny, aby
   nasel ten jediny dulezity.

   Stav proto dostane vypln ve sve barve a tecka mizi - barva uz to rekla.
   Fakta zustavaji potichu: bez pozadi, jen tlumeny text. */
.session-tags .badge {
    /* Fakta o prehravani (jazyk, titulky) maji stejny tvar jako stavy,
       jen bez barvy: obrys a tlumeny text. Bez ramecku se pri zalomeni
       radku slily s vetou pod nimi a "subtitles EN" na vlastnim radku
       vypadalo jako utrzek textu, ne jako udaj. */
    border-color: var(--border);
    background: transparent;
    color: var(--text-secondary);
    padding: 3px 9px;
    gap: 0;
}

.session-tags .badge .dot { display: none; }

.session-tags .badge.good,
.session-tags .badge.info,
.session-tags .badge.warning,
.session-tags .badge.serious,
.session-tags .badge.critical {
    padding: 3px 9px;
    font-weight: 650;
}

.session-tags .badge.info {
    background: color-mix(in oklab, var(--accent) 22%, transparent);
    color: color-mix(in oklab, var(--accent) 74%, var(--text-primary));
}

.session-tags .badge.good {
    background: color-mix(in oklab, var(--good) 20%, transparent);
    color: color-mix(in oklab, var(--good) 78%, var(--text-primary));
}

.session-tags .badge.warning {
    background: color-mix(in oklab, var(--warning) 22%, transparent);
    color: color-mix(in oklab, var(--warning) 82%, var(--text-primary));
}

.session-tags .badge.serious {
    background: color-mix(in oklab, var(--serious) 22%, transparent);
    color: color-mix(in oklab, var(--serious) 82%, var(--text-primary));
}

.session-tags .badge.critical {
    background: color-mix(in oklab, var(--critical) 22%, transparent);
    color: color-mix(in oklab, var(--critical) 82%, var(--text-primary));
}



.flash {
    padding: 11px 15px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
    margin-bottom: 18px;
    font-size: 14px;
    display: flex;
    gap: 10px;
    align-items: flex-start;
}

.flash .dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; flex: none; }
.flash.success .dot { background: var(--good); }
.flash.error   .dot { background: var(--critical); }
.flash.warning .dot { background: var(--warning); }
.flash.info    .dot { background: var(--series-1); }

/* --------------------------------------------------------------------- */
/* Formulare a tlacitka                                                   */
/* --------------------------------------------------------------------- */

.field { margin-bottom: 16px; max-width: 560px; }
.field label { display: block; font-weight: 600; font-size: 13.5px; margin-bottom: 4px; }
.field .hint { color: var(--text-muted); font-size: 12.5px; margin: 4px 0 0; }

input[type="text"], input[type="number"], input[type="password"], input[type="search"],
select, textarea {
    width: 100%;
    padding: 8px 11px;
    border-radius: 8px;
    border: 1px solid var(--axis);
    background: var(--surface-1);
    color: var(--text-primary);
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.35;
}

/* Cas u nocni ulohy: hodiny a minuty vedle sebe, dohromady stejne siroke
   jako sousedni pole s minutami.
   Zamerne dve obycejna cisla, ne `type="time"` ani `<select>`: obojí si
   otevira vyskakovaci okno, ktere kresli prohlizec sam - CSS na nej
   nedosahne a smer, kterym se rozbali, si urcuje podle mista na
   obrazovce, takze u spodniho radku tabulky vyjelo nahoru. */
.time-picker {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 5px;
    width: 110px;
    margin-left: auto;
}

/* V tabulce úloh sedí výběr času v pravém sloupci, proto to zarovnání
   doprava. Ve formuláři ale patří pod svůj popisek - jinak stojí u pravého
   okraje a k popisku vlevo se nehlásí. */
.field .time-picker { margin-left: 0; justify-content: flex-start; }

.time-picker input {
    width: 100%;
    text-align: center;
    padding-inline: 6px;
    /* Cislice v jednom sloupci - jinak pole poskakuje podle toho,
       jestli je v nem "03", nebo "11". */
    font-variant-numeric: tabular-nums;
}

.time-picker span { color: var(--text-secondary); }

textarea { min-height: 92px; resize: vertical; font-family: ui-monospace, "Cascadia Code", monospace; font-size: 13px; }

/* :focus-visible, ne :focus.
   Rozdil je v tom, kdy prohlizec povazuje ramecek za uzitecny. Pri :focus
   dostalo modry ramecek i zaskrtavatko, na ktere jsi jen klikl mysi - vis
   prece, kam jsi klikl, takze ramecek nic nerika a jen prekazi. Naopak pri
   pohybu tabulatorem je nutny, jinak clovek netusi, kde je.
   :focus-visible presne tohle rozliseni dela za nas: u textovych poli
   ramecek zustava vzdycky, u zaskrtavatek a prepinacu jen pri klavesnici. */
input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: 2px solid var(--series-1);
    outline-offset: 1px;
    border-color: var(--series-1);
}

/* Zaskrtavatka a prepinace.
 *
 * Kreslime si je sami, protoze systemove vypadaji na kazdem stroji jinak
 * a v tmavem rezimu obvykle jako skvrna. Tvar je kulaty a barva tataz
 * jako u hlavniho tlacitka - zaskrtnuti je rozhodnuti, stejne jako
 * kliknuti na Ulozit, tak ma vypadat stejne.
 *
 * `accent-color` zustava jako zaloha: kdyz prohlizec `appearance: none`
 * neumi (starsi Safari), vykresli aspon sve vlastni v nasi barve.
 */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }

input[type="checkbox"]:not([hidden]), input[type="radio"]:not([hidden]) {
    appearance: none;
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    flex: none;
    margin: 0;
    border: 2px solid var(--border-strong, var(--border));
    border-radius: 50%;          /* kulate i u zaskrtavatka - zamerne */
    background: var(--surface-1);
    cursor: pointer;             /* ruka: je to ovladaci prvek, ne text */
    display: inline-grid;
    place-content: center;
    transition: background 120ms ease, border-color 120ms ease;
}

/* Znacka uvnitr. U zaskrtavatka fajfka, u prepinace tecka - aby se dalo
   na prvni pohled poznat "jedno z", ne "libovolne z". */
input[type="checkbox"]:not([hidden])::before {
    content: "";
    width: 10px;
    height: 10px;
    transform: scale(0);
    transition: transform 120ms ease;
    background: var(--accent-ink);
    clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 18%, 84% 0, 38% 66%);
}
input[type="radio"]:not([hidden])::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    transform: scale(0);
    transition: transform 120ms ease;
    background: var(--accent-ink);
}

input[type="checkbox"]:checked, input[type="radio"]:checked {
    background: linear-gradient(135deg, var(--accent-2), var(--accent));
    border-color: transparent;
}
input[type="checkbox"]:checked::before,
input[type="radio"]:checked::before { transform: scale(1); }

/* Napul zaskrtnute - "Vybrat vse", kdyz je vybrana jen cast. Misto
   fajfky vodorovna carka. Stav nastavuje jen skript (indeterminate),
   do formulare se nijak neposila. */
input[type="checkbox"]:indeterminate {
    background: linear-gradient(135deg, var(--accent-2), var(--accent));
    border-color: transparent;
}
input[type="checkbox"]:not([hidden]):indeterminate::before {
    height: 2px;
    border-radius: 1px;
    clip-path: none;
    transform: scale(1);
}

input[type="checkbox"]:hover:not(:disabled),
input[type="radio"]:hover:not(:disabled) { border-color: var(--accent); }

input[type="checkbox"]:disabled, input[type="radio"]:disabled {
    cursor: not-allowed;
    opacity: .55;
}

/* Popisek k zaskrtavatku je soucast toho ovladaciho prvku - klik na nej
   ho prepne -, takze ma mit tentyz kurzor. Bez toho to vypada, ze se
   trefit musis presne do ctverecku. */
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) { cursor: pointer; }

/* Stejny odstup pod skupinou jako pod .field - at je jedno, jestli za
   ni nasleduje dalsi pole, nebo rada tlacitek. */
.radio-set { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }

/* --- nastaveni databaze: ukaz jen tu cast, ktera plati --------------- */
/* Trida na formulari rika, ktery druh databaze je vybrany. Vykresli ji
   uz server, takze pri nacteni stranky nic neproblikne a bez JavaScriptu
   je videt spravna polovina. Skryta pole se dal odesilaji - diky tomu se
   nastaveni te druhe databaze pri ulozeni nesmaze. */
.db-form.is-sqlite   .db-part[data-for="postgres"] { display: none; }
.db-form.is-postgres .db-part[data-for="sqlite"]   { display: none; }

.radio-card {
    display: flex;
    gap: 11px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    background: var(--surface-1);
}

.radio-card:hover { border-color: var(--axis); }
.radio-card input { margin-top: 3px; }
/* Nazev na vlastni radek. Jako radkovy prvek splyval s popisem do jedne
   souvisle vety ("Pouzivat zasobnik spojeni Drzi par spojeni...") a delsi
   popisky se tim staly necitelne. */
.radio-card .title { display: block; font-weight: 620; font-size: 14px; }
.radio-card .desc {
    display: block;
    margin-top: 3px;
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.5;
}

.btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 15px;
    border-radius: 8px;
    border: 1px solid var(--axis);
    background: var(--surface-1);
    color: var(--text-primary);
    font-family: var(--font);
    font-size: 14px;
    font-weight: 550;
    cursor: pointer;
    text-decoration: none;
}

.btn:hover { background: var(--surface-2); }

/* Hlavni tlacitko nese barvu aplikace, ne prvni barvu serie. Drive to
   byla tataz vec - dnes uz ne: serie identifikuji kategorie v grafu
   a tlacitko s nimi nema co spolecneho. */
.btn.primary {
    background: linear-gradient(135deg, var(--accent-2), var(--accent));
    color: var(--accent-ink);
    font-weight: 600;

    /* Zadny ramecek - schvalne, a stalo to dva pokusy.

       `border-color: transparent` nechavalo prosvitat vypln jeste
       jednou (kresli se az pod ramecek), takze tlacitko melo kolem sebe
       posunuty stin sebe sama. Jednobarevny ramecek to zlepsil, ale na
       malem tlacitku porad drhnul: vypln jde z fialove do modre, kdezto
       obrys mel jednu barvu - v levem rohu tedy nesedel.

       Bez ramecku zadny rozpor nevznikne. Chybejici pixel dorovnava
       odsazeni, takze tlacitko ma stejnou velikost jako ostatni. */
    border: none;
    padding: 9px 16px;
}

.btn.primary:hover { filter: brightness(1.07); }

/* Nevratna akce. Barva je semanticka (--critical), ne dalsi odstin serie -
   stavove barvy se s barvami grafu zamerne nemichaji. */
.btn.danger {
    background: var(--critical);
    border-color: var(--critical);
    color: #fff;
}

.btn.danger:hover { filter: brightness(1.07); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* --------------------------------------------------------------------- */
/* Strankovani                                                            */
/* --------------------------------------------------------------------- */

.pager {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 16px;
    font-size: 13.5px;
    color: var(--text-secondary);
}

/* --------------------------------------------------------------------- */
/* Prihlaseni                                                             */
/* --------------------------------------------------------------------- */

.login-page {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
}

.login-box {
    width: 100%;
    max-width: 340px;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 28px;
}

/* Řádek pod polem s heslem, zarovnaný doprava. */
.forgot-row {
    display: flex;
    justify-content: flex-end;
    margin-top: 8px;
}

/* Tlačítko, které vypadá jako odkaz.
   Musí to být <button>, ne <a>: nikam nevede, jen otevírá okno -
   a čtečka obrazovky to má vědět.
   Proto se z něj musí sundat výchozí vzhled tlačítka (pozadí, rámeček,
   odsazení, vlastní písmo), jinak vypadá jako šedý obdélník. */
.link-button {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    font-size: 13px;
    color: var(--series-1);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
    text-decoration-thickness: 1px;
}

.link-button:hover { color: var(--text-primary); }
.link-button:focus-visible { outline: 2px solid var(--series-1); outline-offset: 3px; border-radius: 3px; }

/* Nadpis skupiny uvnitř dlouhé sekce nastavení.

   Karta s deseti poli za sebou vypadá jako jedno nastavení. Kdo nečte
   všechen text, nepozná, že „Vzhled" a „Čas v grafech" spolu nesouvisí.
   Linka nad nadpisem to rozdělí na díly, které jdou přeletět očima.

   První skupina v kartě linku nemá - nad ní je nadpis karty. */
.skupina {
    margin: 26px 0 14px;
    padding-top: 18px;
    border-top: 1px solid var(--border);
    font-size: 13px;
    font-weight: 700;
    /* Barva aplikace, ne bílá. Nadpis skupiny stojí mezi popiskami polí,
       které jsou taky tučné a světlé - bílý nadpis se v nich ztratí.
       Verzálky a rozpal písmen dělají zbytek: čte se to jako předěl,
       ne jako další položka. */
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.skupina:first-of-type {
    margin-top: 4px;
    padding-top: 0;
    border-top: none;
}

/* Věta pod nadpisem skupiny - co ta skupina vlastně řídí. */
.skupina + .skupina-popis {
    margin: -8px 0 14px;
    color: var(--text-muted);
    font-size: 12.5px;
}

/* --------------------------------------------------------------------- */
/* Vyskakovací okno                                                       */
/* --------------------------------------------------------------------- */

.dialog {
    max-width: 520px;
    width: calc(100% - 32px);
    background: var(--surface-1);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 26px 28px;
    /* Okno kreslí prohlížeč mimo běžný tok stránky, takže barvy musí
       přijít z tokenů znovu - nezdědí je od .login-page. */
}

.dialog::backdrop { background: rgba(0, 0, 0, 0.55); }

.dialog h2 { font-size: 18px; margin: 0 0 12px; }
.dialog p { margin: 0 0 14px; font-size: 14px; color: var(--text-secondary); }

.dialog-label {
    font-size: 11.5px !important;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted) !important;
    margin: 0 0 5px !important;
}

.dialog pre {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 11px 13px;
    margin: 0 0 16px;
    overflow-x: auto;
    font-size: 12.5px;
    line-height: 1.5;
}

.dialog pre code { font-family: ui-monospace, "Cascadia Code", monospace; }

/* Místo, kam se doplní vlastní hodnota - odlišené, ale ne křiklavé. */
.dialog pre em {
    font-style: normal;
    color: var(--series-1);
    font-weight: 600;
}

.dialog code {
    font-family: ui-monospace, "Cascadia Code", monospace;
    font-size: 12.5px;
    background: var(--surface-2);
    padding: 1px 5px;
    border-radius: 4px;
}

.dialog form { margin-top: 4px; }

/* Nabidka nahradni cesty ("Nefunguje import pres API?").

   Musi se odlisit od poznamek kolem. V sede poznamek splyvalo s okolnim
   textem a vypadalo to jako dalsi vysvetlivka - pritom je to jedina
   zachrana pro toho, komu plugin pres API nefunguje. */
details.fallback {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 12px;
    background: var(--surface-2);
}

details.fallback > summary {
    cursor: pointer;
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary);
}

details.fallback > summary:hover { color: var(--series-1); }
details.fallback[open] > summary { margin-bottom: 4px; }

/* --------------------------------------------------------------------- */
/* Prohlizec logu (Nastaveni -> Log)                                      */
/* --------------------------------------------------------------------- */

.log-controls {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.log-controls label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 12px;
    color: var(--text-secondary);
}

.log-controls select { width: auto; }

/* Vlastni posuvnik uvnitr ramecku. Log je ze sve podstaty dlouhy a siroky:
   bez tohohle by rostl do vysky pres celou stranku a dlouhe radky by
   roztahly celou stranku do sirky. */
.log-view {
    margin-top: 14px;
    max-height: 60vh;
    overflow: auto;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 12px;
}

.log-line {
    font-family: ui-monospace, "Cascadia Code", monospace;
    font-size: 12.5px;
    line-height: 1.55;
    /* Radek se nezalamuje - zalomeny cas a uroven by se spatne prohledavaly
       okem. Misto toho se okno posouva do strany. */
    white-space: pre;
    color: var(--text-secondary);
}

/* Barva nese jen zvyrazneni, informaci nese samo slovo ERROR/WARNING
   v textu radku - proto je citelny i pro toho, kdo barvy nerozezna. */
.log-line.error,
.log-line.critical { color: var(--critical); }
.log-line.warning  { color: var(--serious); }
.log-line.info     { color: var(--text-primary); }

.code-block {
    font-family: ui-monospace, "Cascadia Code", monospace;
    font-size: 12.5px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 12px;
    overflow-x: auto;
    margin: 10px 0;
}

/* --------------------------------------------------------------------- */
/* Uzsi obrazovky                                                         */
/* --------------------------------------------------------------------- */

/* Tlačítko menu. Na desktopu není - tam je celý seznam pořád vidět. */
.menu-tlacitko { display: none; }

.menu-carky {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 18px;
}

.menu-carky i {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
}

@media (max-width: 860px) {
    .layout { grid-template-columns: 1fr; }
    .sidebar {
        position: static;
        height: auto;
        /* Menu se rozbaluje pod hlavičku, takže panel musí umět druhý
           řádek - proto `wrap`, ne prostý řádek. */
        flex-flow: row wrap;
        align-items: center;
        gap: 10px;
        overflow-x: visible;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }

    /* Burger.

       Deset položek se na 390px displej nevejde: seznam byl široký
       794 px, takže byly vidět DVĚ a na zbytek se muselo rolovat do
       strany - a že se roluje, nebylo poznat. Teď je pod tlačítkem,
       na kterém stojí, kde člověk zrovna je.

       Zaškrtávátko a štítek, ne JavaScript: menu musí jít otevřít
       i tehdy, když skript neproběhne. */
    .menu-tlacitko {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-left: auto;
        padding: 8px 12px;
        border: 1px solid var(--border);
        border-radius: 10px;
        color: var(--text-primary);
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        user-select: none;
    }

    .menu-prepinac:focus-visible + .menu-tlacitko {
        outline: 2px solid var(--series-1);
        outline-offset: 2px;
    }

    /* Zavřené menu zabírá nulu; otevřené se rozloží přes celou šířku
       pod hlavičku. */
    .nav { display: none; }

    .menu-prepinac:checked ~ .nav {
        display: flex;
        flex-direction: column;
        width: 100%;
        gap: 2px;
        padding-bottom: 6px;
    }

    /* Na řádek se vejde jen jedna položka, takže se nemá kde zalomit. */
    .nav a { white-space: nowrap; padding: 10px 12px; }

    /* Proužek u aktivní položky se na desktopu opírá o hranu postranního
       panelu (`left: -14px`). Tady žádná taková hrana není, takže by
       visel mimo obrazovku - patří k položce samotné. */
    .nav a.active::before { left: 0; border-radius: 3px; }

    /* Patička se schová jen se zavřeným menu. S otevřeným patří pod
       odkazy - je v ní stav sběrače, odhlášení, verze s aktualizací
       a licence. Dřív byla na mobilu schovaná pořád, takže se z telefonu
       nedalo odhlásit ani aktualizovat a verze nebyla nikde vidět. */
    .sidebar-foot { display: none; }
    .menu-prepinac:checked ~ .sidebar-foot {
        display: block;
        width: 100%;
        padding: 12px 12px 6px;
        border-top: 1px solid var(--border);
    }
    .main { padding: 18px 16px 48px; }

    /* Dlaždice po jedné na řádek dělaly ze stránky nekonečné rolování.
       Na 350 px obsahu se při 150px vejdou dvě. */
    .kpi-row {
        grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
        gap: 10px;
    }

    /* Nadpis karty a poznámka vedle sebe se na úzké obrazovce lámaly
       oba naráz - z „How to send" byly dva řádky a poznámka se do nich
       zaklínila. Pod sebou se to čte jako nadpis a podtitul. */
    .card-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
    }

    /* Popisky os v grafu.

       SVG má pevný viewBox 760 jednotek a roztahuje se na šířku, takže
       se s ním zmenšuje i text: na 390px displeji vycházel popisek
       z 11 jednotek na 4,6 SKUTEČNÝCH pixelů, což se přečíst nedá.
       V jednotkách viewBoxu je proto na úzké obrazovce větší - měřítko
       je tam kolem 0,42, takže 22 jednotek vyjde na čitelných 9 px.

       Víc už ne: popisek se kreslí doleva od osy a musí se vejít do
       levého okraje grafu (viz margin_left v charts.py). */
    .axis-label { font-size: 22px; }
}

@media print {
    .sidebar, .filters, .btn-row { display: none; }
    .card { break-inside: avoid; }
}

/* ---------------------------------------------------------------------
   Ukazatel prubehu bezici ulohy
   --------------------------------------------------------------------- */
.task-progress { margin-top: 12px; }

.task-progress-bar {
    height: 8px;
    border-radius: 999px;
    background: var(--surface-2);
    overflow: hidden;
}

.task-progress-bar i {
    display: block;
    height: 100%;
    background: var(--series-1);
    /* Prechod na novou sirku, at pruh neposkakuje po davkach. */
    transition: width 0.4s ease;
}

/* Kdyz celkovy pocet nezname, pruh nic nemeri - proto pruhovany
   a bez tvrzeni o procentech. */
.task-progress-bar i.neurcity {
    background: repeating-linear-gradient(
        45deg, var(--series-1), var(--series-1) 10px,
        var(--surface-2) 10px, var(--surface-2) 20px);
    opacity: 0.7;
}

.task-progress-note {
    margin-top: 6px;
    font-size: 12.5px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
   Barvy, ktere neoznacuji stav, ale identitu
   ---------------------------------------------------------------------
   Stavove barvy (good/warning/serious/critical) jsou vyhrazene pro stav
   a nesmi se pouzit na neco jineho - jinak by zelena chvili znamenala
   "v poradku" a chvili "role spravce". Tyhle znacky proto berou barvu
   ze serie, ne ze stavu. Text u nich zustava vzdycky. */
.badge.role     .dot { background: var(--series-7); }   /* spravce      */
.badge.jellyfin .dot { background: var(--series-1); }   /* data z API   */
.badge.ffprobe  .dot { background: var(--series-3); }   /* data ze souboru */
.badge.chosen   .dot { background: var(--series-4); }   /* vychozi stopa */

/* ---------------------------------------------------------------------
   Kolacovy graf (prstenec)
   --------------------------------------------------------------------- */
.donut-wrap {
    display: flex;
    align-items: center;
    gap: 22px;
    flex-wrap: wrap;
}

.donut { flex: none; transform: rotate(-90deg); }   /* zacatek nahore, ne vpravo */

.donut-seg {
    fill: none;
    stroke-width: 26;
    /* Uzka mezera mezi dily - jinak dva sousedni odstiny splynou v jeden. */
    stroke-linecap: butt;
    transition: opacity 0.15s ease;
}
.donut-seg:hover { opacity: 0.82; cursor: default; }

/* Text uprostred se otaci zpatky - cely obrazek je otoceny o -90 stupnu. */
.donut-total, .donut-unit {
    transform: rotate(90deg);
    transform-origin: center;
    font-variant-numeric: tabular-nums;
}
.donut-total { fill: var(--text-primary); font-size: 20px; font-weight: 700; }
.donut-unit  { fill: var(--text-muted);   font-size: 11px; }

.donut-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 1 1 190px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.donut-legend li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
}

.donut-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.donut-value {
    flex: none;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Počet dílů na plakátu seriálu. Vlevo nahoře, aby se nepral
   s velikostí souboru vpravo dole. */
.media-badge {
    position: absolute;
    top: 6px;
    left: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    background: rgba(0, 0, 0, 0.62);
    color: #fff;
    font-variant-numeric: tabular-nums;
}

/* Vlastni vyber souboru. Nativni `type="file"` si prohlizec kresli sam
   vcetne popisku ("Vybrat soubor", "Soubor nevybran") a rídi se pritom
   svym jazykem, ne nastavenim aplikace. Skryjeme ho tedy do <label>
   a vedle nakreslime vlastni tlacitko - klik na label pole otevre. */
.file-picker {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}

/* `display: none` by pole vyradilo z ovladani klavesnici. Takhle je
   dostupne, jen neni videt - a ramecek pri tabulatoru dostane tlacitko. */
.file-picker input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.file-picker input[type="file"]:focus-visible + .btn {
    outline: 2px solid var(--series-1);
    outline-offset: 1px;
}

.file-picker .file-name { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------------------------------------------------- */
/* Hlaska o vysledku akce                                                 */
/* --------------------------------------------------------------------- */

/* Drzi se u horni hrany okna, ne v toku stranky. Vetsina akci se spousti
   tlacitkem dole (uklid historie, import, zalohy) a po presmerovani se
   stranka vraci tam, kde clovek byl - hlaska v toku by mu utekla nahoru
   a nikdo by se nedozvedel, jak to dopadlo. */
.flash-toast {
    position: fixed;
    top: 14px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    width: min(720px, calc(100vw - 28px));
    animation: flash-prichod 0.18s ease-out;
}

.flash-toast .flash {
    margin: 0;
    align-items: center;
    /* Vlastni podklad a stin: prekryva obsah stranky, takze nesmi byt
       ani z casti pruhledna. */
    background: var(--surface-1);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
}

.flash-toast.odchazi { opacity: 0; transition: opacity 0.55s ease; }

.flash-close {
    margin-left: auto;
    border: 0;
    background: none;
    color: var(--text-muted);
    font-size: 20px;
    line-height: 1;
    padding: 0 2px;
    cursor: pointer;
}

.flash-close:hover { color: var(--text-primary); }

@keyframes flash-prichod {
    from { opacity: 0; transform: translate(-50%, -8px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Kdo si vypnul animace, dostane hlasku rovnou. */
@media (prefers-reduced-motion: reduce) {
    .flash-toast { animation: none; }
    .flash-toast.odchazi { transition: none; }
}


/* ---------------------------------------------------------------------------
   Okna (<dialog>)

   Nativní okno prohlížeče: umí Esc, zaostření i ztmavené pozadí samo od
   sebe. Stylujeme jen to, co má vypadat jako zbytek aplikace - vzhled si
   bere od karty, protože je to tentýž obsah, jen vytažený dopředu.
   --------------------------------------------------------------------------- */
.okno {
    width: min(520px, calc(100vw - 32px));
    /* Prohlížeč dává <dialog> ve výchozím stylu `overflow: auto`, takže
       cokoliv, co přeteče (našeptávač kalendáře), ořízne. Dlouhý obsah
       si posuv řeší sám uvnitř `.okno-obsah`, tady ho nepotřebujeme. */
    overflow: visible;
    padding: 22px 24px 24px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface-1);
    color: var(--text);
    box-shadow: 0 24px 60px rgb(0 0 0 / 45%);
}

/* Bez tohohle je pozadí za oknem jen lehce šedé a stránka pod ním pořád
   přetahuje pozornost. */
.okno::backdrop {
    background: rgb(0 0 0 / 55%);
}

.okno-hlava {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.okno-hlava h2 {
    margin: 0;
    font-size: 18px;
}

/* Křížek. Je to <button> ve formuláři s method="dialog", takže okno
   zavře i bez JavaScriptu. */
.okno-zavrit {
    padding: 2px 10px;
    font-size: 20px;
    line-height: 1.2;
}

.okno .field:last-of-type {
    margin-bottom: 18px;
}


/* Mapa a její ovládání.

   Tlačítka leží NAD mapou (position: absolute), ne pod ní: kdo se
   přiblížil a chce zpátky, nemá koukat, kam mu tlačítko odskočilo. */
.mapa-obal { position: relative; }

.mapa-ovladani {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mapa-tlacitko {
    width: 30px;
    height: 30px;
    padding: 0;
    display: grid;
    place-items: center;
    font-size: 16px;
    line-height: 1;
    /* Poloprůhledné pozadí: tlačítko musí být čitelné nad pevninou
       i nad oceánem, a přitom pod ním má být vidět, co zakrývá. */
    background: color-mix(in oklab, var(--surface-1) 82%, transparent);
    backdrop-filter: blur(3px);
}

.mapa-napoveda { margin: 8px 0 0; }
.chart-napoveda { margin: 8px 0 0; }

/* Mapa světa na stránce Síť. Poměr stran drží viewBox (360:180), takže
   se sama přizpůsobí šířce karty a nikdy se nedeformuje. */
.mapa {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 10px;
    border: 1px solid var(--border);
}

/* Kurzor napoví, že se s mapou dá hýbat. */
.mapa { cursor: grab; touch-action: none; }
.mapa:active { cursor: grabbing; }
.mapa.je-priblizena { cursor: grabbing; }

.mapa-bod { transition: opacity 120ms ease; }
.mapa-bod:hover { opacity: 0.8; }


/* Našeptávač k psanému datu.

   Kreslí se do rodiče pole, ne do <body>: okno (<dialog>) je v horní
   vrstvě a cokoliv připnutého k body by se pod ním schovalo. */
.kalendar {
    position: absolute;
    z-index: 30;
    top: calc(100% + 6px);
    left: 0;
    width: 268px;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 10px 34px rgba(0, 0, 0, 0.32);
    padding: 10px;
}

.kalendar-hlava {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.kalendar-mesic {
    font-size: 13.5px;
    font-weight: 600;
    text-transform: capitalize;
}

.kalendar-sipka {
    font: inherit;
    font-size: 17px;
    line-height: 1;
    color: var(--text-secondary);
    background: none;
    border: 0;
    border-radius: 7px;
    width: 28px;
    height: 28px;
    cursor: pointer;
}
.kalendar-sipka:hover { background: var(--surface-2); color: var(--text-primary); }

.kalendar-mrizka {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}

.kalendar-den-tydne {
    font-size: 10.5px;
    color: var(--text-muted);
    text-align: center;
    padding-bottom: 4px;
    text-transform: lowercase;
}

.kalendar-den {
    font: inherit;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
    background: none;
    border: 0;
    border-radius: 7px;
    height: 30px;
    cursor: pointer;
}
.kalendar-den:hover:not(:disabled) { background: var(--surface-2); }
.kalendar-den:disabled { color: var(--text-muted); opacity: 0.45; cursor: default; }
/* Dnešek je orámovaný, vybraný den vyplněný - dvě různé informace,
   které se můžou potkat na jednom dni. */
.kalendar-den.dnes { box-shadow: inset 0 0 0 1px var(--axis); }
.kalendar-den.vybrany {
    background: var(--series-1);
    color: #fff;
    font-weight: 600;
}

/* Okno s vlastním obdobím. Dvě pole vedle sebe, pod nimi rychlé volby. */
/* Číslo a jeho jednotka vedle sebe (kapacita úložiště).

   Vlastní třída, ne půjčená `.obdobi-pole`: ta se na úzkém displeji
   skládá pod sebe, což u dvojice „3 | TB" nedává smysl - jednotka
   patří k číslu i na mobilu. */
.pole-s-jednotkou {
    /* Pole a k nemu jedno az dve tlacitka (nebo jednotka). Flex, ne
       mrizka o dvou sloupcich: do te se treti prvek nevesel a spadl na
       vlastni radek pres celou sirku, takze tlacitko Obnovit vypadalo
       jako hlavni akce karty - cimz rozhodne neni. */
    display: flex;
    gap: 10px;
    align-items: center;
}
/* Roste jen pole vlevo; jednotka i tlacitka si drzi svou sirku. */
.pole-s-jednotkou > :first-child { flex: 1 1 auto; min-width: 0; }
.pole-s-jednotkou > :not(:first-child) { flex: 0 0 auto; width: auto; }
.pole-s-jednotkou input { width: 100%; }
.pole-s-jednotkou > .btn { white-space: nowrap; }

.obdobi-pole {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}
.obdobi-pole input { width: 100%; }
.obdobi-rychle { margin-top: 12px; flex-wrap: wrap; }

/* Na mobilu jsou pole „Od" a „Do" pod sebou a kalendář se vejde.

   Vedle sebe kotví kalendář u levé hrany DRUHÉHO pole, takže na 390px
   displeji sahal od 202 do 470 - osmdesát pixelů mimo obrazovku a nešel
   dopsat. `min(268px, 100%)` k tomu drží šířku i na úzkých displejích,
   kde je samo okno užší než těch 268. */
@media (max-width: 560px) {
    .obdobi-pole { grid-template-columns: minmax(0, 1fr); }
    .kalendar { width: min(268px, 100%); }
}

/* Hláška ukázky. Vyjede zdola uprostřed, počká pár vteřin a zmizí -
   stránka se přitom nikam nehne, což je celý smysl: člověk zůstane tam,
   kde byl, i s tím, co měl rozepsané. */
.hlaska-na-miste {
    position: fixed;
    left: 50%;
    bottom: 26px;
    transform: translate(-50%, 12px);
    z-index: 60;
    max-width: min(520px, calc(100vw - 32px));
    background: var(--surface-2);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-left: 3px solid var(--series-1);
    border-radius: 10px;
    padding: 12px 16px;
    font-size: 13.5px;
    line-height: 1.45;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.32);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.16s ease, transform 0.16s ease;
}

.hlaska-na-miste.vidi {
    opacity: 1;
    transform: translate(-50%, 0);
}

@media (prefers-reduced-motion: reduce) {
    .hlaska-na-miste { transition: opacity 0.16s ease; transform: translate(-50%, 0); }
}

/* Nová verze. Dřív to byl drobný odznáček vedle čísla verze a splýval
   s ním - přitom je to jediná věc v patičce, kvůli které tam má člověk
   kouknout. Teď je to tlačítko přes celou šířku panelu, které otevře
   okno s popisem změn. */
.verze-nova {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    text-align: left;
    font: inherit;
    font-size: 12.5px;
    line-height: 1.35;
    color: var(--text-primary);
    background: color-mix(in oklab, var(--warning) 16%, var(--surface-1));
    border: 1px solid color-mix(in oklab, var(--warning) 45%, transparent);
    border-radius: 9px;
    padding: 8px 10px;
    cursor: pointer;
}

/* Nové překlady: totéž tlačítko, jen klidnější. Nová verze je varovná
   oranžová, protože se má něco stát; překlady jen říkají, že se dá mít
   víc jazyků - nic se nerozbilo a nic nehoří. */
.verze-nova.verze-preklady {
    background: color-mix(in oklab, var(--series-1) 12%, var(--surface-1));
    border-color: color-mix(in oklab, var(--series-1) 40%, transparent);
}
.verze-nova.verze-preklady .dot { background: var(--series-1); animation: none; }

.verze-nova:hover {
    background: color-mix(in oklab, var(--warning) 26%, var(--surface-1));
}

.verze-nova .dot {
    background: var(--warning);
    flex: none;
    /* Tepe, aby si toho oko všimlo i koutkem. Kdo má animace vypnuté
       v systému, dostane klidnou tečku - viz media dotaz níž. */
    animation: tep 2.2s ease-in-out infinite;
}

.verze-nova-note { color: var(--text-secondary); }

@keyframes tep {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .verze-nova .dot { animation: none; }
}

/* Popis změn v okně. Skládá ho updates.poznamky_html() z markdownu,
   takže tady stačí dát rozumné rozestupy pár značkám. */
.poznamky h4 {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    margin: 16px 0 6px;
}
.poznamky h4:first-child { margin-top: 0; }
.poznamky ul { margin: 0 0 10px 18px; padding: 0; }
.poznamky li { margin-bottom: 6px; font-size: 13.5px; line-height: 1.5; }
.poznamky p  { font-size: 13.5px; line-height: 1.5; margin: 0 0 10px; }
.poznamky code {
    font-size: 12.5px;
    background: var(--surface-2);
    padding: 1px 5px;
    border-radius: 5px;
}

/* Verze v patičce postranního panelu. Drobným písmem: je to údaj, který
   je potřeba jednou za čas, ne něco, co má tahat pozornost. */
.verze {
    margin-top: 12px;
    font-size: 12px;
    color: var(--text-muted);
}

.verze a { text-decoration: none; }


/* Filtr v historii. Mřížka, ne řádek: polí je osm a na užší obrazovce
   se musí zalomit sama, jinak by z nich byl vodorovný posuvník. */
.filtr {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: 12px;
    align-items: end;
    margin-bottom: 16px;
}

.filtr-pole { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.filtr-pole label {
    font-size: 12px;
    color: var(--text-muted);
}

.filtr-pole select,
.filtr-pole input { width: 100%; }

/* Hledání názvu je to nejširší pole - ať má prostor na dvě kolonky. */
.filtr-hledani { grid-column: span 2; }

.filtr-tlacitka {
    display: flex;
    gap: 8px;
    grid-column: 1 / -1;
}


/* Okno s filtrem je širší než ostatní: je v něm mřížka o osmi polích,
   a při šířce běžného okna by z ní byl jeden dlouhý sloupec. */
.okno-siroke { width: min(760px, calc(100vw - 32px)); }


/* Obsah okna, který může být dlouhý (streamy, lidé). Roluje se uvnitř
   okna, ne celou stránkou - jinak by okno vyrostlo přes obrazovku a jeho
   hlavička s křížkem by utekla nahoru. */
.okno-obsah {
    max-height: 70vh;
    overflow-y: auto;
    /* Místo na posuvník, ať text neposkakuje při filtrování. */
    padding-right: 4px;
}

.okno-obsah .session { break-inside: avoid; }


/* Atribut `hidden` znamená "tohle není vidět" - jenže prohlížeč ho řeší
   pravidlem [hidden] { display: none }, které přebije každé konkrétnější
   `display`. A .session má display:flex, takže filtr v okně řádky sice
   označil za skryté, a ony zůstaly na obrazovce.

   Tohle je přesně ten případ, kdy je !important na místě: `hidden` není
   styl, ale stav. */
[hidden] { display: none !important; }


/* Tlačítko "zobrazit všechna" stojí na místě, kde by jinak byl první
   stream - proto je vysoké jako dlaždice streamu, ne jako běžné
   tlačítko. Karta si tím drží svou výšku bez ohledu na to, kolik se
   zrovna hraje. */
/* "Skryto, protoze jich je hodne" neni hlavni akce stranky - je to
   vysvetleni, proc tu neco neni, a nabidka to ukazat. Plna barevna plocha
   pres celou sirku z toho delala nejvyraznejsi prvek na strance, ac je to
   zastupce obsahu, ktery se sem nevesel.

   Proto tlumene: podklad karty, prerusovany obrys (naznacuje "tady neco
   chybi") a barva jen na druhem radku, kde je vyzva ke kliknuti. */
/* Vedome BEZ tridy `primary` v sablone: hlavni akce stranky to neni.
   Drive ji melo a bylo to nejvyraznejsi tlacitko na cele strance. */
.session-vice {
    width: 100%;
    justify-content: center;
    padding: 22px 16px;
    font-size: 15px;
    border-radius: var(--radius);
    /* Tentyz prechod jako karta prehravani - tlacitko stoji presne tam,
       kde by karty byly, takze ma vypadat jako jejich ozvena. Slabsi,
       protoze zastupuje obsah, ktery tu neni; prerusovany obrys to
       dopovi. Ploche pozadi bylo naopak neviditelne: splynulo s kartou
       pod sebou a vypadalo jako prazdne misto. */
    background:
        radial-gradient(75% 190% at 0% 0%,
                        color-mix(in oklab, var(--accent-2) 26%, transparent),
                        transparent 58%),
        radial-gradient(60% 150% at 100% 100%,
                        color-mix(in oklab, var(--accent) 16%, transparent),
                        transparent 62%),
        var(--surface-1);
    border: 1px solid color-mix(in oklab, var(--accent) 45%, var(--border));
    color: var(--text-secondary);
    font-weight: 500;
}

.session-vice strong { color: var(--text-primary); font-weight: 600; }

.session-vice:hover {
    border-color: var(--accent);
    filter: brightness(1.12);
}

.session-vice .session-vice-note { color: var(--accent); font-weight: 600; }


/* Druhý řádek v tlačítku "skryto kvůli počtu": je to doplněk k důvodu,
   ne samostatná informace, takže drobněji a méně výrazně. */
.session-vice-note {
    font-size: 13px;
    opacity: 0.85;
    font-weight: 400;
}


/* =====================================================================
   KLASICKY VZHLED

   Puvodni podoba aplikace, prepinatelna v Nastaveni -> Rozhrani.
   Vsechno nize plati jen pri `<html data-skin="klasicky">`.

   Neni to jen jina paleta. Novy vzhled zmenil i tvary: karta prehravani
   ma barevny nadech, odznaky stavu maji vypln misto tecky, hlavni cislo
   stoji vedle krivky. Klasicky vzhled je vraci - proto je tahle sekce
   delsi nez seznam barev.

   Grafy se prebarvi samy: kresli se pres promenne (--accent, --series-*,
   --good...), takze staci prepsat je a Python se nemeni.
   ===================================================================== */

:root[data-skin="klasicky"] {
    --page:            #f9f9f7;
    --surface-1:       #fcfcfb;
    --surface-2:       #f2f1ed;
    --text-primary:    #0b0b0b;
    --text-secondary:  #52514e;
    --text-muted:      #898781;
    --border:          rgba(11, 11, 11, 0.10);
    --grid:            #e1e0d9;
    --axis:            #c3c2b7;

    --series-1: #2a78d6;
    --series-2: #eb6834;
    --series-3: #1baf7a;
    --series-4: #eda100;
    --series-5: #e87ba4;
    --series-6: #008300;
    --series-7: #4a3aa7;
    --series-8: #e34948;

    --good:     #0ca30c;
    --warning:  #fab219;
    --serious:  #ec835a;
    --critical: #d03b3b;

    /* Barva aplikace byla drive tataz jako prvni barva serie - a obe
       strany prechodu stejne, takze z prechodu zbude plna barva. */
    --accent:     var(--series-1);
    --accent-2:   var(--series-1);
    --accent-ink: #ffffff;
    --rail:       var(--surface-1);

    --linka-1: var(--series-1);
    --linka-2: var(--series-2);
    --linka-3: var(--series-3);

    --radius: 10px;
}

@media (prefers-color-scheme: dark) {
    :root[data-skin="klasicky"]:not([data-theme="light"]) {
        --page:           #0d0d0d;
        --surface-1:      #1a1a19;
        --surface-2:      #232322;
        --text-primary:   #ffffff;
        --text-secondary: #c3c2b7;
        --text-muted:     #898781;
        --border:         rgba(255, 255, 255, 0.10);
        --grid:           #2c2c2a;
        --axis:           #383835;

        --series-1: #3987e5;
        --series-2: #d95926;
        --series-3: #199e70;
        --series-4: #c98500;
        --series-5: #d55181;
        --series-6: #008300;
        --series-7: #9085e9;
        --series-8: #e66767;
    }
}

:root[data-skin="klasicky"][data-theme="dark"] {
    --page:           #0d0d0d;
    --surface-1:      #1a1a19;
    --surface-2:      #232322;
    --text-primary:   #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted:     #898781;
    --border:         rgba(255, 255, 255, 0.10);
    --grid:           #2c2c2a;
    --axis:           #383835;

    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --series-4: #c98500;
    --series-5: #d55181;
    --series-6: #008300;
    --series-7: #9085e9;
    --series-8: #e66767;
}

/* --- tvary, ktere novy vzhled zmenil ------------------------------- */

/* Vybrana polozka menu mela obarvenou plochu, ne prouzek u kraje. */
[data-skin="klasicky"] .nav a.active::before { display: none; }

/* Vybrany chip mel prohozene barvy pisma a podkladu. */
[data-skin="klasicky"] .chip.active,
[data-skin="klasicky"] .chip.active:hover {
    background: var(--text-primary);
    color: var(--page);
    border-color: var(--text-primary);
    font-weight: 550;
}

/* Popisek dlazdice byl bezny text, ne verzalky. */
[data-skin="klasicky"] .tile-label {
    font-size: 12.5px;
    letter-spacing: 0;
    text-transform: none;
    font-weight: 400;
    color: var(--text-secondary);
}

/* Karta prehravani a plakaty byly ploche. */
[data-skin="klasicky"] .session { background: var(--surface-1); }
[data-skin="klasicky"] .session-poster,
[data-skin="klasicky"] .poster-frame {
    background: var(--surface-2);
    box-shadow: none;
}
[data-skin="klasicky"] .session-bar i { background: var(--series-1); }
[data-skin="klasicky"] .session-bitrate { color: var(--text-primary); }

/* Odznaky mely tecku a sedou pilulku, at uz sly o stav nebo o fakt. */
[data-skin="klasicky"] .session-tags .badge {
    border-color: var(--border);
    background: var(--surface-2);
    color: var(--text-secondary);
    font-weight: 600;
    padding: 2px 8px;
    gap: 5px;
}
[data-skin="klasicky"] .session-tags .badge .dot { display: block; }

[data-skin="klasicky"] .delta { font-weight: 500; }

/* Sloupce byly vyssi a bez zare pod bodem na krivce. */
[data-skin="klasicky"] .hbar-track { height: 15px; }
[data-skin="klasicky"] .sparkline .chart-hit circle,
[data-skin="klasicky"] .chart .chart-hit circle { filter: none; }

/* Tlacitko "je jich hodne" bylo plne barevne. */
[data-skin="klasicky"] .session-vice {
    background: var(--series-1);
    border: 1px solid var(--series-1);
    color: #fff;
}
[data-skin="klasicky"] .session-vice strong { color: #fff; }
[data-skin="klasicky"] .session-vice .session-vice-note { color: rgb(255 255 255 / 82%); }

/* Hlavni tlacitko melo obrys a plnou barvu. */
[data-skin="klasicky"] .btn.primary {
    background: var(--series-1);
    border: 1px solid var(--series-1);
    padding: 8px 15px;
    font-weight: 550;
}

/* ------------------------------------------------------------------ */
/* Vlastní přehled                                                     */
/* ------------------------------------------------------------------ */
.dash-ovladani {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
}

/* Šest sloupců, aby vyšly třetiny i půlky. Pod 900 px jde všechno pod
   sebe: z grafu v třetině úzké obrazovky by byl proužek. */
.dash-plocha { display: flex; flex-direction: column; gap: 18px; }

/* Rozestup dělá výhradně `gap`, stejně jako u `.grid-2` na ostatních
   stránkách. Karta uvnitř sekce si ale nese vlastní spodní okraj 18 px,
   takže bez tohohle byla mezera dvojnásobná proti Jazykům nebo Síti. */
.dash-sekce > *:last-child { margin-bottom: 0; }

@media (min-width: 900px) {
    .dash-plocha {
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        gap: 18px;
        align-items: start;
    }
    .dash-sekce.dash-tretina { grid-column: span 2; }
    .dash-sekce.dash-pul     { grid-column: span 3; }
    .dash-sekce.dash-cela    { grid-column: span 6; }
}

.dash-vyzva { text-align: center; padding: 28px 20px; }

/* --- okno s rozvržením --------------------------------------------- */
/* Skládá se tady, ne přetahováním skutečných panelů: panel s grafem je
   vysoký přes půl obrazovky, takže při jeho tažení nebylo vidět, kam
   míří. Na mřížce dlaždic je celé rozvržení naráz.

   Okno má strop výšky a uvnitř se dělí na hlavu, dva posuvné sloupce
   a patu. Bez toho rostlo s počtem dlaždic, až nabídka i tlačítka
   skončily pod spodním okrajem obrazovky - a nedalo se k nim dostat. */
.okno-rozvrzeni {
    width: min(1040px, calc(100vw - 40px));
    max-height: min(88vh, 900px);
    /* Sloupce si posuv řeší samy; okno nic neořezává. */
    overflow: hidden;
}

/* `display` patří výhradně na otevřené okno. Zavřený <dialog> skrývá
   prohlížeč vlastním `display: none` - a obyčejné `display: flex` mu to
   přebije, takže okno zůstane viset na stránce i po zavření. Přesně to
   se stalo: křížek okno zavřel, ale nebylo to vidět. */
.okno-rozvrzeni[open] {
    display: flex;
    flex-direction: column;
}

.okno-sloupce {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 18px;
    /* `min-height: 0` je nutnost, ne kosmetika: bez něj se posuvný
       potomek v gridu roztáhne podle obsahu a přeteče okno. */
    min-height: 0;
    flex: 1;
}

.dash-sloupec {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.dash-sloupec > .card-note { margin-bottom: 8px; }

/* Nabídka je vpravo, ne pod mřížkou - jinak se s přibývajícími sekcemi
   odsouvá dolů a zmizí pod okrajem. */
@media (max-width: 860px) {
    .okno-sloupce { grid-template-columns: minmax(0, 1fr); }
    .dash-sloupec-nabidka { max-height: 240px; }
}

.dash-mrizka {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 8px;
    padding: 10px;
    min-height: 92px;
    /* Posouvá se jen mřížka, ne celé okno. */
    overflow-y: auto;
    flex: 1;
    border-radius: 12px;
    background: var(--surface-2);
    border: 1px solid var(--rail);
    position: relative;      /* kvůli proužku, kam dlaždice spadne */
}
.dash-mrizka.dash-prazdno::before {
    content: attr(data-prazdno);
    color: var(--text-muted);
    font-size: 13px;
    grid-column: 1 / -1;
    text-align: center;
    padding: 22px 0;
}

.dash-dlazdice {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 54px;
    padding: 8px 8px 8px 12px;
    border-radius: 10px;
    background: var(--surface-1);
    border: 1px solid var(--rail);
    cursor: grab;
    user-select: none;
}
.dash-mrizka.dash-tahne .dash-dlazdice { cursor: grabbing; }
.dash-dlazdice.dash-tretina { grid-column: span 2; }
.dash-dlazdice.dash-pul     { grid-column: span 3; }
.dash-dlazdice.dash-cela    { grid-column: span 6; }
.dash-tazena { opacity: 0.35; }

.dash-dl-nazev { font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.dash-dl-nastroje { display: flex; gap: 5px; flex: none; }
.dash-dl-nastroje .btn { padding: 2px 8px; font-size: 12px; cursor: pointer; }
.dash-sirka { min-width: 30px; font-variant-numeric: tabular-nums; }

/* Kam dlaždice spadne. Kreslí se absolutně, takže se rozmístění kvůli
   němu nemění - a rozhodnutí "kam to patří" se nemá o co překlápět. */
.dash-cil {
    position: absolute;
    width: 3px;
    border-radius: 2px;
    background: var(--accent);
    box-shadow: 0 0 10px color-mix(in oklab, var(--accent) 70%, transparent);
    pointer-events: none;
    z-index: 5;
}

.dash-nabidka-seznam {
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
    flex: 1;
    padding-right: 4px;
}
.dash-polozka {
    display: flex;
    flex-direction: column;
    gap: 3px;
    text-align: left;
    padding: 9px 11px;
    border-radius: 10px;
    border: 1px solid var(--rail);
    background: var(--surface-2);
    color: inherit;
    cursor: pointer;
    font: inherit;
}
.dash-polozka:hover:not(:disabled) { border-color: var(--accent); }
.dash-polozka:disabled { opacity: 0.4; cursor: default; }
.dash-polozka-nazev { font-weight: 600; font-size: 12.5px; }
.dash-polozka-popis { font-size: 11.5px; color: var(--text-muted); }

/* Pata drží tlačítka na místě, ať je v mřížce cokoliv. */
.okno-pata {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin: 16px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--rail);
    flex: none;
}


/* --------------------------------------------------------------------- */
/* Co platí jen pro širokou obrazovku a co jen pro úzkou                  */
/* --------------------------------------------------------------------- */
/*
   Server neví, na čem se člověk dívá, takže pošle obojí a vybere CSS.
   Streamů se na mobil vejde míň: karta tam zabírá celou šířku a čtyři
   pod sebou znamenají, že zbytek stránky je mimo obrazovku.

   Stojí to na konci schválně. Jsou to pomocné třídy, které musí přebít
   `display` z třídy prvku (`.btn-row` má `display: flex`) - a při stejné
   specificitě vyhrává to, co je v souboru níž.
*/
.verze-licence {
    margin-top: 4px;
    font-size: 11.5px;
}

.verze-licence a { color: var(--text-muted); text-decoration: none; }
.verze-licence a:hover { text-decoration: underline; }

.jen-mobil { display: none; }

@media (max-width: 860px) {
    .jen-desktop { display: none; }
    .jen-mobil { display: flex; }
}

/* Seznam zapomenutých diváků v kartě Odklízení historie. Není to
   přehledová tabulka, ale dvojice "kdo" a "co se s tím dá dělat", tak
   nemá hlavičku ani linky - jen dost místa, aby tlačítko nelepilo
   na jméno. */
table.zapomenuti { width: 100%; border-collapse: collapse; margin-top: 6px; }
table.zapomenuti td { padding: 6px 0; vertical-align: top; border: 0; }
table.zapomenuti td:last-child { text-align: left; }
table.zapomenuti td.akce { text-align: right; white-space: nowrap; width: 1%; }
table.zapomenuti .hint { display: block; margin: 2px 0 0; }
table.zapomenuti form { display: inline; }

/* Zaškrtávátko s popiskem pod ním. Dosud se to psalo inline u každého
   pole zvlášť; se stromem oblastí v Nastavení jich je najednou devět,
   takže má smysl to pojmenovat. */
.prepinac {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    cursor: pointer;
    margin-bottom: 10px;
}
.prepinac input { margin-top: 3px; flex: none; }
.prepinac .hint { display: block; margin: 2px 0 0; }

/* Strom oblastí: svislá linka drží pohromadě to, co spolu souvisí,
   a odsazení říká „platí jen s tím nad sebou". */
.strom { border-left: 2px solid var(--border); padding-left: 14px; margin-top: 10px; }
.prepinac.strom-pod { margin-left: 24px; }
/* Strom práv jednoho účtu, dokud platí skupina: je vidět, co pro účet
   platí, ale je jasné, že se to tady nemění. */
.prava-strom.zamceno { opacity: .55; }
.prava-strom.zamceno .prepinac { cursor: default; }

/* Oddělovač mezi dvěma způsoby přihlášení. Čára s „nebo" uprostřed říká
   „dvě cesty, ne dva kroky" - dvě tlačítka pod sebou bez ní vypadají
   jako postup. */
.login-nebo {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 14px 0;
    color: var(--text-muted);
    font-size: 12.5px;
}
.login-nebo::before, .login-nebo::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

/* Kód pro Quick Connect. Čte se z obrazovky a přepisuje do jiné
   aplikace, takže velký, jednoznačný a s mezerami mezi znaky - aby se
   nepletla nula s písmenem O. */
.quick-kod {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 34px;
    font-weight: 600;
    letter-spacing: 6px;
    text-align: center;
    padding: 16px 10px;
    margin: 6px 0 10px;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    background: var(--surface-1);
    color: var(--text-primary);
}

/* Výběr cílového titulu - přiřazení historie z archivu k živému titulu.
   Výsledky jsou pod polem v toku stránky, ne vyskakovací vrstva: v okně
   (<dialog>) s posuvníkem by se plovoucí nabídka ořízla. */
.vyber-cile input[type="search"] { width: 100%; }
.vyber-cile-nalezy {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-1);
}
.vyber-cile-nalezy li + li { border-top: 1px solid var(--border); }
.vyber-cile-nalezy button {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 8px 12px;
    border: 0;
    background: none;
    color: var(--text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.vyber-cile-nalezy button:hover,
.vyber-cile-nalezy button:focus-visible { background: var(--surface-2); }
.vyber-cile-nalezy small { color: var(--text-muted); font-size: 12px; }
.vyber-cile-nalezy .prazdno { padding: 8px 12px; color: var(--text-muted); }
.vyber-cile-vybrano {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 6px 6px 12px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
}
.vyber-cile-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.vyber-cile-text small { color: var(--text-muted); font-size: 12px; font-weight: 400; overflow-wrap: anywhere; }

/* Malý plakát vedle názvu v nabídkách přiřazení. Pevný rozměr a šedé
   pozadí: když obrázek chybí, políčko zůstane a řádky se nerozjedou. */
.plakatek {
    flex: none;
    width: 34px;
    height: 51px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--surface-2);
}
.plakatek img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Hromadné přiřazení: řádek = archivovaná položka a vedle výběr cíle. */
.prirazeni-radky { display: grid; gap: 14px; }
.prirazeni-radek {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    gap: 12px;
    align-items: start;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border);
}
@media (max-width: 700px) {
    .prirazeni-radek { grid-template-columns: 1fr; }
}

/* Okna archivu (přiřazení, mazání) mají dva kroky v jednom formuláři:
   výběr a potvrzení. Formulář i viditelný krok se natahují na výšku okna,
   aby posouval jen seznam a patička s tlačítky zůstala dole. `display` jen
   na krok bez `hidden` - jinak by přebilo skrytí prohlížeče. */
.okno-kroky { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.okno-krok:not([hidden]) { display: flex; flex-direction: column; flex: 1; min-height: 0; }

/* Rekapitulace: archivovaná položka → vybraný cíl, obojí s plakátem. */
.rekapitulace { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.rekapitulace li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 12px;
    align-items: center;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
}
/* Pod posledním řádkem už je čára patičky - druhá by byla navíc. */
.prirazeni-radek:last-child,
.rekapitulace li:last-child { border-bottom: 0; padding-bottom: 0; }
.rekap-polozka { display: flex; gap: 12px; align-items: center; min-width: 0; }
.rekap-sipka { color: var(--text-muted); font-size: 18px; }
@media (max-width: 700px) {
    .rekapitulace li { grid-template-columns: 1fr; gap: 6px; }
    .rekap-sipka { transform: rotate(90deg); justify-self: start; margin-left: 8px; }
}

/* Mazání z archivu: celý řádek je popisek zaškrtávátka, takže se dá
   kliknout kamkoliv. „Vybrat vše" je oddělené čarou nad seznamem. */
.mazani-vse {
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 0 8px 12px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border);
    font-weight: 600;
    cursor: pointer;
}
.mazani-radky { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.mazani-radek {
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 8px;
    border-radius: 6px;
    cursor: pointer;
}
.mazani-radek:hover { background: var(--surface-2); }
.mazani-seznam { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
