/* ─────────────────────────────────────────────────────────────────────────────
   QUICK-ADD
   The quick-add hub — one glass modal, every kind of entry.

   Part 9 of 11, cut from the 5,142-line app.css. THE ORDER OF THESE
   FILES IS LOAD-BEARING — they are one cascade, split for navigation only, and
   index.php links them in this sequence. Moving one changes which rule wins.
   ───────────────────────────────────────────────────────────────────────────── */
/* =========================================
   QUICK-ADD HUB — one fixed-size glass modal,
   6 tabs swap the body with ZERO size change
   (no flashing). Shared design language for
   every tab + the AI (smart inbox) flow.
   ========================================= */

/* The card is SIZED TO ITS CONTENT between a floor and a ceiling — js/app.js
   fitQuickHub() measures the visible tab and writes --hub-h, and the height
   transition below makes the change a settle rather than a jump (the old fixed
   820px left the AI tab 58% empty and sheared the Entry form). overflow hidden
   so the picker sheet slides INSIDE the card. */
.modal-card.quick-hub {
    width: 680px;
    max-width: 680px;
    height: var(--hub-h, auto);
    min-height: 460px;
    max-height: min(88vh, 860px);
    padding: 0;                 /* header / tabs / intro / body / foot own their padding */
    overflow: hidden;
    transition: height 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
    .modal-card.quick-hub { transition: none; }
}

/* TITLE ROW — one anchor for the card; the tabs live on their own row below */
.quick-hub .modal-header {
    margin: 0;
    padding: 22px 28px 0;
    border: none;
    gap: 12px;
    align-items: center;
}
/* single-purpose opens (edit / contextual) close the head with a divider, since
   they have neither a tab row nor an intro line to do it */
.quick-hub:not(.show-tabs) .modal-header {
    padding: 22px 28px 16px;
    border-bottom: 1px solid var(--divider);
}
.quick-hub .modal-title-single { font-size: 19px; }

/* TAB ROW — the house underline seg-tab grammar: text only (the old mixed icon
   set made six unequal shapes), one hairline carrying the active underline. */
.quick-tabs {
    display: none;
    gap: 0;
    margin: 16px 28px 0;
    border-bottom: 1px solid var(--divider);
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.quick-tabs::-webkit-scrollbar { display: none; }
.quick-hub.show-tabs .quick-tabs { display: flex; }
.modal-title-single { flex: 1; margin: 0; }

.qtab {
    flex: 0 0 auto;
    margin-right: 20px;
    padding: 0 1px 11px;
    border: none; background: transparent; cursor: pointer;
    color: var(--text-muted);
    font-family: inherit;
    position: relative;
    transition: color 0.18s ease;
}
.qtab:last-child { margin-right: 0; }
.qtab span { font-size: 13px; font-weight: var(--fw-semibold); letter-spacing: 0.005em; white-space: nowrap; }
.qtab:hover { color: var(--text-main); }
.qtab.active { color: var(--text-main); }
.qtab.active::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
    border-radius: 2px; background: var(--text-main);
}

/* short contextual intro under the tabs — the tab row already carries the
   hairline, so this one doesn't add a second */
.modal-intro {
    margin: 14px 28px 0;
    padding: 0;
    font-size: 12.5px; line-height: 1.55;
    color: var(--text-muted);
    border-bottom: none;
}
.modal-intro:empty { display: none; }

/* body scrolls between the fixed head and footer */
.quick-hub #modal-form-body {
    padding: 18px 28px 20px;
    margin: 0;
    min-height: 0;              /* flex child must be allowed to shrink to scroll */
}
.quick-hub .modal-foot {
    position: relative;
    padding: 16px 28px 20px;
    border-top: 1px solid var(--divider);
    margin: 0;
    background: var(--bg-card);
}
/* content fades UNDER the footer, so a cut always reads as deliberate */
.quick-hub .modal-foot::before {
    content: '';
    position: absolute; left: 0; right: 0; top: -28px; height: 28px;
    background: linear-gradient(to bottom, transparent, var(--bg-card));
    pointer-events: none;
}
.modal-foot .btn-save-full { margin-top: 0; }

