/* Aplikace TFP — one stylesheet, no build step, no external requests. */

/* Brand colours taken from the CNI logo (cni.hu): red #E83D36 on white.
 *
 * That exact red is used for fills — the logo tile, buttons, the active nav
 * item — where it sits behind white text and only needs a 3:1 contrast ratio
 * (it measures 4.08:1). It is NOT used for text on white: 4.08 falls short of
 * the 4.5 that body text needs, so links use a darker shade of the same hue
 * (#C42B25, 5.65:1). Dark mode lightens it instead, for the same reason. */
:root {
    --brand:     #e83d36;
    --brand-dk:  #c42b25;
    --brand-bg:  #fdeceb;

    --bg:        #f4f6f8;
    --surface:   #ffffff;
    --surface-2: #f8fafc;
    --border:    #dde3ea;
    --text:      #1a2029;
    --muted:     #64748b;
    --accent:    #c42b25;
    --accent-dk: #9b1c1c;
    --ok:        #157347;
    --ok-bg:     #e7f5ec;
    --warn:      #a86404;
    --warn-bg:   #fdf3e2;
    /* Deliberately a deeper, browner red than the brand, so an error never
       reads as just another branded element. */
    --err:       #8f1d18;
    --err-bg:    #fbeaec;
    /* Blue stays for neutral information — it is the one hue that cannot be
       confused with the brand or with an error. */
    --info:      #2b6cb0;
    --info-bg:   #e8f1fb;
    --mark-bg:   #fff8e1;
    --mark-bg-hover: #fdefc4;
    /* Text on a brand-filled surface. The brand red is the same in both
       themes, so this token is not redefined below — it exists so a rebrand
       does not mean hunting down six hard-coded #fff. */
    --on-brand:  #ffffff;
    --radius:    8px;
    --shadow:    0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
    /* Tells the browser how to paint what CSS does not reach: scrollbars, the
       <select> popup, autofill, the date picker. Without it those follow the
       system even when the user has chosen the opposite here. */
    color-scheme: light;
}

/* --- dark palette -----------------------------------------------------
   Two ways in, one palette:

     1. :root[data-theme="dark"] — the user asked for dark. The server writes
        that attribute into <html> from users.theme, so it is there before the
        first byte of CSS is parsed and nothing flashes.
     2. @media + :not([data-theme]) — the user has no preference stored, so
        the system decides. The :not() guard is the load-bearing part: without
        it a dark system would override a deliberately chosen light theme.

   The values are written twice on purpose — CSS cannot share a declaration
   block between a selector and a media query, and the alternative (a second
   set of --dark-* variables) doubles the names instead. Change one, change
   the other. */

:root[data-theme="dark"] {
        /* The brand red keeps its role on fills, but text and links move to a
           lighter tint of it — #E83D36 on this background is only 4.2:1. */
        --brand:     #e83d36;
        --brand-dk:  #ff6b63;
        --brand-bg:  #3a1614;

        --bg:        #0f1419;
        --surface:   #161c24;
        --surface-2: #1c242e;
        --border:    #2a333f;
        --text:      #e5eaf0;
        --muted:     #94a3b8;
        --accent:    #ff8078;
        --accent-dk: #ffa199;
        --ok:        #4ade80;
        --ok-bg:     #14301f;
        --warn:      #fbbf24;
        --warn-bg:   #33280c;
        --err:       #ff9b94;
        --err-bg:    #3a1518;
        --info:      #7dd3fc;
        --info-bg:   #10283b;
        --mark-bg:   #2e2a15;
        --mark-bg-hover: #3d381d;
        /* A black shadow is invisible on a dark surface. What separates a card
           from the page here is a faint light edge, not a drop shadow. */
        --shadow:    0 1px 2px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .05);
        color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
            /* The brand red keeps its role on fills, but text and links move to a
               lighter tint of it — #E83D36 on this background is only 4.2:1. */
            --brand:     #e83d36;
            --brand-dk:  #ff6b63;
            --brand-bg:  #3a1614;

            --bg:        #0f1419;
            --surface:   #161c24;
            --surface-2: #1c242e;
            --border:    #2a333f;
            --text:      #e5eaf0;
            --muted:     #94a3b8;
            --accent:    #ff8078;
            --accent-dk: #ffa199;
            --ok:        #4ade80;
            --ok-bg:     #14301f;
            --warn:      #fbbf24;
            --warn-bg:   #33280c;
            --err:       #ff9b94;
            --err-bg:    #3a1518;
            --info:      #7dd3fc;
            --info-bg:   #10283b;
            --mark-bg:   #2e2a15;
            --mark-bg-hover: #3d381d;
                /* A black shadow is invisible on a dark surface. What separates a card
               from the page here is a faint light edge, not a drop shadow. */
            --shadow:    0 1px 2px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .05);
            color-scheme: dark;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { font-size: 1.45rem; margin: 0 0 .25rem; }
h2 { font-size: 1.1rem; margin: 2rem 0 .75rem; }

.mono  { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: .92em; }
.muted { color: var(--muted); }
.small { font-size: .88em; }
.nowrap { white-space: nowrap; }
.num   { text-align: right; font-variant-numeric: tabular-nums; }

/* --- top bar ---------------------------------------------------------- */

.topbar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 0 1.25rem;
    height: 56px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    /* A thin brand rule under the header ties the page to the identity without
       flooding a data-dense screen with red. */
    box-shadow: inset 0 -3px 0 var(--brand);
    position: sticky;
    top: 0;
    z-index: 20;
}

.brand { display: flex; align-items: center; gap: .65rem; color: inherit; }
.brand:hover { text-decoration: none; }
/* The logo has no background of its own, so it keeps a white tile — that way
   it reads correctly in dark mode too, without needing a second asset. */
.brand-mark {
    display: block;
    height: 30px;
    width: auto;
    background: #fff;
    padding: 3px 6px;
    border-radius: 5px;
}
.brand-mark-lg { height: 54px; padding: 6px 10px; }
.brand-text { font-weight: 600; white-space: nowrap; }

