:root {
    color-scheme: dark;
    --bg: #0f1115;
    --surface: #171a21;
    --border: #262b36;
    --text: #e6e8eb;
    --muted: #9aa3b2;
    --primary: #23d887;
    --link: #3898ec;
    --on-primary: #04130c;
    --danger: #f7546a;
}

:root[data-theme="light"] {
    color-scheme: light;
    --bg: #f4f6f9;
    --surface: #ffffff;
    --border: #e2e6ec;
    --text: #1a1d23;
    --muted: #5c6573;
    --primary: #16a368;
    --link: #2563eb;
    --on-primary: #ffffff;
    --danger: #d83452;
}

* { box-sizing: border-box; }

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

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

/* ── App shell: fixed left sidebar + scrollable content column ───────── */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
    position: sticky;
    top: 0;
    align-self: flex-start;
    flex: 0 0 240px;
    height: 100vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 1.25rem 0.85rem;
    background: var(--surface);
    border-right: 1px solid var(--border);
}

.sidebar .brand {
    font-weight: 700;
    color: var(--primary);
    font-size: 1.1rem;
    padding: 0.25rem 0.65rem;
}
.sidebar .brand:hover { text-decoration: none; }

.sidebar-nav { display: flex; flex-direction: column; gap: 1.25rem; }
.nav-group { display: flex; flex-direction: column; gap: 0.15rem; }
.nav-group-label {
    color: var(--muted);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    padding: 0 0.65rem 0.25rem;
}

.nav-link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.65rem;
    border-radius: 8px;
    color: var(--text);
    font-size: 0.92rem;
    font-weight: 500;
    border-left: 3px solid transparent;
}
.nav-link:hover { background: var(--bg); text-decoration: none; }
.nav-link.is-active {
    background: var(--bg);
    color: var(--primary);
    border-left-color: var(--primary);
}
.nav-icon { flex: 0 0 auto; opacity: 0.85; }
.nav-link.is-active .nav-icon { opacity: 1; }

/* Collapsible nav section — native <details>, no JavaScript. */
.nav-collapsible { display: flex; flex-direction: column; gap: 0.15rem; }
.nav-collapsible > summary { cursor: pointer; list-style: none; }
.nav-collapsible > summary::-webkit-details-marker { display: none; }
.nav-collapsible-summary::after {
    content: '';
    margin-left: auto;
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
}
.nav-collapsible[open] .nav-collapsible-summary::after { transform: rotate(45deg); }
.nav-subgroup { display: flex; flex-direction: column; gap: 0.15rem; padding-left: 1.4rem; margin-top: 0.15rem; }

/* ── Content column: sticky topbar + scrolling main ──────────────────── */
.app-content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1.5rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}
.topbar-title { margin: 0; font-size: 1.15rem; font-weight: 600; }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 0.85rem; }

/* ── Breadcrumbs (drobečková navigace) ───────────────────────────────── */
.breadcrumbs { min-width: 0; }
.breadcrumbs__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    font-size: 1.05rem;
}
.breadcrumbs__item { display: inline-flex; align-items: center; gap: 0.4rem; min-width: 0; }
.breadcrumbs__item:not(:first-child)::before { content: "/"; color: var(--muted); opacity: 0.55; }
.breadcrumbs__link { color: var(--muted); text-decoration: none; white-space: nowrap; }
.breadcrumbs__link:hover { color: var(--link); text-decoration: underline; }
.breadcrumbs__current {
    color: var(--text);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Theme switch lives in the user dropdown — a menu item that flips the label
   + icon by theme (sun → switch to light, moon → switch to dark). */
button.user-menu-item { width: 100%; background: none; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.theme-switch__dark, .theme-switch__light { display: inline-flex; align-items: center; gap: 0.55rem; }
.theme-switch__light { display: none; }
:root[data-theme="light"] .theme-switch__dark { display: none; }
:root[data-theme="light"] .theme-switch__light { display: inline-flex; }

/* AI Agent health indicator — dot + hover tooltip. */
.agent-health { position: relative; display: inline-flex; align-items: center; gap: 0.4rem; cursor: default; }
.agent-health__dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.agent-health__dot.is-ok { background: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 22%, transparent); }
.agent-health__dot.is-down { background: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 22%, transparent); }
.agent-health__label { font-size: 0.82rem; color: var(--muted); }
.agent-health__pop {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 50;
    min-width: 15rem;
    display: none;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.7rem 0.85rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}
/* Transparent bridge across the gap so the cursor can travel from the badge
   into the tooltip without un-hovering and hiding it. */
.agent-health__pop::before { content: ""; position: absolute; top: -0.5rem; left: 0; right: 0; height: 0.5rem; }
.agent-health:hover .agent-health__pop,
.agent-health:focus-within .agent-health__pop { display: flex; }
.agent-health__pop-head { font-weight: 600; margin-bottom: 0.15rem; }
.agent-health__row { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.82rem; color: var(--muted); }
.agent-health__row-note { color: var(--text); }
.agent-health__row.is-bad .agent-health__row-note { color: var(--danger); font-weight: 600; }
.agent-health__link { display: inline-flex; align-items: center; gap: 0.4rem; color: inherit; }
.agent-health__link:hover { text-decoration: none; }

