/* Vzhled sladěný s mikrotik.cernota.cz: teplý krémový light režim jako
   výchozí, oranžový akcent, zaoblené karty s jemným stínem, boční "rail"
   navigace s popisky. Tmavý režim přes přepínač v topbaru (localStorage). */
:root {
    --bg: #f7f5f1;
    --surface: #ffffff;
    --surface-2: #f1eee7;
    --rail: #ffffff;
    --border: #e8e3d9;
    --text: #201e1a;
    --text-2: #8b8477;
    --off: #cec8ba;

    --accent: #f2611d;
    --accent-2: #6d75e0;
    --ok: #1caa82;
    --warn: #dfa100;
    --crit: #e0483f;

    --wash-accent: rgba(242, 97, 29, .14);
    --wash-accent-soft: rgba(242, 97, 29, .07);
    --wash-crit: rgba(224, 72, 63, .14);
    --wash-warn: rgba(223, 161, 0, .14);
    --border-crit: rgba(224, 72, 63, .4);

    --radius: 16px;
    --radius-sm: 10px;
    --shadow: 0 1px 2px rgba(30, 24, 10, .04), 0 10px 24px -10px rgba(30, 24, 10, .12);
}

:root[data-theme="dark"] {
    --bg: #171614;
    --surface: #201e1a;
    --surface-2: #292620;
    --rail: #1b1917;
    --border: #363228;
    --text: #f3efe6;
    --text-2: #a49a89;
    --off: #4c473c;

    --accent: #ff7a3d;
    --accent-2: #8990f5;
    --ok: #2fd39d;
    --warn: #f2b93d;
    --crit: #ff6259;

    --wash-accent: rgba(255, 122, 61, .16);
    --wash-accent-soft: rgba(255, 122, 61, .09);
    --wash-crit: rgba(255, 98, 89, .16);
    --wash-warn: rgba(242, 185, 61, .16);
    --border-crit: rgba(255, 98, 89, .4);

    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 24px -10px rgba(0, 0, 0, .45);
}
:root[data-theme="light"] .only-dark { display: none; }
:root:not([data-theme="light"]) .only-light { display: none; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    background: var(--bg);
    color: var(--text);
    font: 13.5px/1.5 -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { font-size: 21px; margin: 0; font-weight: 700; letter-spacing: -.2px; }
h2 { font-size: 14.5px; margin: 26px 0 10px; font-weight: 700; color: var(--text-2); }
.muted { color: var(--text-2); font-size: 12px; }

/* ------- rozvržení: boční rail + obsah ------- */
.app { display: flex; min-height: 100vh; }
.rail {
    width: 220px; flex-shrink: 0;
    background: var(--rail);
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column;
    padding: 18px 14px;
    position: sticky; top: 0; height: 100vh;
}
.rail-logo {
    display: flex; align-items: center; gap: 10px;
    padding: 4px 6px 18px; text-decoration: none !important;
}
.rail-logo-mark {
    font-size: 19px; width: 36px; height: 36px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm); background: var(--surface-2);
}
.rail-logo-name { display: block; font-size: 13.5px; font-weight: 700; color: var(--text); line-height: 1.25; }
.rail-logo-sub { display: block; font-size: 11px; color: var(--text-2); line-height: 1.25; }
.rail-section-label {
    font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
    color: var(--text-2); padding: 12px 10px 6px;
}
.rail-nav { display: flex; flex-direction: column; gap: 2px; }
.rail-item {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 9px 10px; border-radius: var(--radius-sm);
    color: var(--text-2); font-size: 13.5px; font-weight: 500; background: none; border: none;
    font-family: inherit; cursor: pointer; text-align: left;
}
.rail-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.rail-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.rail-item.active { background: var(--surface-2); color: var(--text); font-weight: 700; }
.rail-item.active svg { color: var(--accent); }
.rail-foot { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border); }

.shell { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    padding: 22px 28px 6px;
    background: var(--bg);
    position: sticky; top: 0;
}
.tb-brand { line-height: 1.25; }
.tb-name { font-size: 13.5px; font-weight: 700; }
.tb-sub { font-size: 11px; color: var(--text-2); }
.tb-divider { width: 1px; height: 26px; background: var(--border); }
.topbar-status { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pill {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
    border-radius: 999px; padding: 5px 12px; font-size: 12px; color: var(--text-2);
}
.pill-ok { color: var(--ok); }
.pill-bad { color: var(--crit); border-color: var(--border-crit); }
.icon-btn {
    width: 34px; height: 34px; padding: 0; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--text-2); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
}
.icon-btn svg { width: 16px; height: 16px; }
.icon-btn:hover { color: var(--text); border-color: var(--accent); }
.icon-btn.spinning svg { animation: spin 0.8s linear infinite; }
.icon-btn.spinning { pointer-events: none; opacity: 0.7; }
.btn-update-available { color: var(--warn); border-color: var(--warn); }
.btn-update-available:hover { color: var(--warn); border-color: var(--warn); background: var(--wash-warn); }
.row-action { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
.btn-update-project {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 11.5px; padding: 3px 8px; border-radius: var(--radius-sm);
    background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2); cursor: pointer;
    transition: all .15s ease;
}
.btn-update-project:hover { color: var(--accent); border-color: var(--accent); }
@keyframes spin { 100% { transform: rotate(360deg); } }
.content { padding: 10px 28px 40px; max-width: 1100px; width: 100%; }

/* ------- karty ------- */
.card {
    background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
    border-radius: var(--radius); padding: 16px 18px;
}
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; background: var(--text-2); }
.dot-on { background: var(--ok); box-shadow: 0 0 5px rgba(28, 170, 130, .5); }
.dot-off { background: var(--off); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; margin-bottom: 6px; }

/* ------- Rozcestník: karta projektu (redesign 2026-08-08) ------- */
/* Hierarchie: identita nahoře (název + popis), živý provoz dole pod linkou.
   Patička je ukotvená ke dnu (margin-top:auto) — grid karty stejné řady
   roztahuje na jednotnou výšku, takže se linky patiček protnou v jednu
   vodorovnou osu přes celou mřížku, i když mají karty různě dlouhý popis. */
.proj-card { display: flex; flex-direction: column; gap: 0; }
/* Rozbitý projekt musí jít najít bez čtení všech karet. Bez výplně —
   `--wash-crit` na celé kartě by přebilo vlastní obsah karty. */
.proj-card-bad { border-color: var(--border-crit); }

.proj-head { display: flex; align-items: flex-start; gap: 8px; }
/* O bod výš než původních 13.5px (= velikost běžného textu v kartě), aby
   název byl jednoznačně první úroveň. overflow-wrap kvůli identifikátorům
   bez mezer (nejdelší "dobijecka-kaktus"). */