.nav { display: flex; gap: .25rem; margin-right: auto; }
.nav a {
    padding: .4rem .7rem;
    border-radius: 6px;
    color: var(--muted);
    font-weight: 500;
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav a.is-active { background: var(--brand-bg); color: var(--brand-dk); font-weight: 600; }

/* Skupiny nahore jsou obycejne odkazy; stranky skupiny jsou v .subnav pod
   hlavickou (zadne rozbalovaci menu - Balint, 17. 9. 2026). */
.nav a.nav-top { white-space: nowrap; }

.topbar-right { display: flex; align-items: center; gap: 1rem; }

/* Global search in the middle of the top bar. */
.topsearch { flex: 0 1 22rem; margin: 0 auto; }
.topsearch input[type=search] {
    width: 100%; padding: .4rem .7rem; font-size: .9rem;
    border: 1px solid var(--border); border-radius: 6px; background: var(--surface-2); color: var(--text);
}
.topsearch input[type=search]:focus { outline: 2px solid var(--brand); outline-offset: 1px; background: var(--surface); }
@media (max-width: 900px) { .topsearch { display: none; } }
.search-big .f-order { flex: 1 1 24rem; }
.search-order { padding: 1rem 1.25rem; }
.search-order-head { display: flex; justify-content: space-between; align-items: center; gap: .75rem; flex-wrap: wrap; }
.search-order-head .order-company { margin-left: .5rem; }
.search-order-chips { display: flex; gap: .3rem; flex-wrap: wrap; }
.search-facts { display: flex; flex-wrap: wrap; gap: .5rem 2rem; margin: .8rem 0 .4rem; }
.search-facts > div { display: flex; flex-direction: column; }
.search-facts dt { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.search-facts dd { margin: 0; font-weight: 600; }
.search-order details { margin-top: .5rem; }
.search-order summary { cursor: pointer; font-size: .9rem; color: var(--accent); padding: .3rem 0; }
.search-order .grid-inner { margin: .3rem 0 .6rem; }
.search-links { display: flex; gap: .4rem; flex-wrap: wrap; margin: .8rem 0 0; }
.search-order.is-shipped { background: var(--ok-bg); box-shadow: inset 3px 0 0 var(--ok); }
.search-order.is-partial { background: var(--info-bg); box-shadow: inset 3px 0 0 var(--info); }

/* Second row: the pages of the active group as tabs, always in view. Sticks
   under the topbar. On a computer it wraps into a second line: scrolling it
   sideways with a hidden scrollbar cut off the end of the row unseen once
   Administration had 11 pages (Balint 12. 10. 2026: "a Beallitasok mar nem
   latszodik"). On a phone it scrolls sideways rather than wrapping into
   three lines. */
.subnav {
    display: flex;
    flex-wrap: wrap;
    gap: .15rem;
    padding: 0 1.25rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 56px;
    z-index: 19;
}
@media (max-width: 40rem) {
    .subnav {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }
    .subnav::-webkit-scrollbar { display: none; }
}
.subnav a {
    white-space: nowrap;
    display: inline-block;
    padding: .55rem .8rem .45rem;
    color: var(--muted);
    font-size: .92rem;
    font-weight: 500;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}
.subnav a:hover { color: var(--text); text-decoration: none; background: var(--surface-2); }
.subnav a.is-active { color: var(--brand-dk); border-bottom-color: var(--brand); font-weight: 600; }
.lang { display: flex; gap: .2rem; }
.lang a {
    font-size: .78rem;
    font-weight: 600;
    color: var(--muted);
    padding: .15rem .4rem;
    border-radius: 4px;
}
.lang a.is-active { background: var(--brand); color: #fff; }

/* Freshness of the stock data, shown on every page. Colour alone would not
   carry it for a colour-blind operator, so the wording ("3 min ago" vs
   "never") does the real work and the dot only reinforces it. */
.syncdot {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .8rem;
    color: var(--muted);
    white-space: nowrap;
}
.syncdot-mark {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
    background: var(--ok);
}
.syncdot.is-stale { color: var(--warn); font-weight: 600; }
.syncdot.is-stale .syncdot-mark { background: var(--warn); }
.syncdot-link { color: inherit; }
.syncdot-link:hover { text-decoration: none; }
.syncdot-link:hover .syncdot { color: var(--text); }
@media (max-width: 900px) { .syncdot-text { display: none; } }

.whoami { font-size: .88rem; display: flex; align-items: center; gap: .4rem; }

/* User menu: name + role is the button; language, theme and logout sit in
   a small panel under it. Click to open (details), closed by app.js on a
   click elsewhere or Esc. */
.user-menu { position: relative; }
.user-menu > summary {
    cursor: pointer; list-style: none; padding: .35rem .6rem; border-radius: 6px;
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover, .user-menu[open] > summary { background: var(--surface-2); }
.user-menu-caret { font-size: .75em; opacity: .55; margin-left: .1rem; }
.user-menu-panel {
    position: absolute; right: 0; top: calc(100% + .35rem); z-index: 40;
    min-width: 15rem; padding: .5rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
    box-shadow: 0 10px 28px rgba(15, 23, 42, .16);
}
.user-menu-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .35rem .4rem; }
.user-menu-row + .user-menu-row { border-top: 1px solid var(--border); }
.user-menu-label { font-size: .8rem; color: var(--muted); }
.user-menu-logout { justify-content: flex-end; }
.user-menu .theme { flex-direction: column; align-items: stretch; gap: .1rem; }
.user-menu .theme button { text-align: left; display: flex; gap: .5rem; align-items: center; font-size: .85rem; }
.user-menu-theme { color: var(--muted); font-size: .8rem; }
.user-menu .theme button.is-active .user-menu-theme { color: inherit; }

.role {
    font-style: normal;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .1rem .35rem;
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--muted);
    border: 1px solid var(--border);
}
.role-admin    { background: var(--info-bg); color: var(--info); border-color: transparent; }
.role-user     { background: var(--ok-bg);   color: var(--ok);   border-color: transparent; }

/* --- layout ----------------------------------------------------------- */

.wrap { max-width: 1500px; margin: 0 auto; padding: 1.5rem 1.25rem 4rem; }
.wrap-narrow { max-width: 420px; padding-top: 6vh; }

.page-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 1rem; margin-bottom: 1.25rem; }
.page-head-actions { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; }
.lead { margin: 0; color: var(--muted); }

.back { display: inline-block; margin-bottom: 1rem; color: var(--muted); }

.foot { text-align: center; padding: 2rem 1rem; color: var(--muted); font-size: .85rem; }

.split { display: grid; grid-template-columns: 1fr 340px; gap: 1.5rem; align-items: start; }
@media (max-width: 1000px) { .split { grid-template-columns: 1fr; } }
.split-side {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.25rem;
}
.split-side h2 { margin-top: 0; }

/* --- alerts ----------------------------------------------------------- */

.alert {
    padding: .75rem 1rem;
    border-radius: var(--radius);
    margin-bottom: 1rem;
    border: 1px solid transparent;
}
.alert-ok   { background: var(--ok-bg);   color: var(--ok);   border-color: currentColor; }
.alert-err  { background: var(--err-bg);  color: var(--err);  border-color: currentColor; }
.alert-warn { background: var(--warn-bg); color: var(--warn); border-color: currentColor; }

/* --- forms ------------------------------------------------------------ */

label { display: block; font-size: .85rem; font-weight: 600; margin-bottom: .3rem; color: var(--muted); }

input[type=text], input[type=email], input[type=password], input[type=search], select {
    width: 100%;
    padding: .5rem .65rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
}
input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }

/* Koncept upominky: popisek vlevo, pole vpravo; na uzkem displeji pod sebou. */
/* Nastaveni posty: uzka pole jako u ostatnich formularu v Nastaveni. Bez
   stropu by se adresa i heslo roztahly pres celou sirku stranky. */
.mail-form { max-width: 32rem; }

.mail-draft { max-width: 62rem; }
/* Skryta pole (CSRF, akce) jsou prvni deti formulare; bez tohohle by prvni
   radek dostal odstup, jako by nad nim neco bylo. */
.mail-draft > div:first-of-type { margin-top: 0; }
.mail-field { display: grid; grid-template-columns: 7rem minmax(0, 1fr); gap: .3rem 1rem; align-items: start; }
.mail-label { display: block; margin: 0; padding-top: .55rem; font-size: .85rem; font-weight: 600; color: var(--muted); }
.mail-static { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .75rem; padding-top: .45rem; }
.mail-draft textarea {
    width: 100%;
    min-height: 26rem;
    padding: .6rem .75rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
    line-height: 1.45;
    resize: vertical;
}
.mail-draft textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.mail-field > div > small { display: block; margin-top: .25rem; }
.mail-footer { margin-top: .5rem; font-size: .8rem; color: var(--muted); }
.mail-footer summary { cursor: pointer; }
.mail-footer p { margin: .45rem 0 0; }
.mail-history { margin: .35rem 0 0; padding-left: 1.2rem; }

/* MFA: QR nese vlastní bílé pozadí (kvůli tmavému režimu), stačí ho zarámovat. */
.mfa-qr { display: inline-block; padding: 8px; background: #fff; border-radius: 8px; line-height: 0; }
.mfa-secret { font-size: 1.15rem; letter-spacing: .12em; user-select: all; }
.mfa-codes { columns: 2; gap: 1.5rem; margin: .5rem 0 0; padding: 0; }
.mfa-codes li { list-style: none; font-size: 1.05rem; letter-spacing: .08em; padding: .1rem 0; }
.mail-actions { display: flex; justify-content: flex-end; gap: .75rem; }
@media (max-width: 40rem) {
    .mail-field { grid-template-columns: minmax(0, 1fr); }
    .mail-label { padding-top: 0; }
}

.stack { display: flex; flex-direction: column; gap: .25rem; }
.stack label { margin-top: .75rem; }
.stack > .btn { margin-top: 1.25rem; }
.row { display: flex; gap: .5rem; margin-top: 1.25rem; }
.check { display: flex; align-items: center; gap: .5rem; margin-top: 1rem; font-weight: 500; color: var(--text); }
.check input { width: auto; }
/* Oblasti uctu na strance Uzivatele (#7): zaskrtavatka pohromade v ramecku. */
.user-areas { margin-top: 1rem; padding: .25rem .75rem .75rem; border: 1px solid var(--border); border-radius: 6px; }
.user-areas legend { padding: 0 .3rem; font-weight: 600; }
.user-areas .check { margin-top: .5rem; }

.inline { display: inline; }

/* Formulář v kartě — import objednávky a jeho návrh ke schválení. Řádky pod
   sebou potřebují dýchat; bez toho na sobě popisek, pole a tabulka seděly. */
.card-form {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.25rem;
    margin-bottom: 1.25rem;
}
/* Rozestupy řídí karta, ne výchozí okraje odstavců — jinak se sčítají. */
.card-form > * + * { margin-top: 1rem; }
/* Order upload folded to one line; the form inside keeps the card's rhythm. */
.import-fold { padding-top: .8rem; padding-bottom: .8rem; }
.import-fold > summary {
    cursor: pointer; list-style: none; font-weight: 600; color: var(--text);
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
}
.import-fold > summary::-webkit-details-marker { display: none; }
.import-fold > summary .import-fold-plus {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.5rem; height: 1.5rem; border-radius: 6px;
    background: var(--brand); color: #fff; font-weight: 700; line-height: 1;
}
.import-fold[open] > summary .import-fold-plus { transform: rotate(45deg); }
.import-fold[open] > summary { margin-bottom: 1rem; }
.import-fold > form > * + * { margin-top: 1rem; }
.import-fold > form > p { margin: 0; }
.card-form > p { margin: 0; }
.card-form h2 { margin: 0; }
.card-form .lead { margin: .35rem 0 0; }
.card-form .f-row {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem 1rem;
    align-items: flex-end;
}

/* Výběr souboru. Nativní tlačítko si nápis píše samo podle jazyka prohlížeče,
   takže je pod tímhle schované: skutečný input leží průhledně přes celý blok
   a nese `required` i fokus, vidět je náš vlastní popisek. */
.filepick {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    max-width: 100%;
}
.filepick > input[type=file] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
}
.filepick-btn { white-space: nowrap; }
/* Fokus patří vidět na tom, co je vidět — input sám je průhledný. */
.filepick > input[type=file]:focus-visible ~ .filepick-btn {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}
.filepick-name {
    font-size: .85rem;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.filepick-name.has-file { color: var(--text); font-weight: 600; }

.filters {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: flex-end;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem;
    margin-bottom: 1.25rem;
}
.f { min-width: 150px; }
.f-grow { flex: 1; min-width: 240px; }
.f-narrow { min-width: 120px; }
.f-actions { display: flex; gap: .5rem; }

/* --- buttons ---------------------------------------------------------- */

.btn {
    display: inline-block;
    padding: .5rem .9rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dk); border-color: var(--brand-dk); }