/* AI diagnostics page. */
.ai-card-title { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.9rem; font-size: 1.05rem; }
.ai-checks, .ai-config, .ai-tools, .ai-runs { width: 100%; border-collapse: collapse; }
.ai-checks td, .ai-config td { padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
.ai-checks__label, .ai-config td:first-child { color: var(--muted); width: 40%; }
.ai-checks tr.is-bad .ai-checks__note { color: var(--danger); font-weight: 600; }
.ai-tools td { padding: 0.45rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.ai-tools__name { width: 30%; white-space: nowrap; }
.ai-tools__desc { color: var(--muted); }
.ai-runs th { text-align: left; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); padding: 0.35rem 0.6rem 0.35rem 0; border-bottom: 1px solid var(--border); }
.ai-runs td { padding: 0.45rem 0.6rem 0.45rem 0; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.ai-runs__text { color: var(--muted); }
.ai-status { font-size: 0.78rem; padding: 0.1rem 0.45rem; border-radius: 999px; background: var(--bg); border: 1px solid var(--border); }
.ai-status--failed { color: var(--danger); }
.ai-status--completed { color: var(--primary); }

/* AI connection test. */
.agent-test__bar { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; }
.agent-test__warn { color: var(--muted); font-size: 0.82rem; }
.agent-test__loading { color: var(--muted); font-size: 0.85rem; }
.agent-test__result { margin-top: 0.9rem; padding: 0.7rem 0.85rem; border-radius: 8px; border: 1px solid var(--border); display: flex; flex-direction: column; gap: 0.35rem; }
.agent-test__result.is-ok { border-color: color-mix(in srgb, var(--primary) 50%, var(--border)); }
.agent-test__result.is-bad { border-color: color-mix(in srgb, var(--danger) 50%, var(--border)); }
.agent-test__result small { color: var(--muted); }

/* User menu — native <details> dropdown, no JS. */
.user-menu { position: relative; }
.user-menu > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.5rem 0.3rem 0.35rem;
    border-radius: 8px;
    cursor: pointer;
    list-style: none;
    color: var(--text);
    font-size: 0.9rem;
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover { background: var(--bg); }
.user-menu[open] > summary { background: var(--bg); }
.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--primary);
    color: var(--on-primary);
    font-weight: 700;
    font-size: 0.8rem;
}
.user-name { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu[open] > summary .nav-icon { transform: rotate(180deg); }

.user-menu-pop {
    position: absolute;
    right: 0;
    top: calc(100% + 0.4rem);
    min-width: 200px;
    display: flex;
    flex-direction: column;
    padding: 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
.user-menu-head {
    padding: 0.4rem 0.6rem;
    color: var(--muted);
    font-size: 0.8rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0.25rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.user-menu-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.6rem;
    border-radius: 7px;
    color: var(--text);
    font-size: 0.9rem;
}
.user-menu-item:hover { background: var(--bg); text-decoration: none; }

.app-main { flex: 1 1 auto; min-width: 0; width: 100%; padding: 2rem 1.5rem; }

/* ── Mobile: sidebar collapses to a top strip ────────────────────────── */
@media (max-width: 768px) {
    .app-shell { flex-direction: column; }
    .sidebar {
        position: static;
        flex-basis: auto;
        height: auto;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.5rem 1rem;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }
    .sidebar-nav { flex-direction: row; flex-wrap: wrap; gap: 0.25rem 0.75rem; }
    .nav-group { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0.25rem; }
    .nav-group-label { display: none; }
    .nav-link { border-left: none; padding: 0.4rem 0.6rem; }
    .nav-link.is-active { border-left: none; }
    .user-name { display: none; }
}

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1.25rem 1.5rem;
}

table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 0.6rem 0.5rem; border-bottom: 1px solid var(--border); }
th { color: var(--muted); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; }

.btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--primary);
    color: var(--on-primary);
    font-weight: 600;
    border: none;
    border-radius: 8px;
    padding: 0.5rem 0.9rem;
    cursor: pointer;
}
.btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--border); }

/* A submit button that reads as a text link — for inline POST actions (archive). */
.link-button {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--primary);
    cursor: pointer;
    text-decoration: none;
}
.link-button:hover { text-decoration: underline; }

/* Segmented control — a labelled radio group styled as a row of pill buttons.
   Discrete choices (length, tone) the AI prompt maps to; the hidden radio drives
   state so :has(:checked) highlights the active segment with no JS. */
.segmented {
    display: inline-flex;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}
.segmented__opt {
    position: relative;
    display: inline-flex;
    /* The option is a <label>; kill the global `label` bottom margin, which
       otherwise paints a stripe under the pills inside the bordered group. */
    margin: 0;
}
.segmented__opt + .segmented__opt {
    border-left: 1px solid var(--border);
}
.segmented__opt input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}
.segmented__opt span {
    padding: 0.45rem 0.9rem;
    font-size: 0.9rem;
    color: var(--text);
    user-select: none;
    white-space: nowrap;
}
.segmented__opt:has(input:checked) span {
    background: var(--primary);
    color: var(--on-primary);
    font-weight: 600;
}
.segmented__opt:has(input:focus-visible) span {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* Modal dialog — backdrop fades in, dialog pops up (Bootstrap/Metronic style). */
.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, 0.55);
    animation: modal-backdrop-in 0.18s ease-out;
}
.modal-dialog {
    width: 100%;
    max-width: 440px;
    animation: modal-dialog-in 0.22s cubic-bezier(0.2, 0.8, 0.25, 1);
}
.modal-dialog--wide { max-width: 720px; }

/* AI preview: one selectable card per generated block. Whole card is a <label>,
   so a click anywhere toggles its checkbox; :has() reflects the state live. */