.proj-name { flex: 1; min-width: 0; font-size: 14.5px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
/* Odkaz na vlastní subdoménu (dnes jen mcp_server) — menší sourozenec
   `.icon-btn` z topbaru, jen 24px místo 34px kvůli menšímu okolí. */
.proj-open {
    flex-shrink: 0; width: 24px; height: 24px; padding: 0; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--text-2); background: var(--surface-2); border: 1px solid var(--border);
}
.proj-open svg { display: block; }
.proj-open:hover { color: var(--accent); border-color: var(--accent); text-decoration: none; }

.proj-desc { margin: 5px 0 12px; color: var(--text-2); font-size: 12.5px; line-height: 1.45; overflow-wrap: anywhere; }
/* Zapuštěný proužek, ať se nespletl s popisem (dřív jen o půl bodu menší
   šedá vedle sebe). Pole `note` dnes nemá vyplněné žádný projekt, ale
   `Project` ho v modelu má, tak na to CSS existuje. */
.proj-note {
    margin: 0 0 12px; padding: 6px 9px; border-radius: var(--radius-sm);
    background: var(--surface-2); color: var(--text-2); font-size: 11.5px; line-height: 1.45;
}

/* Svisle, ne vedle sebe: štítek + meta řádek se vedle sebe do sloupce
   mřížky nevejdou a zalamovaly by se jen u NĚKTERÝCH karet (krátké systemd
   štítky vs. delší cron meta) — nestejné patičky v jedné řadě jsou přesně
   ten nepořádek, který tenhle redesign odstraňuje. */
.proj-foot {
    margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border);
    display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
}
.proj-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 11.5px; color: var(--text-2); line-height: 1.4; }
.proj-meta .sep { opacity: .45; }
.proj-ico { width: 14px; height: 14px; flex-shrink: 0; }

.ext-link {
    background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
    border-radius: var(--radius); padding: 14px 16px; display: block; font-weight: 700; font-size: 13.5px;
}
.ext-link:hover { color: var(--accent); text-decoration: none; }