.btn-danger { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-danger:hover { filter: brightness(.92); }
.btn-quiet { background: transparent; color: var(--muted); }
.btn-quiet:hover { background: var(--surface-2); color: var(--text); }
.btn-small { padding: .28rem .55rem; font-size: .85rem; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

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

/* Wide tables scroll inside their own box rather than pushing the page sideways.
   Note that setting overflow on one axis makes this element a scroll container
   on both — which is what the sticky header below anchors to, so the two must
   be considered together. */
.table-scroll {
    /* Horizontally only. There used to be a max-height here so the table
       scrolled inside its own box with the header pinned, but that made the
       rows-per-page control look broken: picking 100 rows gave the same short
       box as 20, just with more to scroll inside it. A choice the user makes
       has to be visible on the page, so the box grows and the page scrolls.
       The cost is the pinned header — see .grid th below. */
    overflow-x: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.grid { width: 100%; border-collapse: collapse; font-size: .9rem; }
/* Tight enough that a 20-row page fits a normal window; loosen this and the
   page starts scrolling, which is what the paging is here to avoid. */
.grid th, .grid td { padding: .42rem .7rem; text-align: left; border-bottom: 1px solid var(--border); }
.grid th {
    background: var(--surface-2);
    font-size: .76rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--muted);
    white-space: nowrap;
    /* The header is no longer pinned. Sticky anchors to the nearest scrolling
       ancestor, and .table-scroll only scrolls sideways now — so `top: 0` here
       would have no effect on a page that scrolls vertically, and making it
       work again would mean putting the height cap back. Between a pinned
       header and a rows-per-page control that does what it says, the control
       wins; the header is one flick of the scroll wheel away. */
    z-index: 5;
    /* border-bottom on a sticky cell scrolls away with the row underneath,
       so the separating line is drawn with a shadow instead. */
    border-bottom: 0;
    box-shadow: inset 0 -1px 0 var(--border);
}
/* --- sortable headers --- */
.grid th.sortable { cursor: pointer; user-select: none; }
.grid th.sortable:hover { color: var(--text); background: var(--brand-bg); }
.grid th.is-sorted { color: var(--brand-dk); }
.sort-ind { opacity: .35; font-size: .9em; margin-left: .15em; }
.sort-ind.is-active { opacity: 1; color: var(--brand); }
.sort-ind sup { font-size: .7em; margin-left: .1em; }

.interval-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem;
}
.interval-form .muted { flex-basis: 100%; margin: .25rem 0 0; }
.interval-form > div { flex: 1; min-width: 260px; }
.warn-text { color: var(--warn); }

.grid tbody tr:hover { background: var(--surface-2); }
.grid tbody tr:last-child td { border-bottom: 0; }
.grid tfoot td { background: var(--surface-2); font-weight: 600; }
.grid .empty { text-align: center; color: var(--muted); padding: 2.5rem; }
.col-check { width: 36px; text-align: center; }
.err-cell { max-width: 320px; font-size: .82rem; color: var(--err); }

/* A roll the operator has ticked off, and one the desktop app flagged. */
tr.is-marked  { background: var(--mark-bg); box-shadow: inset 3px 0 0 var(--brand); }
tr.is-marked:hover { background: var(--mark-bg); filter: brightness(.98); }
tr.is-inactive { opacity: .55; }
/* An order every container of which has left: the whole row reads as done,
   so the queue can be skimmed without opening each one. */
tr.is-shipped  { background: var(--ok-bg); box-shadow: inset 3px 0 0 var(--ok); }
tr.is-shipped:hover { background: var(--ok-bg); filter: brightness(.98); }
/* ...and one that has partly left: the same shape in light blue, so a half
   delivery (Stefanovicz 80/2024) stands out from both the open and the done
   ones (Bálint, 15 Sep 2026). */
tr.is-partial  { background: var(--info-bg); box-shadow: inset 3px 0 0 var(--info); }
tr.is-partial:hover { background: var(--info-bg); filter: brightness(.98); }

.chip {
    display: inline-block;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: .1rem .35rem;
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--muted);
    vertical-align: middle;
}
/* "selected by me" and "flagged for deletion upstream" can sit on the same row
   and mean very different things, so they must not look alike. Selection is
   accent-coloured (an action of yours); the flag is a warning. */
.chip-mark { background: var(--brand-bg); color: var(--brand-dk); box-shadow: inset 0 0 0 1px currentColor; }
.chip-warn { background: var(--warn-bg); color: var(--warn); }
.chip-info { background: var(--info-bg); color: var(--info); }
.chip-ok   { background: var(--ok-bg);   color: var(--ok); }
.chip-err  { background: var(--err-bg);  color: var(--err); }

/* --- issue tray ------------------------------------------------------- */

.tray {
    background: var(--surface);
    border: 2px solid var(--brand);
    border-radius: var(--radius);
    padding: 1rem 1.25rem;
    margin-bottom: 1.25rem;
    box-shadow: var(--shadow);
}
.tray-head { display: flex; align-items: baseline; gap: .75rem; margin-bottom: .6rem; }
.tray-list {
    list-style: none;
    margin: 0 0 .9rem;
    padding: 0;
    max-height: 190px;
    overflow-y: auto;
    font-size: .88rem;
}
.tray-list li {
    display: grid;
    grid-template-columns: 90px 1fr 190px 110px 28px;
    align-items: center;
    gap: .75rem;
    padding: .25rem 0;
    border-bottom: 1px solid var(--border);
}
.tray-remove {
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: 1.1rem;
    line-height: 1;
    padding: .15rem .35rem;
    border-radius: 4px;
    cursor: pointer;
}
.tray-remove:hover { background: var(--err-bg); color: var(--err); }
.tray-list li:last-child { border-bottom: 0; }
.tray-actions { display: flex; gap: .5rem; justify-content: flex-end; }

.bulk-bar { display: flex; align-items: center; gap: .75rem; margin-top: 1rem; }
/* "Rosszul olvasta" under the draft: the button (or the note) and one line of why. */
.misread-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
/* E-mail to the customer: a quiet box with the tick and the addresses, and
   under an order the short log of what already went out. */
.notice-box {
    margin: 1rem 0 0; padding: .7rem .9rem;
    border: 1px solid var(--border); border-left: 3px solid var(--info);
    border-radius: 8px; background: var(--surface-2);
}
.notice-box .check { margin-top: 0; }
.notice-box .f { margin-top: .5rem; }
.notice-box .f input { max-width: 40rem; }
.notice-box .notice-hint { display: block; margin-top: .3rem; }
.notice-log { list-style: none; margin: .6rem 0 0; padding: 0; font-size: .85rem; }
.notice-log li { margin: .15rem 0; }
.notice-form { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .5rem; }
.notice-form input[type=text] { flex: 1 1 18rem; max-width: 36rem; }
.notice-forget { margin-top: .4rem; }
.ship-all { margin-left: .4rem; vertical-align: middle; }

/* --- cards ------------------------------------------------------------ */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 4px solid var(--border);
    border-radius: var(--radius);
    padding: .9rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}
.card-ok   { border-left-color: var(--ok); }
.card-warn { border-left-color: var(--warn); }
.card-err  { border-left-color: var(--err); }
.card-info { border-left-color: var(--info); }
.card-label { font-size: .75rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.card-value { font-size: 1.6rem; line-height: 1.2; font-variant-numeric: tabular-nums; }
.card .muted { font-size: .8rem; }

/* --- facts ------------------------------------------------------------ */

.facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1px;
    background: var(--border);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    margin: 0 0 1.5rem;
}
.facts > div { background: var(--surface); padding: .7rem .9rem; }
.facts dt { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin-bottom: .2rem; }
.facts dd { margin: 0; font-weight: 600; white-space: pre-line; overflow-wrap: anywhere; }
/* Dlouha hodnota (poznamka, sirky materialu) dostane celou radku. */
.facts .wide { grid-column: 1 / -1; }