.ai-block {
    display: block;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.7rem 0.85rem;
    margin-bottom: 0.6rem;
    transition: border-color 0.15s ease, opacity 0.15s ease;
}
.ai-block:has(input) { cursor: pointer; }
.ai-block:has(input:checked) { border-color: var(--primary); }
.ai-block:has(input):not(:has(input:checked)) { opacity: 0.5; }
.ai-block__title { font-weight: 600; }
.ai-block input[type="checkbox"] { width: auto; margin-right: 0.5rem; vertical-align: middle; }
.ai-block p { margin: 0.35rem 0 0; }
.ai-block ul { margin: 0.35rem 0 0; }
@keyframes modal-backdrop-in {
    from { opacity: 0; }
    to { opacity: 1; }
}
@keyframes modal-dialog-in {
    from { opacity: 0; transform: translateY(-14px) scale(0.96); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Zavírání — modal_controller přidá .modal-backdrop--closing, dohraje exit
   animaci a teprve pak spustí odebrání z DOM (LiveComponent akci). */
.modal-backdrop--closing { animation: modal-backdrop-out 0.16s ease-in forwards; }
.modal-backdrop--closing .modal-dialog { animation: modal-dialog-out 0.18s ease-in forwards; }
@keyframes modal-backdrop-out {
    from { opacity: 1; }
    to { opacity: 0; }
}
@keyframes modal-dialog-out {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to { opacity: 0; transform: translateY(-14px) scale(0.96); }
}
@media (prefers-reduced-motion: reduce) {
    .modal-backdrop, .modal-dialog,
    .modal-backdrop--closing, .modal-backdrop--closing .modal-dialog { animation: none; }
}

input, textarea, .field {
    width: 100%;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.55rem 0.7rem;
    color: var(--text);
}

/* All multi-line text areas share one height; only vertical resize allowed. */
textarea, textarea.field {
    min-height: 11rem;
    font: inherit;
    line-height: 1.5;
    resize: vertical;
}

label { display: block; margin-bottom: 0.35rem; color: var(--muted); font-size: 0.9rem; }
/* Symfony tags required fields' labels with .required — mark them with an asterisk. */
label.required::after { content: " *"; color: var(--danger); font-weight: 600; }
.form-row { margin-bottom: 1rem; }
.search { max-width: 320px; margin-bottom: 1rem; }

/* Two-column responsive field grid. Short fields sit side by side; fields that
   need the full width opt in with .span-2. Collapses to one column on narrow
   viewports. */
.form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 1.5rem;
}
.form-grid .form-row { margin-bottom: 1.1rem; }
.form-grid .span-2 { grid-column: 1 / -1; }

.form-section {
    grid-column: 1 / -1;
    margin: 0.5rem 0 0.25rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.form-section:first-child { margin-top: 0; padding-top: 0; border-top: none; }

@media (max-width: 560px) {
    .form-grid { grid-template-columns: 1fr; }
}

/* ---- Data grid: total count, per-page selector, pager ---- */
.datagrid-toolbar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    margin-bottom: 0.6rem;
    color: var(--muted);
    font-size: 0.85rem;
}

.datagrid-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 1rem;
    color: var(--muted);
    font-size: 0.85rem;
}
.datagrid-footer .datagrid-info { display: flex; align-items: center; gap: 0.6rem; }

/* Narrow, auto-width version of the .field select — sits inline in the footer. */
.datagrid-perpage {
    width: auto;
    padding: 0.3rem 1.6rem 0.3rem 0.6rem;
    font-size: 0.85rem;
    cursor: pointer;
}

.datagrid-pager { display: inline-flex; gap: 0.3rem; }
.btn-page {
    min-width: 2rem;
    height: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 0.5rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
}
.btn-page:hover:not(:disabled):not(.is-active) {
    border-color: var(--primary);
    color: var(--primary);
}
.btn-page.is-active {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
    font-weight: 600;
    cursor: default;
}
.btn-page:disabled { opacity: 0.4; cursor: not-allowed; }
.datagrid-ellipsis { padding: 0 0.15rem; color: var(--muted); align-self: center; }

/* ---- Dense data grid (Excel-style): scroll, sticky head, filters, sort, resize, columns ----
   The compact list the client asked for (meeting 22.7.2026): many rows on screen,
   filters in the column headers, click-to-sort, drag-to-resize and show/hide columns. */
.datagrid-toolbar {
    justify-content: flex-start;
    gap: 0.75rem;
}
.datagrid-count { margin-left: auto; white-space: nowrap; }
.datagrid-search { width: auto; flex: 0 1 18rem; margin: 0; font-size: 0.82rem; padding: 0.3rem 0.55rem; }

/* Uložená zobrazení (plán 0042, Z5): roletka pojmenovaných kombinací sloupců, šířek,
   filtrů a řazení — vlevo v panelu, protože se z ní vybírá jako první. */
.datagrid-views { display: flex; align-items: center; gap: 0.35rem; }
.datagrid-views-select { width: auto; margin: 0; font-size: 0.82rem; padding: 0.3rem 0.55rem; max-width: 12rem; }
.datagrid-views-btn {
    padding: 0.3rem 0.55rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.82rem;
    cursor: pointer;
    white-space: nowrap;
}
.datagrid-views-btn:hover { border-color: var(--primary); color: var(--primary); }
.datagrid-views-save { display: inline-flex; align-items: center; gap: 0.35rem; }
.datagrid-views-save[hidden] { display: none; }
.datagrid-views-save .field { width: auto; margin: 0; font-size: 0.82rem; padding: 0.3rem 0.55rem; max-width: 11rem; }

/* Column picker: a button that drops a checkbox menu built client-side. */
.datagrid-columns { position: relative; }
.datagrid-columns-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.85rem;
    cursor: pointer;
}
.datagrid-columns-btn:hover { border-color: var(--primary); color: var(--primary); }
.datagrid-columns-menu {
    position: absolute;
    top: calc(100% + 0.3rem);
    left: 0;
    z-index: 20;
    min-width: 12rem;
    max-height: 60vh;
    overflow-y: auto;
    padding: 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
.datagrid-columns-menu label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border-radius: 6px;
    font-size: 0.85rem;
    cursor: pointer;
    white-space: nowrap;
}
.datagrid-columns-menu label:hover { background: var(--bg); }
/* The global form styling stretches inputs to full width; keep the checkbox at
   its natural size so the label sits right next to it (not pushed to the right). */
.datagrid-columns-menu input { width: auto; flex: 0 0 auto; margin: 0; cursor: pointer; }

/* Scroll container — keeps the header (and filter row) pinned while the body scrolls. */
.datagrid-scroll {
    overflow: auto;
    max-height: 72vh;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
}

table.datagrid {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    table-layout: auto; /* controller switches to fixed once column widths are measured */
    font-size: 0.85rem;
}
table.datagrid th,
table.datagrid td {
    padding: 0.28rem 0.55rem;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--border);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The header labels stay pinned to the top of the scroll box; the filter row
   pins just below them. --dg-head-h is measured and set by the resize controller. */
