/* ============================================================
   K-Kate — eelarve & pakkumine. Hand-rolled design system.
   Teal-green + charcoal brand. No framework, no build step.
   Token system is authoritative (docs/design/brand-and-design-system.md).
   ============================================================ */

/* Inter, self-hosted (no-CDN rule; oli ainuke rikkuja — Google Fonts link base.html-is).
   Variable font (wght 100–900) covers the 400/500/600/700 the UI uses; latin-ext
   carries š/ž for Estonian. Files: static/fonts/, Inter v20, OFL license. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url(/static/fonts/inter-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url(/static/fonts/inter-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --brand: #1B8268; --brand-dark: #14614C; --brand-tint: #E8F2EE;
  --ink: #1D2125; --muted: #5C6670; --line: #E1E5E9; --bg: #F6F8F7; --surface: #FFFFFF;
  --accent: #E5811C; --accent-tint: #FBEEDC; --accent-ink: #8A4E0C;
  --ok: #1A7F37; --ok-tint: #E7F5EC;
  --warn: #B7791F; --warn-tint: #FBF1DC; --warn-ink: #8A5A12;
  --err: #C2362B; --err-tint: #FBE9E7;
  --sp-1: .25rem; --sp-2: .5rem; --sp-3: .75rem; --sp-4: 1rem; --sp-5: 1.25rem; --sp-6: 1.5rem; --sp-8: 2rem;
  --r-sm: 6px; --r-md: 8px; --r-lg: 12px; --r-pill: 999px;
  --shadow-1: 0 1px 2px rgba(29,33,37,.06); --shadow-2: 0 8px 30px rgba(29,33,37,.18);
  --border: 1px solid var(--line);
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* ---- base ---- */
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font-sans); background: var(--bg); color: var(--ink);
  font-size: 15px; line-height: 1.5; -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { margin: 0; }
h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; font-weight: 700; }
h3 { font-size: 1rem; font-weight: 600; }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.nowrap { white-space: nowrap; }
.muted { color: var(--muted); }
.right { text-align: right; }
input, select, textarea, button { font: inherit; }
/* hidden attr must always win: author display rules (button, .tabpanel, …) beat the
   UA's [hidden]{display:none} by cascade origin, so JS `el.hidden = true` silently
   failed on styled elements (bit the tabpanels once, then the import fallback button) */