/* ONE primary action + a preference, not two rival buttons */
.qa-save-row { display: flex; align-items: center; gap: 16px; }
.qa-keep { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 0; cursor: pointer; }
.qa-keep input {
    flex: 0 0 auto; width: 16px; height: 16px;
    accent-color: var(--text-main); cursor: pointer;
}
.qa-keep span { font-size: 12px; font-weight: var(--fw-medium); color: var(--text-muted); line-height: 1.35; }
.qa-save-row .qa-save-main {
    flex: 0 0 auto; min-width: 178px; justify-content: center;
    border-radius: var(--radius-sm);
    /* One button size in the system, so emphasis comes from the 178px min-width
       and the padding rather than from a bespoke 15px that is no longer a step
       on the ladder. */
    padding: 15px 30px; font-size: var(--text-base); font-weight: var(--fw-bold);
}

/* ---- Entry (transaction) fast layout ---- */
.qa-type-pills { flex-wrap: wrap; gap: 3px; margin-bottom: 18px; }
.qa-type-pills .btn-pill { flex: 1 1 auto; min-width: 70px; }

/* AMOUNT WELL — the hero figure as a proper figure-unit (quiet caption stacked
   over a tabular display number) on a recessed field, instead of a currency code
   marooned 300px away from its own number. */
.qa-amount-block {
    background: var(--bg-main);
    border-radius: var(--radius-lg);
    padding: 16px 24px 20px;
    margin-bottom: 22px;
    transition: box-shadow 0.16s ease;
}
.qa-amount-block:focus-within { box-shadow: inset 0 0 0 1px var(--divider-strong); }
.qa-amount-block .amount-wrapper { flex-direction: column; gap: 2px; }
.qa-amount-block .amount-currency {
    position: static; left: auto;
    font-size: 9.5px; letter-spacing: 0.1em;
    font-weight: var(--fw-medium);
}
.qa-amount-block .input-amount-huge {
    font-size: 46px; font-weight: var(--fw-bold);
    letter-spacing: -0.015em;
    border-bottom: none; padding: 0; margin: 0;
}
.qa-amount-block .input-amount-huge::placeholder { color: var(--text-muted); opacity: 0.4; }

/* option-pill rail — ONE control per field. The rail IS the picker (it used to
   sit above a dropdown holding the same value); the trailing "All (n)" chip
   opens the full list in the sheet. One row, scrolls horizontally (iOS chip
   rail), edges fade out, bleeds to the card edge. Chassis + ink active state
   come from the SHARED RECIPES filter-pill group. */
.qa-acc-pills {
    position: relative;          /* anchors the sliding .pill-glider */
    display: flex; flex-wrap: nowrap; gap: 6px;
    overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
    /* the rail no longer bleeds past the content column: it starts and ends on the
       same 28px grid as every input, and the sticky "All (n)" chip needs a clean
       right edge to pin against (a mask would fade the chip with it) */
    margin: 0; padding: 2px 0 6px;
    scroll-snap-type: x proximity;
}
.qa-acc-pills::-webkit-scrollbar { display: none; }
.qa-acc-pills:empty { display: none; }
.qa-acc-pill {
    position: relative; z-index: 1;   /* above the glider capsule */
    flex: 0 0 auto; scroll-snap-align: start;
    padding: 9px 15px;
    background: var(--bg-main);
    color: var(--text-muted);
    font-size: 12.5px;
}
.qa-acc-pill:hover { color: var(--text-main); }
/* the full-list chip — outlined (an action, not another option) and STICKY to the
   rail's right edge, so it stays reachable however far the pills have scrolled */
.qa-acc-pill.qa-acc-more {
    position: sticky; right: 0; z-index: 2;
    scroll-snap-align: none;
    background: var(--bg-card);
    /* the second shadow is an opaque skirt on the left so pills scroll UNDER the
       chip instead of colliding with it */
    box-shadow: inset 0 0 0 1px var(--divider-strong), -22px 0 0 -6px var(--bg-card);
    color: var(--text-muted);
}
.qa-acc-pill.qa-acc-more:hover { color: var(--text-main); box-shadow: inset 0 0 0 1px var(--text-main); }
/* WHICH CONTROL IS SHOWN — never two for one field, and the right one per reach:
   the chip rail is the TOUCH affordance (thumb-scrollable, iOS/Wise), so it owns
   the field on the phone; on the desktop the house dropdown owns it, where a
   pointer picks a named row out of a list faster than it scrubs a rail. Both stay
   in the DOM and in sync through the native select underneath, so a resize (or a
   pick in either one) just swaps which is visible — no state to reconcile. */