table.datagrid thead .datagrid-head th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--surface);
    font-weight: 600;
    color: var(--muted);
    user-select: none;
}
/* Header cell inner layout: the sortable label grows, the filter funnel sits at
   the end. min-width:0 lets the label ellipsize when the column is dragged narrow. */
.datagrid-th {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    min-width: 0;
    width: 100%;
}
.datagrid-th > .datagrid-sort-label { flex: 1 1 auto; }

/* Filter funnel + popover (Excel-style per-column filtering, plan 0034 v2). */
.datagrid-filter { position: relative; flex: none; display: inline-flex; align-items: center; gap: 0.1rem; }
.datagrid-filter-btn,
.datagrid-filter-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    background: none;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    border-radius: 4px;
}
.datagrid-filter-btn:hover,
.datagrid-filter-clear:hover { color: var(--primary); background: var(--bg); }
.datagrid-filter-btn.is-active { color: var(--primary); }
.datagrid-filter-clear { font-size: 1rem; line-height: 1; }

/* position:fixed so the popover escapes the grid's scroll container rather than
   being clipped by it; the controller sets top/left from the funnel's rect. */
.datagrid-filter-pop {
    position: fixed;
    z-index: 60;
    min-width: 12rem;
    max-width: 90vw;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
    font-weight: 400;
    color: var(--text);
    white-space: normal;
}
/* The class sets display:flex, which would otherwise beat the UA [hidden] rule
   and leave the popover permanently visible at 0,0 intercepting clicks. */
.datagrid-filter-pop[hidden] { display: none; }
.datagrid-filter-pop .field { margin: 0; width: 100%; font-size: 0.82rem; padding: 0.25rem 0.4rem; }
.datagrid-filter-enum { display: flex; flex-direction: column; gap: 0.15rem; max-height: 14rem; overflow: auto; }
.datagrid-filter-check { display: flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; cursor: pointer; }
.datagrid-filter-check input { width: auto; flex: 0 0 auto; margin: 0; }
.datagrid-filter-actions { display: flex; gap: 0.4rem; justify-content: flex-end; }
.datagrid-filter-apply,
.datagrid-filter-cancel {
    padding: 0.25rem 0.6rem;
    font-size: 0.8rem;
    border-radius: 6px;
    cursor: pointer;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
}
.datagrid-filter-apply { background: var(--primary); border-color: var(--primary); color: var(--on-primary); font-weight: 600; }
.datagrid-filter-apply:hover { opacity: 0.9; }
.datagrid-filter-cancel:hover { border-color: var(--primary); color: var(--primary); }

/* Sortable header button — fills the cell, arrow shows the active direction. */
.datagrid-sort {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 1 1 auto;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    font-weight: 600;
    cursor: pointer;
    text-align: left;
}
.datagrid-sort:hover { color: var(--primary); }
.datagrid-sort { min-width: 0; overflow: hidden; }
/* Let the label shrink and ellipsize when the column is dragged narrower than
   the word; the sort arrow keeps its size. */
.datagrid-sort-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.datagrid-sort-arrow { flex: none; font-size: 0.7rem; opacity: 0.4; }
.datagrid-sort.is-active { color: var(--text); }
.datagrid-sort.is-active .datagrid-sort-arrow { opacity: 1; color: var(--primary); }

/* Body rows: hover highlight, tighter alternating feel via hover only. */
table.datagrid tbody .datagrid-row:hover > td { background: var(--bg); }
table.datagrid tbody td a { color: var(--link); }
.datagrid-empty { padding: 0.6rem 0.55rem; color: var(--muted); white-space: normal; }

/* Resize handle: a grabbable strip on the right edge of each header cell.
   The header cells are position:sticky (above), which also anchors these. */
.datagrid-resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 7px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    touch-action: none;
}
.datagrid-resizer::after {
    content: '';
    position: absolute;
    top: 20%;
    right: 3px;
    width: 1px;
    height: 60%;
    background: var(--border);
}
.datagrid-head th:hover .datagrid-resizer::after { background: var(--primary); }
table.datagrid.is-resizing { user-select: none; cursor: col-resize; }

/* Expand chevron + subrow (nested detail, e.g. offers under an opportunity). */
.datagrid-expand-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.3rem;
    height: 1.3rem;
    padding: 0;
    background: none;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    transition: transform 0.12s ease;
}
.datagrid-expand-btn.is-open { transform: rotate(90deg); color: var(--text); }
.datagrid-subrow > td { padding: 0; background: var(--bg); white-space: normal; }
.datagrid-subrow .datagrid-subrow-inner { padding: 0.35rem 0.55rem 0.5rem 2rem; }
.datagrid-col-expand { width: 2.2rem; text-align: center; padding-left: 0.2rem; padding-right: 0.2rem; }
.datagrid-col-right { text-align: right; }
.datagrid-col-right .datagrid-th { justify-content: flex-end; }
.datagrid-col-right .datagrid-sort { flex: 0 1 auto; }
/* ---- Lišta filtrů inboxu poptávek (plán 0044, P1-29) ----
   Inbox není excelový grid (filtry nejsou v hlavičkách), takže roletky stojí nad tabulkou:
   dvě řádky, které se na úzkém okně zlomí. Vzhled polí je sdílený (.field), tady se jen
   zúží a doplní odsazení. */
