/* ============================================================
   StockManager — design tokens

   Akcent je navigace, průběh a akce. Sémantická barva je výhradně stav
   zboží — ty dvě se nikdy nemíchají.

   Inkoust má čtyři stupně, ne tři: --fg-0 je tvrzení a číslo, --fg-3 je
   popisek. Se třemi si popisek tabulky a doplňující věta brali týž odstín,
   takže hlavička sloupce vážila stejně jako jeho obsah.

   Plocha je vrstvená PRŮHLEDNÝM inkoustem (--layer-1..3), ne třemi
   samostatnými barvami. Proto v tmavém tématu nepotřebuje druhou sadu
   hodnot a proto vrstva nad vrstvou pořád funguje.

   Písmo má tři role, ne dvě: próza, tabulární číslo (--font-data) a
   strojový kód (--font-code). Číslo ve sloupci a SKU jsou různé věci,
   i když obojí vypadá „mono".
   ============================================================ */
/* ============================================================
   Písma — hostovaná, ne z CDN

   Content-Security-Policy téhle aplikace nepouští cizí hosty, takže woff2 leží
   v public/fonts a stahuje se odsud. Rozhodnuto vlastníkem 27. 8. 2026.

   DVĚ PODSADY, ne jedna. Podsada latin nese á é í ó ú ý, latin-ext nese č ď ě ň ř š ť ů ž —
   celé UI je česky, takže s jednou z nich by každé druhé slovo vypadlo do zálohy a věta
   by se sazbou rozpadla na dvě písma. Kdo přidá další řez, přidává ho dvakrát.

   Petrona je variabilní (jeden soubor pro 400–700), IBM Plex Mono má řez na soubor.
   Kurzíva Petrony se nestahuje, protože ji žádná obrazovka nepoužívá.
   ============================================================ */

@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/plex-mono-400-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/plex-mono-400-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/plex-mono-500-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/plex-mono-500-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/plex-mono-700-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/plex-mono-700-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Petrona";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/petrona-400-700-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Petrona";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/petrona-400-700-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
    /* teplý papír — kniha pohybů je papír, ne obrazovka */
    --paper:      #F4F1EB;
    --surface:    #FFFFFF;
    --layer-1:    rgba(28, 25, 23, .022);
    --layer-2:    rgba(28, 25, 23, .045);
    --layer-3:    rgba(28, 25, 23, .075);
    --line:       rgba(28, 25, 23, .085);
    --line-firm:  rgba(28, 25, 23, .16);
    /* Linka papíru, pevná linka a podbarvení sloupce, který řadí. Přidáno 27. 8. 2026.
       --band existuje proto, že --layer-1 má 2,2 % a na většině monitorů je pod prahem
       viditelnosti: pruhování jím vypadá jako žádné pruhování. --rule vyplňuje mezeru mezi
       --line (8,5 %, oddělení řádků) a --line-firm (16 %, obrys prvku): hlavička potřebuje
       linku, která je vidět, ale není to rámeček. */
    --band: rgba(28, 25, 23, .034);
    --rule: rgba(28, 25, 23, .14);
    --well: rgba(28, 25, 23, .028);

    /* inkoust ve čtyřech stupních */
    --fg-0: #16130F;
    --fg-1: #3D3730;
    --fg-2: #6B6259;
    --fg-3: #948A7E;

    /* inkoust dovozce; --accent-live jen pro položku panelu, na které stojím */
    --accent:       #1B3A5C;
    --accent-hover: #142C46;
    --accent-tint:  #2E6DA8;
    --accent-live:  #2E6DA8;
    --accent-wash:  rgba(27, 58, 92, .085);
    --accent-on:    #FFFFFF;

    /* odkaz v obsahu — vlastní token, ne accent: accent je akce a navigace */
    --link:       #1B3A5C;
    --link-hover: #142C46;

    /* značka ANHE */
    --anhe-paper:     #F1ECE7;
    --anhe-gold:      #B8965F;
    /* Zlatá čitelná jako TEXT. Do 27. 8. 2026 byla definovaná jen tady, tedy jen ve světlém
       tématu — v tmavém zůstala tmavohnědá na téměř černé. Obcházely to dva přepisy u
       konkrétních komponent (.tile-label, .figure.is-gold), které token přebíjely na
       --anhe-gold. Token má teď hodnotu ve všech tématech a ty přepisy jsou proto smazané:
       třetí obcházka by přišla s prvním dalším místem, kde se zlatá použije jako text. */
    --anhe-gold-deep: #8A6E3E;
    --anhe-ink:       #262626;
    --anhe-desk:      #E4DCD2;

    /* stav zboží — a nic jiného */
    --quarantine:    #8A4604;
    --quarantine-bg: rgba(184, 106, 20, .12);
    --warehouse:     #146B34;
    --warehouse-bg:  rgba(20, 107, 52, .11);
    --blocked:       #A81618;
    --blocked-bg:    rgba(168, 22, 24, .1);
    --exception:     #63189F;
    --exception-bg:  rgba(99, 24, 159, .1);

    /* směr zápisu v knize pohybů */
    --up:   #146B34;
    --down: #A81618;

    --radius:      10px;
    --radius-sm:   6px;
    --radius-hair: 3px;
    --shadow:      0 1px 2px rgba(28,25,23,.04), 0 4px 14px -6px rgba(28,25,23,.08);
    --shadow-lift: 0 2px 4px rgba(28,25,23,.06), 0 12px 26px -10px rgba(28,25,23,.14);

    /* Tři role, a od 27. 8. 2026 opravdu tři písma. Do té doby --font-data a --font-code
       byly ZNAK ZA ZNAKEM tentýž stack: tokeny tvrdily tři role a dodávaly dvě, takže číslo
       ve sloupci a SKU vypadaly stejně, i když to jsou různé věci.

       Próza zůstává systémová schválně. Je to nástroj, ve kterém někdo sedí celý den; vyměnit
       písmo běžného textu za webové znamená zaplatit stažení za text, který se nemá zdobit,
       ale číst. Nadpis a číslo jsou to, co drží tvar obrazovky, a ty webové jsou. */
    --font-text: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
    --font-disp: "Petrona", Georgia, "Times New Roman", serif;
    --font-data: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
    --font-code: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --paper: #14120F;
        --surface: #1C1A16;
        --layer-1: rgba(245, 241, 235, .028);
        --layer-2: rgba(245, 241, 235, .055);
        --layer-3: rgba(245, 241, 235, .085);
        --line: rgba(245, 241, 235, .09);
        --line-firm: rgba(245, 241, 235, .19);
        --anhe-gold-deep: #D9BC85;
        --band: rgba(245, 241, 235, .04);
        --rule: rgba(245, 241, 235, .2);
        --well: rgba(245, 241, 235, .032);
        --fg-0: #F6F2EC; --fg-1: #DCD4C9; --fg-2: #A69C8F; --fg-3: #7C7367;
        --accent: #A6C8EC; --accent-hover: #C6DDF6; --accent-tint: #7FA6D0;
        --accent-live: #C6DDF6; --accent-wash: rgba(166, 200, 236, .13); --accent-on: #10202F;
        --link: #A6C8EC; --link-hover: #C6DDF6;
        --quarantine: #EFAE5C; --quarantine-bg: rgba(239, 174, 92, .15);
        --warehouse: #69CE8A; --warehouse-bg: rgba(105, 206, 138, .14);
        --blocked: #EE8A8A; --blocked-bg: rgba(238, 138, 138, .14);
        --exception: #CBA2EF; --exception-bg: rgba(203, 162, 239, .14);
        --up: #69CE8A; --down: #EE8A8A;
        --shadow: 0 1px 2px rgba(0,0,0,.5), 0 4px 14px -6px rgba(0,0,0,.55);
        --shadow-lift: 0 2px 4px rgba(0,0,0,.5), 0 12px 26px -10px rgba(0,0,0,.65);
    }
}

:root[data-theme="light"] {
    --paper: #F4F1EB; --surface: #FFFFFF;
    --layer-1: rgba(28, 25, 23, .022);
    --layer-2: rgba(28, 25, 23, .045);
    --layer-3: rgba(28, 25, 23, .075);
    --line: rgba(28, 25, 23, .085); --line-firm: rgba(28, 25, 23, .16);
    --anhe-gold-deep: #8A6E3E;
    --band: rgba(28, 25, 23, .034);
    --rule: rgba(28, 25, 23, .14);
    --well: rgba(28, 25, 23, .028);
    --fg-0: #16130F; --fg-1: #3D3730; --fg-2: #6B6259; --fg-3: #948A7E;
    --accent: #1B3A5C; --accent-hover: #142C46; --accent-tint: #2E6DA8;
    --accent-live: #2E6DA8; --accent-wash: rgba(27, 58, 92, .085); --accent-on: #FFFFFF;
    --link: #1B3A5C; --link-hover: #142C46;
    --quarantine: #8A4604; --quarantine-bg: rgba(184, 106, 20, .12);
    --warehouse: #146B34; --warehouse-bg: rgba(20, 107, 52, .11);
    --blocked: #A81618; --blocked-bg: rgba(168, 22, 24, .1);
    --exception: #63189F; --exception-bg: rgba(99, 24, 159, .1);
    --up: #146B34; --down: #A81618;
    --shadow: 0 1px 2px rgba(28,25,23,.04), 0 4px 14px -6px rgba(28,25,23,.08);
    --shadow-lift: 0 2px 4px rgba(28,25,23,.06), 0 12px 26px -10px rgba(28,25,23,.14);
}