select.qa-has-rail + .qa-select { display: none; }             /* touch: rail wins */
@media (min-width: 641px) {
    .qa-acc-pills { display: none; }                           /* pointer: dropdown wins */
    select.qa-has-rail + .qa-select { display: flex; }
}

/* attachment input (was inline-styled) — compact single-line file field */
.qa-file-input { padding: 10px 18px; font-size: 13px; }

/* ---- house select: pill trigger + in-card picker sheet ---- */
/* the native select stays in the DOM for its value/change wiring — just unseen */
.qa-native-hidden {
    position: absolute !important;
    width: 1px; height: 1px; opacity: 0;
    pointer-events: none; overflow: hidden; clip-path: inset(50%);
}
.qa-select {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 13px 16px 13px 22px;
    border: 1px solid transparent; border-radius: var(--radius-pill);
    background: var(--bg-main); color: var(--text-main);
    font-family: inherit; font-size: var(--text-base); font-weight: var(--fw-semibold);
    cursor: pointer; text-align: left;
    transition: border-color 0.16s ease, background 0.16s ease;
}
.qa-select:hover { border-color: var(--divider-strong); }
.qa-select:focus-visible { outline: none; border-color: var(--theme-color); }
.qa-select-val { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qa-select-code { flex: 0 0 auto; font-size: 11px; font-weight: var(--fw-semibold); color: var(--text-muted); }
.qa-select-chev { flex: 0 0 auto; font-size: 19px; color: var(--text-muted); }
.qa-select.is-placeholder .qa-select-val { color: var(--text-muted); font-weight: var(--fw-medium); }

/* the picker — a sheet that slides up INSIDE the modal card (iOS/Wise):
   caption header, filter field on long lists, ✓-marked rows (menu grammar) */
.qa-picker {
    position: absolute; inset: 0; z-index: 40;
    display: flex; flex-direction: column;
    background: var(--bg-card); border-radius: inherit;
    transform: translateY(103%); visibility: hidden;
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), visibility 0.3s;
}
.qa-picker.open { transform: none; visibility: visible; }
.qa-picker-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 22px 22px 12px 30px;
}
.qa-picker-title {
    font-size: 11px; font-weight: var(--fw-medium);
    letter-spacing: var(--tracking-caps); text-transform: uppercase;
    color: var(--text-muted);
}
.qa-picker-search {
    display: flex; align-items: center; gap: 8px;
    margin: 0 24px 12px; padding: 11px 18px;
    border-radius: var(--radius-pill); background: var(--bg-main);
}
.qa-picker-search .material-icons { font-size: 18px; color: var(--text-muted); }
.qa-picker-search input {
    flex: 1; min-width: 0; border: none; background: transparent; outline: none;
    font-family: inherit; font-size: 14px; font-weight: var(--fw-medium); color: var(--text-main);
}
.qa-picker-list {
    flex: 1; overflow-y: auto;
    display: flex; flex-direction: column; gap: 2px;
    padding: 2px 16px calc(18px + env(safe-area-inset-bottom, 0px));
}
.qa-picker-row {
    display: flex; align-items: center; gap: 10px;
    padding: 13px 14px; border: none; border-radius: var(--radius-md);
    background: transparent; cursor: pointer; text-align: left;
    font-family: inherit; font-size: 14px; font-weight: var(--fw-medium); color: var(--text-main);
    transition: background 0.14s ease;
}
.qa-picker-row:hover { background: var(--bg-main); }
.qa-picker-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qa-picker-code { flex: 0 0 auto; font-size: 11px; color: var(--text-muted); }
.qa-picker-check { flex: 0 0 auto; font-size: 18px; opacity: 0; }
.qa-picker-row.is-sel { font-weight: var(--fw-semibold); }
.qa-picker-row.is-sel .qa-picker-check { opacity: 1; }
.qa-amount-block { margin: 2px 0 22px; }
/* the former "More details" fields — now always visible, one continuous stack */
.qa-more-body { display: flex; flex-direction: column; gap: 16px; padding-top: 2px; }
.qa-more-body .form-grid-2 { margin-bottom: 0; }
.qa-hint {
    display: flex; gap: 8px; align-items: flex-start;
    padding: 10px 12px; border-radius: var(--radius-md);
    font-size: 12px; line-height: 1.5; color: var(--text-muted);
}
.qa-hint .material-icons { font-size: 15px; flex-shrink: 0; margin-top: 1px; }
.qa-hint-warn { background: rgba(245, 158, 11, 0.08); border: 1px solid rgba(245, 158, 11, 0.25); }
.qa-hint-info { background: rgba(59, 130, 246, 0.08); border: 1px solid rgba(59, 130, 246, 0.25); }
/* the AI reader's warnings join this group instead of minting .ai-note-* */
.qa-hint-danger { background: color-mix(in srgb, var(--danger-red) 8%, transparent); border: 1px solid color-mix(in srgb, var(--danger-red) 28%, transparent); }
.qa-hint-quiet { background: var(--bg-main); }
.qa-hint strong { color: var(--text-main); font-weight: var(--fw-semibold); }
.qa-hint--block { display: block; }
/* Opt-in variant: the whole hint is a <label> wrapping a checkbox (e.g. auto-MPF) */
.qa-hint-choice { cursor: pointer; user-select: none; }
.qa-hint-choice input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--text-main); cursor: pointer; flex-shrink: 0; margin-top: 1px; }
.qa-hint-choice strong { color: var(--text-main); font-weight: var(--fw-semibold); }