.inbox-filters { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
.inbox-filters-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.inbox-filters-search { flex: 1 1 18rem; min-width: 0; margin: 0; }
.inbox-filters-select { width: auto; margin: 0; flex: 0 0 auto; }
.inbox-filters-date { width: auto; margin: 0; flex: 0 0 auto; }
.inbox-filters-label { color: var(--muted); font-size: 0.85rem; }
.inbox-filters-count { margin-left: auto; color: var(--muted); font-size: 0.85rem; white-space: nowrap; }
.inbox-filters-reset {
    padding: 0.3rem 0.6rem;
    background: var(--surface);
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.82rem;
    cursor: pointer;
}
.inbox-filters-reset:hover { border-color: var(--primary); color: var(--primary); }

/* ---- Položky v rozbaleném řádku zakázky (plán 0042, Z6) ----
   Pokračování tabulky, ne vložená karta: stejná velikost písma i vlasové linky jako grid,
   čísla vpravo, inputy bez rámečku, dokud na ně obchodník nejede myší. Strukturu rozpisu
   (kalkulátor, varianty, přidávání řádků) tady vědomě nenajdeš — ta je na detailu. */
/* Táž velikost písma jako řádky zakázek (table.datagrid) — rozbalení má být pokračování
   tabulky, ne menší text uvnitř ní. */
.opportunity-lines { font-size: 0.85rem; }
.opportunity-lines-table { width: 100%; border-collapse: collapse; }
.opportunity-lines-table th {
    padding: 0.1rem 0.4rem;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--muted);
    text-align: left;
}
.opportunity-lines-table td {
    padding: 0.05rem 0.4rem;
    border-top: 1px solid var(--border);
    vertical-align: middle;
}
.opportunity-lines-table tbody tr:hover > td { background: var(--surface); }
.opportunity-lines-num { text-align: right; white-space: nowrap; }
.opportunity-lines-num th { text-align: right; }
.opportunity-lines-total { font-weight: 600; }
.opportunity-lines-unit { color: var(--muted); margin-left: 0.2rem; }
.opportunity-lines-sum td { color: var(--muted); }

/* Buňka se edituje na místě: input nese hodnotu, ale nekreslí se, dokud na něj nejde myš —
   proto seznam čte jako text a přesto se do něj dá psát bez otvírání čehokoli. */
.opportunity-lines-input {
    width: 100%;
    margin: 0;
    padding: 0.05rem 0.25rem;
    font: inherit;
    color: inherit;
    background: none;
    border: 1px solid transparent;
    border-radius: 4px;
}
.opportunity-lines-input:hover { border-color: var(--border); }
.opportunity-lines-input:focus {
    border-color: var(--primary);
    background: var(--bg);
    outline: none;
}
.opportunity-lines-input-num { width: 6rem; text-align: right; }
.opportunity-lines-note,
.opportunity-lines-msg { margin: 0.15rem 0.4rem; color: var(--muted); font-size: 0.74rem; }
.opportunity-lines-msg.is-error { color: #e5484d; }
.opportunity-lines-msg[hidden] { display: none; }

/* ---- Tom Select (ux-autocomplete) theming ----
   The vendor tom-select.default.css is a light theme; on this dark UI it clashes.
   These overrides drive Tom Select off the same CSS variables as .field so the
   widget matches the native inputs and follows light/dark automatically.
   The select keeps its `field` class, which Tom Select copies onto .ts-wrapper —
   we neutralise that outer box and style the inner .ts-control instead. */
.ts-wrapper.field {
    padding: 0;
    border: 0;
    background: none;
    border-radius: 0;
    width: 100%;
}
/* Doubled .ts-wrapper raises specificity above vendor's .ts-wrapper.single
   .ts-control; background-image:none kills the vendor white gradient. */
.ts-wrapper.ts-wrapper.field .ts-control {
    background: var(--bg);
    background-image: none;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.55rem 2.2rem 0.55rem 0.7rem;
    color: var(--text);
    box-shadow: none;
    min-height: 0;
    font-size: inherit;
    line-height: 1.4;
}
.ts-wrapper.ts-wrapper.field .ts-control input,
.ts-wrapper.ts-wrapper.field .ts-control .item { color: var(--text); }
.ts-wrapper.ts-wrapper.field .ts-control input::placeholder { color: var(--muted); }
/* Open / focused: primary ring like a focused field, keep all corners rounded.
   `.input-active` is added when a single-select opens; the vendor default theme
   forces a white .ts-control there, so we re-assert the dark background (and win
   on specificity via the doubled .ts-wrapper + the state class). */
.ts-wrapper.ts-wrapper.field.focus .ts-control,
.ts-wrapper.ts-wrapper.field.input-active .ts-control,
.ts-wrapper.ts-wrapper.field.dropdown-active .ts-control {
    background: var(--bg);
    background-image: none;
    border-color: var(--primary);
    border-radius: 8px;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 25%, transparent);
}
/* Caret + clear button. */
.ts-wrapper .ts-control:after { border-color: var(--muted) transparent transparent; }
.ts-wrapper .clear-button { color: var(--muted); }
.ts-wrapper .clear-button:hover { color: var(--text); }
/* Dropdown panel. Doubled class (.ts-dropdown.ts-dropdown) raises specificity
   above vendor tom-select.default.css, which loads after app.css. The panel is
   appended to <body>, not inside .ts-wrapper, so descendant selectors can't reach it. */