/* --- detail kalkulace: tabulka variant ----------------------------- */

/* Varianta, kterou obchodnik nezadal (mnozstvi 1): ukazana, ale zasedla. */
.grid .var-off { opacity: .45; }
/* Radek, na kterem zalezi nejvic (hruby zisk). */
.grid tr.is-key td { font-weight: 600; background: var(--surface-2); }

/* --- pager ------------------------------------------------------------ */

.pager-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem 1rem;
    margin-top: 1rem;
}
.pager-count { font-size: .85rem; color: var(--muted); }

.pager { display: flex; gap: .25rem; flex-wrap: wrap; justify-content: center; }
.pager a, .pager > span {
    padding: .3rem .6rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    min-width: 34px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.pager a:hover { background: var(--brand-bg); border-color: var(--brand); text-decoration: none; }
.pager .is-current { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
/* Gap marker and the disabled prev/next arrows are not controls — no border,
   no hover, and they must not read as something you can click. */
.pager .is-gap { border-color: transparent; background: none; min-width: 1.2rem; padding: .3rem .2rem; color: var(--muted); }
.pager .is-off { color: var(--border); background: none; }

.pager-size { font-size: .85rem; color: var(--muted); display: flex; align-items: center; gap: .3rem; }
.pager-size a, .pager-size span {
    padding: .15rem .45rem;
    border-radius: 4px;
    font-variant-numeric: tabular-nums;
}
.pager-size a:hover { background: var(--brand-bg); text-decoration: none; }
.pager-size .is-current { background: var(--brand); color: #fff; font-weight: 600; }

/* --- login ------------------------------------------------------------ */

.login-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 2rem;
    box-shadow: var(--shadow);
}
.login-brand { text-align: center; margin-bottom: 1.5rem; }
/* block-level image needs the auto margins to sit centred in the card */
.login-brand .brand-mark { margin: 0 auto; }
.login-brand h1 { margin: .75rem 0 .25rem; font-size: 1.2rem; }
.login-lang { display: flex; gap: .4rem; justify-content: center; margin-top: 1.5rem; }
.login-lang a { font-size: .78rem; font-weight: 600; color: var(--muted); padding: .2rem .5rem; border-radius: 4px; }
.login-lang a.is-active { background: var(--brand); color: #fff; }

/* The device link for the handheld, shown once after it is generated. It is a
   long token that has to be retyped or sent on, so it wraps rather than
   scrolling out of sight. */
.scan-link-text p { margin: .25rem 0; }
.scan-link .mono {
    overflow-wrap: anywhere;
    font-size: .9rem;
    line-height: 1.4;
}

/* The device link, shown once after it is generated, with the QR beside it.
   Wraps to one column on a narrow screen so the code never gets squeezed. */
.scan-link { display: flex; gap: 1rem; align-items: flex-start; flex-wrap: wrap; }
.scan-link-qr { flex: 0 0 auto; line-height: 0; }
.scan-link-qr svg { display: block; border-radius: 4px; }
.scan-link-text { flex: 1 1 16rem; min-width: 0; }


/* Rolls of one pallet, folded away under it. A <details> rather than a link to
   a detail page: the whole point of this listing is comparing pallets, and
   that stops working the moment reading one means leaving the page. */
.pallet-rolls > td { padding: 0 !important; background: var(--surface-2); }
.pallet-rolls summary {
    padding: .45rem .75rem;
    cursor: pointer;
    font-size: .9rem;
    color: var(--accent);
}
.pallet-rolls summary::marker { color: var(--muted); }
/* "Loading…" (or the error) until the rolls arrive (data-lazy): the cell has no padding of its own. */
.pallet-rolls .lazy-body { padding: 0 .75rem .5rem; }
.stock-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: .6rem 0 .2rem; }
/* One roll off a hold: a small cross right after the number / chip. */
.hold-x { display: inline; margin: 0; }
.hold-x-btn {
    border: 0; background: none; padding: 0 .15rem; margin-left: .1rem;
    color: var(--muted); font: inherit; font-weight: 700; line-height: 1; cursor: pointer;
}
.hold-x-btn:hover { color: var(--err); }

/* Orders and Shipping: one order = one block. The main row and its folded
   "Status and lines" row used to look like two equal rows of one table, so
   twenty orders read as forty lines that flow into each other (Bálint,
   15 Sep 2026). Now the order number is a badge, the customer is bold, the
   block opens with a heavier rule, and the folded row is a quiet, indented
   strip inside the block rather than a row of its own. */
.grid tr.order-row > td {
    border-top: 2px solid var(--border);
    padding-top: .6rem;
    padding-bottom: .6rem;
}
.grid tr.order-row:first-child > td { border-top: 0; }
.order-no {
    display: inline-block;
    padding: .12rem .5rem;
    border-radius: 6px;
    background: var(--brand-bg);
    color: var(--brand-dk);
    font-weight: 700;
    letter-spacing: .01em;
}
tr.is-shipped .order-no { background: var(--ok-bg); color: var(--ok); }
tr.is-partial .order-no { background: var(--info-bg); color: var(--info); }
.order-company { font-weight: 600; font-size: 1.02em; }
.grid tr.loc-rows > td {
    background: var(--surface-2);
    padding: 0 .7rem 0 1.6rem;
    border-bottom: 1px solid var(--border);
}
.grid tr.loc-rows:hover { background: transparent; }
.grid tr.loc-rows > td > details > summary {
    padding: .3rem 0;
    font-size: .85rem;
    color: var(--muted);
    cursor: pointer;
}
.grid tr.loc-rows > td > details[open] > summary { color: var(--text); font-weight: 600; padding-bottom: .5rem; }

/* Shipping: packed / ordered under the roll count - a thin bar, full when
   every ordered roll is on a pallet. */
.progress {
    height: 4px;
    margin-top: .25rem;
    border-radius: 2px;
    background: var(--border);
    overflow: hidden;
}
.progress > span { display: block; height: 100%; background: var(--warn); }
.progress-done { color: var(--ok); font-weight: 600; }
.progress-done + .progress > span { background: var(--ok); }

/* Order list: the status chip stays on one line, the note under it wraps
   inside a bounded width. A free-text note on one line ("TO:Premium Concept
   Proiect Srl") plus the long Hungarian column headers pushed the Delete
   button out of a 1920 px window at 150 % zoom. */
/* The cell now holds the machine state, its machines + "x/y sor" and the
   manual status (ProductionState): it wraps between them, never inside one. */
.order-status { white-space: normal; min-width: 9rem; }
.order-status .chip, .order-machines { white-space: nowrap; }
.order-note   { white-space: normal; max-width: 16rem; overflow-wrap: anywhere; }
/* Poznamka rampy visi pod cislem objednavky, tedy v mono sloupci - veta ale
   neni cislo a strojopisem se cte hure. */
.order-row .mono .order-note { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; font-size: .78rem; }
.grid-inner { margin: 0 0 .5rem; font-size: .9rem; }
.grid-inner th { background: transparent; font-weight: 600; }
.grid-inner tr.is-warned { background: var(--warn-bg); }


/* A roll the operator took back on the handheld. Shown only on request, and
   struck through rather than greyed out — greyed reads as "inactive", struck
   reads as "this happened and was undone", which is what it is. */
tr.is-voided td { text-decoration: line-through; opacity: .55; }

/* The order number is the filter people reach for first — it deserves the room.
   It also needs type="text" spelled out: the base input rule selects on the
   attribute, and an input without one gets no styling at all. */
.f-order {
    flex: 1 1 22rem;
    min-width: 16rem;
    max-width: 32rem;
    font-size: 1.05rem;
    padding: .6rem .75rem;
}

/* A single setting on one line: label, value with its unit, and the button that
   saves it. Baseline-aligned rather than stretched — a form control that is
   taller than the text next to it reads as two unrelated things. */
.setting-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem;
    margin: .25rem 0 1.75rem;
}
.setting-row label {
    margin: 0;
    font-weight: 600;
    color: var(--text);
}
.setting-row .btn { flex: 0 0 auto; }

/* The unit belongs to the number, so it sits inside the field's frame rather
   than floating beside it. */
.unit-field {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding-right: .65rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
}
.unit-field input {
    width: 6rem;
    border: 0 !important;
    background: transparent;
    text-align: right;
}
.unit-field input:focus { outline: none; }
.unit-field:focus-within { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.unit-field .unit { color: var(--muted); font-size: .9em; }

/* --- receivables ------------------------------------------------------- */

/* The ageing tiles double as filters, so the cards have to survive being
   wrapped in an <a> without picking up link colour or underline. */
a.card { text-decoration: none; color: inherit; }
a.card:hover { border-color: var(--brand); }

.ar-ageing { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.25rem; }
.ar-ageing .chip { text-decoration: none; }

/* Deliberately quieter than .tray: this is a summary you may collapse, not a
   working tray that needs to shout. */
.ar-group {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: .75rem 1.1rem;
    margin-bottom: 1.25rem;
}
.ar-group > summary { cursor: pointer; font-weight: 600; }
.ar-group[open] > summary { margin-bottom: .7rem; }

.alert-info { background: var(--info-bg); color: var(--info); border-color: currentColor; }

/* The line that admits the grace filter is on. It carries the way out, so the
   link must not disappear into the surrounding text. */
.ar-grace-note { margin-bottom: 1rem; }
.ar-grace-note a { margin-left: .4rem; font-weight: 600; }

/* Two single-value settings side by side. Each is a label, a number and a
   button, so stacked they would eat the whole screen and leave a blank strip
   between them. Collapses to one column when there is no room. */
.settings-cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 0 2.5rem;
    align-items: start;
}
.settings-cols > section > h2 { margin-top: 0; }

/* The activity log, directly under the user list in the same column — not
   below the whole two-column block, where the tall "new user" form would push
   it off the screen and it would read as missing. Separated by a rule rather
   than a card: it is the list's continuation, not a widget floating on it. */
.users-activity {
    margin-top: 2rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
}
.users-activity > h2 { margin-top: 0; }

/* Theme switch — same segmented shape as the language switch beside it, so
   the topbar keeps one visual idiom instead of gaining a second control that
   looks like something else. Three states, because the third one (follow the
   system) is what most people already have and must stay reachable. */
.theme {
    display: inline-flex;
    gap: .1rem;
    align-items: center;
}
.theme button {
    border: 0;
    background: transparent;
    color: var(--muted);
    font: inherit;
    line-height: 1;
    padding: .3rem .45rem;
    border-radius: 5px;
    cursor: pointer;
}
.theme button:hover { color: var(--text); background: var(--surface-2); }
.theme button.is-active { color: var(--brand-dk); background: var(--brand-bg); }
.theme button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Currency split under the headline. The total is in forints because that is
   what SAP totals, but nine of every ten of them come from a EUR invoice —
   this is where you read the euro figure without doing arithmetic. */
.ar-cursplit { display: flex; flex-wrap: wrap; gap: .1rem .75rem; font-size: .8rem; margin-top: .15rem; }
.ar-cursplit span { font-variant-numeric: tabular-nums; }
.ar-technical-note { margin: -.5rem 0 1rem; font-size: .85rem; }

/* Mezisoučty nad saldem: co je vidět a co se od toho odečítá. Tlumené, aby
   poslední řádek — saldo — zůstal tím, co oko najde první. */
.grid tfoot tr.ar-subtotal td { color: var(--muted); font-weight: 400; border-bottom: 0; padding-top: .2rem; padding-bottom: .2rem; }

/* Součty vedle filtrů, ne pod tabulkou: kdo se ptá „kolik nám dluží", to nemá
   hledat po odscrollování osmdesáti řádků. Zarovnané doprava, ale zalomí se
   pod filtry, jakmile na ně není místo. */
.f-sums {
    margin-left: auto;
    display: flex;
    flex-direction: column;
    gap: .1rem;
    align-items: flex-end;
    min-width: 0;
}
.ar-sum {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    font-size: .8rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.ar-sum b { font-weight: 600; min-width: 7.5rem; text-align: right; }
.ar-sum-label { white-space: nowrap; }
/* Saldo je to, co si člověk odnese — proto větší a v barvě textu, zatímco
   mezisoučty nad ním zůstávají tlumené. */
.ar-sum.is-total { font-size: 1rem; color: var(--text); padding-top: .15rem; }
.ar-sum.is-total b { font-weight: 700; }

/* Two buttons in a page header belong together on the right, not one in the
   middle where space-between would fling it. Wrapping them in one block keeps
   them side by side next to each other. */
.page-actions { display: flex; gap: .5rem; flex: 0 0 auto; }

/* The text pulled out of an imported PDF, folded away under the draft. Lines
   come from somebody else's document and can be arbitrarily long, so they wrap
   instead of stretching the page sideways, and the block scrolls rather than
   pushing the confirm button off the screen. */
.pdf-text { margin: .25rem 0 1rem; }
.pdf-text > summary {
    cursor: pointer;
    font-size: .9rem;
    color: var(--accent);
    padding: .2rem 0;
}
.pdf-text > summary::marker { color: var(--muted); }
.pdf-text pre {
    margin: .4rem 0 0;
    padding: .6rem .75rem;
    max-height: 22rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: .35rem;
    font-size: .85rem;
    line-height: 1.45;
}

/* The production-queue controls, folded under an order together with its lines.
   A row of fields rather than a form block: this gets touched many times a day,
   so it has to sit in one line and not push the lines table down the page. */
.queue-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .6rem;
    padding: .6rem .75rem;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: .35rem;
    margin: .4rem 0 .6rem;
}
.queue-form .f { margin: 0; }
.queue-form .f:not(.f-narrow):not(.f-actions) { flex: 1 1 14rem; min-width: 0; }
.queue-form label { font-size: .75rem; color: var(--muted); }
.queue-form .notice-box { flex: 1 1 100%; margin: .2rem 0 0; }

/* Co má sklad pro objednávku. Sbalené jako řádky objednávky: u hotové zakázky
   už tuhle otázku nikdo neřeší, ale u nové je to první, na co se člověk ptá. */
.stock-prop { margin: .2rem 0 .4rem; }
.stock-prop > summary {
    cursor: pointer;
    font-size: .9rem;
    color: var(--accent);
    padding: .2rem 0;
}
.stock-prop > summary::marker { color: var(--muted); }
/* Jeden materiál a co k němu na skladě leží. Rozměry a kusy, ne m²: člověk
   se rozhoduje podle toho, co je v regálu, ne podle přepočtu. */
.stock-line { margin: .5rem 0 .9rem; }
.stock-line-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .2rem .7rem;
    margin-bottom: .25rem;
}
/* Rozměr, který jde vydat rovnou. Zvýrazněný proto, že je to jediný řádek,
   podle kterého se dá jednat — zbytek je tentýž materiál k rozřezání. */