/* ------- přihlášení ------- */
.login-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; }
.login-box {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
    padding: 36px 40px; width: 320px; text-align: center;
    display: flex; flex-direction: column; gap: 12px;
}
.login-logo {
    font-size: 26px; width: 52px; height: 52px; margin: 0 auto;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm); background: var(--surface-2);
}
.login-box h1 { font-size: 19px; }
.login-box p { margin: 0; }
.login-box button { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.login-box button:hover { background: var(--accent); filter: brightness(1.08); }
.login-error { background: var(--wash-crit); color: var(--crit); border-radius: var(--radius-sm); padding: 8px; font-size: 13px; }

/* ------- formuláře ------- */
input, select, button {
    font: inherit; color: var(--text);
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: 7px 12px;
}
input:focus, select:focus { outline: none; border-color: var(--accent); }
button { cursor: pointer; }
button:hover { border-color: var(--accent); }

/* Plovoucí panel neuložených změn. Vlastní podklad, rámeček a vnitřní
   odsazení — dřív to byl jen text a tlačítko nalepené na okraje obsahu. */
.save-bar {
    position: sticky; bottom: 14px;
    display: flex; align-items: center; justify-content: flex-end;
    gap: 20px;
    padding: 12px 16px; margin-top: 16px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.save-bar button {
    padding: 10px 22px; background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
    border-radius: var(--radius-sm);
}
.save-bar button:hover { filter: brightness(1.08); }

@media (max-width: 760px) {
    .app { flex-direction: column; }
    .rail {
        width: 100%; height: auto; position: static;
        flex-direction: row; align-items: center; padding: 8px 10px;
        gap: 6px;
    }
    .rail-logo-name, .rail-logo-sub, .rail-section-label { display: none; }
    .rail-logo { padding: 4px; flex-shrink: 0; }
    .rail-nav { flex-direction: row; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .rail-item { width: 40px; height: 40px; padding: 0; justify-content: center; flex-shrink: 0; }
    .rail-item span:not(.rail-badge) { display: none; }
    .rail-foot { margin: 0 0 0 auto; padding-top: 0; border-top: 0; flex-shrink: 0; }
    .tb-brand, .tb-divider { display: none; }
    .content { padding: 12px; }
}

/* ------- MCP: dlaždice ------- */
/* Hierarchie: ikona+krátký štítek (co to je) -> velké číslo s jednotkou
   (kolik) -> jeden krátký podřádek (kontext). Dřív byl štítek dlouhá věta
   a jednotka až v podřádku, takže se to při čtení slévalo. */
.tiles {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
    gap: 12px; margin-bottom: 18px;
}
.tile {
    background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
    border-radius: var(--radius); padding: 13px 15px 14px;
}
.tile-head { display: flex; align-items: center; gap: 6px; }
.tile-ico { width: 13px; height: 13px; color: var(--text-2); flex-shrink: 0; }
.tile-label {
    font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
    color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile-value {
    display: flex; align-items: baseline; gap: 7px;
    font-size: 26px; font-weight: 700; line-height: 1.1;
    margin: 9px 0 5px; font-variant-numeric: tabular-nums;
}
.tile-value .dot { width: 9px; height: 9px; margin: 0; align-self: center; }
.tile-value.val-ok { color: var(--ok); }
.tile-value.val-bad { color: var(--crit); }
.tile-unit {
    font-size: 11.5px; font-weight: 500; color: var(--text-2);
    letter-spacing: .01em; white-space: nowrap;
}
.tile-sub { font-size: 11.5px; color: var(--text-2); line-height: 1.45; }
/* Textová hodnota v dlaždici (adresa, "scrypt hash") — 26px je pro text moc. */
.tile-value-sm { font-size: 16px; word-break: break-all; }

/* ------- MCP: vodorovný žebříček dnů ------- */
/* Sedm hodnot se čte lépe jako tabulka s pruhy než jako svislý graf: den,
   pruh i číslo jsou na jednom řádku, hodnoty jsou vidět bez hoveru a nula je
   explicitní nula, ne dvoupixelový pahýl. Zároveň to JE tabulková podoba
   dat, takže není potřeba zvlášť "table view". */
/* table-layout: fixed + <colgroup> je záměrná oprava skutečné chyby (31. 7.
   2026): `.hbar-proj`/`.hbar-day` mají šířku na VNITŘNÍM flex boxu (display:
   flex je na <th>, takže prohlížeč kolem něj vytvoří anonymní table-cell —
   width property se ale váže k flex boxu, ne k té anonymní buňce). Pro
   automatický table-layout to znamená, že ANI label, ANI pruhový sloupec
   nemá z pohledu algoritmu "specified width" — přebytečnou šířku tabulky si
   pak nepoměrně strhl label sloupec (jeho obsahová/max-content šířka ~120px
   je vyšší než skoro nulová šířka prázdného `.hbar-track`), takže reálně
   vykreslený pruh byl jen pár desítek px u pravého okraje a mezi jménem a
   pruhem zela prázdná mezera - ověřeno screenshotem z headless Chromia, ne
   jen výpočtem. `<colgroup>` dává šířku jednoznačně a autoritativně přímo
   sloupci, bez ohledu na display/flex uvnitř buněk. */
.hbars { width: 100%; border-collapse: collapse; margin: 12px 0 4px; table-layout: fixed; }
.hbars-col-label { width: 120px; }
.hbars--days .hbars-col-label { width: 96px; }
/* Nejdelší jméno nástroje (tesla_tire_pressure_trend) je 25 znaků, o dost
   delší než nejdelší jméno projektu (~15) — širší sloupec než .hbars--projects,
   ať se elipsa neuplatní na běžných jménech. */
.hbars--tools .hbars-col-label { width: 170px; }
/* Šířka počítá nejen s nejdelším jménem (MistralAI-MCPClient, 19 znaků),
   ale i se jménem + štítkem "podvržený"/"ověřeno DNS" na jednom řádku
   (viz .hbars--bots .hbar-proj níže) — hodnota doladěná a ověřená reálným
   renderem, ne jen výpočtem šířky textu. */
.hbars--bots .hbars-col-label { width: 235px; }
.hbars-col-num { width: 52px; }
.hbars-cap {
    caption-side: top; text-align: left;
    font-size: 11.5px; color: var(--text-2); padding-bottom: 8px;
}
.hbars tr { border-bottom: 1px solid var(--border); }
.hbars tr:last-child { border-bottom: none; }
.hbars td, .hbars th { padding: 7px 0; vertical-align: middle; }
/* 96px (dřív 132 px, zúženo 31. 7. 2026): co se ubere labelu, dostane pruh
   (`.hbar-cell` je `width: auto`) — a to u všech řádků. Obsah je den (min-width
   20px) + mezera + datum (~41 px v nejširším testovaném fontu) = 68 px, s
   dnešní tečkou 83 px, takže 96 px má rezervu ~13 px.
   Původních 132 px si vynucovala **pilulka „dnes"** (samotná 49 px), která je
   přitom jen na jednom řádku ze sedmi — kvůli ní se plýtvalo místem u všech
   ostatních. Je proto nahrazená tečkou (viz `.dot-accent` v mcp.html); dnešní
   řádek zůstává odlišený i tmavší barvou přes `.hbar-today`. */
.hbar-day {
    width: 96px; text-align: left; font-weight: 400;
    display: flex; align-items: center; gap: 7px;
    font-size: 12.5px; color: var(--text-2);
}
.hbar-dow { font-weight: 700; color: var(--text); min-width: 20px; }
.hbar-date { font-variant-numeric: tabular-nums; }
/* Tečka nese vlastní margin pro použití v textu — tady odsazení řeší gap. */
.hbar-day .dot { margin-right: 0; flex-shrink: 0; }
.hbar-cell { padding-left: 4px; padding-right: 12px; width: auto; }
.hbar-track {
    height: 14px; background: var(--surface-2);
    border-radius: 4px; overflow: hidden;
}
.hbar-fill {
    height: 100%; background: var(--accent);
    border-radius: 4px;                 /* zaoblený konec dat */
    min-width: 4px;
}
.hbar-num {
    width: 52px; text-align: right;
    font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.hbar-num-zero { color: var(--text-2); font-weight: 400; }
.hbar-today .hbar-dow, .hbar-today .hbar-num { color: var(--text); }

.chart-foot {
    display: flex; flex-wrap: wrap; gap: 6px 22px;
    padding-top: 12px; margin-top: 8px; border-top: 1px solid var(--border);
    font-size: 12px; color: var(--text-2);
}
.chart-foot strong { color: var(--text); }
.chart-foot .foot-bad strong { color: var(--crit); }

/* Hustý referenční seznam až 150 cest (apache.html) — novinový vícesloupcový
   tok místo `.hbars` tabulky s pruhem, tam by 150 řádků bylo neúměrně
   dlouhé. `column-width` samo spočítá počet sloupců podle šířky karty. */
.path-list { column-width: 260px; column-gap: 24px; margin: 10px 0 4px; }
.path-list div {
    display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
    padding: 5px 0; border-bottom: 1px solid var(--border);
    break-inside: avoid;
}
.path-list code {
    font-size: 12px; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; min-width: 0;
}
.path-list .path-count { font-size: 12px; color: var(--text-2); flex-shrink: 0; }
.hint-inline { opacity: .75; }

/* ------- MCP: sekce a řádky ------- */
.sect { margin-bottom: 16px; }
.sect-head {
    display: flex; align-items: center; gap: 10px;
    padding-bottom: 10px; border-bottom: 2px solid var(--border);
}
.sect-head h2 { margin: 0; font-size: 15px; }
.sect-count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; height: 22px; padding: 0 7px;
    border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border);
    font-size: 12px; font-weight: 700; color: var(--text-2);
}
.sect-count-bad { color: var(--crit); border-color: var(--border-crit); }
.sect-action { margin-left: auto; }

/* Přepínač okna grafu „Průběh" (24/48/72 h) — malý segmented control vedle
   nadpisu sekce, stejné odsazení doprava jako `.sect-action`. */
.okno-toggle { display: flex; gap: 4px; }
.okno-toggle a {
    padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border);
    font-size: 12px; font-weight: 600; color: var(--text-2);
    text-decoration: none; line-height: 1.4;
}
.okno-toggle a:hover { border-color: var(--text-2); color: var(--text); }
.okno-toggle-active, .okno-toggle-active:hover {
    background: var(--accent); border-color: var(--accent) !important;
    color: #fff !important;
}
.sect-note { margin: 10px 0 4px; max-width: 76ch; }

.row {
    display: flex; align-items: center; gap: 16px;
    padding: 13px 0; border-bottom: 1px solid var(--border);
}
.row:last-child { border-bottom: none; padding-bottom: 2px; }
.row-dim { opacity: .55; }
.row-main { min-width: 0; flex: 1; }
.row-title {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    font-weight: 700; font-size: 13.5px; word-break: break-all;
}
.row-title-quiet { font-weight: 600; color: var(--text-2); }
.row-meta {
    display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
    margin-top: 5px; font-size: 11.5px; color: var(--text-2);
}
.row-meta code { font-size: 11px; }
.row-meta .sep { opacity: .45; }
.row-quiet { padding: 9px 0; }

.tag {
    display: inline-flex; align-items: center; gap: 5px;
    border-radius: 999px; padding: 2px 9px;
    font-size: 11px; font-weight: 600;
    background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2);
    white-space: nowrap;
}
.tag-ok { color: var(--ok); }
.tag-bad { color: var(--crit); border-color: var(--border-crit); }
.tag .dot { margin-right: 0; }

.empty { color: var(--text-2); font-size: 12.5px; padding: 12px 0 2px; margin: 0; }
.hint { color: var(--text-2); font-size: 11.5px; line-height: 1.55; margin: 2px 0 0; }
.used-none { opacity: .85; font-style: italic; }
.btn-danger { color: var(--crit); border-color: var(--border-crit); font-size: 12.5px; white-space: nowrap; }
.btn-danger:hover { background: var(--wash-crit); border-color: var(--crit); }
.btn-quiet { color: var(--text-2); font-size: 12px; padding: 5px 10px; white-space: nowrap; }
.btn-quiet:hover { color: var(--crit); border-color: var(--border-crit); }
.notice { border-radius: var(--radius-sm); padding: 10px 14px; font-size: 13px; margin-bottom: 14px; }
.notice-ok { background: var(--surface-2); color: var(--ok); border: 1px solid var(--border); }
.notice-bad { background: var(--wash-crit); color: var(--crit); }

@media (max-width: 620px) {
    .row { flex-wrap: wrap; }
    .tile-value { font-size: 21px; }
    /* Na mobilu je `.hbar-date` skryté, takže v labelu zůstane jen zkratka dne
       (20 px) a případná dnešní tečka (15 px) — 104 px byla šířka z doby, kdy
       tu ještě musela vyjít pilulka „dnes". */
    .hbar-day { width: 60px; font-size: 12px; }
    .hbars--days .hbars-col-label { width: 60px; }
    .hbar-date { display: none; }
}

/* ------- editor .env (/config) ------- */
.env-toolbar {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    margin: 4px 0 14px;
}
.env-filter {
    display: flex; align-items: center; gap: 8px;
    background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
    border-radius: var(--radius-sm); padding: 0 12px;
    flex: 1; min-width: 220px; max-width: 420px;
}
.env-filter svg { color: var(--text-2); flex-shrink: 0; }
.env-filter input {
    border: none; background: none; box-shadow: none;
    padding: 9px 0; width: 100%; font-size: 13px;
}
.env-filter input:focus { outline: none; }
.env-filter:focus-within { border-color: var(--accent); }

.env-sect { margin-bottom: 14px; }
.env-row { align-items: flex-start; }
.env-key { font-size: 12.5px; font-weight: 700; word-break: break-all; }
.env-control { width: 300px; flex-shrink: 0; }
.env-control input { width: 100%; font-size: 12.5px; }
.env-readonly {
    display: block; font-size: 12.5px; color: var(--text-2);
    word-break: break-all; padding: 7px 0;
}
/* Text štítku zůstává v čitelné inkoustové barvě — --warn (#dfa100) má proti
   bílé kartě kontrast jen 2,27:1 (měřeno validátorem), což je na 11px text
   málo. Výstražná barva proto jen v podkladu a rámečku, informaci nese text. */
.tag-secret {
    color: var(--text);
    background: var(--wash-warn);
    border-color: var(--warn);
}

.pw-form .row:last-of-type { border-bottom: none; }
.pw-form .row input { width: 300px; flex-shrink: 0; }
.pw-actions { display: flex; justify-content: flex-end; padding-top: 12px; }
.pw-actions button {
    background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
.pw-actions button:hover { filter: brightness(1.08); }

@media (max-width: 720px) {
    .env-row { flex-wrap: wrap; }
    .env-control, .pw-form .row input { width: 100%; }
}

/* ------- přidání klíče do .env ------- */
.add-key { padding: 0; margin-bottom: 14px; }
.add-key-summary {
    display: flex; align-items: center; gap: 8px;
    padding: 14px 18px; cursor: pointer; font-weight: 700; font-size: 13.5px;
    list-style: none;
}
.add-key-summary::-webkit-details-marker { display: none; }
.add-key-summary svg { color: var(--accent); flex-shrink: 0; }
.add-key-summary:hover { color: var(--accent); }
.add-key-hint { font-weight: 400; margin-left: auto; }
.add-key[open] .add-key-summary { border-bottom: 2px solid var(--border); }
.add-key-form { padding: 4px 18px 16px; }
.add-key-form > .row input[type="text"] { width: 300px; flex-shrink: 0; }
.add-key-section { display: flex; gap: 8px; width: 300px; flex-shrink: 0; }
.add-key-section select { flex: 1; min-width: 0; font-size: 12.5px; }
.add-key-section input { flex: 1; min-width: 0; font-size: 12.5px; }
.add-key-form .hint { padding-top: 12px; max-width: 76ch; }

@media (max-width: 720px) {
    .add-key-hint { display: none; }
    .add-key-form > .row input[type="text"], .add-key-section { width: 100%; }
}

/* ------- neuložené změny v editoru .env ------- */
/* [hidden] musí přebít display:flex u .save-bar, jinak by schování neúčinkovalo. */
.save-bar[hidden] { display: none; }
.save-bar-count {
    font-size: 12.5px; font-weight: 600; color: var(--accent);
    margin-right: auto; padding-left: 4px;
}
/* Zvýraznění změněného řádku — aby bylo i při zapnutém filtru vidět, co se mění. */
.env-row-dirty { background: var(--wash-accent); box-shadow: inset 3px 0 0 var(--accent); }
.env-row-dirty .env-key { color: var(--accent); }
.env-toolbar-note { margin-left: auto; }
@media (max-width: 720px) { .env-toolbar-note { display: none; } }

/* ================= Zdraví RPi5 (/zdravi) ================= */
/* Doplněno 31. 7. 2026. Sparkline a meter jsou převzaté z
   mikrotik.cernota.cz (assets/style.css), odkud pochází celý design systém
   hubu — ať se stejná věc nekreslí na dvou místech dvěma způsoby. */

/* ------- sparkline (historie 24 h ze sysstat CSV) ------- */
/* Dva grafy (teplota, zátěž CPU) pod sebou se sdílenou časovou osou —
   dřív vedle sebe (.spark-row), Honza si to spletl s jedním grafem
   rozděleným napůl. Výška grafu i barva jedné řady jde přes proměnné, ať
   se dá měnit na jednom místě (i pro JS marker, viz health.js). */
/* margin-top navíc oproti sdílenému .sect-note (jen 4px odstup) — text nad
   grafem („Data sbírá cron…") a nadpis „TEPLOTA CPU" byly moc u sebe. */
.spark-stack { --spark-h: 104px; --spark-gut: 42px; display: flex; flex-direction: column; gap: 4px; margin-top: 14px; }
.spark-block { --spark-color: var(--accent); }
.spark-block--cpu { --spark-color: var(--accent-2); }
.spark-block + .spark-block { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 6px; }

.spark-plot { display: grid; grid-template-columns: var(--spark-gut) 1fr; align-items: stretch; }
.spark-plot--axis { margin-top: 2px; }

.spark-yaxis { position: relative; }
.spark-ylabel {
    position: absolute; right: 8px; transform: translateY(-50%);
    font-size: 10.5px; line-height: 1; color: var(--text-2);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.spark-ylabel--prumer { color: var(--text); font-weight: 600; }

/* Dva "řádky" uvnitř jednoho absolutně pozicovaného kontejneru: rysky
   nahoře, poznámka o oknu pod nimi — jinak poslední ryska (typicky blízko
   pravého okraje) koliduje s poznámkou zarovnanou taky doprava. */
.spark-xaxis { position: relative; height: 30px; }
.spark-tick {
    position: absolute; top: 0; transform: translateX(-50%);
    font-size: 10.5px; line-height: 1; color: var(--text-2);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.spark-tick--pulnoc { color: var(--text); font-weight: 600; }
.spark-xnote { position: absolute; right: 0; top: 15px; font-size: 10.5px; color: var(--text-2); }

/* preserveAspectRatio="none" v šabloně natáhne 100x30 viewBox na celou šířku;
   non-scaling-stroke drží tah 1,5 px i mřížku/prahy, aby se nedeformovaly. */
.spark { display: block; width: 100%; height: var(--spark-h); overflow: visible; }
.spark polyline {
    fill: none; stroke: var(--spark-color); stroke-width: 1.5;
    vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round;
}
.spark-area { stroke: none; }
.spark-stop-0 { stop-color: var(--spark-color); stop-opacity: .20; }
.spark-stop-1 { stop-color: var(--spark-color); stop-opacity: 0; }

.spark-grid line { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.spark-grid .spark-grid--prumer { stroke: var(--text-2); stroke-opacity: .45; }
.spark-grid .spark-grid-v { stroke-opacity: .55; }
.spark-grid .spark-grid-v--pulnoc { stroke-opacity: 1; }

/* Práh se kreslí, jen když se k němu data reálně blíží (health.py) — v
   klidném stavu (běžně desítky stupňů/procent pod prahem) se nevykreslí
   vůbec, ať graf nepůsobí poplašně bez důvodu. */
.spark-prah { stroke-width: 1.25; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.spark-prah--warn { stroke: var(--warn); }
.spark-prah--crit { stroke: var(--crit); }
.spark-band { fill: var(--wash-crit); }

.spark-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.spark-title {
    font-size: 11px; font-weight: 600; letter-spacing: .03em;
    text-transform: uppercase; color: var(--text-2);
}
.spark-now { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.spark-range { font-size: 11.5px; color: var(--text-2); margin-left: auto; font-variant-numeric: tabular-nums; }
.spark-empty {
    height: var(--spark-h); display: flex; align-items: center;
    font-size: 12px; color: var(--text-2);
}

@media (max-width: 720px) {
    .spark-stack { --spark-h: 76px; --spark-gut: 32px; }
    .spark-ylabel, .spark-tick, .spark-xnote { font-size: 9.5px; }
    .spark-ylabel { right: 5px; }
    .spark-xnote { display: none; }
}

/* ------- pruh využití (disky) ------- */
.meter { background: var(--surface-2); border-radius: 999px; height: 7px; overflow: hidden; margin-top: 7px; }
.meter i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.meter-ok i { background: var(--ok); }
.meter-warn i { background: var(--warn); }
.meter-crit i { background: var(--crit); }
.disk-row { padding: 11px 0; border-bottom: 1px solid var(--border); }
.disk-row:last-child { border-bottom: 0; }
.disk-head { display: flex; align-items: baseline; gap: 8px; }
.disk-name { font-weight: 600; font-size: 13.5px; }
.disk-mount { font-size: 11.5px; color: var(--text-2); font-family: ui-monospace, monospace; }
.disk-num { margin-left: auto; font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--text-2); }
.disk-num strong { color: var(--text); }

/* ------- dlaždice: varovná úroveň (doplnění k val-ok/val-bad) ------- */
.tile-value.val-warn { color: var(--warn); }

/* ------- AI verdikt ------- */
/* Text od modelu má odstavce a odrážky — zachovat zlomy řádků, ale nechat
   zalamovat dlouhé řádky (pre-wrap, ne pre). */
.ai-msg {
    white-space: pre-wrap; overflow-wrap: anywhere;
    font-size: 13px; line-height: 1.55; margin: 10px 0 0;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: 12px 14px;
}
.chk-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 0; }
.chk {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 11.5px; font-weight: 600; padding: 3px 9px;
    border-radius: 999px; border: 1px solid var(--border); background: var(--surface-2);
}
.chk-bad { background: var(--wash-crit); border-color: var(--border-crit); }
.chk-detail { font-size: 11.5px; color: var(--text-2); margin-top: 8px; line-height: 1.5; }

/* ------- žebříček chyb podle projektu ------- */
/* Label projektu musí mít PEVNOU šířku, jinak se rozbije zarovnání pruhů.
   `.hbars` je obyčejná <table> s automatickým layoutem, takže šířku prvního
   sloupce určuje nejširší obsah napříč VŠEMI řádky. Původní verze měla jen
   `white-space: nowrap` bez šířky, takže:
     - sloupec se roztahoval podle nejdelšího názvu (`mcp_server_akce`),
     - a jakmile měl jediný projekt štítek „log zastaralý", povyrostl o jeho
       šířku a zúžil pruhy i všem ostatním řádkům, které se štítkem nemají nic
       společného. Geometrie se tedy měnila podle nesouvisejícího stavu.
   Řešení je stejné jako u fungujícího `.hbar-day` na kartě /mcp: flex
   kontejner s pevnou šířkou. Flexem přestává být table-cell (obalí ho
   anonymní buňka), takže `width` platí definitivně a nedopočítává se
   z obsahu.

   120px (dřív 148 px, zúženo 31. 7. 2026 na přání Honzy — širší pruh dostal
   přednost před vždy plně viditelným nejdelším názvem): `.hbar-cell` má
   `width: auto`, takže co se ubere labelu, dostane pruh, a to u VŠECH řádků.
   Naměřeno na reálných sedmi názvech: nejdelší `mcp_server_akce` má ~110 px ve
   fontech z body stacku (124 px v nejširším testovaném DejaVu Bold), druhý
   `docker_upgrade` ~104 px, ostatní ≤ 78 px. Ve 120 px se tedy v běžném stavu
   (bez stavové tečky) vejdou všechny názvy, elipsa hrozí jen dvěma nejdelším
   a jen v nejširších fontech nebo když k nim přibude tečka. Krátká jména
   (`zalohy`, 48 px) tím ztratila zbytečnou mezeru před pruhem. */
.hbar-proj {
    width: 120px; text-align: left;
    display: flex; align-items: center; gap: 7px;
    font-size: 12.5px; font-weight: 600;
}
.hbar-proj-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* `.hbar-proj` má fixní šířku 120px nezávisle na `.hbars-col-label` (viz
   komentář výš) — u nástrojů se přijala elipsa, ale u jmen botů/cest je
   celé jméno hlavní obsah řádku, proto tu šířku boxu přepisujeme na
   stejnou hodnotu, jakou má sloupec v <colgroup>. */
/* U rodin botů se jméno + štítek "podvržený"/"ověřeno DNS" na jeden řádek
   nevejdou (žádná pevná šířka by seděla na "MistralAI-MCPClient" i "Amazonbot"
   zároveň) — bez zalomení štítek přetekl mimo label sloupec a posunul
   viditelný začátek pruhu, takže se zdálo, že pruh "leze" na text. Zalomení
   drží levý okraj pruhu na stejném místě u všech řádků bez ohledu na to,
   jestli štítek je, nebo není. */
.hbars--bots .hbar-proj {
    width: 235px;
    /* Zalomení zůstává jako pojistka pro budoucí delší jméno rodiny (dnes
       se při 235px neuplatní na žádném řádku) — bez ní by se historie z
       31.7./8.8.2026 (přetečený štítek posouvá začátek pruhu) mohla vrátit. */
    flex-wrap: wrap; row-gap: 2px; align-items: center;
}
/* Tečka nese vlastní margin pro použití v textu — tady odsazení řeší gap. */
.hbar-proj .dot { margin-right: 0; flex-shrink: 0; }

/* Stav logu se v žebříčku značí tečkou, ne textovým štítkem: štítek by se do
   pevné šířky vedle 15znakového názvu nevešel a musel by sloupec roztáhnout,
   čímž bychom byli zpátky u původního problému. Slovní vysvětlení je pod
   tabulkou (a projekt jmenovitě i ve výstraze nahoře na stránce). */
.dot-warn { background: var(--warn); }
.dot-crit { background: var(--crit); }
/* Dnešní den v žebříčku na /mcp — dřív to byla pilulka „dnes", která ale
   vynucovala o 36 px širší label sloupec u všech řádků. */
.dot-accent { background: var(--accent); }

.log-legend {
    display: flex; flex-wrap: wrap; gap: 4px 16px;
    margin-top: 10px; font-size: 11.5px; color: var(--text-2);
}
.log-legend span { display: inline-flex; align-items: center; }
.log-legend .dot { margin-right: 6px; }

/* Detailní výpis chyb je jiné rozvržení (flex `.row`) než tabulka nad ním,
   takže potřebuje vlastní nadpis — bez něj vypadal jako pokračování
   patičky grafu. */
.log-detail-head {
    margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--border);
    font-size: 11px; font-weight: 600; letter-spacing: .03em;
    text-transform: uppercase; color: var(--text-2);
}
/* Tabulka i seznam pod ní začínají na stejné svislici (x=0 obsahu karty):
   `.hbars td/th` mají `padding: 7px 0`, `.row` má `padding: 13px 0`. */

@media (max-width: 620px) {
    /* Na mobilu je pruh nejcennější (karta je nejužší), takže se ubírá
       stejným poměrem jako na desktopu. Nejdelší název měří ~102 px při 12px
       v reálných fontech, takže se do 108 px vejde; v nejširších fontech se
       zkrátí elipsou. */
    .hbar-proj { width: 108px; font-size: 12px; }
    .hbars--projects .hbars-col-label { width: 108px; }
    .hbars--tools .hbars-col-label { width: 108px; }
    .hbars--bots .hbars-col-label { width: 108px; }
}
.log-err {
    font-size: 12px; font-family: ui-monospace, monospace; overflow-wrap: anywhere;
    color: var(--text-2); margin-top: 4px; line-height: 1.5;
}
.log-err-time { color: var(--text); font-weight: 600; margin-right: 6px; }

/* Poslední volání nástrojů: náhled výsledku je vždy vidět, celý (uložený,
   max. 2000 znaků z call_audit.py) se rozbalí bez JS přes <details>. */
.call-result { margin-top: 4px; }
.call-result > summary {
    cursor: pointer; font-size: 12px; font-family: ui-monospace, monospace;
    color: var(--text-2); overflow-wrap: anywhere; line-height: 1.5;
}
.call-result > summary::marker { color: var(--accent); }
.call-result > summary:hover { color: var(--text); }
.call-result-full {
    font-size: 12px; font-family: ui-monospace, monospace; overflow-wrap: anywhere;
    color: var(--text-2); line-height: 1.5; white-space: pre-wrap;
}
.call-result > .call-result-full { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); }
.call-result-short { margin-top: 4px; }

/* ------- výstražná poznámka (vedle notice-ok / notice-bad) ------- */
/* .notice-bad si barvu textu nastavuje, takže ji tady musím taky — jinak by
   varování zdědilo výchozí barvu a vypadalo jako neutrální text. */
.notice-warn { background: var(--wash-warn); color: var(--text); border: 1px solid var(--warn); }
/* Štítek "log zastaralý" apod. Žlutá jen v podkladu a rámečku, text zůstává
   inkoustový — --warn má proti bílé kontrast jen 2,27:1, na 11px je to málo. */
.tag-warn { color: var(--text); background: var(--wash-warn); border-color: var(--warn); }

/* ------- drobné metriky (uptime, síť) ------- */
/* `auto-fit, minmax(150px,1fr)` počítalo počet sloupců podle šířky okna, a
   při 5 položkách (Uptime, Throttling, WLAN0, ETH0, Načteno) to mezi ~700 a
   ~900px okna vycházelo na 3 sloupce → 3+2 rozpad, kde ETH0 (patří k WLAN0)
   skončí na samostatném řádku pod Uptime, ne pod WLAN0 — vypadá to rozházené
   (nález 31. 7. 2026, ověřeno screenshotem přes headless Chromium na více
   šířkách). Fixní 5/2 sloupce (žádné auto-fit) tomu předchází stejně jako
   `<colgroup>` u `.hbars` — sloupce se nedopočítávají z volné šířky. */
/* margin-top: karta „Systém" jde rovnou ze `.sect-head` (nadpis + linka) do
   mřížky, bez mezitímního `.sect-note` odstavce, který dělá odstup u
   ostatních sekcí — bez vlastní mezery ležela hodnota `UPTIME` hned na
   linkou (nález 31.7.2026). */
.mini-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px 18px; margin-top: 14px; }
@media (max-width: 960px) {
    /* Musí být AŽ ZA nepodmíněným `.mini-grid` výše — stejná specificita,
       takže při opačném pořadí v souboru by pozdější pravidlo (i mimo media
       query) vyhrálo bez ohledu na šířku okna. Přesně tahle chyba se stala
       napoprvé (31.7.2026): pravidlo bylo omylem v dřívějším @media bloku
       (`.hbar-day`/`.hbar-proj`, o desítky řádků výš) a nikdy se neuplatnilo.

       Práh 960 px (dřív 620 px) je vyšší, než by čekal zbytek souboru (ten
       má 620/720/760 px) — záměrně, protože `.rail` (postranní nav) se
       zhroutí na vodorovný pruh až pod 760 px (viz `.rail` media query o
       desítky řádků výš). NAD 760 px zabírá nav pevných 220 px navíc ke
       kartě, takže právě v pásmu ~760–950 px zbývalo na 5 sloupců jen
       ~80–100 px na sloupec — dost na to, aby se hodnota jako "4 d 20 h
       35 min" zalomila uprostřed (přesně tohle Honza nahlásil a bylo to i
       reprodukované screenshotem na 820 px). 960 px dává i na nejširší
       hodnoty rezervu. */
    .mini-grid { grid-template-columns: repeat(2, 1fr); }
}
.mini-label {
    font-size: 11px; font-weight: 600; letter-spacing: .03em;
    text-transform: uppercase; color: var(--text-2);
}
.mini-value { font-size: 14px; font-weight: 600; margin-top: 3px; font-variant-numeric: tabular-nums; }
.mini-sub { font-size: 11.5px; color: var(--text-2); margin-top: 2px; }

/* ------- interaktivní sparkline (tooltip + marker, health.js) ------- */
/* Pozicovací rámec. Marker i tooltip jsou HTML prvky nad SVG, protože
   viewBox 100x30 s preserveAspectRatio="none" natahuje osy nerovnoměrně —
   SVG <circle> by z toho vyšel jako elipsa. */
.spark-wrap { position: relative; }
/* Kurzor napovídá, že se v grafu dá něco zjistit. */
.spark-wrap .spark { cursor: crosshair; }

.spark-dot {
    position: absolute; width: 9px; height: 9px; border-radius: 50%;
    background: var(--spark-color, var(--accent)); border: 2px solid var(--surface);
    /* Střed kruhu na souřadnici bodu, ne jeho levý horní roh. */
    transform: translate(-50%, -50%);
    pointer-events: none; z-index: 2;
    box-shadow: 0 0 0 1px var(--spark-color, var(--accent));
}

/* Svislé vodítko od markeru — u vyššího grafu (104px) se bez něj hůř
   odečítá, který čas na ose X bod odpovídá. */
.spark-cross {
    position: absolute; top: 0; bottom: 0; width: 1px;
    background: var(--spark-color, var(--accent)); opacity: .35;
    transform: translateX(-.5px); pointer-events: none; z-index: 1;
}

.spark-tip {
    position: absolute; z-index: 3; pointer-events: none;
    /* Nad bodem s malou mezerou, vodorovně vystředěný (left dopočítá JS). */
    transform: translate(-50%, calc(-100% - 12px));
    white-space: nowrap;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    padding: 5px 9px; font-size: 11.5px; font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* Blízko horního okraje (vysoký bod) by tooltip nad bodem vylezl z karty
   ven — překlopí se pod bod (health.js přepíná tuhle třídu). */
.spark-tip--below { transform: translate(-50%, 12px); }
.spark-tip[hidden], .spark-dot[hidden], .spark-cross[hidden] { display: none; }

/* ------- Docker (/docker) ------- */
/* Cesta k compose projektu v hlavičce sekce — vpravo, drobně, ať nekonkuruje
   názvu projektu. Na úzkém okně se skryje, tam je přednější jméno a počty. */
.dock-path {
    margin-left: auto; font-size: 11px; color: var(--text-2);
    font-family: ui-monospace, monospace; white-space: nowrap;
}
@media (max-width: 720px) {
    .dock-path { display: none; }
}

/* Dlaždice na /docker: fixní počet sloupců, ne `auto-fit`.
   Sdílené `.tiles` používá `repeat(auto-fit, minmax(196px, 1fr))`, což se při
   ČTYŘECH dlaždicích rozpadne na 3 + 1 — osamocená čtvrtá dlaždice na vlastní
   řádce vypadá rozbitě (reálně ověřeno screenshotem při 960 px, kde vnitřní
   šířka obsahu vyjde na 684 px = 3,49 sloupce).
   Proto pevné počty s explicitními zlomy: 4 dlaždice se vejdou až od
   4×196 + 3×12 = 820 px vnitřní šířky, což je při railu 220 px a odsazení
   obsahu 56 px okno ~1100 px. Mezi tím 2×2 (nikdy sirotek), pod 460 px jeden
   sloupec. Pořadí je záměrné: základní pravidlo první, media query za ním. */
.tiles-4 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 1100px) {
    .tiles-4 { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 459px) {
    .tiles-4 { grid-template-columns: 1fr; }
}

/* ------- potvrzování vyřešených problémů (/zdravi) ------- */
/* Výstraha s tlačítkem: text vlevo, tlačítko vpravo, na úzkém okně pod sebou.
   `.notice` samo nemá display, takže se flex zapíná až tady u varianty
   s tlačítkem — původní výstrahy bez tlačítka zůstávají beze změny. */
.notice-ack { display: flex; align-items: flex-start; gap: 12px; }
.notice-text { flex: 1; min-width: 0; }
.ack-form { flex-shrink: 0; }
.btn-ack {
    display: inline-flex; align-items: center; gap: 5px;
    font: inherit; font-size: 11.5px; font-weight: 600; line-height: 1;
    padding: 5px 10px; border-radius: 999px; cursor: pointer;
    /* Průhledné pozadí, ať tlačítko dědí barvu výstrahy (žlutá i červená) a
       nemusí mít dvě varianty. */
    color: inherit; background: transparent;
    border: 1px solid currentColor; opacity: .75;
}
.btn-ack:hover { opacity: 1; background: var(--surface); }

/* Rozbalovací seznam potvrzených — potvrzené problémy nemizí beze stopy. */
.ack-done {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: 10px 14px; margin-bottom: 14px;
    font-size: 13px;
}
.ack-done > summary {
    cursor: pointer; color: var(--text-2); font-size: 12px; font-weight: 600;
}
.ack-done > summary:hover { color: var(--text); }
.ack-row {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 9px 0; border-bottom: 1px solid var(--border);
}
.ack-row:last-child { border-bottom: none; padding-bottom: 2px; }
.ack-text { flex: 1; min-width: 180px; color: var(--text-2); text-decoration: line-through; }
.ack-when { font-size: 11.5px; color: var(--text-2); white-space: nowrap; }

@media (max-width: 620px) {
    /* Na úzkém okně by tlačítko vedle textu nechalo na text ~150 px. */
    .notice-ack { flex-direction: column; align-items: stretch; }
    .ack-form { align-self: flex-end; }
}

/* ------- Modální okna & dialogy ------- */
.modal-backdrop {
    position: fixed; inset: 0; z-index: 1000;
    background: rgba(0, 0, 0, .65); backdrop-filter: blur(5px);
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
}
.modal-backdrop[hidden] { display: none; }
.modal-box {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow);
    max-width: 720px; width: 100%; max-height: 85vh;
    display: flex; flex-direction: column; overflow: hidden;
}
.modal-box-large {
    max-width: min(1300px, 96vw);
    max-height: 92vh;
}
.modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 18px; border-bottom: 1px solid var(--border);
    flex-wrap: wrap; gap: 10px;
}
.modal-head h3 { margin: 0; font-size: 15px; font-weight: 700; }
.modal-body {
    padding: 16px; margin: 0; overflow-y: auto;
    font-size: 12.5px; line-height: 1.5; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    max-height: 60vh; background: var(--surface-2);
}
.modal-body-large {
    max-height: 78vh;
    min-height: 420px;
}
.modal-body.log-wrap {
    white-space: pre-wrap !important;
    word-break: break-all;
}

/* ------- Command Palette (Ctrl+K) ------- */
.cmd-box {
    max-width: 580px; width: 100%; border-radius: var(--radius);
    padding: 0; box-shadow: 0 20px 40px rgba(0,0,0,.35);
}
.cmd-input-wrap {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.cmd-input-wrap input {
    flex: 1; border: none; background: transparent; padding: 0;
    font-size: 15px; font-weight: 500; color: var(--text); outline: none;
}
.cmd-badge {
    font-size: 11px; padding: 2px 6px; border-radius: 4px;
    background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border);
}
.cmd-results {
    max-height: 380px; overflow-y: auto; padding: 6px;
    display: flex; flex-direction: column; gap: 2px;
}
.cmd-item {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px; border-radius: var(--radius-sm);
    color: var(--text); text-decoration: none !important;
    cursor: pointer;
}
.cmd-item:hover, .cmd-item-selected {
    background: var(--surface-2); color: var(--accent);
}
.cmd-item-title { font-size: 13.5px; font-weight: 600; }
.cmd-item-desc { font-size: 11.5px; color: var(--text-2); }
.cmd-empty { padding: 24px; text-align: center; color: var(--text-2); font-size: 13px; }

/* ------- Akce v polích formuláře (oko, kopírovat) ------- */
.input-with-action { display: flex; align-items: center; gap: 6px; width: 100%; }
.input-with-action input { flex: 1; min-width: 0; }
.btn-eye-active { color: var(--accent); border-color: var(--accent); }

/* ------- Toast notifikace ------- */
.hub-toast {
    position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(100px);
    background: var(--surface); color: var(--text); border: 1px solid var(--border);
    padding: 9px 18px; border-radius: 999px; box-shadow: var(--shadow);
    font-size: 12.5px; font-weight: 600; z-index: 2000;
    transition: transform .25s ease, opacity .25s ease; opacity: 0; pointer-events: none;
}
.hub-toast-show { transform: translateX(-50%) translateY(0); opacity: 1; }

/* ------- Aktivní auto-refresh tlačítko ------- */
#auto-refresh-toggle.active {
    color: var(--ok); border-color: var(--ok); background: var(--wash-accent-soft);
}