.ts-dropdown.ts-dropdown {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-top: 0.3rem;
    color: var(--text);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
.ts-dropdown.ts-dropdown .option { color: var(--text); padding: 0.45rem 0.7rem; background: none; }
.ts-dropdown.ts-dropdown .option.active,
.ts-dropdown.ts-dropdown .option:hover {
    background: color-mix(in srgb, var(--primary) 22%, transparent);
    color: var(--text);
}
.ts-dropdown.ts-dropdown .option[aria-selected="true"] { color: var(--primary); }
.ts-dropdown.ts-dropdown .no-results,
.ts-dropdown.ts-dropdown .optgroup-header { color: var(--muted); background: none; }

/* Flash toasts — top-right, auto-dismissing notifications. */
.toast-container {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: min(360px, calc(100vw - 2rem));
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-left: 4px solid var(--primary);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    animation: toast-in 0.2s ease-out;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.toast.is-hiding {
    opacity: 0;
    transform: translateX(0.5rem);
}

.toast--success { border-left-color: var(--primary); }
.toast--error { border-left-color: var(--danger); }
.toast--warning { border-left-color: #d97706; }
.toast--info { border-left-color: #3b82f6; }

.toast__message { flex: 1; line-height: 1.4; }

.toast__close {
    flex-shrink: 0;
    padding: 0;
    background: none;
    border: 0;
    color: var(--muted);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
}
.toast__close:hover { color: var(--text); }

@keyframes toast-in {
    from { opacity: 0; transform: translateX(1rem); }
    to { opacity: 1; transform: translateX(0); }
}

/* Coloured category label. Background is set inline (per category); the text
   colour is chosen for contrast via the modifier class. */
.category-badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-size: 0.78rem;
    line-height: 1.4;
    white-space: nowrap;
    vertical-align: middle;
}
.category-badge--light { color: #ffffff; }
.category-badge--dark { color: #111111; }
.category-badge.is-archived { opacity: 0.55; }

.category-badges {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    vertical-align: middle;
}

/* Soft pill badge for lifecycle states (inquiry status, opportunity stage).
   The hue arrives inline via the --badge-color custom property, so a single
   class serves every state; text is the colour, fill/border are tinted mixes. */
.status-badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    color: var(--badge-color, var(--muted));
    background: color-mix(in srgb, var(--badge-color, var(--muted)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--badge-color, var(--muted)) 35%, transparent);
}

/* ---- AI chat: typing indicator (agent přemýšlí…) ---- */
.typing-dots {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-right: .4rem;
    vertical-align: middle;
}
.typing-dots span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--muted);
    animation: typing-bounce 1.2s infinite ease-in-out;
}
.typing-dots span:nth-child(2) { animation-delay: .15s; }
.typing-dots span:nth-child(3) { animation-delay: .3s; }
@keyframes typing-bounce {
    0%, 60%, 100% { transform: translateY(0); opacity: .4; }
    30% { transform: translateY(-4px); opacity: 1; }
}

/* Blok čerstvě přepsaný agentem — jemný nájezd při přepisování obsahu. */
.blk-fresh {
    animation: blk-fresh-in .5s ease;
}
@keyframes blk-fresh-in {
    from { opacity: .25; }
    to { opacity: 1; }
}

/* Chat nad úkolem (plán 0030) — panel se při otevření plynule vysune. Tlačítko
   „💬 Chat" je přepínač; opětovný stisk panel zase zasune. Výšku nejde animovat
   z 0 na auto, proto grid-rows trik: řádek gridu jede 0fr → 1fr, tj. animuje se
   SKUTEČNÁ výška obsahu (nic se nedeformuje, obsah pod se odsune plynule). Vnitřek
   má overflow:hidden + min-height:0, aby ho řádek mohl při 0fr sbalit. */
.task-chat-panel {
    display: grid;
    grid-template-rows: 1fr;
    margin-top: .6rem;
    animation: task-chat-expand .24s ease-out;
}
.task-chat-panel__inner {
    overflow: hidden;
    min-height: 0;
    border-top: 1px solid var(--border);
    padding-top: .6rem;
}
@keyframes task-chat-expand {
    from { grid-template-rows: 0fr; opacity: .3; }
    to { grid-template-rows: 1fr; opacity: 1; }
}
/* Zavírání: Stimulus (chat-toggle) přidá tuto třídu, počká na animationend a teprve
   pak spustí živou akci, která panel odstraní — takže se plynule zasune místo skoku. */
.task-chat-panel--closing {
    animation: task-chat-collapse .2s ease-in forwards;
}
@keyframes task-chat-collapse {
    from { grid-template-rows: 1fr; opacity: 1; }
    to { grid-template-rows: 0fr; opacity: .2; }
}
@media (prefers-reduced-motion: reduce) {
    .task-chat-panel, .task-chat-panel--closing { animation: none; }
}

/* Kalkulátor — cenové hladiny jako karty (plán 0029). Ve výběrovém režimu
   (modal) je karta klikatelný <label> a zvýraznění řídí ryze CSS přes
   :has(input:checked) — okamžité, bez čekání na server. Nativní radio je skryté
   (výběr ukazuje karta), ale zůstává kvůli data-model a přístupnosti. */
.calc-tiers {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: .75rem;
}
.calc-tier {
    position: relative;
    display: block;
    border: 2px solid var(--border, #ddd);
    border-radius: 10px;
    padding: .75rem;
}
.calc-tier--select { cursor: pointer; }
.calc-tier--select input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.calc-tier__label {
    color: var(--muted);
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .03em;
}
.calc-tier__price { font-size: 1.25rem; font-weight: 700; margin: .15rem 0; }
.calc-tier__total { color: var(--muted); font-size: .8rem; }
/* Zvýraznění: vybraná karta (modal) nebo doporučená kotva (stránka). */
.calc-tier--anchor,
.calc-tier--select:has(input:checked) {
    border-color: var(--primary);
    background: color-mix(in srgb, var(--primary) 8%, transparent);
}
.calc-tier--anchor .calc-tier__price,
.calc-tier--select:has(input:checked) .calc-tier__price { color: var(--primary); }
.calc-tier--select:has(input:focus-visible) {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Rozpis položek na zakázce — JEDNA tabulka (ADR 0016 amendment bod 14).
   Sekce (Sdílené položky, Varianty) jsou `<tbody>` s oddělovacím řádkem, takže
   plochý a variantní rozpis mají stejné sloupce i stejné písmo. Rámečky sekcí
   dělá vlasová linka nad hlavičkou, ne karta — jinak by to zase byla tři různá
   zobrazení pod sebou.
   --------------------------------------------------------------------------- */
.breakdown-section > td {
    padding: 0.5rem 0.4rem 0.35rem;
    border-top: 2px solid var(--border);
    background: var(--bg);
}
.breakdown-variant--chosen > .breakdown-section > td { border-top-color: var(--primary); }
.breakdown-section-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.breakdown-section-hint {
    color: var(--muted);
    font-size: 0.78rem;
    margin-left: 0.4rem;
}
.breakdown-section-tools {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.breakdown-section-tools .btn {
    padding: 0.15rem 0.45rem;
    font-size: 0.8rem;
}
.breakdown-section-sum { font-size: 0.82rem; color: var(--muted); white-space: nowrap; }
.breakdown-badge {
    font-size: 0.72rem;
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--primary);
    border-radius: 999px;
}
.breakdown-badge--chosen { background: var(--primary); color: #111; }
.breakdown-empty {
    padding: 0.5rem 0.4rem;
    color: var(--muted);
    font-size: 0.82rem;
    font-style: italic;
}
.breakdown-empty--warn { color: #dc2626; font-style: normal; }

/* Pruh hromadných akcí: viditelnost řídí CSS podle skutečně zaškrtnutých řádků
   (`:has`), ne JavaScript — po re-renderu Live komponenty se tak stav pruhu
   nemůže rozejít s tím, co je v DOM opravdu zaškrtnuté. */
.breakdown-bulk {
    display: none;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.6rem;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--primary);
    border-radius: 8px;
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    font-size: 0.85rem;
}
.breakdown:has([data-line-select-target="box"]:checked) .breakdown-bulk { display: flex; }

/* ── Reporting: grafy (P1-07) ─────────────────────────────────────────────────
   Grafy jsou serverem vykreslené HTML (AssetMapper, žádný build → žádná grafová
   knihovna): pruh je <span> se šířkou/výškou v procentech. Barvy nesou práci, ne
   dekoraci — akcent = letos / jediná série, šedá = loňský kontext, ordinální rampa
   = kroky tunelu (pořadí je součástí významu). Tmavý režim má vlastní kroky, ne
   převrácené světlé. */
:root {
    --chart-accent: var(--primary);
    --chart-context: #6b7686;
    /* Druhý rovnocenný slot kategorické palety (spotřeba tokenů: vstup × výstup).
       Šedá `--chart-context` je vyhrazená pro KONTEXT (loňský rok) — jako peer série
       neprojde CVD kontrolou proti akcentu, proto vlastní odstín. Validováno skillem
       dataviz proti oběma podkladům. */
    --chart-series-2: #6366f1;
    --chart-grid: var(--border);
    --funnel-1: #1d7954;
    --funnel-2: #1f9764;
    --funnel-3: #21b876;
    --funnel-4: #23d887;
}

:root[data-theme="light"] {
    --chart-context: #7f8a98;
    --chart-series-2: #4f46e5;
    --funnel-1: #70c6a2;
    --funnel-2: #47b688;
    --funnel-3: #1aa56b;
    --funnel-4: #138f5c;
}

/* Jeden filtrační řádek nad všemi grafy — ne per graf, aby nemohly ukazovat
   různé výseky týchž dat. */
.report-filters {
    display: flex;
    gap: 0.6rem;
    align-items: center;
    flex-wrap: wrap;
}
/* Odsazení řeší sourozenecké pravidlo uvnitř boardu, ne globální `.card + .card`
   (to by přesouvalo karty i na ostatních stránkách). */
.report-board > * + * { margin-top: 1rem; }
.report-filters__label { color: var(--muted); font-size: 0.85rem; }
.report-filters__hint { color: var(--muted); font-size: 0.78rem; flex: 1 1 14rem; min-width: 12rem; }

.report-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr));
    gap: 1rem;
}
.report-grid > .card { min-width: 0; }

.chart-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.9rem;
}
.chart-title { margin: 0; font-size: 1rem; }
.chart-note { margin: 0.2rem 0 0; color: var(--muted); font-size: 0.8rem; line-height: 1.45; }
/* Proporcionální číslice: tabular-nums dělá z velkého čísla rozsypaný čaj. */
.chart-figure { font-size: 1.75rem; font-weight: 600; line-height: 1.1; }
.chart-delta { font-weight: 600; }
.chart-delta--up { color: var(--primary); }
.chart-delta--down { color: var(--danger); }

.chart-legend {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
    font-size: 0.78rem;
    color: var(--muted);
}
.chart-legend__item { display: inline-flex; align-items: center; gap: 0.35rem; }
.chart-key { width: 0.7rem; height: 0.7rem; border-radius: 2px; }
.chart-key--accent { background: var(--chart-accent); }
.chart-key--context { background: var(--chart-context); }
.chart-key--series2 { background: var(--chart-series-2); }

/* Široký obsah roluje sám v sobě; stránka vodorovně nikdy. */
.table-scroll { overflow-x: auto; }
.chart-table { margin-top: 0.9rem; font-size: 0.85rem; }
.chart-table > summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; }
.chart-table table { margin-top: 0.5rem; font-variant-numeric: tabular-nums; }
.chart-table th, .chart-table td { padding: 0.3rem 0.4rem; }