.grid-inner tr.is-fit { background: var(--ok-bg); }
.grid-inner tr.is-fit td { font-weight: 600; }

/* Upozornění nad obsahem — varování u návrhu objednávky, chybějící token na
   stránce nasazení. Doteď nemělo žádný styl, takže seznam varování u importu
   vypadal jako obyčejná odrážka a dal se přehlédnout. */
.notice {
    background: var(--warn-bg);
    border-left: 3px solid var(--warn);
    border-radius: var(--radius);
    padding: .8rem 1rem;
    margin: 0 0 1.25rem;
}
.notice > p { margin: .35rem 0 0; }
.notice strong { color: var(--warn); }
ul.notice { padding-left: 2rem; }
ul.notice li + li { margin-top: .25rem; }
.notice-warn { border-left-color: var(--warn); }
/* A green notice for "nothing found" — the data check's best outcome should
   not look like a warning. */
.notice-ok   { background: var(--ok-bg); border-left-color: var(--ok); }
.notice-ok strong { color: var(--ok); }

/* Rows of the data check: every row is a finding, so the whole table reads
   amber. Same tint as the flagged import rows. */
.grid-check tr.is-warned { background: var(--warn-bg); }

/* Day navigation of the digest: previous day, the day itself, next day. */
.digest-nav {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin: 0 0 1.25rem;
}
.digest-day { font-size: 1.15rem; }

/* Heti terv: a day is a heading with its totals; today gets the brand mark. */
.plan-day { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; margin: 1.4rem 0 .5rem; }
.plan-day.is-today { color: var(--brand-dk); }
.plan-day-total { font-weight: 400; }
.plan-empty { margin: 0 0 .5rem; }

/* Záznam o posledních nasazeních. Řádky jsou krátké, ale je jich dvacet —
   scrolluje se uvnitř, ne celá stránka. */
.deploy-log {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: .7rem .9rem;
    max-height: 16rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: .85rem;
    line-height: 1.5;
}

/* Gyártás (Bálint, 25 Sep 2026): the six machines one under the other — the
   name, a timeline of the next hours and the jobs in it as text below. The
   timeline starts at "now" on the left; hatched = outside working hours. */