/* ------- PWA na iOS: standalone (spuštěno z plochy) -------
   Hook je :root[data-standalone], NE @media (display-mode: standalone) –
   atribut nastavuje inline skript v head_meta.php ještě před načtením
   téhle tabulky stylů (bere v úvahu i navigator.standalone, spolehlivější
   napříč verzemi iOS než media query), takže nikdy neprobleskne
   "prohlížečová" varianta rozhraní. MUSÍ být na konci souboru. */

/* Bezpečná oblast nahoře (notch / Dynamic Island) a po stranách */
:root[data-standalone] .topbar {
    padding-top: calc(env(safe-area-inset-top) + 14px);
    padding-bottom: 8px;
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
}

@media (max-width: 760px) {
    :root[data-standalone] .rail {
        padding-top: calc(env(safe-area-inset-top) + 8px);
        padding-left: max(10px, env(safe-area-inset-left));
        padding-right: max(10px, env(safe-area-inset-right));
    }
    :root[data-standalone] .topbar {
        padding-top: 10px;
    }
}

@media (min-width: 761px) {
    :root[data-standalone] .rail {
        padding-top: calc(env(safe-area-inset-top) + 18px);
        padding-left: max(14px, env(safe-area-inset-left));
        padding-bottom: max(14px, env(safe-area-inset-bottom));
    }
}