:root[data-theme="dark"] {
    --paper: #14120F;
    --surface: #1C1A16;
    --layer-1: rgba(245, 241, 235, .028);
    --layer-2: rgba(245, 241, 235, .055);
    --layer-3: rgba(245, 241, 235, .085);
    --line: rgba(245, 241, 235, .09);
    --line-firm: rgba(245, 241, 235, .19);
    --anhe-gold-deep: #D9BC85;
    --band: rgba(245, 241, 235, .04);
    --rule: rgba(245, 241, 235, .2);
    --well: rgba(245, 241, 235, .032);
    --fg-0: #F6F2EC; --fg-1: #DCD4C9; --fg-2: #A69C8F; --fg-3: #7C7367;
    --accent: #A6C8EC; --accent-hover: #C6DDF6; --accent-tint: #7FA6D0;
    --accent-live: #C6DDF6; --accent-wash: rgba(166, 200, 236, .13); --accent-on: #10202F;
    --link: #A6C8EC; --link-hover: #C6DDF6;
    --quarantine: #EFAE5C; --quarantine-bg: rgba(239, 174, 92, .15);
    --warehouse: #69CE8A; --warehouse-bg: rgba(105, 206, 138, .14);
    --blocked: #EE8A8A; --blocked-bg: rgba(238, 138, 138, .14);
    --exception: #CBA2EF; --exception-bg: rgba(203, 162, 239, .14);
    --up: #69CE8A; --down: #EE8A8A;
    --shadow: 0 1px 2px rgba(0,0,0,.5), 0 4px 14px -6px rgba(0,0,0,.55);
    --shadow-lift: 0 2px 4px rgba(0,0,0,.5), 0 12px 26px -10px rgba(0,0,0,.65);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--paper);
    color: var(--fg-0);
    font-family: var(--font-text);
    font-size: 14px;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-disp); text-wrap: balance; margin: 0; }

/* --- utility --------------------------------------------------- */

.eyebrow {
    font-size: 11px; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--fg-2);
}
.code { font-family: var(--font-code); font-size: .92em; letter-spacing: -.01em; }
.num  { font-family: var(--font-code); font-variant-numeric: tabular-nums; }
.hint { color: var(--fg-2); font-size: 14.5px; margin: 0; }
.lnk { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
.lnk:hover { color: var(--link-hover); }
.lnk:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.pill {
    display: inline-flex; align-items: center; gap: .35em;
    padding: 2px 8px; border-radius: 999px;
    font-size: 12px; font-weight: 650; letter-spacing: .01em;
    white-space: nowrap;
}
.pill-quarantine { background: var(--quarantine-bg); color: var(--quarantine); }
.pill-warehouse  { background: var(--warehouse-bg);  color: var(--warehouse); }
.pill-blocked    { background: var(--blocked-bg);    color: var(--blocked); }
.pill-exception  { background: var(--exception-bg);  color: var(--exception); }
/* Two tones that carry no item status: Správa badges a compliance rule with who it applies
   to, which is a fact about the rule and not about any batch. The mock draws those with its
   own .req-chip; a second badge vocabulary saying the same thing in the same place is what
   makes a stylesheet drift, so the pill grew the two tones it was missing instead. */
.pill-accent     { background: var(--accent-wash);   color: var(--accent); }
.pill-plain      { background: var(--layer-1);  color: var(--fg-1); }

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--accent-tint);
    outline-offset: 2px;
    border-radius: 4px;
}

/* --- kostra: panel, lišta obrazovky, plocha --------------------------
   Osm odkazů v jedné vodorovné liště se nedalo přečíst jako celek a
   neuneslo skupiny; panel je unese a ještě zbyde místo na to, aby u
   položky stálo, kolik tam čeká. Lišta zůstává jako `.topbar`, ale nese
   už jen jméno obrazovky, její kontext a akce, které na ni patří.
   ------------------------------------------------------------------- */

.app { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100vh; }

.rail {
    position: sticky; top: 0; align-self: start;
    height: 100vh;
    background: var(--layer-1);
    border-right: 1px solid var(--line);
    padding: 16px 12px 18px;
    display: flex; flex-direction: column; gap: 2px;
    overflow-y: auto;
}

/* Značka na trojnásobku (přání vlastníka 27. 8. 2026): logo 30 → 90 px, jméno 18 → 54 px.
   STOHOVANĚ, ne vedle sebe: panel je široký 236 px a po vnitřním okraji zbývá 212, kdežto
   devadesátipixelové logo plus „Sklad" v 54 px vedle sebe měří přes 230 — vedle sebe by se
   značka o panel neuřízla jen tak, že by přetekla. Nadpis pod logem se navíc čte jako
   podpis obrázku, což značka je. */
.brand {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 8px; padding: 4px 8px 20px;
}
.brand-logo { flex: none; height: 90px; width: auto; display: block; }
.brand-name {
    font-family: var(--font-disp); font-size: 54px; font-weight: 600;
    letter-spacing: -.02em; display: block; line-height: 1;
}
/* Nadřádek se nezvětšuje třikrát — vlastník řekl logo a jméno. Z 9,5 na 13 px jen proto, aby
   pod pětapadesátipixelovým jménem nevypadal jako překlep. */
.brand-sub {
    font-family: var(--font-data); font-size: 13px; letter-spacing: .16em;
    text-transform: uppercase; color: var(--anhe-gold-deep); display: block;
    margin-top: 4px;
}

/* the 安和 characters are charcoal and would vanish in a dark panel, so the mark
   flattens to a light silhouette rather than sitting on a backing plate */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .brand-logo { filter: brightness(0) invert(1); opacity: .9; }
}
:root[data-theme="dark"]  .brand-logo { filter: brightness(0) invert(1); opacity: .9; }
:root[data-theme="light"] .brand-logo { filter: none; opacity: 1; }

.rail-group {
    margin: 0; padding: 14px 9px 4px;
    font-size: 10.5px; font-weight: 600; letter-spacing: .09em;
    text-transform: uppercase; color: var(--fg-3);
}
.rail-item {
    display: flex; align-items: center; gap: 9px;
    padding: 7px 9px;
    border-radius: var(--radius-sm);
    font-size: 13px; color: var(--fg-1);
    text-decoration: none; white-space: nowrap;
}
.rail-item:hover { background: var(--layer-2); }
.rail-item[aria-current="page"] { background: var(--accent); color: var(--accent-on); font-weight: 600; }
/* Tečka říká, že za položkou něco stojí a čeká — v panelu širokém 232 px je to
   jediné, co se vedle názvu vejde, a pilulku by tam nikdo nepřečetl. */
.rail-item .dot { margin-left: auto; }
.rail-foot { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line); }
/* Přepnutí uživatele je tvarem řádek panelu, ale musí to být tlačítko ve formuláři:
   odkaz, který odhlašuje, umí spustit i prefetch prohlížeče bez kliknutí. */
.rail-user {
    display: flex; align-items: center; gap: 9px;
    padding: 6px 9px; width: 100%;
    border: 0; background: transparent; cursor: pointer;
    font-family: inherit; text-align: left;
    border-radius: var(--radius-sm);
}
.rail-user:hover { background: var(--layer-2); }
.rail-avatar {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    background: var(--anhe-gold); color: #1B1409;
    display: grid; place-items: center;
    font-size: 11px; font-weight: 700;
}
.rail-name { font-size: 12px; color: var(--fg-1); }

.topbar {
    position: sticky; top: 0; z-index: 5;
    display: flex; align-items: center; gap: 14px;
    padding: 11px 24px;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
}
.topbar h1 { font-size: 17px; font-weight: 600; letter-spacing: -.02em; }
.topbar-context { font-size: 12px; color: var(--fg-2); }
.topbar-tools { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* --- svislý rytmus obsahu --------------------------------------------
   Mezeru mezi bloky obrazovky vlastní SCHRÁNKA, ne bloky v ní. Čtyři schránky, jedno číslo.

   Do revize 27. 8. 2026 to tak měla jen `.screen`. `.page`, `.flow` a `.admin-main` mezeru
   neměly a spoléhaly na `.card + .card`, tedy na pravidlo, které platí jen když je předchozí
   sourozenec taky karta — za hláškou (`x-ui.note`) nebo za filtrem se karta nalepila s 0 px.
   Dorovnávalo se to ručně třídou `mt-16` na 26 místech a na třech se na ni zapomnělo
   (`documents/labels`, `admin/products/show`, `admin/products/index`). Tady se zapomenout nedá.

   `gap` a ne `> * + * { margin-top }`: mezera v mřížce (`.boards`, `.tiles`, `.doc-forms`)
   se tím nechá na `gap` té mřížky. Sousedský `+` do ní prosakoval a druhá karta v řádku
   začínala o 16 px níž než první — kvůli tomu tu stály tři rušící pravidla.
   ------------------------------------------------------------------- */

.screen, .page, .flow, .admin-main, .stack { display: flex; flex-direction: column; gap: 16px; }

/* `.stack` je pro OBAL uvnitř schránky, který sám staví karty pod sebe — formulář Správy, který
   drží dvě karty, nebo slovníček v Nápovědě. Schránka mu mezeru dát nemůže: `gap` platí jen pro
   vlastní potomky, takže dvě karty uvnitř `<form>` se lepily s 0 px. Bez pojmenování by se to
   řešilo obnovením `.card + .card`, a to je právě to pravidlo, které prosakovalo do mřížek. */

.screen { padding: 20px 24px 44px; }

/* Tečka stavu — kompaktní náhrada pilulky tam, kde jde o stav a ne o jeho jméno. */
.dot { width: 6px; height: 6px; border-radius: 50%; flex: none; display: inline-block; }
.dot-quarantine { background: var(--quarantine); }

/* Pod 900 px se panel stává vodorovným pásem: skupiny a patička odejdou,
   protože v jednom řádku nemají co dělat, a zbydou samotné odkazy. */
@media (max-width: 900px) {
    .app { grid-template-columns: minmax(0, 1fr); }
    .rail {
        position: static; height: auto;
        flex-direction: row; align-items: center;
        overflow-x: auto; padding: 8px 12px;
        border-right: 0; border-bottom: 1px solid var(--line);
    }
    /* Pod 900 px je panel vodorovný pás. Trojnásobná značka by z něj udělala pás vysoký
       110 px, tedy čtvrtinu telefonu, ještě než se ukáže první položka. */
    .brand { flex-direction: row; align-items: center; gap: 10px; padding: 0 10px 0 4px; }
    .brand-logo { height: 30px; }
    .brand-name { font-size: 18px; letter-spacing: -.01em; }
    .brand-sub, .rail-group, .rail-foot { display: none; }
    .rail-item { padding: 6px 10px; }
    .topbar { padding: 10px 16px; }
    .screen { padding: 16px 16px 32px; }
}

/* --- home / task chooser ---------------------------------------- */

.page { max-width: 1080px; margin: 0 auto; padding: 40px 20px 56px; }
.page-wide { max-width: 1320px; }

/* Nadřádek a věta, kterou obrazovka otevírá. Nadpis nemá: jméno obrazovky nese lišta.
   Osm pixelů NAD mezeru schránky, tedy 24 místo 16: pod úvodní větou má být o něco víc
   vzduchu než mezi kartami, jinak čte jako první řádek prvního bloku. */
.ask { margin-bottom: 8px; }

.chain { display: grid; gap: 10px; }
@media (min-width: 900px) { .chain { grid-template-columns: repeat(3, 1fr); } }

.act {
    position: relative; display: flex; flex-direction: column; gap: 6px;
    padding: 16px 18px 18px;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow);
    text-align: left; font: inherit; color: inherit; cursor: pointer;
    transition: box-shadow .16s ease, transform .16s ease, border-color .16s ease;
}
.act:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); border-color: var(--line-firm); }
.act-head { display: flex; align-items: center; gap: 10px; }
.act-step {
    flex: none; width: 24px; height: 24px; border-radius: 6px;
    background: var(--accent-wash); color: var(--accent);
    font-family: var(--font-code); font-size: 12px; font-weight: 700;
    display: grid; place-items: center;
}
.act-name { font-family: var(--font-disp); font-weight: 650; font-size: 17px; letter-spacing: -.01em; }
.act-what { color: var(--fg-2); font-size: 14px; }
.act-count { margin-top: 4px; }
.act-key {
    position: absolute; top: 14px; right: 14px;
    font-family: var(--font-code); font-size: 11px; color: var(--fg-2);
    border: 1px solid var(--line); border-radius: 4px; padding: 0 5px;
}