/* ---- AI tab (smart inbox) — same design language ---- */
/* the drop target is a RECESSED FIELD, not a dashed outline — the app's only
   dashed border used to live here. Same quiet-track grammar as the amount well
   and the Documents rail; it fills the tab so the card never shows dead space. */
.ai-drop {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 260px;
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    background: var(--bg-main);
    padding: 38px 24px; text-align: center; cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
    color: var(--text-muted);
}
.ai-drop:hover { border-color: var(--divider-strong); }
.ai-drop.drag { border-color: var(--text-main); background: var(--bg-hover); color: var(--text-main); }
.ai-big { font-size: 40px; line-height: 1; margin-bottom: 10px; color: var(--text-main); }
/* the glyph takes the wrapper's size instead of the Material base 24px, so .ai-big
   is self-sufficient — callers that set an inline font-size still win */
.ai-big .material-icons { font-size: inherit; }
.ai-drop-title { font-weight: 600; color: var(--text-main); font-size: 15px; }
.ai-drop-sub { font-size: 13px; margin-top: 4px; }
.ai-hint { font-size: 12px; color: var(--text-muted); margin-top: 16px; text-align: center; line-height: 1.5; }

/* ── BRING YOUR OWN KEY ───────────────────────────────────────────────────────
   Stands where the drop zone would have been, so it reads as the first step of
   the same flow rather than an error that interrupted it. Deliberately NOT a
   warning colour: nothing has gone wrong, the reader is simply being asked for
   something. It borrows the recessed field of .ai-drop and the type scale of
   the drop title, so the two screens feel like one. See js/ai-key.js. */
.aik {
    background: var(--bg-main);
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    padding: 26px 24px 22px;
}
.aik-head { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 18px; }
.aik-icon { font-size: 22px; color: var(--text-main); flex-shrink: 0; margin-top: 1px; }
.aik-title { font-weight: 600; color: var(--text-main); font-size: 15px; line-height: 1.35; }
.aik-why { font-size: 12.5px; line-height: 1.55; color: var(--text-muted); margin-top: 5px; }
.aik-field { margin-bottom: 10px; }
/* THE FIELD HAS TO INVERT HERE. .modal-input is a RECESSED well — it reads because
   it sits on the white card. This panel is itself recessed (same --bg-main), so the
   default input vanishes into it: a placeholder floating on nothing. Inside .aik the
   input becomes the RAISED element instead, which is the same figure/ground rule the
   house uses everywhere, just the other way up.
   tabular figures so a pasted key reads as a run of characters, not a word. */