.prod-nav { gap: .5rem; }
.prod-board { display: flex; flex-direction: column; gap: 1rem; }
.prod-row { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: .4rem 1rem; align-items: start; }
.prod-row + .prod-row { border-top: 1px solid var(--border); padding-top: 1rem; }
.prod-axis-row + .prod-row { border-top: 0; padding-top: 0; }
.prod-name { display: flex; flex-direction: column; gap: .3rem; align-items: flex-start; }
.prod-name strong { font-size: 1.15rem; }
.prod-axis { position: relative; height: 1.2rem; font-size: .75rem; color: var(--muted); }
.prod-tick { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; font-variant-numeric: tabular-nums; }
.prod-tick-now { left: 0; transform: none; color: var(--brand-dk); font-weight: 600; }
.prod-bar {
    position: relative;
    height: 2.4rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
.prod-bar.is-over { box-shadow: inset 5px 0 0 var(--err); }
.prod-off {
    position: absolute; top: 0; bottom: 0;
    background: repeating-linear-gradient(135deg, var(--surface-2) 0 6px, var(--border) 6px 8px);
}
.prod-grid { position: absolute; top: 0; bottom: 0; border-left: 1px dashed var(--border); }
.prod-block {
    position: absolute; top: 4px; bottom: 4px;
    display: flex; align-items: center;
    min-width: 3px;
    padding: 0 .35rem;
    overflow: hidden;
    white-space: nowrap;
    font-size: .78rem;
    color: var(--info);
    background: var(--info-bg);
    border: 1px solid var(--info);
    border-radius: 4px;
}
.prod-block span { position: relative; overflow: hidden; text-overflow: ellipsis; }
/* The knife changeover at the start of a job (MachineSchedule::SETUP_MIN each). */
.prod-setup {
    position: absolute; top: 0; bottom: 0; left: 0;
    background: repeating-linear-gradient(135deg, transparent 0 4px, currentColor 4px 5px);
    opacity: .35;
    border-right: 1px solid currentColor;
}
.prod-split { display: block; }
.prod-rounds { font-weight: 600; }
.prod-setups input { width: 3.5rem; }
/* Slitting stock rolls again: the strip cut off is scrap, written off (Balint). */
.cutplan-scrap { color: var(--err); }
.cutplan-extjumbo { margin: 0; }
.prod-block:hover { text-decoration: none; filter: brightness(.95); }
.prod-block.is-running { color: var(--warn); background: var(--warn-bg); border-color: var(--warn); font-weight: 600; }
.prod-block.kind-free { color: var(--muted); background: var(--surface-2); border: 1px dashed var(--muted); }
.prod-list { list-style: none; margin: .45rem 0 0; padding: 0; font-size: .88rem; }
.prod-list > li { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 0 .5rem; margin: .25rem 0; }
.prod-list li.is-running .prod-time { color: var(--warn); font-weight: 600; }
.prod-time { display: inline-block; min-width: 8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.prod-foot { margin: .3rem 0 0; }

/* One machine: running job, its queue, the add form, the week's history. */
.prod-back { margin: 0 0 .25rem; }
.prod-tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1rem; }
.prod-now { padding: .8rem 1rem; background: var(--warn-bg); border: 1px solid var(--warn); border-radius: var(--radius); }
.prod-now.is-over { background: var(--err-bg); border-color: var(--err); }
.prod-now-what { font-size: 1.05rem; margin-bottom: .3rem; }
.prod-over { color: var(--err); }
.prod-free { font-weight: 400; margin-left: .4rem; }
.prod-actions { display: flex; flex-wrap: wrap; gap: .35rem; align-items: flex-start; margin-top: .5rem; }
.prod-queue { list-style: none; margin: 0; padding: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.prod-job { display: grid; grid-template-columns: 11rem minmax(0, 1fr) auto; gap: .4rem 1rem; align-items: start; padding: .6rem .8rem; border-top: 1px solid var(--border); box-shadow: inset 4px 0 0 var(--info); }
.prod-job:first-child { border-top: 0; }
.prod-job:target { background: var(--mark-bg); }
.prod-job-time { display: flex; flex-direction: column; font-variant-numeric: tabular-nums; }
.prod-job > .prod-actions { margin-top: 0; justify-content: flex-end; }
.prod-edit { margin-top: .2rem; }
.prod-edit > summary { list-style: none; display: inline-block; padding-left: 0; }
.prod-edit > summary::-webkit-details-marker { display: none; }
.prod-edit-form { display: flex; flex-wrap: wrap; gap: .5rem .9rem; align-items: flex-end; margin: .5rem 0; }
.prod-edit-form label { display: flex; flex-direction: column; gap: .2rem; font-size: .85rem; }
.prod-edit-form input[type=text] { min-width: 14rem; }
.prod-dur { display: inline-flex; flex-wrap: wrap; gap: .4rem; }
.prod-dur .unit-field input { width: 3.5rem; }
.prod-add { display: flex; flex-direction: column; align-items: flex-start; gap: .3rem; max-width: 64rem; }
.prod-add > label { margin-top: .6rem; font-weight: 600; }
.prod-add select, .prod-add input[type=text] { width: 100%; }

/* Running = yellow, queued = blue, done = green (Bálint). The chip for a
   running machine and the green Done buttons. */
.chip-run { background: var(--warn-bg); color: var(--warn); box-shadow: inset 0 0 0 1px currentColor; }
.btn-ok { background: var(--ok); border-color: var(--ok); color: #fff; }
.btn-ok:hover { filter: brightness(.92); }
.btn-ok-quiet { color: var(--ok); border-color: var(--ok); }
.btn-ok-quiet:hover { background: var(--ok-bg); }

/* A job of several order lines: its name/count on top, one row per line. */
.prod-job-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem; }
.prod-lines { list-style: none; margin: .1rem 0 0; padding: 0; }
.prod-lines li { margin: .1rem 0; }
.prod-list .prod-lines li { margin: 0; }
/* A knife string ("1530→120+118+…+222R") or a long code has no space to
   break at: without this it ran past the card on a phone or tablet and the
   last knives were cut off (E38/E47). "anywhere" also lets the grid column
   shrink, so the text wraps in its column instead of under the buttons. */
.prod-job-what, .prod-now-what, .prod-list > li > div,
.prod-job-head, .prod-job-head strong, .prod-lines li,
.prod-pick-order legend, .prod-pick-order label,
.cutplan-line, .cutplan-variant h3 { min-width: 0; overflow-wrap: anywhere; }

/* The order-line picker: grouped by item code (or by order), a filter on
   top, the count of what is ticked under it. Scrolls inside itself. */
.prod-add-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem 1rem; margin-top: .6rem; }
.prod-pick { width: 100%; max-width: 56rem; }
.prod-pick [hidden] { display: none !important; }
.prod-pick-filter { width: 100%; margin: .3rem 0 .4rem; }
.prod-pick-list {
    max-height: 26rem;
    overflow: auto;
    padding: .2rem .6rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.prod-pick-order { margin: .5rem 0; padding: 0; border: 0; }
.prod-pick-order + .prod-pick-order { padding-top: .5rem; border-top: 1px solid var(--border); }
.prod-pick-order legend { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .5rem; padding: 0; }
.prod-pick-order label { display: flex; align-items: baseline; gap: .5rem; margin: .15rem 0 .15rem .3rem; font-weight: 400; cursor: pointer; }
.prod-pick-order label:has(input:checked) { background: var(--info-bg); border-radius: 4px; }
.prod-pick-whole { color: var(--muted); }
.prod-pick-count { margin: .4rem 0 0; }
.prod-pick-count.is-mixed { color: var(--err); }
.prod-add-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1rem; }.prod-where { display: flex; flex-wrap: wrap; gap: .4rem 1.2rem; margin: .6rem 0 .4rem; padding: 0; border: 0; }
.prod-where label { font-weight: 400; }

/* Settings: the machines' working hours. */
.prod-hours-times { display: grid; grid-template-columns: auto auto; gap: .4rem .8rem; align-items: center; justify-content: start; }
.prod-days { display: flex; flex-wrap: wrap; gap: .3rem .9rem; margin: .8rem 0 .4rem; padding: 0; border: 0; }
.prod-days legend { margin-bottom: .3rem; padding: 0; font-weight: 600; }

/* Tablet: the buttons of a queued job go under its text, in the text's
   column, so the heading keeps the width and is never drawn under them
   (E47: 768 px, 13 outputs). */
@media (max-width: 64rem) {
    .prod-job { grid-template-columns: 9rem minmax(0, 1fr); }
    .prod-job > .prod-actions { grid-column: 2; justify-content: flex-start; }
}

@media (max-width: 40rem) {
    .prod-row { grid-template-columns: minmax(0, 1fr); }
    .prod-name { flex-direction: row; align-items: center; }
    .prod-axis-row .prod-name { display: none; }
    /* "most" on its own line, the hour marks under it - they would overlap. */
    .prod-axis { height: 2.3rem; }
    .prod-tick { top: 1.1rem; }
    .prod-tick-now { top: 0; }
    .prod-job { grid-template-columns: minmax(0, 1fr); }
    .prod-list > li { grid-template-columns: minmax(0, 1fr); }
    .prod-job > .prod-actions { grid-column: auto; justify-content: flex-start; }
}

/* QR kódok: order number and customer as copyable PNG codes (Kiosztás template). */
.qr-search { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin: 0 0 .4rem; }
.qr-search input[type=search] { flex: 1 1 18rem; max-width: 30rem; }
.qr-table td { vertical-align: middle; }
.qr-cell { text-align: center; min-width: 9rem; }
.qr-cell .qr-img { display: block; margin: 0 auto .3rem; max-width: 220px; height: auto; background: #fff; }
.qr-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: .3rem .6rem; }
.qr-copied { color: var(--ok); }
.qr-copy-failed { color: var(--err); }
/* .btn nastavuje display, takze bez tohohle by hidden neskryl (Masolas bez Clipboard API). */
.qr-actions [hidden] { display: none !important; }
.qr-table tr.is-shipped td { color: var(--muted); }

/* Címke-elírások: the name as it was written on the label stands out. */
.label-typo { color: var(--err); }
.labeltypos-rolls { margin-top: 1.5rem; }
.labeltypos-rolls > summary { cursor: pointer; font-weight: 600; margin-bottom: .6rem; }

/* Kiosztás-tervező (TEST): the picker folds away once there is a plan; each
   group shows its demand, then the two variants side by side. The bar draws
   the knife setting to scale on the jumbo: edge, knives, fillers hatched. */
.cutplan-pick > summary { cursor: pointer; margin-bottom: .6rem; }
.cutplan-opts { display: flex; flex-wrap: wrap; gap: .5rem 1.2rem; border: 1px solid var(--border); border-radius: var(--radius); padding: .5rem .9rem .8rem; margin: .8rem 0; }
.cutplan-opts legend { font-weight: 600; padding: 0 .3rem; }
.cutplan-opts label { display: flex; flex-direction: column; gap: .2rem; font-size: .9rem; }
.cutplan-opts input { width: 7rem; }
.cutplan-group { margin-top: 2rem; padding-top: 1rem; border-top: 2px solid var(--border); }
.cutplan-group h2 { margin-top: 0; }
.cutplan-params { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem 1rem; margin: .4rem 0 .8rem; }
.cutplan-params label { display: flex; flex-direction: column; gap: .2rem; font-size: .9rem; }
.cutplan-fill input { width: 18rem; max-width: 100%; }
.cutplan-fill-src { flex: 1 1 100%; }
.cutplan-demand { margin-bottom: .8rem; }
.cutplan-variants { display: grid; grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr)); gap: 1rem; margin-top: .6rem; }
.cutplan-variant { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: .9rem 1rem; min-width: 0; }
.cutplan-variant.is-recommended { border-color: var(--ok); box-shadow: 0 0 0 1px var(--ok), var(--shadow); }
.cutplan-variant h3 { margin: 0 0 .2rem; font-size: 1.05rem; }
.cutplan-metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: .4rem .8rem; margin: .7rem 0; }
.cutplan-metrics div { background: var(--surface-2); border-radius: 6px; padding: .35rem .55rem; }
.cutplan-metrics dt { font-size: .75rem; color: var(--muted); }
.cutplan-metrics dd { margin: 0; font-weight: 600; }
.cutplan-patterns { padding-left: 1.3rem; margin: .6rem 0; }
.cutplan-patterns > li { margin-bottom: .9rem; }
.cutplan-bar { display: flex; height: 1.9rem; border: 1px solid var(--border); border-radius: 4px; overflow: hidden; font-size: .7rem; background: var(--err-bg); }
.cutplan-bar > span { display: flex; align-items: center; justify-content: center; overflow: hidden; white-space: nowrap; border-right: 1px solid var(--surface); }
.cutplan-bar > span:last-child { border-right: 0; }
.cp-edge { background: var(--err-bg); }
.cp-knife { background: var(--info-bg); color: var(--info); font-weight: 600; }
.cp-knife.cp-fill { background: repeating-linear-gradient(45deg, var(--warn-bg), var(--warn-bg) 4px, var(--surface-2) 4px, var(--surface-2) 8px); color: var(--warn); }
.cutplan-line { margin: .35rem 0 .2rem; }
.cutplan-shares { list-style: none; padding: 0; margin: 0; color: var(--muted); }
.cutplan-shares strong { color: var(--text); }
.cutplan-stock { color: var(--warn); font-weight: 600; }
.cutplan-create { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem .8rem; border-top: 1px solid var(--border); padding-top: .7rem; margin-top: .4rem; }
.cutplan-create label { display: flex; flex-direction: column; gap: .2rem; font-size: .9rem; }
.cutplan-legend { margin-top: 1.5rem; }
/* One button for the whole plan (Balint: all or nothing); per group the variant and the machine. */
.cutplan-choose { display: flex; align-items: center; gap: .45rem; margin-top: .7rem; padding-top: .6rem; border-top: 1px solid var(--border); font-weight: 600; cursor: pointer; }
.cutplan-machine { margin: .9rem 0 0; }
.cutplan-machine label { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .5rem; font-size: .92rem; }
.cutplan-machine select { width: auto; min-width: 7rem; }
.cutplan-create-all { margin: 1.6rem 0 0; padding: 1rem 1.1rem; background: var(--surface); border: 2px solid var(--ok); border-radius: var(--radius); box-shadow: var(--shadow); }
.cutplan-create-all .cutplan-create { border-top: 0; padding-top: 0; margin-top: 0; }
/* Vevonkent barva nozu v pruhu (vic zakazniku v planu) - svetle, aby cislo
   sirky bylo citelne i v tmavem rezimu; stejne barvy v print.css. */