/* Popisek nad blokem, ke kterému patří: nahoře vzduch, dole nic — mezeru pod ním by
   schránka přidala znovu a popisek by se vznášel mezi dvěma bloky bez vazby na jeden. */
.strip-label { margin: 18px 0 -6px; }

/* Poměr, kde zásoba leží — tentýž tvar jako pruh na rozcestníku, jen menší. */
.split {
    display: block; width: 100%; max-width: 120px; height: 5px;
    border-radius: var(--radius-hair);
    overflow: hidden;
    background: var(--layer-2);
}
.split-seg-quarantine { fill: var(--quarantine); }
.split-seg-warehouse  { fill: var(--warehouse); }
.col-split { width: 12%; }

/* --- dlaždice hodnoty na rozcestníku --------------------------------
   Číslo je tvrzení obrazovky, takže má hmotnost a negativní tracking;
   nad ním mikrolabel a pod ním věta, která říká, odkud to číslo je a co
   s ním. Pruh po kusech, který tu stál dřív, sčítal nesouměřitelné věci
   — koruny a dny se sčítat dají, kusy různého zboží ne.
   ------------------------------------------------------------------- */

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); gap: 12px; }

/* Barva dlaždice říká, ČÍM to číslo je, a proto se nesmí brát z palety stavu zboží — ta
   znamená karanténu, sklad, blokováno, výjimku a nic jiného (viz hlavička tohoto souboru).
   Rozvrh je tedy:

     hodnota zásoby → akcent, protože je to fakt o skladu a cesta na Stav skladu,
     drží karanténa → --quarantine, protože ta dlaždice DOSLOVA mluví o zboží v karanténě,
     nehýbe se      → --anhe-gold, značková barva bez sémantiky stavu: zlato, které leží.

   Decentnost je v tom, kolik barvy: plocha ji nese v osmi procentech, plnou barvu má jen
   svislá hrana a číslo. Vybarvit celou dlaždici by znamenalo tři křiklavé plochy vedle sebe
   a čtvrtou informaci — „která je důležitější" — kterou nikdo nezadal. */
.tile {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 15px 17px 14px;
    display: flex; flex-direction: column; gap: 6px;
    text-decoration: none; color: inherit;
    overflow: hidden;
}
/* Svislá hrana je ::before, ne border-left: s borderem by se o tři pixely rozešla vnitřní
   šířka dlaždic, které hranu mají, a těch bez ní. */
.tile::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--line-firm);
}
a.tile:hover { border-color: var(--line-firm); box-shadow: var(--shadow-lift); }

.tile-value  { background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.tile-value::before { background: var(--accent); }
.tile-value .tile-label { color: var(--accent); }

.tile-held  { background: color-mix(in srgb, var(--quarantine) 8%, var(--surface)); }
.tile-held::before { background: var(--quarantine); }
.tile-held .tile-label { color: var(--quarantine); }

.tile-idle  { background: color-mix(in srgb, var(--anhe-gold) 10%, var(--surface)); }
.tile-idle::before { background: var(--anhe-gold); }
.tile-idle .tile-label { color: var(--anhe-gold-deep); }

.tile-label {
    font-size: 10.5px; font-weight: 650; letter-spacing: .09em;
    text-transform: uppercase; color: var(--fg-3);
}
.tile-note { font-size: 11.5px; color: var(--fg-2); line-height: 1.45; }
.tile-note .code { color: var(--fg-1); }

/* Číslo, které je tvrzením obrazovky. */
.figure {
    font-family: var(--font-data); font-variant-numeric: tabular-nums;
    font-size: 29px; font-weight: 600; letter-spacing: -.035em; line-height: 1.02;
    color: var(--fg-0);
    display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.figure small {
    font-family: var(--font-text); font-size: 12px; font-weight: 500;
    letter-spacing: 0; color: var(--fg-2);
}
.figure.is-quarantine { color: var(--quarantine); }
.figure.is-gold { color: var(--anhe-gold-deep); }

/* Sekce rozcestníku: co stojí a nehýbe se.
   Řádek je grid o dvou sloupcích, ne o pěti. Pět sloupců dávalo pěti údajům stejnou váhu,
   a čtenář z nich musel poskládat, který řádek je nejhorší — přitom právě jedno z nich
   (chybějící kusy, dny v karanténě) je to jediné, podle čeho se řadí priorita. To číslo
   proto stojí samo vlevo, má hmotnost a pod sebou jednotku; identita a věta „co s tím
   udělat“ jdou vpravo pod sebe. Číslo nese pohled, věta nese akci. */
.boards { display: grid; gap: 14px; }
@media (min-width: 1100px) { .boards { grid-template-columns: 1fr 1fr; } }
/* Grid srovná bílou plochu obou karet, ale ne to, co je v ní: jedna karta má tři řádky a
   větu o hranici, druhá dva a nic, takže se paty rozjely a karty vypadaly různě vysoké.
   Karta je proto sloupec, tělo v ní roste a pata se drží spodní hrany — pak sedí obě
   paty na stejné lince bez ohledu na to, kolik řádků nad nimi je. */
.boards > .card { display: flex; flex-direction: column; }
.boards > .card > .card-body { flex: 1; }
.boards .board-foot { margin-top: auto; }

/* `.board-head` je zrušená (27. 8. 2026). Byla to DRUHÁ hlavička karty: flex řádek uvnitř
   těla, bez linky, kdežto `.card-head` každé jiné karty v aplikaci `border-bottom` má. Proto
   hlavička těchhle dvou karet splývala s obsahem — nechyběla mezera, chyběla ta hlavička.
   Karty teď předávají `title` do `x-ui.card` jako všechny ostatní. */

/* Tělo karty s tabulí nemá vnitřní okraj: linkovaný papír musí jít od hrany ke hraně,
   jinak pruh končí 18 px před okrajem karty a čte se jako podbarvený blok, ne jako linka. */
.board-card > .card-body { padding: 0; }
.board { display: grid; }
.board-row {
    position: relative;
    display: grid;
    grid-template-columns: 5.25rem minmax(0, 1fr);
    column-gap: 16px;
    padding: 11px 18px 11px 15px;
    align-items: start;
    /* Obě karty stojí vedle sebe v mřížce 1fr 1fr a jejich řádky mají různý počet vět:
       Karanténa dvě, Pod minimem tři (`.board-do`). Bez pevné výšky proto řádky napříč
       mezerou nesedí na stejných linkách a dvě karty se čtou jako jedna rozbitá tabulka. */
    min-height: 4.75rem;
}
/* Linka papíru. */
.board-row:nth-child(even) { background: var(--band); }
/* Stavová hrana (rozhodnutí vlastníka 27. 8. 2026). NENÍ to podbarvený řádek — dřívější
   rozhodnutí, že za hranou obarví jedině číslo a ne řádek, platí dál a pořád se pozná,
   který řádek je první. Hrana říká stav zboží, tedy jedinou věc, o které v téhle aplikaci
   sémantická barva mluví. */
.board-row::before {
    content: "";
    position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--line-firm);
}
.board-row.over::before  { background: var(--quarantine); }
.board-row.short::before { background: var(--blocked); }
/* Pravá strana je vlastní sloupec, ne další položky téhož gridu: karanténa má o řádek víc
   než Pod minimem („chybí v regálu“), a s auto-placementem by ten řádek spadl pod číslo. */
.board-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.board-row + .board-row { border-top: 1px solid var(--line); }

/* Číslo, podle kterého se řádky řadí. */
/* Sloupec, který řadí, je vidět JAKO sloupec: číslo sedí ve vlastním podbarveném poli,
   ne volně v řádku. Písmo je --font-data, tedy to tabulární — ne --font-code, který je
   pro SKU. */
.board-fig {
    text-align: right;
    font-family: var(--font-data);
    font-variant-numeric: tabular-nums;
    font-size: 23px;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--fg-0);
    align-self: start;
    padding: 2px 10px 4px;
    background: var(--well);
    border-radius: var(--radius-hair);
}
.board-fig small {
    display: block;
    font-family: var(--font-data);
    font-size: 9.5px;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--fg-2);
    margin-top: 3px;
}
/* Za hranou obarví jedině to číslo. Podbarvit celý řádek znamenalo, že se v kartě se
   třemi řádky ztratí, který z nich je ten nejstarší. */