/* Plocha grafu obratu: osa vlevo, mřížka pod sloupci, popisky měsíců pod plochou
   (kontejner roste s obsahem — pevná výška by popisky odřízla). */
.plot { display: grid; grid-template-columns: max-content 1fr; gap: 0.6rem; }
.plot__ticks {
    position: relative;
    height: 11rem;
    align-self: start;
    font-size: 0.7rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.plot__ticks span { position: absolute; right: 0; transform: translateY(-50%); }
.plot__ticks span:nth-child(1) { top: 0; }
.plot__ticks span:nth-child(2) { top: 50%; }
.plot__ticks span:nth-child(3) { top: 100%; }
.plot__area { position: relative; min-width: 0; }
.plot__grid {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 11rem;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    pointer-events: none;
}
/* Vlasová plná linka, o odstín od plochy — mřížka není data. */
.plot__grid span { border-top: 1px solid var(--chart-grid); }

/* Mřížka patří ZA značky, ne přes ně. */
.cols { position: relative; z-index: 1; display: flex; align-items: flex-end; gap: 0.25rem; }
.cols__group { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; }
/* Celý měsíční pruh je cíl pro hover (title), ne 12px sloupeček. */
.cols__pair {
    height: 11rem;
    width: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 2px; /* mezera v barvě plochy odděluje sousední sloupce, ne obrys */
}
.cols__label { font-size: 0.68rem; color: var(--muted); padding-top: 0.3rem; }
.cols__group:hover .cols__label { color: var(--text); }

/* Pruh: 4px zakulacený konec dat, hranatý u základní linky. */
.bar {
    display: block;
    flex: 1 1 0;
    max-width: 14px;
    min-height: 0;
    border-radius: 4px 4px 0 0;
    align-self: flex-end;
}
.bar--accent { background: var(--chart-accent); }
.bar--context { background: var(--chart-context); }
.bar--h { border-radius: 0 4px 4px 0; height: 100%; max-width: none; }

/* Konverze obchodníků: jméno · pruh · číslo. Hodnota je vpravo v koloně,
   proto tabular-nums. */
.bars { display: flex; flex-direction: column; gap: 0.55rem; }
.bars__row {
    display: grid;
    grid-template-columns: minmax(7rem, 11rem) 1fr 3.4rem;
    gap: 0.6rem;
    align-items: center;
    min-height: 1.5rem; /* cíl pro hover je řádek, ne pruh */
}
.bars__label { font-size: 0.85rem; min-width: 0; }
.bars__sample { display: block; color: var(--muted); font-size: 0.7rem; }
.bars__track { position: relative; height: 0.8rem; background: color-mix(in srgb, var(--muted) 14%, transparent); border-radius: 0 4px 4px 0; }
.bars__track > .bar--h { position: absolute; left: 0; top: 0; }
/* Průměr týmu jako svislá linka — čárkovaná by se pletla s mřížkou. */
.bars__mark { position: absolute; top: -0.2rem; bottom: -0.2rem; width: 1px; background: var(--text); opacity: 0.55; }
.bars__value { text-align: right; font-size: 0.85rem; font-variant-numeric: tabular-nums; }

/* Tunel: krok = pruh přes celou kohortu, mezi kroky řádek s úbytkem. */
.funnel { display: flex; flex-direction: column; gap: 0.35rem; }
.funnel__row { display: grid; grid-template-columns: minmax(7rem, 9rem) 1fr; gap: 0.6rem; align-items: center; min-height: 1.6rem; }
.funnel__label { font-size: 0.85rem; }
.funnel__hint { display: block; color: var(--muted); font-size: 0.7rem; }
.funnel__track { position: relative; display: flex; align-items: center; gap: 0.5rem; min-height: 1.4rem; }
.funnel__bar { height: 1.4rem; border-radius: 0 4px 4px 0; min-width: 2px; flex: 0 0 auto; }
.funnel__bar--1 { background: var(--funnel-1); }
.funnel__bar--2 { background: var(--funnel-2); }
.funnel__bar--3 { background: var(--funnel-3); }
.funnel__bar--4 { background: var(--funnel-4); }
/* Číslo za pruhem, ne v něm: do krátkého pruhu se nevejde a odřezávat se nesmí. */
.funnel__count { font-size: 0.85rem; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.funnel__share { color: var(--muted); font-weight: 400; font-size: 0.78rem; }
.funnel__drop { padding-left: calc(7rem + 0.6rem); color: var(--muted); font-size: 0.75rem; }

@media (max-width: 640px) {
    .funnel__drop { padding-left: 0; }
    .bars__row, .funnel__row { grid-template-columns: 1fr; }
    .bars__value { text-align: left; }
}

/* ── Spotřeba tokenů agenta (/admin/ai) ───────────────────────────────────────
   Spojnice je inline SVG vykreslené serverem (žádná grafová knihovna): linka 2px,
   mřížka vlasová a plná, koncový bod s prstencem v barvě plochy, aby byl čitelný
   i v místě křížení. Osa X je HTML pod plochou — v SVG s nerovnoměrným škálováním
   by se text roztáhl. */
.linechart { display: block; width: 100%; height: 11rem; overflow: visible; }
.linechart__grid { stroke: var(--chart-grid); stroke-width: 1; vector-effect: non-scaling-stroke; }
.linechart__line {
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke; /* jinak preserveAspectRatio="none" linku rozmázne */
}
.linechart__line--completion { stroke: var(--chart-accent); }
.linechart__line--prompt { stroke: var(--chart-series-2); }
.linechart__dot { stroke: var(--surface); stroke-width: 2; vector-effect: non-scaling-stroke; }
.linechart__dot--completion { fill: var(--chart-accent); }
.linechart__dot--prompt { fill: var(--chart-series-2); }
.linechart__crosshair { stroke: var(--text); stroke-width: 1; opacity: 0.45; vector-effect: non-scaling-stroke; }
/* Zóna dne je cíl hoveru/focusu — průhledná, ale klikatelná (fill: transparent
   ano, `none` by ji pro pointer zneviditelnilo). */
.linechart__zone { fill: transparent; outline: none; }
.linechart__zone:focus-visible { fill: color-mix(in srgb, var(--text) 8%, transparent); }

.linechart__labels { position: relative; height: 1rem; margin-top: 0.15rem; }
.linechart__labels span {
    position: absolute;
    transform: translateX(-50%);
    font-size: 0.68rem;
    color: var(--muted);
    white-space: nowrap;
}

.linechart__tooltip {
    position: absolute;
    top: 0.25rem;
    transform: translateX(0.5rem);
    max-width: 16rem;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    box-shadow: 0 6px 20px rgb(0 0 0 / 25%);
    font-size: 0.78rem;
    line-height: 1.45;
    white-space: pre-line;
    pointer-events: none;
    z-index: 2;
}
/* U pravého okraje se tooltip překlopí, aby nevyčuhoval z karty. */
.linechart__tooltip.is-flipped { transform: translateX(-100%) translateX(-0.5rem); }

/* Dlaždice souhrnu: velké číslo je proporcionální (tabular-nums by ho rozsypalo),
   drobný popisek pod ním nese jednotku a podíl. */
.token-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.75rem 1.25rem;
}
.token-tile { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.token-tile__label { color: var(--muted); font-size: 0.78rem; }
.token-tile__value { font-size: 1.15rem; font-weight: 600; }
.token-tile__note { color: var(--muted); font-size: 0.72rem; }