.cp-knife.cp-c0, .cp-swatch.cp-c0 { background: #cfe3fb; color: #1a2029; }
.cp-knife.cp-c1, .cp-swatch.cp-c1 { background: #cdeecb; color: #1a2029; }
.cp-knife.cp-c2, .cp-swatch.cp-c2 { background: #fcdcb8; color: #1a2029; }
.cp-knife.cp-c3, .cp-swatch.cp-c3 { background: #e3d3f6; color: #1a2029; }
.cp-knife.cp-c4, .cp-swatch.cp-c4 { background: #c6ecee; color: #1a2029; }
.cp-knife.cp-c5, .cp-swatch.cp-c5 { background: #f8cfdd; color: #1a2029; }
.cp-knife.cp-c6, .cp-swatch.cp-c6 { background: #f3eca9; color: #1a2029; }
.cp-knife.cp-c7, .cp-swatch.cp-c7 { background: #d9dde3; color: #1a2029; }
.cp-knife.cp-c8, .cp-swatch.cp-c8 { background: #b9d7c2; color: #1a2029; }
.cp-knife.cp-c9, .cp-swatch.cp-c9 { background: #f1c7b1; color: #1a2029; }
.cp-knife.cp-c10, .cp-swatch.cp-c10 { background: #c5cff5; color: #1a2029; }
.cp-knife.cp-c11, .cp-swatch.cp-c11 { background: #e8d9b5; color: #1a2029; }
.cutplan-colours { display: flex; flex-wrap: wrap; gap: .3rem .9rem; margin: .2rem 0 .6rem; font-size: .85rem; }
.cutplan-reels { margin: .2rem 0 .6rem; padding: .35rem .6rem; background: var(--surface-2); border-radius: 6px; }
.cutplan-colour { display: inline-flex; align-items: center; gap: .35rem; }
.cp-swatch { display: inline-block; width: 1.1rem; height: .8rem; border: 1px solid var(--border); border-radius: 2px; }
.cutplan-opts .cutplan-check { flex-direction: row; align-items: flex-end; max-width: 26rem; }
.cutplan-opts .cutplan-check input[type=checkbox] { width: auto; margin-right: .35rem; }
.cutplan-mini { margin: 1rem 0; padding: .8rem 1rem; border: 1px solid var(--border); border-left: 4px solid var(--info); border-radius: var(--radius); background: var(--surface); }
.cutplan-mini h3 { margin: 0 0 .2rem; font-size: 1.05rem; }
.plan-why { color: var(--warn, #b7791f); margin-top: .1rem; }
.inline-form { display: inline; }
.plan-close { display: block; margin-top: .35rem; }
.cutplan-manual { margin: 1rem 0; padding: .6rem 1rem; border: 1px dashed var(--border); border-radius: var(--radius); background: var(--surface); }
.cutplan-manual summary { cursor: pointer; }
.cutplan-manual-row { margin: .5rem 0; padding: .3rem .6rem; border: 0; border-left: 3px solid var(--border); }
.cutplan-manual-row .cutplan-check { display: flex; gap: .35rem; align-items: baseline; flex-wrap: wrap; margin: .15rem 0; }
.cutplan-manual-row input[type=checkbox] { width: auto; }
@media (max-width: 600px) {
    .cutplan-variants { grid-template-columns: 1fr; }
    .cutplan-bar { font-size: .6rem; }
}

/* --- zalohy (swtfp-backup-kit) -----------------------------------------
   The kit's stylesheet (assets/backupkit/, never edited here) takes its
   colours from --bk-* variables. Pointing them at this theme's own tokens
   makes the backup page and the header badge follow light/dark with it.
   Declared on :root like the tokens, so the dark overrides above apply. */
:root {
    --bk-muted: var(--muted); --bk-surface: var(--surface-2); --bk-border: var(--border); --bk-line: var(--border);
    --bk-ok: var(--ok); --bk-ok-bg: var(--ok-bg); --bk-ok-ink: var(--ok);
    --bk-err: var(--err); --bk-err-bg: var(--err-bg); --bk-err-line: var(--err); --bk-err-ink: var(--err);
    --bk-warn-bg: var(--warn-bg); --bk-warn-line: var(--warn); --bk-warn-ink: var(--warn);
    --bk-btn-bg: var(--surface); --bk-btn-hover: var(--surface-2); --bk-btn-line: var(--border); --bk-btn-ink: var(--text);
    --bk-pri: var(--brand); --bk-pri-hover: var(--brand-dk); --bk-on-pri: var(--on-brand);
    --bk-tag-bg: var(--surface-2); --bk-tag-ink: var(--text); --bk-restore-bg: var(--err-bg);
}

/* --- Beszerzesi elorejelzes (?p=forecast) --------------------------------
   Podklady s nahranim po radcich, sbalene parametry, vysledek. */
.fc-inputs td { vertical-align: top; }
.fc-upload { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.fc-run { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }
.fc-params > summary { cursor: pointer; }
.fc-params[open] > summary { margin-bottom: 1rem; }
.fc-param-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem 1.25rem; }
.fc-param-lists { margin-top: 1.25rem; }
.fc-field { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.fc-field label { margin-bottom: 0; }
.fc-wide { grid-column: 1 / -1; }
.fc-field input[type=date], .fc-field textarea {
    width: 100%;
    padding: .5rem .65rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
}
.fc-field textarea { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: .85rem; resize: vertical; }
.fc-field textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.fc-field.has-error input, .fc-field.has-error textarea { border-color: var(--warn); box-shadow: 0 0 0 1px var(--warn); }
.fc-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.25rem; }
.fc-downloads { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem; margin: .75rem 0 1.25rem; }
.fc-pi .fc-pi-head td { background: var(--surface-2); border-top: 2px solid var(--border); }
.fc-orders { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem 1.5rem; margin-bottom: 1.5rem; }
.fc-order h4 { margin: 0 0 .5rem; }
.fc-list { margin: .35rem 0 0; padding-left: 1.2rem; }
.fc-result h3 { margin-top: 2rem; }
/* Rendelesek hetenkent: prvni tyden je objednavka, ktera se dava ted. */
.fc-weeks td { vertical-align: top; }
.fc-weeks tr.fc-week-first td { background: var(--info-bg); border-top: 2px solid var(--info); border-bottom: 2px solid var(--info); }
.fc-weeks tr.fc-week-first td:first-child { border-left: 2px solid var(--info); }
.fc-weeks tr.fc-week-first td:last-child { border-right: 2px solid var(--info); }
.facts .fc-fact-week { background: var(--info-bg); }
/* Tydny "Megrendelve": oznaceny tyden zeleny okraj vlevo, male PI pole. */
.fc-weeks tr.fc-week-marked td:first-child { box-shadow: inset 4px 0 0 var(--ok); }
.fc-week-act { white-space: nowrap; }
.fc-week-act form, .fc-week-act .chip { margin: .15rem .2rem .15rem 0; vertical-align: middle; }
.fc-pi-form { display: inline-flex; gap: .3rem; align-items: center; }
.fc-pi-form input[type=text] { width: 11rem; padding: .3rem .45rem; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
/* PI znacky (samo / rucne), u sparovanych "Nem ez". */
.fc-link { white-space: normal; margin: .2rem 0; font-size: .85em; }
.fc-link form { margin-left: .3rem; }

/* Kiosztas-tervezo: souhrn stranky nahore a nad vytvorenim (revize rychlosti 12. 10.) -
   skupiny, ulohy, cas po strojich, vynechane radky a proc, odkazy na skupiny s upozornenim. */
.cutplan-summary { margin: 1rem 0; padding: .7rem 1rem; background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--ok); border-radius: var(--radius); }
.cutplan-summary p { margin: .2rem 0; }
.cutplan-summary .cutplan-left { color: var(--err); }
.cutplan-summary .cutplan-left a { color: inherit; text-decoration: underline; }
.cutplan-create-all .cutplan-summary { margin-top: 0; border: 0; padding: 0; }
form.cutplan-create { margin: 0 0 1rem; }
/* Dlouha odpoved serveru (planovani): hlaska misto zamrzle stranky. */
.busy-overlay { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
    background: rgba(15, 23, 42, .35); }
.busy-overlay p { margin: 0 1rem; padding: 1rem 1.4rem; max-width: 32rem; background: var(--surface); color: var(--text);
    border-radius: var(--radius); box-shadow: var(--shadow); font-weight: 600; }

/* =====================================================================
   Vizualni upravy (Balint 12. 10. 2026: "atlathatobb legyen, ne logjon
   le az oldalrol, a fontos dolgok kiemelve, a magyarazat kisebb betuvel,
   a csempek, amikre kattintanak, szepen kiemelve"). Balint schvalil
   vsechny bloky A-J podle nahledu 12. 10. 2026.
   ===================================================================== */

/* A. Horni lista na notebooku (1024-1200 px): text vedle loga pryc, mensi
      mezery - stranka uz nejezdi o par pixelu do strany. */
@media (max-width: 1200px) {
    .topbar { gap: 1rem; padding: 0 1rem; }
    .brand-text { display: none; }
    .topbar-right { gap: .6rem; }
    .topsearch { flex-basis: 16rem; min-width: 0; }
}

/* B. Dvousloupcove stranky (Uzivatele): hlavni sloupec se smi zuzit,
      tabulka se posouva ve svem ramu; na uzsim notebooku pod sebou. */
.split > * { min-width: 0; }
@media (max-width: 1100px) { .split { grid-template-columns: 1fr; } }

/* C. Kazda tabulka ve svem posuvnem ramu; vnitrni (v rozbalovacim radku,
      v kartce objednavky) se posouvaji do strany na svem miste, ale bez
      druheho ramu v ramu. */
.table-scroll-plain { background: none; border: 0; border-radius: 0; box-shadow: none; }

/* D. Nadpisy: nazev stranky vyraznejsi, oddily citelne oddelene. */
h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; font-weight: 650; }

/* E. Vysvetlujici text mensi a tissi nez obsah, at oko jde na data. */
.lead { font-size: .9rem; max-width: 78ch; line-height: 1.5; }
small, .small { font-size: .84rem; }
.f small, small.muted, .muted small { color: var(--muted); }

/* F. Kartky, na ktere jde kliknout: zvednou se, oramuji a ukazou sipku. */
a.card { color: inherit; text-decoration: none; cursor: pointer; position: relative;
    transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease; }
a.card::after { content: "→"; position: absolute; right: .9rem; top: .75rem; color: var(--muted);
    font-size: 1rem; transition: transform .15s ease, color .15s ease; }
a.card:hover { text-decoration: none; transform: translateY(-1px);
    border-color: var(--brand); box-shadow: var(--shadow), 0 0 0 1px var(--brand); }
a.card:hover::after { color: var(--brand); transform: translateX(2px); }
a.card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* G. Rozbalovaci radky (Allapot es sorok, Reszletek): je videt, ze se na
      ne klika - ikona, barva odkazu, zvyrazneni pri najeti. */
summary { cursor: pointer; }
.grid tr.loc-rows > td > details > summary { color: var(--accent); font-weight: 500; }
.grid tr.loc-rows > td > details > summary:hover,
.stock-prop > summary:hover { text-decoration: underline; }
.grid tr.loc-rows > td > details[open] > summary { color: var(--text); }

/* H. Dulezita cisla vyrazneji: hodnota na kartce a jeji popisek. */
.card-value { font-weight: 650; }
.card-label { font-weight: 600; }
.grid tfoot td { font-weight: 700; }

/* I. Klavesnice: viditelny fokus u odkazu, tlacitek a rozbalovacich radku
      (pole maji svuj fokus - cervena kolem automaticky vybraneho hledani
      by vypadala jako chyba). */
a:focus-visible, button:focus-visible, summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    a.card, a.card::after { transition: none; }
    a.card:hover { transform: none; }
}

/* J. Mai teendok: kartky vedou na sve seznamy niz na strance; seznam
      po skoku zacina pod lepivou hlavickou, ne pod ni schovany. */
.jump-target { scroll-margin-top: 112px; }