.board-row.over .board-fig { color: var(--quarantine); }
.board-row.short .board-fig { color: var(--blocked); }

.board-id { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; min-width: 0; }
.board-code { font-family: var(--font-code); font-weight: 700; font-size: 13.5px; }
.board-label { color: var(--fg-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-note { color: var(--fg-2); font-size: 12.5px; }
/* Co s tím řádkem udělat — věta, ne sloupec, a proto smí být odkaz. */
.board-do { font-size: 13px; color: var(--accent); text-decoration: none; }
.board-do:hover { text-decoration: underline; }
.board-need {
    color: var(--blocked); font-size: 11px; font-weight: 700;
    letter-spacing: .05em; text-transform: uppercase;
}
/* Věta, která vysvětluje, co v kartě znamená „za hranou". Je to legenda, ne akce, takže
   sedí pod lištou akcí a bez podkladu — jinak by soutěžila s tlačítky nad sebou. */
.board-legend {
    padding: 10px 18px 12px; font-size: 12.5px;
    border-top: 1px solid var(--line);
}

/* Patro karty, ne poslední řádek jejího těla: akce sedí pod pevnou linkou a na podkladu,
   takže je u obou karet na stejné lince bez ohledu na to, kolik mají řádků. */
.board-foot {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 12px 18px; border-top: 1px solid var(--rule);
    background: var(--layer-1);
}
.board-foot:last-child { border-radius: 0 0 var(--radius) var(--radius); }
.board-legend:last-child { border-radius: 0 0 var(--radius) var(--radius); }

/* --- stepper (narrow step bar) ----------------------------------- */

.stepper {
    position: sticky; top: 0; z-index: 20;
    display: flex; background: var(--surface);
    border-bottom: 1px solid var(--line);
    overflow-x: auto; scrollbar-width: none;
}
.stepper::-webkit-scrollbar { display: none; }

.step {
    flex: 1 0 auto; min-width: 118px;
    display: flex; align-items: center; gap: 8px;
    padding: 9px 14px 8px;
    border: 0; border-bottom: 3px solid var(--line);
    background: transparent; font: inherit; color: var(--fg-2);
    cursor: default; white-space: nowrap;
}
.step-mark {
    flex: none; width: 19px; height: 19px; border-radius: 50%;
    display: grid; place-items: center;
    font-family: var(--font-code); font-size: 11px; font-weight: 700;
    border: 1.5px solid var(--line-firm); color: var(--fg-2);
}
.step-name { font-size: 13.5px; }

.step.done { color: var(--fg-1); border-bottom-color: var(--accent); cursor: pointer; }
.step.done .step-mark { background: var(--accent); border-color: var(--accent); color: var(--accent-on); }
.step.done:hover { background: var(--accent-wash); }

.step.now { color: var(--fg-0); border-bottom-color: var(--accent); background: var(--accent-wash); }
.step.now .step-mark { border-color: var(--accent); color: var(--accent); border-width: 2px; }
.step.now .step-name { font-weight: 700; }

.step.next .step-name { opacity: .75; }

/* context strip — shows what's already selected, so nobody gets lost */
.context {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    padding: 9px 20px; background: var(--layer-1);
    border-bottom: 1px solid var(--line);
    font-size: 13px; color: var(--fg-2);
}
.chip {
    display: inline-flex; align-items: baseline; gap: 6px;
    padding: 2px 9px; background: var(--surface);
    border: 1px solid var(--line); border-radius: 999px;
}
.chip b { font-weight: 600; color: var(--fg-1); font-family: var(--font-code); font-size: 12.5px; }

/* --- form column -------------------------------------------------- */

.flow { max-width: 760px; margin: 0 auto; padding: 28px 20px 40px; }
/* Věta o kroku sedí nad oběma sloupci, takže druhý blok navazuje bez horního odsazení. */
.flow-body { padding-top: 0; }

/* Dvousloupcové tělo kroku: obsah a rekapitulace. Sloupec vpravo je sticky, protože
   „do jaké šarže zapisuji" musí být vidět i po deseti naskenovaných řádcích — jako řada
   chipů nad obsahem to při delším výpisu odjelo z obrazovky. */
.flow-split {
    max-width: 1180px;
    display: grid; grid-template-columns: minmax(0, 1fr) 264px;
    gap: 20px; align-items: start;
}
.flow-main { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.flow-recap { position: sticky; top: 76px; }
@media (max-width: 1040px) {
    .flow-split { grid-template-columns: minmax(0, 1fr); }
    .flow-recap { position: static; }
}

.recap { display: flex; flex-direction: column; }
.recap-line {
    display: flex; align-items: baseline; gap: 10px;
    padding: 8px 16px; font-size: 12.5px;
}
.recap-line + .recap-line { border-top: 1px solid var(--line); }
.recap-label { flex: none; width: 74px; color: var(--fg-3); font-size: 11.5px; }
.recap-line b { font-family: var(--font-code); font-weight: 650; color: var(--fg-0); }
.flow-wide { max-width: 1000px; }

.step-head { margin-bottom: 8px; }
/* Veta, ktera krok vysvetluje. Jmeno kroku nese lista, tak zbyva jen tohle. */
.step-hint { margin: 0 0 4px; }

.card {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.card-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 13px 18px; border-bottom: 1px solid var(--rule);
}
.card-head h2 { font-size: 15px; font-weight: 650; }
.card-body { padding: 18px; }
/* Zrcadlí .ledger-foot: věta pod tabulkou, která říká, co součet znamená. */
.card-foot {
    padding: 10px 18px; border-top: 1px solid var(--line);
    font-size: 13px; color: var(--fg-2);
}

.fields { display: grid; gap: 16px; }
@media (min-width: 640px) { .fields-2 { grid-template-columns: 1fr 1fr; } }

.field { display: flex; flex-direction: column; gap: 5px; }
.field > label { font-size: 13.5px; font-weight: 600; color: var(--fg-1); }
.field small { color: var(--fg-2); font-size: 12.5px; }

input[type="text"], input[type="date"], input[type="number"], select, textarea {
    font: inherit; font-size: 15px; color: var(--fg-0);
    background: var(--surface); border: 1px solid var(--line-firm);
    border-radius: var(--radius-sm); padding: 9px 11px; width: 100%;
    min-height: 42px; /* touch target */
}
input.code-in, .num-in { font-family: var(--font-code); font-variant-numeric: tabular-nums; }
input:hover, select:hover { border-color: var(--fg-2); }
input.bad, .bad { border-color: var(--blocked); background: var(--blocked-bg); }

.err { color: var(--blocked); font-size: 13px; display: flex; gap: 6px; align-items: flex-start; }

/* --- tables --------------------------------------------------------- */

.tbl-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
/* Hlavička sloupce: tabulární písmo a PEVNÁ linka pod sebou. Vlasovka na 8,5 % držela
   hlavičku a první řádek na stejné váze, takže se osmisloupcová tabulka neměla o co zachytit. */
th {
    text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--fg-2);
    font-family: var(--font-data);
    padding: 10px 12px; border-bottom: 1px solid var(--rule);
    background: var(--surface); position: sticky; top: 0;
}
/* Linkovaný papír: řádky odděluje PRUH, ne linka pod každým z nich. Osm sloupců se po
   vlasovkách nečte — oko po řádku ujede a čte číslo z řádku vedle. Rozhodnuto vlastníkem
   27. 8. 2026. Podbarvuje se každý druhý, takže linka nese informaci „tenhle řádek je jeden
   celek", ne dekoraci. */
td { padding: 9px 12px; }
tbody tr:nth-child(even) { background: var(--band); }
tbody tr:hover { background: var(--accent-wash); }
.r { text-align: right; }
td.qty, th.qty { text-align: right; font-family: var(--font-code); font-variant-numeric: tabular-nums; }
/* Znaménko říká směr, barva ho říká rychleji — kniha pohybů se čte dolů po sloupci. */
.qty-in  { color: var(--warehouse); font-weight: 650; }
.qty-out { color: var(--blocked); font-weight: 650; }
.tbl-dense td, .tbl-dense th { padding: 7px 12px; }
/* Podřádek FIFO je součást řádku nad sebou, takže pruh dědí od něj, ne od své parity. */
.sub-row:nth-child(even), .sub-row:nth-child(odd) { background: var(--layer-1); }
/* Podřádek patří k řádku nad sebou: potopený papír a svislá čára v prvním, prázdném
   sloupci. V rozpadu FIFO to je rozdíl mezi „tyhle šarže patří k této položce“ a plochým
   seznamem, ze kterého vazba není vidět. */
.sub-row td { background: var(--layer-1); color: var(--fg-1); font-size: 13.5px; }
.sub-row td:first-child { padding-left: 34px; position: relative; }
.sub-row td:first-child::before {
    content: ""; position: absolute; left: 18px; top: 0; bottom: 0;
    border-left: 2px solid var(--line-firm);
}
.tbl-scan td { padding: 5px 8px; vertical-align: middle; }
.tbl-scan input { min-height: 38px; }
/* Buňka akcí: tlačítko a hláska na jedné lince a zarovnané na střed řádku, aby „Zavést SKU"
   sedělo ve stejné výšce jako číslo v poli množství vedle. Wrap, protože hláska o neznámém
   SKU je delší než sloupec a lámat se musí ona, ne tlačítko. */
.tbl-scan .col-actions {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.tbl-scan .col-actions .btn { flex: none; }
/* Řádek pod tabulkou: „Další položka" a věta o zahazování prázdných řádků. Tlačítko vkládá
   scanner.js, protože bez JavaScriptu je vidět všech deset řádků a přidávat není co. */
.scan-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 4px; }

/* --- checklist -------------------------------------------------------
   Odpověď je slovo, ne značka. Do návrhu 2027 to byly tři čtverce 34 px
   s „Ano / Ne / —" a čtvrtý s „?"; pomlčka není odpověď, kterou by šlo
   přečíst ani slyšet, a enum si to sám přiznával v docblocku. Segmentovaný
   přepínač unese celé slovo, takže hádat nemusí nikdo.
   ------------------------------------------------------------------- */

.check { display: grid; gap: 8px; padding: 15px 18px; }
.check + .check { border-top: 1px solid var(--line); }
.check-top { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.check-name { font-size: 13.5px; font-weight: 600; color: var(--fg-0); }
.check-why { color: var(--fg-2); font-size: 12px; max-width: 74ch; line-height: 1.45; }
.check-req { font-size: 11px; }

.segs {
    display: inline-flex; align-self: start;
    border: 1px solid var(--line-firm);
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface);
}
/* Návrh kreslí segmenty jako <button>, což nemůže nést hodnotu formuláře a potřebovalo by
   JavaScript, který CSP téhle aplikace nepustí. Jsou to skutečné radiobuttony: input sedí
   uvnitř labelu, je vyňatý z kresby a label si čte svůj vlastní :checked. Klávesnice a
   čtečka dostanou pravou skupinu radiobuttonů, oko dostane návrh. */
.seg {
    position: relative;
    display: inline-flex; align-items: center;
    padding: 6px 11px;
    font-family: inherit; font-size: 12px; font-weight: 600;
    color: var(--fg-2); cursor: pointer; white-space: nowrap;
}
.seg + .seg { border-left: 1px solid var(--line); }
.seg input {
    position: absolute; width: 1px; height: 1px;
    opacity: 0; margin: 0; pointer-events: none;
}
.seg:hover { background: var(--layer-2); }
.seg:has(input:focus-visible) { outline: 2px solid var(--accent-tint); outline-offset: -2px; }

.seg.on-yes:has(input:checked) { background: var(--warehouse-bg); color: var(--warehouse); }
.seg.on-no:has(input:checked)  { background: var(--blocked-bg);   color: var(--blocked); }
.seg.on-na:has(input:checked)  { background: var(--exception-bg); color: var(--exception); }
.seg.on-off:has(input:checked) { background: var(--layer-3);      color: var(--fg-1); }

/* Dvě stejně široká pole, ne 1.3 : 1. „Doloženo čím" a „poznámka" jsou vedle sebe a různá
   šířka u dvou sousedních polí bez důvodu čte jako nedodělek — a důvod tu není, protože do
   obou se píše věta. */
.check-proof { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; max-width: 660px; }
@media (max-width: 800px) { .check-proof { grid-template-columns: minmax(0, 1fr); } }
.check-proof input { width: 100%; }

/* Důvod, který rozhoduje o zápisu, se ptá sám a hned — ne až chybou po uložení. */
/* Vykřičník před větou, ne ikona: je to jediný znak, který se vytiskne i přečte. */
.note-mark { flex: none; font-weight: 700; }

.check-need {
    display: flex; align-items: baseline; gap: 7px;
    margin: 0; padding: 7px 11px;
    border-radius: var(--radius-sm);
    background: var(--exception-bg); color: var(--exception);
    font-size: 12px; line-height: 1.45;
    max-width: 74ch;
}

/* --- zapsané řádky na obrazovce Hotovo ------------------------------
   Monospace řádky na potopeném papíru. Návrh je používá na všech šesti obrazovkách
   Hotovo — je to výpis toho, co právě dosedlo do knihy, ne knihu samotnou; ta je
   tabulka (.tbl-ledger). Obojí bylo v repu prohozené: kniha se kreslila těmito řádky
   a Hotovo tabulkou. Kniha je narovnaná, Hotovo čeká na vlastní úkol, protože k výpisu
   s ID pohybu musí zapisovací cesta ta ID vrátit. Do té doby tyhle třídy nikdo nepoužívá
   — smazat je by ale znamenalo zahodit tvar, který návrh šestkrát kreslí. */

.ledger {
    background: var(--layer-1);
    border: 1px solid var(--line); border-radius: var(--radius);
    overflow: hidden;
}
.ledger-head {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 11px 16px; border-bottom: 1px solid var(--line);
    background: var(--surface);
}
.ledger-lines { margin: 0; padding: 12px 16px; overflow-x: auto; }
.ledger-line {
    font-family: var(--font-code); font-size: 13px;
    font-variant-numeric: tabular-nums; white-space: pre;
    color: var(--fg-1); line-height: 1.85;
}
.ledger-line b { color: var(--fg-0); font-weight: 700; }
.ledger-foot {
    padding: 10px 16px; border-top: 1px solid var(--line);
    font-size: 13px; color: var(--fg-2);
}

.done-mark {
    display: flex; align-items: center; gap: 14px; margin-bottom: 20px;
}
.done-mark .ring {
    flex: none; width: 44px; height: 44px; border-radius: 50%;
    background: var(--warehouse-bg); color: var(--warehouse);
    display: grid; place-items: center; font-size: 22px; font-weight: 700;
}
.done-mark h2 { font-size: 24px; letter-spacing: -.02em; }

.next-acts { display: grid; gap: 10px; margin-top: 8px; }
@media (min-width: 640px) { .next-acts { grid-template-columns: 1fr 1fr; } }

/* --- action bar ------------------------------------------------------ */

/* Patka OBRAZOVKY: „Zpět" a hlavní akce kroku, oddělené linkou od obsahu nad sebou.
   Odsazení a linka jsou její celý smysl. */
.bar {
    display: flex; align-items: center; gap: 12px;
    margin-top: 24px; padding-top: 18px; border-top: 1px solid var(--line);
}
.bar-spacer { flex: 1; }

/* Řádek formuláře v PATŘE KARTY — jiná práce, jiné jméno (27. 8. 2026).
   Do té doby tuhle roli hrála `.bar`, tedy patka obrazovky s `margin-top: 24px` a linkou.
   Šest karet Dokumentů ji tak používalo uvnitř sebe, takže každá dostala linku a 24px mezeru
   na jiné výšce — podle délky svého popisku. V kartě „Kniha pohybů za období" navíc `.bar`
   sedělo VNOŘENÉ v mřížce `.fields-2`, takže linka i tlačítko skončily v buňce mřížky.
   Tlačítka tím byla rozházená na šesti různých výškách; příčinou nebyl vzhled, ale jedna
   třída ve dvou rolích. */
.form-row {
    display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
    margin: 0; padding: 12px 18px;
    border-top: 1px solid var(--line);
    background: var(--layer-1);
    border-radius: 0 0 var(--radius) var(--radius);
}
/* Akce vpravo, aby u všech karet stála na téže svislici. */
.form-row > .btn { margin-left: auto; }

/* Karta s formulářem: popisek roste, patro zůstává dole. */
.doc-card { display: flex; flex-direction: column; }
.doc-card > .card-body { flex: 1; display: flex; flex-direction: column; gap: 12px; }

/* Tlačítko musí vypadat jako tlačítko, i když je to odkaz.
   `text-decoration: none` je tady kvůli tomu, že bez něj bylo KAŽDÉ tlačítko, které je
   `<a>`, podtržené — .act, .view a .step to měly, .btn ne. Plochu má i `ghost`: na papírovém
   podkladu je průhledné tlačítko jen rámeček kolem textu. A hover se musí poznat, takže je
   to vrstva 2, ne vrstva 1 (ta má 2,2 % inkoustu, což je pod hranicí viditelnosti). */
.btn {
    font: inherit; font-size: 15px; font-weight: 600;
    padding: 11px 20px; min-height: 44px; border-radius: var(--radius-sm);
    border: 1px solid transparent; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    text-decoration: none;
    transition: background .14s ease, border-color .14s ease, transform .06s ease;
}
a.btn, a.btn:hover, a.btn:visited { text-decoration: none; }
/* Stisk je vidět: o pixel dolů. Bez toho není u dotykové obrazovky poznat, že to reagovalo. */
.btn:active { transform: translateY(1px); }

.btn-primary { background: var(--accent); color: var(--accent-on); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-ghost { background: var(--surface); color: var(--fg-1); border-color: var(--line-firm); }
.btn-ghost:hover { background: var(--layer-2); border-color: var(--fg-3); }
/* The one irreversible button in Správa. Outlined rather than filled: it is offered only
   where deleting is actually possible, and it should still not be the loudest thing on the
   screen — the ordinary answer to "this SKU is over" is discontinuing it, not deleting it. */
.btn-danger { background: transparent; color: var(--blocked); border-color: var(--blocked); }
.btn-danger:hover { background: var(--blocked-bg); border-color: var(--blocked); }
/* Nejtišší tlačítko: bez plochy, tlumeným inkoustem — ale s hranou.
   Do 27. 8. 2026 mělo `border-color: transparent` a rámeček dostávalo až po `:hover`. Obhajoba
   v tomhle docblocku zněla „nemá soutěžit s hlavní akcí" a na obrazovce, kde hlavní akce je,
   platí. Na rozcestníku ale žádná není: „Odškrtat kontroly" a „Uvolnit z karantény" JSOU ty
   akce a jsou to v obou kartách jediná tlačítka — takže nejdůležitější ovládání obrazovky bylo
   k nerozeznání od popisku, dokud po něm někdo nejel myší. Tiché zůstává tím, že nemá plochu. */
.btn-quiet {
    background: transparent; color: var(--fg-1);
    border-color: var(--line-firm); padding-inline: 10px;
}
.btn-quiet:hover { background: var(--layer-2); color: var(--fg-0); border-color: var(--fg-3); }
.btn-sm { font-size: 13.5px; padding: 6px 11px; min-height: 34px; }

.note {
    display: flex; gap: 10px; padding: 13px 15px;
    border-radius: var(--radius); font-size: 14px; line-height: 1.45;
}
.note-quarantine { background: var(--quarantine-bg); color: var(--quarantine); }
.note-blocked    { background: var(--blocked-bg);    color: var(--blocked); }
.note-plain      { background: var(--accent-wash);   color: var(--fg-1); }
.note b { font-weight: 700; }
.note-ico { flex: none; font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============================================================
   LOGIN — the one place the ANHE brand leads.
   A sheet of paper on a desk. The desk follows the theme,
   the sheet stays cream so the logo keeps its ground.
   ============================================================ */

.gate {
    min-height: 100vh; display: grid; place-items: center;
    padding: 40px 20px 100px;
    background:
        radial-gradient(ellipse 90% 60% at 50% 0%, #EFE8DF 0%, transparent 70%),
        var(--anhe-desk);
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .gate {
        background: radial-gradient(ellipse 90% 60% at 50% 0%, #201C17 0%, transparent 70%), #14120F;
    }
}
:root[data-theme="light"] .gate {
    background: radial-gradient(ellipse 90% 60% at 50% 0%, #EFE8DF 0%, transparent 70%), var(--anhe-desk);
}
:root[data-theme="dark"] .gate {
    background: radial-gradient(ellipse 90% 60% at 50% 0%, #201C17 0%, transparent 70%), #14120F;
}

.sheet {
    width: min(430px, 100%);
    background: var(--anhe-paper);
    color: var(--anhe-ink);
    border-radius: 2px; /* paper does not round off */
    padding: 42px 40px 34px;
    box-shadow: 0 1px 2px rgba(38,38,38,.10), 0 18px 50px -18px rgba(38,38,38,.38);
    animation: settle .5s cubic-bezier(.2,.7,.3,1) both;
}
@keyframes settle { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.sheet-logo {
    width: 218px; height: 232px; margin: 0 auto 18px;
    /* The lockup without the claim line: .sheet-tagline prints the claim right below,
       and the repo's anhe-logo.png already has it baked in, which would say it twice. */
    background: url("../img/anhe-lockup.png") center / contain no-repeat;
    animation: ink .9s ease-out .1s both;
}
@keyframes ink { from { opacity: 0; } to { opacity: 1; } }

.sheet-tagline {
    margin: 0; text-align: center;
    font-size: 10.5px; font-weight: 600; letter-spacing: .16em; line-height: 1.7;
    text-transform: uppercase; color: var(--anhe-gold-deep);
}

/* taken from the brand lockup: —— 安和 —— */
.sheet-rule {
    display: flex; align-items: center; gap: 14px;
    margin: 26px 0 24px;
}
.sheet-rule::before, .sheet-rule::after {
    content: ""; flex: 1; height: 1px; background: var(--anhe-gold);
    transform: scaleX(0); transform-origin: center;
    animation: draw .7s cubic-bezier(.3,.8,.4,1) .35s both;
}
@keyframes draw { to { transform: scaleX(1); } }
.sheet-rule span {
    font-size: 10.5px; font-weight: 700; letter-spacing: .18em;
    text-transform: uppercase; color: var(--anhe-ink); white-space: nowrap;
}

.sheet-fields { display: grid; gap: 15px; }
.sheet-fields label {
    display: block; margin-bottom: 5px;
    font-size: 12px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: #5E564C;
}
.sheet-fields input {
    width: 100%; min-height: 46px; font-size: 16px;
    background: #FBF8F4; color: var(--anhe-ink);
    border: 1px solid #DCD2C4; border-radius: 2px; padding: 10px 13px;
}
.sheet-fields input:hover { border-color: var(--anhe-gold); }
.sheet-fields input:focus {
    outline: 2px solid var(--anhe-gold); outline-offset: 1px;
    border-color: var(--anhe-gold); border-radius: 2px;
}
.sheet-fields input.bad { border-color: #A33; background: #FBEEEC; }

/* Očičko v poli hesla. Pole si drží plnou šířku a tlačítko leží NAD ním, protože obal
   s dvěma sloupci by heslu ubral šířku a políčko by se přestalo krýt s políčkem pro login
   nad sebou. Pravý vnitřní okraj je proto větší, aby dlouhé heslo neteklo pod ikonu. */
.pw { position: relative; display: block; }
.pw input { padding-right: 46px; }
.pw-eye {
    position: absolute; top: 0; right: 0;
    width: 44px; min-height: 46px; height: 100%;
    display: grid; place-items: center;
    background: transparent; border: 0; padding: 0;
    color: #7A7065; cursor: pointer;
    border-radius: 0 2px 2px 0;
}
.pw-eye:hover { color: var(--anhe-ink); }
.pw-eye:focus-visible { outline: 2px solid var(--anhe-gold); outline-offset: -2px; }
.pw-eye[aria-pressed="true"] { color: var(--anhe-gold-deep); }

.btn-anhe {
    width: 100%; margin-top: 22px;
    font: inherit; font-size: 15.5px; font-weight: 600;
    min-height: 48px; border: 1px solid var(--anhe-ink); border-radius: 2px;
    background: var(--anhe-ink); color: var(--anhe-paper); cursor: pointer;
    transition: background .15s ease;
}
.btn-anhe:hover { background: #3D3833; }
.btn-anhe:focus-visible { outline: 2px solid var(--anhe-gold); outline-offset: 2px; border-radius: 2px; }

.sheet-err {
    display: flex; gap: 9px; margin-bottom: 18px; padding: 11px 13px;
    background: #F7E4E0; border-left: 3px solid #A33; color: #7A211B;
    font-size: 14px; line-height: 1.45;
}

.sheet-note {
    display: flex; gap: 9px; margin-bottom: 18px; padding: 11px 13px;
    background: #F1ECE7; border-left: 3px solid var(--anhe-gold); color: var(--anhe-ink);
    font-size: 14px; line-height: 1.45;
}

.sheet-foot {
    margin: 26px 0 0; padding-top: 16px; border-top: 1px solid #DFD5C7;
    text-align: center; font-size: 12px; color: #7A7167;
}
.gate-sign {
    margin-top: 22px; text-align: center;
    font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #8C8378;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .gate-sign { color: #6B6258; }
}
:root[data-theme="dark"] .gate-sign { color: #6B6258; }
:root[data-theme="light"] .gate-sign { color: #8C8378; }

/* Panel sekcí Správy je .subrail: druhá úroveň pod globálním panelem
   aplikace. Obojí je svislý seznam odkazů, ale první je navigace aplikace
   a druhá navigace jedné obrazovky — dokud se jmenovaly stejně, nemohly
   stát vedle sebe. */
/* --- spacing utilities (replaces style="" from the prototype) ------- */

/* Column widths. The prototype set these with style="", which our CSP drops on the floor.
   Only the one width still asked for by a template survives; the numbered set that came
   from plan 3 went out with the single-page forms the wizards replaced. */
.w-4  { width: 4%; }
/* Restored in task 12: stock-levels/index.blade.php never stopped asking for these two, so
   the SKU and product columns had been rendering without a width since plan 4. */
.w-22 { width: 22%; }
.w-26 { width: 26%; }

/* Columns of the shared scanner table <x-wizard.item-rows>. Named rather than numbered:
   every flow with an items step renders the same four columns. */
.col-sku { width: 34%; }
.col-name { width: 36%; }
/* Hledátko podle názvu ve sloupci Výrobek. Šířka celé buňky, protože názvy jsou dlouhé a
   pole naměřené na obsah by ukázalo první dvě slova. Pilulka typu stojí za ním, takže se
   nesmí lepit na jeho hranu. */
.scan-name { width: 100%; }
.scan-name + .pill { margin-top: 4px; }
.col-qty { width: 16%; }
.col-actions { width: 14%; }

/* The transfer adds a fifth column for the optional manual batch, so the other four give
   room back rather than overflowing the table. */
.tbl-scan.has-batch .col-sku { width: 26%; }
.tbl-scan.has-batch .col-name { width: 26%; }
.tbl-scan.has-batch .col-qty { width: 14%; }
.tbl-scan.has-batch .col-batch { width: 20%; }
.tbl-scan.has-batch .col-actions { width: 14%; }

/* The mock's .act and .view are <button>. Ours are links, because they navigate — a button
   that goes somewhere needs JavaScript, and the CSP has none to give. */
a.act, a.step { text-decoration: none; }

/* A crossroads cell: the card plus, when a flow has unfinished work, the form that throws
   it away. The form cannot live inside the card, because the card is an <a> and a form is
   not allowed inside an anchor — so the grid cell holds both and the card keeps its shape. */
/* The cell exists only so the discard form has something to be positioned against: a
   <form> cannot live inside the card, because the card is an <a>. Stacked underneath, the
   form took height out of the grid cell and left that card shorter than the others in its
   row, with the button hanging below it. Taken out of the flow, every card is the same
   height again and the button sits in its own corner. */
.act-cell { position: relative; display: flex; }
.act-cell > .act { flex: 1; }
.act-discard { position: absolute; left: 14px; right: 14px; bottom: 12px; display: flex; }
.act-discard .btn { padding-inline: 0; }
/* Keeps the card's own text clear of the button laid over it. */
.act-spacer { display: block; height: 22px; }

/* Held stock, read down the column. A badge on every line would say the same thing as the
   column heading; the tint lets the eye find the quarantined rows without reading. */
.qty-quarantine { background: var(--quarantine-bg); color: var(--quarantine); }

/* --- filtr nad seznamem ----------------------------------------------
   Řádek, ne karta: jméno obrazovky a počty nese lišta, takže tady zbývá jen to, čím se
   seznam zužuje. Karta o třech polích brala na obrazovce ke čtení víc místa než čísla,
   která filtrovala.

   Jedna sada čísel pro `x-ui.search`, tedy pro všech devět filtrovaných seznamů. Byly tři
   (`.searchbar`, `.ask-tools`, `.filterbar`) a lišily se zarovnáním řádku, mezerou i šířkou
   pole — viz docblock té komponenty.

   `flex-wrap` je tu kvůli rozbalenému `<details>`: ten si bere celý řádek (`flex: 1 0 100%`),
   takže bez zalomení by vytlačil tlačítka z lišty.
   ------------------------------------------------------------------- */

/* `flex-end`, ne `center`: do lišty vkládá Správa skládané ovládání — `.pick` je popisek NAD
   selectem a `x-admin.toggle` je přepínač s popiskem. Na střed se takový blok s textovým polem
   vedle nezarovná, protože jeho popisek přidá výšku jen nahoře. Prostředek by stačil lištám,
   které skládané ovládání nemají — a to jsou právě ty, které se sem sléhaly ze `.filterbar`. */
.searchbar { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.filter-sku { width: 230px; }
.searchbar-more { font-size: 12.5px; }
.searchbar-more > summary { color: var(--fg-2); cursor: pointer; padding: 6px 4px; }
.searchbar-more > summary:hover { color: var(--fg-1); }
.searchbar-more[open] { flex: 1 0 100%; }
.searchbar-more > .fields { margin-top: 8px; max-width: 620px; }

/* Popisek a hodnota po řádcích — výpis jednoho záznamu, který se čte, ne edituje
   (potvrzení storna). Sloupec popisků má PEVNOU šířku, ne `auto`: každý pár je vlastní grid,
   takže `auto` by si každý řádek naměřil svůj a hodnoty by se mezi řádky rozjely. */
.pairs { display: flex; flex-direction: column; gap: 6px; margin: 0; font-size: 14px; }
.pairs > div { display: grid; grid-template-columns: 8.5rem 1fr; align-items: baseline; gap: 12px; }
.pairs dt { color: var(--fg-3); }
.pairs dd { margin: 0; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }

/* Popisek nad filtrem v jednom řádku s hledáním. Filtr, jehož jediné vysvětlení je text
   vybrané položky, přestane být vysvětlený ve chvíli, kdy si někdo vybere. `min-width` je
   tu proto, že select se jinak scvrkne na nejkratší nabídku a přijde o půl slova. */
.pick { display: flex; flex-direction: column; gap: 3px; }
.pick-label {
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--fg-3);
}
.pick select { min-width: 9rem; }

/* scanner.js writes into this cell: the resolved product name, or why the SKU is unknown. */
.scan-feedback { font-size: 13px; color: var(--fg-2); white-space: nowrap; }
.scan-feedback.bad { color: var(--blocked); background: transparent; }

/* A checkbox and its wording on one line. Used where a single yes/no decision needs the
   question spelled out next to it rather than sitting above as a bare field label. */
.checkline { display: flex; align-items: center; gap: 8px; font-size: 14.5px; cursor: pointer; }
.checkline input { width: 17px; height: 17px; margin: 0; flex: none; }

/* The per-category consequences on the inline "zavést SKU" form. <details> because the form
   has no JavaScript to swap the text when the category select changes, so all six are on the
   page and the person opens the one they chose. */
.hint-blocks { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 14px; }
.hint-block { border-bottom: 1px solid var(--line); padding: 8px 0; }
.hint-block:last-child { border-bottom: 0; }
.hint-block > summary { cursor: pointer; font-weight: 600; font-size: 14.5px; }
.hint-block > summary:focus-visible { outline: 2px solid var(--accent-tint); outline-offset: 2px; }
.hint-block ul { margin: 4px 0 0; padding-left: 20px; color: var(--fg-2); font-size: 14px; }

/* ============================================================
   SPRÁVA — the expert half
   Same tokens, different density. A wizard leads by the hand; Správa does not: a left rail
   instead of a stepper, and editing straight inside the table row.

   The whole vocabulary lands at once, including the classes only later screens use. The
   alternative is patching this file in every task until nobody can see the system in it.
   ============================================================ */

.admin { display: grid; grid-template-columns: 236px minmax(0, 1fr); align-items: start; }

/* min-height je to, co z panelu dělá panel. Podklad --layer-1 se od papíru liší o dva
   procentní body, takže hranu proti pozadí nedělá barva, ale svislá čára border-right vedená
   od lišty ke spodku okna. Bez min-height má panel výšku svých položek, čára skončí v půlce
   obrazovky a zbyde blok, který splývá s papírem — tak se panel „ztratil“ (viz komentář
   u .admin v components/admin/screen.blade.php). Zaoblení mizí ze stejného důvodu: panel
   sedí na hraně okna, ne na kartě. */
.subrail {
    position: sticky; top: 0;
    background: var(--layer-1); border-right: 1px solid var(--line);
    padding: 18px 12px 28px;
    min-height: calc(100vh - 52px);
}

/* Below 900px the rail stops being a column and becomes a horizontal scrolling strip
   across the top (spec §4). display: contents on the groups flattens them into that strip
   so the items sit in one row rather than three. */
@media (max-width: 900px) {
    .admin { grid-template-columns: minmax(0, 1fr); }
    .subrail {
        position: static; min-height: 0; display: flex; gap: 6px;
        overflow-x: auto; padding: 10px 12px;
        border-right: 0; border-bottom: 1px solid var(--line);
    }
    .subrail-group { display: contents; }
    .subrail .eyebrow { display: none; }
}

.subrail-group + .subrail-group { margin-top: 22px; }
.subrail-group > .eyebrow { padding: 0 10px 7px; }

.subrail-item {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 7px 10px; border-radius: var(--radius-sm);
    font-size: 14px; color: var(--fg-1); text-align: left; white-space: nowrap;
}
a.subrail-item { text-decoration: none; }
/* The current item is excluded from the hover state on purpose: :hover would otherwise win
   on specificity, repaint the background pale and leave the accent-on text unreadable. */
a.subrail-item:not([aria-current="page"]):hover { background: var(--surface); }
.subrail-item[aria-current="page"] { background: var(--accent); color: var(--accent-on); font-weight: 600; }
.subrail-item[aria-current="page"] .subrail-n { color: var(--accent-on); opacity: .8; }

/* A section whose screen does not exist yet. Dimmed and inert rather than a link into a
   404 — the mock has no such state because a mock has every screen. */
.subrail-item-off { opacity: .5; cursor: default; }

/* Počet v sekci Správy. Na rozdíl od panelu aplikace ho podpanel Správy MÁ: je na jedné
   obrazovce, ne na každé, takže pět počítání stojí jeden požadavek, ne každý. */
.subrail-n {
    margin-left: auto; font-family: var(--font-code); font-size: 12px;
    font-variant-numeric: tabular-nums; color: var(--fg-2);
}

.admin-main { padding: 30px 26px 44px; max-width: 1040px; }
.admin-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
.admin-head h1 { font-size: 24px; letter-spacing: -.02em; margin: 3px 0 6px; }
.admin-tools { display: flex; gap: 8px; align-items: center; }

/* Editing straight in the row — the field looks like text until it is touched. */
.cell-in {
    border-color: transparent; background: transparent;
    padding: 5px 7px; min-height: 32px; border-radius: 5px;
}
.cell-in:hover { background: var(--layer-1); border-color: var(--line); }
.cell-in:focus { background: var(--surface); border-color: var(--accent-tint); }
.tbl-edit td { padding: 3px 6px; }
/* Zvýraznění řádku pod myší řeší od 27. 8. 2026 obecné `tbody tr:hover`. Zdejší pravidlo
   barvilo BUŇKY, takže řádek Správy svítil jinak než řádek kterékoli jiné tabulky — a protože
   buňka leží nad řádkem, přebilo ho i tam, kde obecné pravidlo platí. */

/* Column widths for the dense edit tables, named rather than written inline: the CSP drops
   a style attribute silently, so the mock's inline widths would simply vanish. */
.col-code { width: 19%; }
.col-label { width: 27%; }
.col-type { width: 19%; }
.col-material { width: 14%; }
.col-skin { width: 13%; }
.col-min { width: 8%; }
.col-count { width: 10%; }
.col-order { width: 9%; }
.col-contact { width: 20%; }
.col-country { width: 12%; }
.col-note { width: 24%; }
.col-sell { width: 13%; }
.col-req { width: 22%; }
.col-values { width: 26%; }
.col-date { width: 12%; }
/* Sazba DPH v příjemce. Bez pevné šířky si `select` naměřil šířku nejdelší nabídky, což je
   „21 %" — tedy čtyři znaky — a v osmisloupcové tabulce z něj zbylo políčko, ve kterém nebylo
   vidět vybrané číslo. Šířka je na SLOUPCI i na poli: sloupec bez ní kolabuje na obsah. */
.col-rate { width: 10%; }
.rate-in { width: 100%; min-width: 5.5rem; font-variant-numeric: tabular-nums; }

/* Název výrobku je druhý řádek v buňce SKU, ne sloupec — proto je .col-sku širší než
   v návrhu a Místo o dva body užší.
   Šířky sloupců knihy pohybů. Vlastní jsou proto, že .col-sku je 34 % v skenovací tabulce,
   kde jsou sloupce tři — v osmisloupcové knize by SKU sebralo třetinu šířky. */
.tbl-ledger .col-date  { width: 13%; }
.tbl-ledger .col-type  { width: 12%; }
.tbl-ledger .col-sku   { width: 18%; }
.tbl-ledger .col-batch { width: 12%; }
.tbl-ledger .col-place { width: 13%; }
.tbl-ledger .col-qty   { width: 9%; }
.tbl-ledger .col-doc   { width: 12%; }
.tbl-ledger .col-who   { width: 12%; }
.tbl-ledger .col-sku .hint { display: block; font-size: 12.5px; }
/* Hrana směru. Odstín, ne plná barva: číslo ve sloupci Množství je to, co směr TVRDÍ, hrana
   ho jen dává najít při čtení dolů. Plnou barvou by hrana soutěžila s pilulkou typu. */
.tbl-ledger tbody tr { border-left: 3px solid transparent; }
.tbl-ledger tbody tr.is-in  { border-left-color: var(--warehouse-bg); }
.tbl-ledger tbody tr.is-out { border-left-color: var(--blocked-bg); }
.col-act { width: 10%; }

/* A checkbox in a list of choices — the product types a compliance rule applies to. The box
   stays a real checkbox and visible, unlike .radio: here the tick IS the answer and there is
   no square to colour in its place. */
.opt {
    display: inline-flex; align-items: center; gap: 6px;
    margin: 2px 8px 2px 0; font-size: 13px; color: var(--fg-2); cursor: pointer;
}
.opt input { margin: 0; }

/* The mock's switch is a <div> flipped by JavaScript. Here the checkbox is real and taken
   out of the paint, and the track reads its own :checked state through :has() — the same
   mechanism that already carries the checklist's answer squares. */
.toggle-wrap {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 13.5px; color: var(--fg-2); cursor: pointer;
}
.toggle-wrap input {
    position: absolute; width: 1px; height: 1px;
    opacity: 0; margin: 0; pointer-events: none;
}
.toggle { display: inline-flex; align-items: center; }
.toggle-text { line-height: 1.2; }
.toggle-track {
    display: inline-flex; align-items: center;
    width: 34px; height: 20px; border-radius: 999px; padding: 2px;
    background: var(--line-firm); transition: background .14s ease;
}
.toggle-knob {
    width: 16px; height: 16px; border-radius: 50%; background: var(--surface);
    transition: transform .14s ease; box-shadow: 0 1px 2px rgba(0,0,0,.25);
}
.toggle-wrap:has(input:checked) { color: var(--fg-1); }
.toggle-wrap:has(input:checked) .toggle-track { background: var(--accent); }
.toggle-wrap:has(input:checked) .toggle-knob { transform: translateX(14px); }
.toggle-wrap:has(input:focus-visible) .toggle-track { outline: 2px solid var(--accent-tint); outline-offset: 2px; }

/* Why a row cannot be changed. Says it in words next to the thing, not in a tooltip. */
.locked {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 12px; color: var(--fg-2);
}

/* A deactivated row: dimmed and sorted last, everywhere in Správa (decision 7). */
.row-off td { opacity: .55; }

/* ============================================================
   Documents — the paper (spec §7)
   Deliberately NOT built from the design tokens: those flip under
   prefers-color-scheme, and a document printed white-on-black is not a
   document. Every colour below is a literal (spec §8 item 9).
   ============================================================ */

.doc-page {
    background: #E4DCD2;
    color: #1C1917;
    font-family: var(--font-text);
    margin: 0;
    padding: 28px 16px 64px;
}

/* The on-screen toolbar: back, print, issue. Never printed. */
.doc-tools {
    display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
    max-width: 210mm; margin: 0 auto 18px;
}

.doc {
    background: #FFFFFF;
    color: #1C1917;
    max-width: 210mm;
    margin: 0 auto;
    padding: 18mm 16mm;
    box-shadow: 0 2px 4px rgba(28,25,23,.06), 0 12px 24px -8px rgba(28,25,23,.14);
}

.doc-head {
    display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; align-items: start;
    padding-bottom: 14px; border-bottom: 2px solid #1C1917;
}
.doc-logo { width: 96px; height: 96px; grid-row: span 2; }
.doc-issuer { font-size: 12px; line-height: 1.5; color: #453F39; }
.doc-issuer p { margin: 0; }
.doc-issuer-name { font-weight: 700; font-size: 14px; color: #1C1917; }
.doc-titles { align-self: end; }
.doc-title { font-family: var(--font-disp); font-size: 21px; margin: 0; letter-spacing: -.01em; }
.doc-subtitle { margin: 3px 0 0; font-size: 14px; color: #453F39; }

.doc-body { padding-top: 16px; font-size: 13px; line-height: 1.55; }

.doc-foot {
    display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
    margin-top: 20px; padding-top: 10px; border-top: 1px solid #CFC6B9;
    font-size: 11px; color: #6E655C;
}
.doc-tools-note { font-size: 13px; color: #453F39; max-width: 62ch; }
.doc-number { font-family: var(--font-code); font-weight: 700; font-size: 13px; color: #1C1917; }

/* A preview is not a document: it has no number and is in no register. */
.doc-void { color: #6B21A8; }
/* Missing importer details make the whole printout undocumentable. */
.doc-warn { color: #B0181A; font-weight: 600; max-width: 52ch; }

/* --- the vocabulary every printout body is built from --- */

.doc-section { margin-top: 18px; }
.doc-section-title {
    font-family: var(--font-disp); font-size: 14px; margin: 0 0 7px;
    padding-bottom: 4px; border-bottom: 1px solid #CFC6B9;
}

/* Header facts: supplier, invoice, date, rule revision. */
.doc-meta { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; margin: 0; font-size: 13px; }
.doc-meta dt { color: #6E655C; }
.doc-meta dd { margin: 0; font-weight: 600; }

.doc-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.doc-table th, .doc-table td {
    text-align: left; vertical-align: top; padding: 5px 8px; border-bottom: 1px solid #E4DED5;
}
.doc-table th {
    font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
    color: #6E655C; border-bottom: 1px solid #CFC6B9;
}
.doc-table td.doc-num { text-align: right; font-variant-numeric: tabular-nums; }
.doc-key { font-family: var(--font-code); font-size: 11px; color: #6E655C; }

/* not_applicable on a required check: an exception, and it has to be visible on a
   black-and-white printer too, so the rule is a border and not only a colour (spec §4 item 10). */
.doc-exception { background: #F3E8FF; }
.doc-exception td:first-child { border-left: 3px solid #6B21A8; }
.doc-exception-mark { color: #6B21A8; font-weight: 700; }

/* One product, one batch, one block — kept whole across a page break. */
.doc-block { margin-top: 14px; padding-top: 10px; border-top: 1px solid #E4DED5; }
.doc-block:first-child { border-top: 0; padding-top: 0; }
.doc-block-title { font-weight: 700; font-size: 14px; margin: 0 0 5px; }

.doc-empty { color: #6E655C; font-style: italic; }
.doc-note { font-size: 11px; color: #6E655C; }

@media print {
    /* The desk, the shadow and the screen tools are furniture, not paper. */
    .doc-page { background: #FFFFFF; padding: 0; }
    .doc-tools { display: none; }
    .doc { box-shadow: none; max-width: none; margin: 0; padding: 0; }

    /* A table longer than a page repeats its heading instead of losing it. */
    .doc-table thead { display: table-header-group; }
    .doc-table tr, .doc-block, .doc-section-title { break-inside: avoid; }
    .doc-section-title { break-after: avoid; }

    a { text-decoration: none; color: inherit; }

    .topbar, .rail { display: none; }
    .help-sheet { break-after: page; }
    .help-steps li, .help-glossary .card { break-inside: avoid; }
}

@page { size: A4; margin: 14mm; }

/* The Dokumenty crossroads: one card per printout, side by side on a wide screen. */
/* Řada, z níž karta bere číslo (PN, MP, TR, KP, AR). Návrh ji má na dlaždici dokumentu,
   v repu chybělo úplně to, čím se dokument v šanonu jmenuje. */
.doc-series {
    font-family: var(--font-code); font-size: 11.5px; font-weight: 700;
    letter-spacing: .06em; padding: 2px 7px; border-radius: var(--radius-sm);
    background: var(--accent-wash); color: var(--accent);
}
/* Arch štítků řadu nemá, protože není doklad. Odznak tam přesto je — přerušovaný a se
   slovem místo čísla: hlavička bez něj měla díru tam, kde ji ostatních pět karet nemá,
   a „chybí" je horší informace než „bez řady". */
.doc-series-none { border-style: dashed; color: var(--fg-3); font-family: var(--font-text); }

.doc-forms { display: grid; gap: 14px; }
@media (min-width: 900px) { .doc-forms { grid-template-columns: 1fr 1fr; } }

/* Nápověda: the process on one printable sheet, the glossary underneath. */
.help-sheet { margin-bottom: 8px; }
.help-steps { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.help-steps > li {
    padding: 14px 0; border-top: 1px solid var(--line);
}
.help-steps > li:first-child { border-top: 0; }
.help-steps h2 { font-size: 16px; margin: 0 0 6px; }
.help-block {
    background: var(--layer-1); border: 1px solid var(--line); border-radius: var(--radius-sm);
    padding: 10px 14px; font-size: 13.5px; color: var(--fg-1);
}
.help-note { margin-top: 18px; color: var(--fg-2); font-size: 13.5px; }
.help-glossary .card { margin-top: 12px; }
.help-glossary .card:first-of-type { margin-top: 0; }