/* Bezpečné odsazení obsahu a plovoucí lišty nad spodním home indikátorem */
:root[data-standalone] .content {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
    padding-bottom: calc(env(safe-area-inset-bottom) + 30px);
}

:root[data-standalone] .save-bar {
    bottom: calc(env(safe-area-inset-bottom) + 14px);
}

:root[data-standalone] .login-page {
    padding: calc(env(safe-area-inset-top) + 16px) max(16px, env(safe-area-inset-right))
             calc(env(safe-area-inset-bottom) + 16px) max(16px, env(safe-area-inset-left));
}

/* Potlačení "gumového" odrazu při svislém scrollu přes okraj */
:root[data-standalone], :root[data-standalone] body { overscroll-behavior-y: none; }

/* Vodorovně scrollované tabulky, logy a kód */
:root[data-standalone] .tbl-wrap,
:root[data-standalone] .log-box,
:root[data-standalone] .rail-nav,
:root[data-standalone] pre { overscroll-behavior-x: contain; }

/* touch-action: manipulation vypne ~300ms čekání na double-tap-zoom –
   okamžitá odezva na dotek */
:root[data-standalone] a, :root[data-standalone] button,
:root[data-standalone] .rail-item, :root[data-standalone] .icon-btn,
:root[data-standalone] .ext-link, :root[data-standalone] .proj-card {
    touch-action: manipulation;
}