[hidden] { display: none !important; }
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, a:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(27,130,104,.40); } 70% { box-shadow: 0 0 0 8px rgba(27,130,104,0); } 100% { box-shadow: 0 0 0 0 rgba(27,130,104,0); } }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- topbar ---- */
.topbar {
  display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
  background: var(--surface); border-bottom: var(--border);
  padding: 0 var(--sp-6); min-height: 60px; position: sticky; top: 0; z-index: 30;
}
.brand { display: inline-flex; align-items: center; gap: 12px; color: var(--ink); font-weight: 700; text-decoration: none; padding: 11px 0; }
.brand:hover { text-decoration: none; }
.brand img { height: 32px; width: auto; display: block; }
.brand span { font-weight: 500; color: var(--muted); font-size: .78rem; border-left: var(--border); padding-left: 12px; }
.topbar nav { display: flex; align-items: center; gap: var(--sp-5); font-size: .9rem; flex-wrap: wrap; }
.topbar nav > a { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); font-weight: 500; padding: 19px 0; border-bottom: 2px solid transparent; text-decoration: none; }
.topbar nav > a:hover { color: var(--brand); text-decoration: none; }
.topbar nav > a.is-active { color: var(--brand); font-weight: 600; border-bottom-color: var(--brand); }
/* waiting-count pill on nav items (open pricebase questions, leftover pending accounts) */
.count-pill { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-pill); background: var(--accent-tint); color: var(--accent-ink); font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.topbar nav > a.is-active .count-pill, .topbar nav > a:hover .count-pill { background: var(--accent); color: #fff; }

/* ---- topbar dropdown menus (Haldus + profile) — plain <details>, JS only closes ---- */
.nav-menus { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
details.menu { position: relative; }
details.menu > summary { display: inline-flex; align-items: center; gap: 7px; list-style: none; cursor: pointer; padding: 8px 12px; border-radius: var(--r-md); font-size: .9rem; font-weight: 500; color: var(--ink); user-select: none; }
details.menu > summary::-webkit-details-marker { display: none; }
details.menu > summary:hover { background: var(--bg); color: var(--brand); }
details.menu > summary.is-active { color: var(--brand); font-weight: 600; }
details.menu[open] > summary { background: var(--brand-tint); color: var(--brand-dark); }
details.menu > summary .caret { width: 9px; height: 9px; border-right: 1.8px solid currentColor; border-bottom: 1.8px solid currentColor; transform: rotate(45deg) translateY(-2px); }
details.menu[open] > summary .caret { transform: rotate(-135deg) translateY(2px); }
.menu__panel { position: absolute; right: 0; top: calc(100% + 6px); min-width: 210px; background: var(--surface); border: var(--border); border-radius: var(--r-md); box-shadow: var(--shadow-2); padding: .4rem; z-index: 50; }
.menu__panel a, .menu__panel button { display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 11px; border: 0; border-radius: var(--r-sm); background: none; color: var(--ink); font: inherit; font-size: .88rem; font-weight: 500; text-align: left; cursor: pointer; text-decoration: none; }
.menu__panel a:hover, .menu__panel button:hover { background: var(--brand-tint); color: var(--brand-dark); text-decoration: none; filter: none; }
.menu__panel a.is-active { color: var(--brand); font-weight: 600; }
.menu__panel hr { border: 0; border-top: var(--border); margin: .4rem 0; }
.menu__panel form { margin: 0; }
.menu__who { padding: 9px 11px 4px; margin: 0; font-size: .78rem; color: var(--muted); }
.menu__who strong { display: block; color: var(--ink); font-size: .85rem; font-weight: 600; }
/* profile trigger: person icon + first name — a labelled control, not a stray text */
summary.profile .avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--brand-tint); color: var(--brand-dark); display: inline-flex; align-items: center; justify-content: center; }
summary.profile .avatar .icon { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---- mobile bottom tabbar (shown only ≤640px; see the media block) ---- */
.tabbar { display: none; }

/* ---- layout ---- */
/* Fluid shell: wide monitors get the width (the jobs/pricebase tables need it),
   capped at 1680px so text pages don't run absurdly long lines. */
main { max-width: min(1680px, 96vw); margin: var(--sp-6) auto var(--sp-8); padding: 0 var(--sp-5); }
main.narrow { max-width: 720px; }
/* Reading/form pages keep the pre-fluid cap — 1600px-wide prose and inputs are a
   regression, not a feature (review finding, 2026-07-16). Data-table pages stay fluid. */
main.reading { max-width: 940px; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; margin-bottom: var(--sp-5); }
.page-head h1 { margin-bottom: .15rem; }
.page-head p { margin: 6px 0 0; }
.lead { color: var(--muted); font-size: .88rem; margin: 6px 0 var(--sp-5); max-width: 680px; }
.row { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
.row > div { flex: 1 1 160px; }
.actions { margin-top: var(--sp-4); display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.actions.end { justify-content: flex-end; }
.back-link { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); text-decoration: none; font-size: .85rem; margin-bottom: var(--sp-4); }

/* ---- cards ---- */
.card { background: var(--surface); border: var(--border); border-radius: var(--r-lg); padding: var(--sp-5); margin-bottom: var(--sp-5); box-shadow: var(--shadow-1); }
.card.flush { padding: 0; overflow: hidden; }
.card-head { display: flex; align-items: flex-start; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.card-head h2, .card-head h1 { flex: 1; }
.card-head .actions { margin-top: 0; }
/* Collapsible card: a <details class="card"> whose <summary> reads like a card header.
   Keeps secondary concerns (missing-price forms, change history, source files) on the page
   but folded away so the review surface isn't a wall. */
details.card > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: var(--sp-3); }
details.card > summary::-webkit-details-marker { display: none; }
details.card > summary h2 { flex: 1; }
details.card > summary::after { content: "\25BE"; color: var(--muted); transition: transform .15s ease; }
details.card[open] > summary::after { transform: rotate(180deg); }
details.card[open] > summary { margin-bottom: var(--sp-4); }
details.card > summary .muted { font-weight: 400; }

/* ---- buttons ---- */
button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 11px 18px; border: 0; border-radius: var(--r-md);
  background: var(--brand); color: #fff; font: inherit; font-weight: 600; cursor: pointer; text-decoration: none;
}
button:hover, .btn:hover { filter: brightness(1.04); text-decoration: none; }
/* Secondary / outline button: a real button affordance (white + border), not a pale label.
   Used for downloads, re-runs, "+ Lisa", "Tühista". */
.btn-ghost { background: var(--surface); color: var(--ink); border: var(--border); box-shadow: var(--shadow-1); }
.btn-ghost:hover { filter: none; background: var(--brand-tint); border-color: #C9E2D8; color: var(--brand-dark); }
.btn-danger { background: var(--err); color: #fff; }
/* Soft/destructive outline — for reversible destructive actions (Deaktiveeri, Lükka tagasi). */
.btn-danger-soft { background: var(--surface); color: var(--err); border: 1px solid #F0BDB7; box-shadow: var(--shadow-1); }
.btn-danger-soft:hover { filter: none; background: var(--err-tint); border-color: var(--err); }
.btn-sm { padding: 8px 12px; font-size: .85rem; }
button.link, .btn-link { background: none; color: var(--brand); padding: 0; font-weight: 600; }
button.link:hover, .btn-link:hover { filter: none; text-decoration: underline; }
.btn-quiet { background: none; color: var(--muted); padding: 6px 4px; font-weight: 400; font-size: .85rem; }
.btn-quiet:hover { filter: none; color: var(--ink); }
form.inline { display: inline; margin: 0; }
.icon { flex: none; width: 1em; height: 1em; vertical-align: -0.125em; }

/* ---- forms ---- */
label { display: block; margin: 0 0 6px; font-weight: 600; font-size: .85rem; }
.field { margin-bottom: var(--sp-4); }
input, select, textarea { width: 100%; padding: 9px 11px; border: var(--border); border-radius: var(--r-sm); background: var(--surface); font-size: .9rem; }
textarea { resize: vertical; line-height: 1.4; }
label.inline { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; margin: var(--sp-2) 0; font-size: .85rem; cursor: pointer; }
label.inline input { width: auto; accent-color: var(--brand); }
details.offer-opts { margin: var(--sp-2) 0; border: var(--border); border-radius: var(--r-md); padding: var(--sp-2) var(--sp-4); background: var(--bg); }
details.offer-opts summary { font-weight: 600; cursor: pointer; }

/* ---- tables ---- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; }
thead tr { background: var(--bg); }
th { text-align: left; color: var(--muted); font-weight: 600; font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; padding: 11px var(--sp-4); }
td { text-align: left; padding: 13px var(--sp-4); border-top: var(--border); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tr.clickable { cursor: pointer; }
tr.clickable:hover { background: var(--bg); }
/* Gentle hover feedback on data-table rows (price base, users, feedback) — not the eelarve editor. */
.table-wrap table:not(.eelarve) tbody tr:hover { background: var(--bg); }
.cell-strong { font-weight: 600; }
.cell-link { color: var(--brand); font-weight: 600; }
/* long object names / underscore file names must not set the table's intrinsic
   width (they forced page-level scroll); floor keeps the column readable */
td.cell-wrap { overflow-wrap: anywhere; min-width: 14rem; }

/* ---- chips (filter) ---- */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-5); }
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 13px;
  border: var(--border); border-radius: var(--r-pill); background: var(--surface);
  color: var(--ink); font-size: .82rem; font-weight: 500; white-space: nowrap; cursor: pointer;
}
.chip:hover { text-decoration: none; border-color: var(--brand); }
.chip.is-active { background: var(--brand); color: #fff; border-color: var(--brand); }
.chip .num { color: var(--muted); }
.chip.is-active .num { color: rgba(255,255,255,.8); }
/* Search box in the chips row: one line beside the chips on wide screens;
   drops to a full-width line of its own (input + nupp still inline) below 900px. */
.toolbar-search { display: flex; align-items: center; gap: var(--sp-1); margin-left: auto; }
.toolbar-search input[type=search] { width: 280px; max-width: 100%; }

/* ---- badges (job status) ---- */
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--r-pill); font-size: .74rem; font-weight: 600; white-space: nowrap; }
.badge::before { font-size: .85em; line-height: 1; }
.badge.pending { background: var(--warn-tint); color: var(--warn-ink); }
.badge.pending::before { content: "\25CB"; }                  /* ○ */
.badge.running, .badge.composing { background: var(--warn-tint); color: var(--warn-ink); }
.badge.running::before, .badge.composing::before { content: "\25CF"; }  /* ● */
.badge.eelarve_ready { background: var(--brand-tint); color: var(--brand-dark); }
.badge.eelarve_ready::before { content: "\25CF"; }            /* ● */
.badge.done { background: var(--ok-tint); color: #13682B; }
.badge.done::before { content: "\2713"; }                     /* ✓ */
.badge.error { background: var(--err-tint); color: var(--err); }
.badge.error::before { content: "\2715"; }                    /* ✕ */
.badge.awaiting { background: var(--warn-tint); color: var(--warn-ink); }
.badge.awaiting::before { content: "\26A0"; }                 /* ⚠ — eelarve_ready but no rows */
/* dashboard live badges: .badge-live swaps the static glyph for an animation —
   a spinning arc while processing, a pulsing dot while queued (pending). */
.badge.badge-live::before { content: none; }
.badge .spin-dot { width: .62em; height: .62em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; display: inline-block; animation: spin .7s linear infinite; }
.badge.pending.badge-live::before { content: "\25CF"; animation: pulse 2s infinite; border-radius: 50%; }
.pill { display: inline-flex; align-items: center; background: var(--brand-tint); color: var(--brand-dark); font-size: .68rem; font-weight: 600; padding: 3px 8px; border-radius: var(--r-pill); text-transform: uppercase; letter-spacing: .02em; }
.pill--muted { background: var(--surface-2, #EEF0F2); color: var(--muted); }
.th-sort { color: inherit; text-decoration: none; }
.th-sort:hover { text-decoration: underline; }
.th-sort.is-active { color: var(--brand); font-weight: 700; }

/* ---- flash messages ---- */
.flash { padding: .6rem .9rem; border-radius: var(--r-md); margin-bottom: var(--sp-4); border: 1px solid transparent; font-size: .9rem; }
.flash-info { background: var(--brand-tint); border-color: #C9E2D8; color: var(--brand-dark); }
.flash-success { background: var(--ok-tint); border-color: #BFE6CC; color: #13682B; }
.flash-warning { background: var(--warn-tint); border-color: #F0E0A8; color: var(--warn-ink); }
.flash-error { background: var(--err-tint); border-color: #F5C2BD; color: var(--err); }

/* ---- notice / attention banner ---- */
.notice { display: flex; align-items: flex-start; gap: 12px; border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-5); font-size: .9rem; }
.notice__icon { line-height: 1.4; flex-shrink: 0; }
.notice--warn { background: var(--accent-tint); border: 1px solid #F0CE9C; color: var(--accent-ink); }
.notice--warn .notice__icon { color: var(--accent); }
.notice--info { background: var(--brand-tint); border: 1px solid #C9E2D8; color: var(--brand-dark); }
.notice--error { background: var(--err-tint); border: 1px solid #F5C2BD; color: var(--err); }
.notice--error .notice__icon { color: var(--err); }
.notice strong { font-weight: 700; }

/* ---- stepper (job lifecycle) ---- */
.stepper { display: flex; align-items: flex-start; justify-content: space-between; gap: 4px; }
.step { display: flex; flex-direction: column; align-items: center; gap: 8px; flex: 1; position: relative; text-align: center; }
.step::before { content: ""; position: absolute; top: 15px; left: -50%; width: 100%; height: 2px; background: var(--line); z-index: 1; }
.step:first-child::before { display: none; }
.step.is-done::before { background: var(--ok); }
.step.is-active::before { background: var(--brand); }
.step.is-error::before { background: var(--err); }
.step__dot { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 600; z-index: 2; background: var(--surface); border: 2px solid var(--line); color: var(--muted); }
.step.is-done .step__dot { background: var(--ok); color: #fff; border-color: var(--ok); }
.step.is-active .step__dot { background: var(--brand); color: #fff; border-color: var(--brand); animation: pulse 2s infinite; }
.step.is-error .step__dot { background: var(--err); color: #fff; border-color: var(--err); }
/* honesty state: the stage "passed" but still waits on something (files/rows/data) */
.step.is-warn .step__dot { background: var(--warn-tint); color: var(--warn-ink); border-color: var(--warn); }
.step.is-warn .step__label { color: var(--warn-ink); font-weight: 600; }
.step.is-warn .step__sub { color: var(--warn-ink); }
.step__label { font-size: .8rem; font-weight: 500; color: var(--muted); }
.step.is-done .step__label { color: var(--ink); font-weight: 600; }
.step.is-active .step__label { color: var(--brand-dark); font-weight: 700; }
.step.is-error .step__label { color: var(--err); font-weight: 700; }
.step__sub { font-size: .72rem; color: var(--muted); }
.step.is-active .step__sub { color: var(--brand); font-weight: 600; }

/* ---- eelarve detail table ---- */
.eelarve__group td { background: var(--brand-tint); color: var(--brand-dark); font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; padding: 7px var(--sp-4); border-top: var(--border); }
.eelarve td { padding: 11px var(--sp-4); }
.eelarve td:first-child { overflow-wrap: anywhere; min-width: 12rem; }
.row-flag { display: inline-flex; align-items: center; background: var(--accent-tint); color: var(--accent-ink); font-size: .68rem; font-weight: 600; padding: 2px 7px; border-radius: var(--r-pill); margin-left: 6px; text-transform: uppercase; letter-spacing: .02em; white-space: nowrap; }
.cell-flag { color: var(--accent); }

/* ---- in-UI eelarve editor (D3/D4) ---- */
.eelarve--edit td { padding: 7px var(--sp-4); }
.eelarve--edit .eelarve__note td { padding: 0 var(--sp-4) 9px; border-top: 0; }
.cell-input { width: 7rem; max-width: 100%; padding: 5px 8px; border: var(--border); border-radius: var(--r-sm); font: inherit; background: #fff; }
.cell-input.num { text-align: right; font-variant-numeric: tabular-nums; }
.cell-input:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: var(--brand); }
.cell-input--wide { width: 100%; color: var(--muted); }
.cell-input.cell-flag { border-color: var(--accent); }
.btn-xs { font-size: .7rem; padding: 0; margin-left: 8px; vertical-align: baseline; }
.knob-editor { margin-top: var(--sp-5); border: var(--border); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); }
.knob-editor summary { cursor: pointer; font-weight: 600; font-size: .9rem; color: var(--brand-dark); }
.knob-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: var(--sp-3) var(--sp-4); margin-top: var(--sp-4); }
.knob-grid label { display: flex; flex-direction: column; gap: 4px; font-size: .8rem; color: var(--muted); }
.knob-grid input { padding: 6px 8px; border: var(--border); border-radius: var(--r-sm); font: inherit; text-align: right; font-variant-numeric: tabular-nums; }

/* ---- review triage (Budget Review v2): flag groups by reason ---- */
.review-progress { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; margin-top: var(--sp-2); }
.review-progress .bar { flex: 1; min-width: 160px; height: 8px; border-radius: var(--r-pill); background: var(--line); overflow: hidden; }
.review-progress .bar i { display: block; height: 100%; background: var(--brand); border-radius: var(--r-pill); }
.review-progress .label { font-size: .85rem; color: var(--muted); }
details.flag-group { border: 1px solid #F0CE9C; border-radius: var(--r-md); background: var(--surface); margin-bottom: var(--sp-3); }
details.flag-group > summary { display: flex; align-items: center; gap: var(--sp-3); list-style: none; cursor: pointer; padding: .8rem var(--sp-4); flex-wrap: wrap; }
details.flag-group > summary::-webkit-details-marker { display: none; }
details.flag-group > summary .reason { font-weight: 700; font-size: .95rem; }
.group-count { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 7px; border-radius: var(--r-pill); background: var(--accent-tint); color: var(--accent-ink); font-size: .78rem; font-weight: 700; font-variant-numeric: tabular-nums; }
details.flag-group > summary .resolve { margin-left: auto; font-size: .84rem; }
details.flag-group > summary .chev { width: 9px; height: 9px; border-right: 1.8px solid var(--muted); border-bottom: 1.8px solid var(--muted); transform: rotate(45deg); transition: transform .15s; }
details.flag-group[open] > summary .chev { transform: rotate(-135deg); }
.flag-rows { border-top: var(--border); padding: var(--sp-1) var(--sp-4) var(--sp-3); }
.flag-row { display: flex; gap: var(--sp-3) var(--sp-4); align-items: center; flex-wrap: wrap; padding: .7rem 0; border-top: var(--border); }
.flag-row:first-child { border-top: 0; }
.flag-row .name { font-weight: 600; font-size: .92rem; flex: 1 1 240px; min-width: 0; overflow-wrap: anywhere; }
.flag-row .meta { display: block; color: var(--muted); font-size: .8rem; font-weight: 400; margin-top: 1px; }
.flag-row .inputs { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.flag-mini { display: flex; gap: var(--sp-2); align-items: flex-end; margin: 0; }
.flag-mini label { font-size: .72rem; font-weight: 600; color: var(--muted); margin: 0; }
.flag-mini input { width: 7.5rem; padding: 8px 10px; text-align: right; font-variant-numeric: tabular-nums; margin-top: 3px; }
.btn-check { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 9px 14px; border: 1px solid var(--brand); border-radius: var(--r-md); background: var(--surface); color: var(--brand-dark); font: inherit; font-size: .86rem; font-weight: 600; cursor: pointer; min-height: 38px; }
.btn-check:hover { filter: none; background: var(--brand-tint); }
.danger-zone { border-color: #F3C3BD; }
.danger-zone h2 { font-size: .95rem; color: var(--err); }

/* ---- D5: per-row add-to-pricebase ---- */
.flag-add { padding: var(--sp-4) 0; border-top: var(--border); }
.flag-add:first-of-type { border-top: 0; }
.flag-add__name { font-weight: 600; margin-bottom: var(--sp-3); }
.flag-add__form { margin-top: var(--sp-2); }
.flag-add__form + .flag-add__form { margin-top: var(--sp-3); }

/* ---- per-row product swap («Vaheta toode», Heiki 2026-08-04) ----
   Folded so 120 editor rows stay readable, but the summary reads as a real button
   (LESSON muted-fold-hides-actions — the sin was muted grey text, not folding). */
details.swap-fold { display: inline-block; margin-top: 4px; }
details.swap-fold > summary { list-style: none; cursor: pointer; user-select: none; }
details.swap-fold > summary::-webkit-details-marker { display: none; }
details.swap-fold[open] { display: block; }
/* own line inside a triage row: wrapped controls otherwise share a visual line with
   the «+ Lisa baasi» mini-form and the two forms read as one (QA 2026-08-06) */
.flag-row details.swap-fold { flex: 1 1 100%; }
.swap-controls { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; margin-top: var(--sp-2); }
.swap-controls input[name=target] { flex: 2 1 280px; min-width: 0; }
.swap-controls input[name=price] { flex: 0 1 190px; }
.swap-controls label.inline { margin: 0; white-space: nowrap; }

/* ---- totals block ---- */
.totals { display: flex; justify-content: flex-end; margin-top: var(--sp-5); }
.totals > div { width: 340px; max-width: 100%; }
.totals .line { display: flex; justify-content: space-between; padding: 6px 0; font-size: .9rem; }
.totals .line span:first-child { color: var(--muted); }
.totals .line.sep { border-bottom: var(--border); }
.totals .grand { display: flex; justify-content: space-between; padding: 12px 0 0; font-size: 1.05rem; font-weight: 700; }

/* ---- modal (native <dialog>) ---- */
dialog { border: none; padding: 0; background: transparent; }
dialog::backdrop { background: rgba(29,33,37,.45); }
.modal { background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--shadow-2); width: 520px; max-width: 92vw; margin: auto; }
.modal--md { width: 480px; }
.modal--sm { width: 420px; }
.modal--pad { padding: var(--sp-5); }
.modal__head { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-5) var(--sp-5) 0; }
.modal__title { font-size: 1.15rem; font-weight: 700; flex: 1; margin: 0; }
.modal__close { background: none; border: none; font-size: 1.4rem; line-height: 1; color: var(--muted); cursor: pointer; padding: 0; }
.modal__close:hover { filter: none; color: var(--ink); }
.modal__body { padding: var(--sp-3) var(--sp-5) var(--sp-5); }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: var(--sp-5); }

/* ---- drawer (right slide-over) ---- */
.drawer-overlay { position: fixed; inset: 0; background: rgba(29,33,37,.35); opacity: 0; pointer-events: none; transition: opacity .2s; z-index: 55; }
.drawer-overlay.is-open { opacity: 1; pointer-events: auto; }
.drawer { position: fixed; top: 0; right: 0; height: 100vh; width: 440px; max-width: 100%; background: var(--surface); box-shadow: var(--shadow-2); transform: translateX(100%); transition: transform .28s ease; z-index: 60; display: flex; flex-direction: column; }
.drawer.is-open { transform: translateX(0); }
.drawer__head { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-5); border-bottom: var(--border); }
.drawer__head h2 { flex: 1; }
.drawer__body { flex: 1; overflow-y: auto; padding: var(--sp-5); }
.drawer__foot { display: flex; justify-content: flex-end; gap: var(--sp-2); padding: var(--sp-4) var(--sp-5); border-top: var(--border); }

/* ---- dropzone + file chips ---- */
.dropzone { display: block; border: 1.5px dashed var(--line); border-radius: var(--r-md); padding: var(--sp-8) var(--sp-5); text-align: center; color: var(--muted); font-size: .9rem; background: var(--bg); cursor: pointer; }
.dropzone.is-dragover { border-color: var(--brand); background: var(--brand-tint); }
.dropzone input[type=file] { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
.dropzone__big { font-size: 1.6rem; margin-bottom: 6px; }
.dropzone__pick { color: var(--brand); font-weight: 600; text-decoration: underline; }
.dropzone__hint { font-size: .78rem; margin-top: 6px; }
.file-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--sp-3); }
.file-chip { display: inline-flex; align-items: center; gap: 8px; background: var(--brand-tint); border-radius: var(--r-pill); padding: 6px 8px 6px 12px; font-size: .82rem; }
.file-chip__remove { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 2px; }
.file-chip__remove:hover { filter: none; color: var(--ink); }
/* invalid file: red chip + inline reason; submit disabled while any are present */
.file-chip.is-bad { background: var(--err-tint); color: var(--err); }
.file-chip__err { font-size: .72rem; font-weight: 600; color: var(--err); }
.file-validation { margin-top: var(--sp-2); font-size: .82rem; font-weight: 600; color: var(--err); }
button[disabled], .btn[disabled] { opacity: .5; cursor: not-allowed; filter: none; }

/* file rows (lähtefailid) */
.file-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.file-row { display: flex; align-items: center; gap: 12px; padding: 10px var(--sp-3); border: var(--border); border-radius: var(--r-md); }
.file-row .meta { flex: 1; min-width: 0; }
.file-row .name { font-size: .9rem; font-weight: 500; }
.file-row .sub { font-size: .78rem; color: var(--muted); }

/* provenance: analysed-content status list + link buckets */
.prov__title { font-size: .95rem; color: var(--muted); margin: var(--sp-5) 0 var(--sp-2); }
.prov__links { font-size: .85em; margin: 6px 0 0; padding-left: 1.1rem; word-break: break-all; }
.ingest-list { display: flex; flex-direction: column; gap: 4px; }
.ingest-row { display: flex; align-items: baseline; gap: 8px; padding: 6px var(--sp-3); border: var(--border); border-radius: var(--r-sm); font-size: .85rem; }
.ingest-row__icon { flex: none; width: 1.1em; text-align: center; }
.ingest-row__name { font-weight: 500; word-break: break-all; }
.ingest-row__kind { flex: none; font-size: .72rem; text-transform: uppercase; letter-spacing: .02em; color: var(--muted); }
.ingest-row__detail { margin-left: auto; font-size: .8rem; }
.ingest-row.is-ok { border-left: 3px solid var(--ok); }
.ingest-row.is-ok .ingest-row__icon { color: var(--ok); }
.ingest-row.is-scanned { border-left: 3px solid var(--brand); }
.ingest-row.is-skipped { border-left: 3px solid var(--warn); background: var(--warn-tint); }
.ingest-row.is-skipped .ingest-row__icon { color: var(--warn-ink); }
.ingest-row.is-error { border-left: 3px solid var(--err); background: var(--err-tint); }
.ingest-row.is-error .ingest-row__icon { color: var(--err); }

/* processing card: live phase + ticking elapsed time */
.processing { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin: 0; }
.processing__phase { font-weight: 500; }
.processing__elapsed { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--muted); font-size: .85rem; }

/* ---- tabs ---- */
.tabs { display: flex; gap: var(--sp-5); border-bottom: var(--border); margin-bottom: var(--sp-5); flex-wrap: wrap; }
.tab { background: none; border: none; border-bottom: 2px solid transparent; color: var(--muted); font: inherit; font-weight: 600; font-size: .92rem; padding: 0 0 10px; margin-bottom: -1px; cursor: pointer; border-radius: 0; }
.tab:hover { filter: none; color: var(--ink); }
.tab[aria-selected="true"] { color: var(--brand); border-bottom-color: var(--brand); }
.tabpanel[hidden] { display: none; }

/* ---- toast ---- */
.toast { position: fixed; top: var(--sp-5); right: var(--sp-5); background: var(--ink); color: #fff; font-size: .88rem; font-weight: 500; padding: 12px 16px; border-radius: var(--r-md); box-shadow: var(--shadow-2); opacity: 0; transform: translateY(-8px); transition: opacity .2s, transform .2s; z-index: 80; pointer-events: none; }
.toast.is-visible { opacity: 1; transform: translateY(0); }

/* ---- stat grid (analytics) ---- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-4); margin-bottom: var(--sp-5); }
.stat { background: var(--surface); border: var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: var(--sp-4) var(--sp-5); }
.stat__n { font-size: 1.6rem; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.stat__l { font-size: .8rem; color: var(--muted); margin-top: 2px; }

/* ---- dashboard v2: attention cards (both numbers are actions) ---- */
.attention { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: var(--sp-5); margin-bottom: var(--sp-5); }
.attn-card { background: var(--surface); border: var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: var(--sp-5); margin: 0; }
.attn-card h2 { font-size: 1rem; }
.attn-card h2 .num { color: var(--brand-dark); }
.attn-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.attn-list li { display: flex; gap: var(--sp-3); align-items: baseline; padding: .45rem 0; border-top: var(--border); font-size: .9rem; }
.attn-list li:first-child { border-top: 0; }
.attn-list .obj { font-weight: 600; flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.attn-list .flag { color: var(--accent-ink); font-size: .8rem; flex: none; }
.attn-list .age { color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums; flex: none; }
.attn-card .cta { margin: var(--sp-3) 0 0; }
.attn-card p.sub { color: var(--muted); font-size: .85rem; margin: .35rem 0 0; }
/* side-fact under an object name: a muted note, never a second status pill */
.note { display: block; color: var(--muted); font-size: .8rem; font-weight: 400; margin-top: 2px; }
.note.attn { color: var(--accent-ink); }

/* ---- Kogu baas v2 (Price Base v2 port): readable rows + click-to-edit ----
   Rows render as data, not as 200 open forms; the editor row opens on click,
   one at a time (app.js). Tab labels carry result counters. */
.tab .num { font-weight: 500; color: var(--muted); font-size: .8rem; }
.tab[aria-selected="true"] .num { color: var(--brand); }
tr.row-view { cursor: pointer; }
tr.row-view:hover { background: var(--bg); }
tr.row-view.is-open { background: var(--brand-tint); }
.row-name { font-weight: 600; }
.row-cat { display: block; color: var(--muted); font-size: .78rem; font-weight: 400; overflow-wrap: anywhere; }
td.cell-name { overflow-wrap: anywhere; min-width: 12rem; }
tr.row-edit { display: none; }
tr.row-edit.is-open { display: table-row; }
tr.row-edit > td { background: var(--brand-tint); border-top: 0; padding: var(--sp-4); }
.edit-form { display: flex; gap: var(--sp-3); align-items: flex-end; flex-wrap: wrap; margin: 0; }
/* field sizes as classes, not inline styles — the phone block flattens them all */
.edit-form .f { flex: 1 1 160px; min-width: 0; }
.edit-form .f--xs { flex: 0 1 90px; }
.edit-form .f--s { flex: 0 1 130px; }
.edit-form .f--l { flex: 2 1 280px; }
.edit-form .f label { font-size: .75rem; margin-bottom: 4px; }
.edit-form .f input, .edit-form .f select { background: var(--surface); }
/* secondary zone under the editor fields: origin + merge fold + nothing loud */
.edit-sub { display: flex; gap: var(--sp-2) var(--sp-4); align-items: center; flex-wrap: wrap; margin-top: var(--sp-3); font-size: .8rem; }
.edit-sub .origin { color: var(--muted); margin-right: auto; }
/* row ⋯-menu (Liida / Kustuta) — same close-on-outside-click JS as the topbar menus */
details.rowmenu { position: relative; display: inline-block; }
details.rowmenu > summary { list-style: none; cursor: pointer; padding: 2px 10px; border-radius: var(--r-sm); color: var(--muted); font-weight: 700; letter-spacing: .1em; user-select: none; }
details.rowmenu > summary::-webkit-details-marker { display: none; }
details.rowmenu > summary:hover { background: var(--bg); color: var(--ink); }
details.rowmenu .panel { position: absolute; right: 0; top: calc(100% + 4px); min-width: 180px; background: var(--surface); border: var(--border); border-radius: var(--r-md); box-shadow: var(--shadow-2); padding: .35rem; z-index: 20; }
details.rowmenu .panel button { display: block; width: 100%; padding: 8px 10px; border: 0; border-radius: var(--r-sm); background: none; color: var(--ink); font: inherit; font-size: .86rem; font-weight: 500; text-align: left; cursor: pointer; }
details.rowmenu .panel button:hover { filter: none; background: var(--brand-tint); color: var(--brand-dark); }
details.rowmenu .panel button.danger { color: var(--err); }
details.rowmenu .panel button.danger:hover { background: var(--err-tint); color: var(--err); }
.table-note { color: var(--muted); font-size: .8rem; padding: var(--sp-3) var(--sp-4); margin: 0; border-top: var(--border); }
/* sticky-header table card. NOT inside .table-wrap and overflow-x:CLIP (not hidden/
   auto) on purpose: any scroll-container ancestor would trap position:sticky, so the
   card clips only horizontally for the border radius and the thead sticks under the
   real topbar height (--topbar-h measured by app.js — the bar wraps on narrow screens). */
.card.flush-sticky { padding: 0; overflow-x: clip; overflow-y: visible; }
.flush-sticky thead th { position: sticky; top: var(--topbar-h, 60px); z-index: 5; background: var(--bg); border-bottom: var(--border); }
.flush-sticky thead th:first-child { border-top-left-radius: calc(var(--r-lg) - 1px); }
.flush-sticky thead th:last-child { border-top-right-radius: calc(var(--r-lg) - 1px); }
/* nth-last-child(2), not last-child: rows come in view+edit pairs and the LAST child
   is the (usually hidden) editor — the last VISIBLE row is one before it */
.flush-sticky tbody tr:nth-last-child(2) td:first-child { border-bottom-left-radius: calc(var(--r-lg) - 1px); }
.flush-sticky tbody tr:nth-last-child(2) td:last-child { border-bottom-right-radius: calc(var(--r-lg) - 1px); }
.flush-sticky tbody tr.row-edit:last-child.is-open > td { border-bottom-left-radius: calc(var(--r-lg) - 1px); border-bottom-right-radius: calc(var(--r-lg) - 1px); }
/* the mobile-sort select lives in the search form but shows only where the thead
   (and its th-sort links) is hidden */
.sort-select-wrap { display: none; }
/* file input styled as a button (audit LOW: naked Choose File between styled buttons);
   the <label> opens the native picker with or without JS */
.file-btn { position: relative; }
.file-btn input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0 0 0 0); }

/* ---- misc ---- */
.empty { text-align: center; padding: var(--sp-8) var(--sp-5); color: var(--muted); }
.empty p { margin: 0 0 var(--sp-4); }
.login-wrap { max-width: 380px; margin: 4rem auto; }
.spinner { display: inline-block; width: 16px; height: 16px; border: 2px solid var(--line); border-top-color: var(--brand); border-radius: 50%; animation: spin .7s linear infinite; vertical-align: -3px; }
ul.questions { padding-left: 1.1rem; }
ul.questions li { margin: .3rem 0; }
ul.sources { list-style: none; padding-left: 0; }
ul.sources li { margin: .4rem 0; }
img.thumb { max-width: 180px; max-height: 180px; margin-top: .3rem; border: var(--border); border-radius: var(--r-sm); }
.footer { max-width: min(1680px, 96vw); margin: 0 auto; padding: var(--sp-5); color: var(--muted); font-size: .82rem; text-align: center; border-top: var(--border); }
.footer strong { color: var(--ink); font-weight: 600; }
.footer__legal { display: block; margin-top: 2px; }

/* ---- mobile ---- */
@media (max-width: 640px) {
  /* one wide element must never wobble the whole page sideways (audit 2026-07-21);
     real wide content scrolls inside .table-wrap, not at page level */
  html, body { overflow-x: clip; }
  .topbar { gap: var(--sp-3); padding: 0 var(--sp-4); min-height: 0; }
  .brand { padding: 12px 0; }
  /* top nav hides — the fixed bottom tabbar is the whole nav on phones */
  .topbar nav, .nav-menus { display: none; }
  body:has(nav.tabbar) { padding-bottom: calc(60px + env(safe-area-inset-bottom)); } /* room for the tabbar — logged-out pages have none */
  .tabbar { display: flex; position: fixed; left: 0; right: 0; bottom: 0; background: var(--surface); border-top: var(--border); z-index: 50; padding-bottom: env(safe-area-inset-bottom); }
  .tabbar > a, .tabbar summary { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 2px 7px; min-height: 52px; color: var(--muted); font-size: .68rem; font-weight: 600; text-decoration: none; cursor: pointer; list-style: none; position: relative; }
  .tabbar summary::-webkit-details-marker { display: none; }
  .tabbar > a:hover, .tabbar summary:hover { color: var(--brand); text-decoration: none; }
  .tabbar > a.is-active { color: var(--brand); }
  .tabbar > a.is-active::before { content: ""; position: absolute; top: 0; left: 25%; right: 25%; height: 2px; background: var(--brand); }
  .tabbar .icon { width: 20px; height: 20px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .tabbar .count-pill { position: absolute; top: 3px; left: calc(50% + 4px); min-width: 17px; height: 17px; font-size: .66rem; }
  /* "Veel" opens as a sheet above the tabbar */
  details.more { flex: 1; position: static; }
  details.more[open] summary { color: var(--brand); }
  .more__panel { position: fixed; left: 0; right: 0; bottom: calc(52px + env(safe-area-inset-bottom)); background: var(--surface); border-top: var(--border); box-shadow: var(--shadow-2); padding: .6rem 1rem .6rem; z-index: 49; max-height: 70vh; overflow-y: auto; }
  .more__panel a, .more__panel button { display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 8px; border: 0; border-radius: var(--r-sm); background: none; color: var(--ink); font: inherit; font-size: .92rem; font-weight: 500; text-align: left; cursor: pointer; text-decoration: none; }
  .more__panel a:hover, .more__panel button:hover { background: var(--brand-tint); color: var(--brand-dark); text-decoration: none; filter: none; }
  .more__panel hr { border: 0; border-top: var(--border); margin: .4rem 0; }
  .more__panel form { margin: 0; }
  .more__panel .icon { width: 17px; height: 17px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .more__label { font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); padding: 6px 8px 2px; margin: 0; }
  main { margin: var(--sp-4) auto; padding: 0 var(--sp-4); }
  .row { gap: var(--sp-3); }
  .row > div { flex-basis: 100%; }
  .page-head .btn, .page-head button { width: 100%; }

  /* default: stack bare tables into cards (legacy-safe) */
  table, thead, tbody, th, td, tr { display: block; }
  thead { display: none; }
  table tr { border: var(--border); border-radius: var(--r-md); padding: .5rem .7rem; margin-bottom: .6rem; }
  table td { border: 0; padding: .25rem 0; }
  td.num, th.num { text-align: left; }

  /* opt-out: tables inside a scroll wrapper stay tabular and scroll horizontally */
  .table-wrap table, .table-wrap thead, .table-wrap tbody, .table-wrap th, .table-wrap td, .table-wrap tr { display: revert; }
  .table-wrap thead { display: table-header-group; }
  .table-wrap tr { border: 0; border-radius: 0; padding: 0; margin: 0; }
  .table-wrap td { border-top: var(--border); padding: 11px var(--sp-4); }
  .table-wrap td.num, .table-wrap th.num { text-align: right; }

  /* dashboard jobs list → a real card list on phones (status + sum at a glance),
     not an off-canvas table. Overrides the .table-wrap opt-out above. */
  .table-wrap .jobs-table, .table-wrap .jobs-table tbody { display: block; }
  .table-wrap .jobs-table thead { display: none; }
  .table-wrap .jobs-table tr { display: flex; flex-wrap: wrap; gap: .25rem .75rem; align-items: baseline; border: var(--border); border-radius: var(--r-md); padding: .8rem .9rem; margin: .6rem .75rem; background: var(--surface); }
  .table-wrap .jobs-table td { display: block; border: 0; padding: 0; }
  .table-wrap .jobs-table td.cell-obj { order: 1; flex-basis: 100%; min-width: 0; text-align: left; }
  .table-wrap .jobs-table td.cell-id { order: 2; font-size: .8rem; }
  .table-wrap .jobs-table td.cell-status { order: 3; }
  .table-wrap .jobs-table td.cell-sum { order: 4; margin-left: auto; font-weight: 600; }
  .table-wrap .jobs-table td.cell-date, .table-wrap .jobs-table td.cell-user { display: none; }
  .card.flush:has(.jobs-table) { background: none; border: 0; box-shadow: none; }

  .stepper { overflow-x: auto; }
  .step { min-width: 56px; }        /* 5 steps × (56px + gaps) fit the ~300px card interior at 390px */
  .step__label { white-space: normal; font-size: .72rem; }
  .step__sub { display: none; }

  /* job-page action cluster: one column, full-width buttons (audit 2026-07-21).
     flex-start, not stretch — pills/badges in other pages' card heads must not
     blockify into full-width bars (review finding). */
  .card-head { flex-direction: column; align-items: flex-start; }
  .card-head .actions { width: 100%; }
  .card-head .actions .btn-ghost, .card-head .actions .btn, .card-head .actions form, .card-head .actions button { width: 100%; }
  /* triage rows become cards: full-width inputs + a 44px check button */
  .flag-row { flex-direction: column; align-items: stretch; }
  .flag-row .inputs, .flag-mini { width: 100%; }
  .flag-mini label { flex: 1; }
  .flag-mini input { width: 100%; }
  .btn-check { width: 100%; min-height: 44px; }
  /* «märgi kontrollituks» in the eelarve table needs a real thumb target */
  .eelarve button.link.btn-xs { display: inline-block; padding: 10px 0; min-height: 44px; }
  /* The editor's swap controls live in a note row of an ~820px-wide scrolling table,
     so on a phone the «Vaheta» button sat ~550px off-screen (QA 2026-08-06). Pin them
     to the wrapper's left edge and cap the width so the whole control set is reachable
     without scrolling the budget table sideways. */
  .eelarve__note .swap-fold, .eelarve__note .swap-controls { position: sticky; left: 0; }
  /* 6.5rem = page gutters (2×~2.8rem incl. the card border) + the note cell's own
     padding; measured against the .table-wrap scrollport at 390px, where a 3.5rem
     guess overshot by ~51px and clipped the controls' right edge (QA 2026-08-06). */
  .eelarve__note .swap-controls { width: calc(100vw - 6.5rem); max-width: 100%; flex-wrap: wrap; }
  .eelarve__note .swap-controls > * { flex: 1 1 100%; }
  .eelarve__note .swap-controls button { min-height: 44px; }

  .drawer { width: 100%; }
}

/* ---- Kogu baas v2 card rows — ≤900px, wider than the generic phone block ----
   Review finding (HIGH): with overflow-x:clip and no .table-wrap, the 7–9-column
   tables CLIPPED their flag/⋯-menu columns between 641 and ~900px with no way to
   scroll to them. Below 900 the tables genuinely don't fit, so the tap-to-edit
   card layout (audit HIGH at 390px) takes over there instead of only ≤640. */
@media (max-width: 900px) {
  .card.flush-sticky { background: none; border: 0; box-shadow: none; overflow: visible; }
  .flush-sticky table, .flush-sticky tbody { display: block; }
  .flush-sticky thead { display: none; }
  .flush-sticky tr.row-view { display: flex; flex-wrap: wrap; gap: .25rem .6rem; align-items: baseline; border: var(--border); border-radius: var(--r-md); padding: .8rem .9rem; margin: 0 0 .6rem; background: var(--surface); }
  .flush-sticky tr.row-view td { display: block; border: 0; padding: 0; }
  .flush-sticky td.cell-name { flex-basis: 100%; min-width: 0; }
  .flush-sticky tr.row-view td.num { text-align: left; }
  .flush-sticky td.cell-menu { margin-left: auto; }
  /* numeric cells label themselves — four bare numbers in a row are unreadable */
  .flush-sticky tr.row-view td[data-th]::before { content: attr(data-th) " "; color: var(--muted); font-size: .75rem; }
  /* value-less cells would render an orphan label (bare “Lisatarv.”) — hide them;
     the templates emit truly empty <td> (no whitespace) for absent values */
  .flush-sticky tr.row-view td:empty { display: none; }
  .flush-sticky tr.row-view.is-open { border-radius: var(--r-md) var(--r-md) 0 0; margin-bottom: 0; }
  .flush-sticky tr.row-edit { display: none; }
  .flush-sticky tr.row-edit.is-open { display: block; border: var(--border); border-top: 0; border-radius: 0 0 var(--r-md) var(--r-md); margin: 0 0 .6rem; padding: 0; background: var(--brand-tint); }
  .flush-sticky tr.row-edit.is-open > td { display: block; }
  .edit-form .f, .edit-form .f--xs, .edit-form .f--s, .edit-form .f--l { flex: 1 1 100%; }
  /* thumb targets: Salvesta is a bare <button class="btn-sm">, Tühista is button.link,
     merge Liida sits in .edit-sub — cover them all (review: the old .btn selector
     matched none of them) */
  .edit-form button, .edit-sub button { width: 100%; min-height: 44px; }
  .flush-sticky details.rowmenu > summary { padding: 10px 14px; min-height: 44px; display: inline-flex; align-items: center; }
  .flush-sticky .table-note { border: 0; padding: var(--sp-2) 0; }
  .flush-sticky .empty { background: var(--surface); border: var(--border); border-radius: var(--r-md); }
  /* the thead's sort links are gone here — the toolbar select takes over */
  .sort-select-wrap { display: block; }
}

/* ---- narrow screens (tablet & down) ----
   AFTER the 640px block on purpose: th./td.col-optional ties with the
   .table-wrap display-revert rules above, so file order must let it win.
   1024 (not 900): with all 9 dashboard columns visible the table's minimum
   width is ~930px, so just above 900 it could never fit — the hide point must
   sit where the remaining columns are guaranteed a scroll-free fit. */
@media (max-width: 1024px) {
  /* dashboard: drop the nice-to-have columns so the jobs table fits */
  th.col-optional, td.col-optional { display: none; }
  .toolbar-search { margin-left: 0; flex: 1 1 100%; }
  .toolbar-search input[type=search] { width: auto; flex: 1; }
}

/* mid widths (small laptop / tablet landscape): denser tables so all columns
   still fit without the wrapper scrolling; phones keep their own spacing above */
@media (min-width: 641px) and (max-width: 1280px) {
  .table-wrap { font-size: .85rem; }
  .table-wrap th, .table-wrap td { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  /* Kogu baas tables (no .table-wrap — sticky thead): same density so the 9-column
     worknode table fits 901–1280px without clipping its ⋯-menu (review finding) */
  .flush-sticky table { font-size: .85rem; }
  .flush-sticky th, .flush-sticky td { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  /* the eelarve-editor note row is (0,2,1)-specific and would keep 16px padding while
     its siblings shrink to 8px — match it so the note inputs align (review finding) */
  .table-wrap .eelarve--edit .eelarve__note td { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  td.cell-wrap { min-width: 10rem; }
}

/* ---- «Mis takistab» card + sticky next-action bar (job page, Block 10 item 2) ---- */
.blockers { color: var(--ink); }
.blockers > div { flex: 1; min-width: 0; }
.blockers__title { font-size: 1.05rem; margin: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.notice--error .blockers__title { color: var(--err); }
.notice--warn .blockers__title { color: var(--accent-ink); }
.blockers__list { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: grid; gap: var(--sp-3); }
.blockers__list > li { border-top: 1px solid rgba(0,0,0,.06); padding-top: var(--sp-3); }
.blockers__list > li:first-child { border-top: 0; padding-top: 0; }
.blockers .act { margin-top: var(--sp-3); }
.jd-actionbar { position: sticky; top: var(--topbar-h, 60px); z-index: 25; display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; background: var(--bg); padding: var(--sp-2) 0; margin: 0 0 var(--sp-4); border-bottom: var(--border); }
.jd-actionbar__causes { margin-right: auto; color: var(--accent-ink); font-weight: 600; text-decoration: none; }
/* «Mis takistab» is reached by an in-page anchor from the sticky bar: without this the card's
   title lands under topbar + bar (measured 124 px desktop / 153 px mobile). --actionbar-h is
   measured by app.js like --topbar-h, because the bar wraps to two rows on phones. */
#mis-takistab { scroll-margin-top: calc(var(--topbar-h, 60px) + var(--actionbar-h, 0px) + 12px); }
@media (max-width: 640px) {
  .jd-actionbar .btn, .jd-actionbar button { width: 100%; }
  .jd-actionbar__causes { flex-basis: 100%; margin-right: 0; }
}

/* ---- manifest form (Block 7 Phase B): a tick per candidate file + a sticky action row.
   app.css `input {width:100%; border…}` would stretch a bare checkbox across its cell. ---- */
table.manifest input[type=checkbox] { width: auto; padding: 0; margin: 0; accent-color: var(--brand); }
ul.manifest-hidden input[type=checkbox] { width:auto; padding:0; margin-right:6px; vertical-align:middle; }
table.manifest .manifest__tick { width: 2rem; text-align: center; }
.manifest-actions { position: sticky; bottom: 0; z-index: 5; background: var(--bg); padding: var(--sp-2) 0; margin-top: var(--sp-3); border-top: var(--border); align-items: center; }
.manifest-actions__hint { font-size: .85rem; }

/* a link that is gated until a checkbox is ticked (recovery-codes page) */
a.is-disabled { pointer-events: none; opacity: .5; }