.aik-field .modal-input {
    background: var(--bg-card);
    border-color: var(--divider);
    font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.aik-field .modal-input:focus { border-color: var(--text-main); }
.aik-note { font-size: 11.5px; line-height: 1.55; color: var(--text-muted); margin: 0; }
/* the link stays the colour of its paragraph — a browser-blue anchor is the one
   thing on this card that would look like it came from somewhere else */
.aik-link {
    color: var(--text-main); font-weight: var(--fw-semibold);
    text-decoration: underline; text-underline-offset: 2px;
    text-decoration-color: var(--divider-strong);
    white-space: nowrap; margin-left: 4px;
}
.aik-link:hover { text-decoration-color: var(--text-main); }

/* The receipt after the fact: which key is running, and the way out of it. */
.aik-badge {
    display: flex; align-items: center; gap: 7px;
    margin-top: 12px; padding: 0 2px;
    font-size: 11.5px; color: var(--text-muted);
}
.aik-badge .material-icons { font-size: 14px; }
.aik-forget {
    margin-left: auto; padding: 0; border: 0; background: none; cursor: pointer;
    font: inherit; color: var(--text-muted);
    text-decoration: underline; text-underline-offset: 2px;
    text-decoration-color: var(--divider-strong);
}
.aik-forget:hover { color: var(--text-main); }
.aik-forget:disabled { opacity: 0.5; cursor: default; }

/* ── THE SETTINGS ROW ──────────────────────────────────────────────────────────
   Sits in the Preferences list, so it borrows that row's geometry rather than
   inventing its own. The input is narrow on purpose: a key is a long opaque run of
   characters and a full-width field invites reading it back, which is exactly what
   this design does not do. Wraps to its own line on a phone. */
.set-ai-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.set-ai-input {
    width: 220px; max-width: 46vw;
    background: var(--bg-main);
    font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
@media (max-width: 560px) {
    #set-ai-row { flex-wrap: wrap; }
    .set-ai-controls { width: 100%; justify-content: flex-start; margin-top: 8px; }
    .set-ai-input { max-width: none; flex: 1 1 auto; }
}

/* ── AI RESULT GRAMMAR ────────────────────────────────────────────────────────
   ONE vocabulary for everything the reader produces (files being read, statement
   lines, reconcile findings): a tracked-caps caption with a count pill, then a
   RECESSED TRACK of quiet hairline rows — the same recessed-field grammar as the
   amount well and the Documents rail. No inner scrollers: the lists run their
   full length and the CARD grows (fitQuickHub), so long results read as one
   list instead of a letterbox inside a half-empty card. */
.ai-sec { margin-top: 22px; }
.ai-sec:first-child { margin-top: 0; }
.ai-sec-head { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.ai-sec-cap {
    font-size: 10px; letter-spacing: var(--tracking-caps); text-transform: uppercase;
    font-weight: var(--fw-medium); color: var(--text-muted);
}
.ai-sec-note { font-size: 11.5px; line-height: 1.5; color: var(--text-muted); margin: -3px 0 9px; }

.ai-list {
    background: var(--bg-main);
    border-radius: var(--radius-lg);
    padding: 4px;
}
.ai-row {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 12px;
    border-radius: var(--radius-md);
    box-shadow: inset 0 -1px 0 var(--divider);
}
/* ONLY the reconcile list's rows carry a category picker AND a Record button; at
   modal width those two ate the description down to a single ellipsis. Those rows
   wrap so the controls drop to their own line. Every other row — which is most of
   them — keeps one line, so a long status pill can't push its figure down. */
.ai-row:has(.qa-select) { flex-wrap: wrap; }
.ai-row:has(.qa-select) .ai-row-desc { flex: 1 1 150px; }
.ai-row:last-child { box-shadow: none; }
.ai-row-date {
    flex: 0 0 auto; width: 76px;
    font-size: 11px; font-weight: var(--fw-medium); color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.ai-row-desc {
    flex: 1; min-width: 0;
    font-size: 12.5px; color: var(--text-main);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ai-row-amt {
    flex: 0 0 auto;
    font-size: 12.5px; font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums; color: var(--text-main);
}
.ai-row-amt--in { color: var(--success-green); }
.ai-row-amt--out { color: var(--danger-red); }
.ai-row-st { flex: 0 0 auto; font-size: 11.5px; font-weight: var(--fw-medium); color: var(--text-muted); }
.ai-row--done { opacity: 0.5; }
.ai-row--done .ai-row-desc { text-decoration: line-through; }
/* per-row category picker + record CTA (the "record these" list) */
.ai-row .qa-select {
    width: auto; max-width: 178px; flex: 0 0 auto;
    padding: 7px 10px 7px 14px; font-size: 12px; font-weight: var(--fw-medium);
    background: var(--bg-card);
}
.ai-row .qa-select-chev { font-size: 16px; }
/* the row CTA stays QUIET until you reach for it — a list of six ink buttons
   shouts louder than the amounts, which are the thing to read first */
.ai-row-rec {
    flex: 0 0 auto;
    padding: 8px 16px; font-size: 12px; font-weight: var(--fw-semibold);
    border-radius: var(--radius-pill);
    background: transparent; color: var(--text-main);
    box-shadow: inset 0 0 0 1px var(--divider-strong);
    transition: background 0.16s ease, color 0.16s ease, box-shadow 0.16s ease;
}
.ai-row-rec:hover { background: var(--text-main); color: var(--bg-card); box-shadow: none; }
.ai-row-rec:disabled { opacity: 0.5; }
.ai-cap-more { font-size: 11px; color: var(--text-muted); text-align: center; padding: 9px 12px 5px; }

/* RECONCILE BOARD — the cross-check verdict as figure-units on one recessed
   panel: the balances that must agree on top, the four finding counts beneath. */
.ai-board { background: var(--bg-main); border-radius: var(--radius-lg); padding: 16px 20px 4px; }
.ai-board-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding-bottom: 15px; }
.ai-board-bal { display: flex; align-items: flex-end; gap: 22px; margin-left: auto; }
.ai-fig { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ai-fig-cap {
    font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase;
    font-weight: var(--fw-medium); color: var(--text-muted); white-space: nowrap;
}
.ai-fig-val {
    font-size: 17px; font-weight: var(--fw-bold); line-height: 1;
    letter-spacing: var(--tracking-tight); font-variant-numeric: tabular-nums;
    color: var(--text-main);
}
.ai-fig-val--off { color: var(--danger-red); }
.ai-fig-val--ok { color: var(--success-green); }
/* TWO up, not four. The reconcile board's captions are one word ("Books",
   "Statement"), but Smart Quoting's are phrases — "Typical won quote", "Hours
   actually logged" — and four of those in a quarter-column collided into one
   another while the figures beside them wrapped mid-number. Two columns give both
   the caption and the value a whole line at the width a modal actually has. */
.ai-board-stats {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 17px 20px;
    border-top: 1px solid var(--divider); padding: 13px 0 15px;
}
.ai-board-stats .ai-fig-cap { white-space: normal; line-height: 1.35; }
.ai-board-stats .ai-fig-val { font-size: 20px; }
.ai-board-stats .ai-fig-val--zero { color: var(--text-muted); opacity: 0.55; }

/* STEP TRACK — "receipt 2 of 5" with a hairline progress bar (the shared
   bar recipe), replacing the row of anonymous dots */
.ai-steps { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.ai-steps-cap {
    flex: 0 0 auto;
    font-size: 10px; letter-spacing: var(--tracking-caps); text-transform: uppercase;
    font-weight: var(--fw-medium); color: var(--text-muted);
}
.ai-steps .pb-bar-track { flex: 1; height: 4px; }
.ai-steps .pb-bar-fill { background: var(--text-main); }

.ai-media {
    width: 100%; height: 180px; border-radius: var(--radius-lg);
    background: var(--bg-main);
    display: flex; align-items: center; justify-content: center;
    color: var(--text-muted); overflow: hidden; margin-bottom: 14px;
}
.ai-media img { width: 100%; height: 100%; object-fit: contain; }
/* the read's own header: what it is + how sure the model is */
.ai-readhead { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.ai-readhead .ai-sec-cap { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ai-actions { display: flex; gap: 10px; margin-top: 20px; }
.ai-actions .btn { flex: 1; justify-content: center; border-radius: var(--radius-sm); padding: 13px; font-weight: var(--fw-bold); }
.ai-actions .ai-confirm { flex: 1.5; }
.ai-summary { text-align: center; padding: 26px 8px 8px; }
.ai-summary .ai-big { color: var(--success-green); margin-bottom: 12px; }
.ai-sum-title { font-size: 18px; font-weight: var(--fw-semibold); color: var(--text-main); }
.ai-sum-sub { color: var(--text-muted); margin-top: 6px; font-variant-numeric: tabular-nums; }

/* transient save toast (fast one-by-one entry) */
.qa-toast {
    position: fixed; left: 50%; bottom: 34px;
    transform: translateX(-50%) translateY(18px);
    background: var(--text-main); color: var(--bg-main);
    padding: 12px 20px; border-radius: var(--radius-pill);
    font-size: 14px; font-weight: 600; z-index: 4000;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
    display: flex; align-items: center; gap: 8px;
    opacity: 0; pointer-events: none;
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.qa-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.qa-toast .material-icons { font-size: 18px; }
/* warning variant — archived/read-only reminder (logo yellow, dark ink, roomier) */
.qa-toast--warn { background: var(--warning-yellow); color: #1a1a1a; max-width: min(560px, calc(100vw - 32px)); padding: 13px 22px; line-height: 1.35; text-align: left; }
.qa-toast--warn .material-icons { flex-shrink: 0; }