/* Výchozí modré/šedé "bliknutí" prohlížeče při tapu nahrazeno čistým :active */
:root[data-standalone] * { -webkit-tap-highlight-color: transparent; }
:root[data-standalone] .rail-item:active { background: var(--surface-2); }
:root[data-standalone] button:active,
:root[data-standalone] .icon-btn:active { filter: brightness(.93); }
:root[data-standalone] .card:active { border-color: var(--accent); }
:root[data-standalone] .ext-link:active { background: var(--surface-2); }

/* Zákaz kontextového menu a nechtěného výběru textu u ovládacích prvků,
   ale zachování výběru u textů, tabulek, logů a inputů */
:root[data-standalone] .rail,
:root[data-standalone] .topbar,
:root[data-standalone] button,
:root[data-standalone] .pill,
:root[data-standalone] .tag {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
:root[data-standalone] .content,
:root[data-standalone] code,
:root[data-standalone] pre,
:root[data-standalone] input,
:root[data-standalone] textarea,
:root[data-standalone] table {
    -webkit-touch-callout: default;
    -webkit-user-select: text;
    user-select: text;
}

/* Tlačítka Zpět a Obnovit v topbaru (viditelná pouze ve standalone režimu) */
.tb-back, .tb-refresh { display: none; }
:root[data-standalone] .tb-back,
:root[data-standalone] .tb-refresh { display: inline-flex; }

