/*
 * ╔══════════════════════════════════════════════════════════════╗
 * ║  MartPlus — styles for Inventory, POS and Reports.           ║
 * ║  Loaded after app.css and built on the same design tokens,   ║
 * ║  so the base app's look carries straight through.            ║
 * ╚══════════════════════════════════════════════════════════════╝
 */

/* ── SHARED BITS ─────────────────────────────────────────────── */
.ta-right  { text-align: right; }
.ta-center { text-align: center; }

.link-btn {
    background: none; border: none; padding: 0; cursor: pointer;
    color: var(--theme-ink); font-size: inherit; font-family: inherit;
    text-decoration: none; font-weight: 500;
}
.link-btn:hover { text-decoration: underline; }

.row-actions { display: flex; gap: 4px; align-items: center; }
.row-actions .btn svg { width: 14px; height: 14px; }

.field-hint { font-size: .7rem; color: var(--text-muted); margin-top: 4px; line-height: 1.45; }
.list-footnote { padding: .6rem 1.25rem; font-size: .75rem; color: var(--text-muted); border-top: 1px solid var(--border); }

.inline-field { display: flex; align-items: center; gap: 6px; font-size: .78rem; color: var(--text-secondary); }
.inline-field .form-control { width: auto; min-width: 0; }

/* Barcodes are read digit-by-digit — monospace keeps them scannable by eye. */
.barcode-chip {
    display: inline-block; font-family: 'Consolas', 'Courier New', monospace;
    font-size: .7rem; color: var(--text-muted); letter-spacing: .04em; margin-top: 2px;
}
.barcode-input { font-family: 'Consolas', 'Courier New', monospace; letter-spacing: .04em; }

.stock-pill { display: inline-block; padding: .15rem .5rem; border-radius: var(--r-sm); font-size: .78rem; font-weight: 600; background: var(--surface-alt); color: var(--text-secondary); }
.stock-pill.stock-low { background: var(--warning-soft); color: var(--warning-ink); }
.stock-pill.stock-out { background: var(--danger-soft); color: var(--danger-ink); }

.row-voided td { opacity: .55; }
.row-voided td:first-child { text-decoration: line-through; }

.chip {
    border: 1px solid var(--border); background: #fff; border-radius: var(--r-pill);
    padding: .2rem .65rem; font-size: .73rem; cursor: pointer; color: var(--text-secondary);
}
.chip:hover { border-color: var(--theme-muted); background: var(--theme-light); color: var(--theme-ink); }
.quick-range { display: inline-flex; gap: 4px; }

kbd {
    background: rgba(255,255,255,.22); border-radius: 4px; padding: 1px 5px;
    font-size: .68rem; font-family: inherit; font-weight: 600;
}

/* Dropdown items also render inside the nav menus. */
.ndi.active { background: var(--theme-light); color: var(--theme-ink); font-weight: 600; }
.ndi.active svg { color: var(--theme-ink); }

/* ── DEV_ADMIN STORE PICKER ──────────────────────────────────── */
.tenant-picker {
    display: flex; align-items: center; gap: 6px;
    border: 1px solid var(--border); border-radius: var(--r-pill); padding: 3px 10px 3px 12px;
}
.tenant-picker svg { width: 14px; height: 14px; color: var(--text-muted); }
.tenant-picker select {
    border: none; background: none; outline: none; font-size: .78rem;
    font-weight: 600; color: var(--text-primary); cursor: pointer; max-width: 160px;
}

/* ── POS ─────────────────────────────────────────────────────── */
/* Two columns: scanning + bill on the left, money on the right. The right column
   sticks so the total is always in the cashier's eye line. */
.pos { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 1.25rem; align-items: start; }

.scan-bar {
    display: flex; align-items: center; gap: .5rem;
    background: #fff; border: 2px solid var(--theme-ink); border-radius: var(--r-md);
    padding: .35rem .5rem .35rem .85rem;
    box-shadow: 0 2px 10px rgba(204,0,0,.14);
}
.scan-icon { display: flex; color: var(--theme-ink); }
.scan-icon svg { width: 18px; height: 18px; }
.scan-input {
    flex: 1; border: none; outline: none; background: none;
    font-size: 1.05rem; font-family: 'Consolas', 'Courier New', monospace;
    letter-spacing: .03em; padding: .5rem 0; color: var(--text-primary);
}
.scan-input::placeholder { font-family: 'Inter', sans-serif; letter-spacing: 0; font-size: .9rem; color: var(--text-muted); }

.scan-hint { font-size: .75rem; color: var(--text-secondary); padding: .4rem .2rem .1rem; min-height: 1.4rem; }
.scan-hint.ok { color: var(--success-ink); font-weight: 500; }
.scan-hint.error { color: var(--danger-ink); font-weight: 500; }

/* Name-search results — keyboard-first, click as a fallback. */
.picker {
    background: #fff; border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: 0 10px 30px rgba(0,0,0,.12); overflow: hidden auto;
    margin-bottom: .75rem; max-height: 260px;
}
.picker-row {
    display: grid; grid-template-columns: 1fr 150px 110px 90px; gap: .75rem; align-items: center;
    width: 100%; text-align: left; padding: .55rem .9rem; border: none; background: none;
    cursor: pointer; font-size: .84rem; border-bottom: 1px solid var(--border);
}
.picker-row:last-child { border-bottom: none; }
.picker-row:hover, .picker-row.active { background: var(--theme-light); }
.picker-row .p-name { font-weight: 600; }
.picker-row .p-bar { font-family: 'Consolas', monospace; font-size: .74rem; color: var(--text-muted); }
.picker-row .p-stock { font-size: .76rem; color: var(--text-secondary); text-align: right; }
.picker-row .p-stock.stock-out { color: var(--danger-ink); font-weight: 600; }
.picker-row .p-price { text-align: right; font-weight: 700; }

.pos-cart .table-wrap { max-height: calc(100vh - 340px); overflow-y: auto; }
.cart-table thead th { position: sticky; top: 0; z-index: 2; }
.cart-table tbody td { padding: .55rem .9rem; }
.cart-empty { text-align: center; padding: 3rem 1rem; color: var(--text-muted); }
.cart-empty svg { width: 42px; height: 42px; opacity: .25; margin: 0 auto .75rem; display: block; }

/* A repeat scan bumps an existing line — the flash is what tells the cashier the
   beep did something, without them having to read the row. */
@keyframes rowFlash { from { background: var(--theme-light2); } to { background: transparent; } }
.cart-table tr.flash td { animation: rowFlash .7s ease; }

.qty-group { display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
.qty-btn {
    width: 30px; height: 30px; border: none; background: var(--body-bg); cursor: pointer;
    font-size: 1rem; font-weight: 700; color: var(--text-secondary); line-height: 1;
}
.qty-btn:hover { background: var(--theme-light); color: var(--theme-ink); }
.qty-input {
    width: 66px; height: 30px; border: none;
    border-left: 1px solid var(--border); border-right: 1px solid var(--border);
    text-align: center; font-size: .875rem; font-weight: 600; outline: none; -moz-appearance: textfield;
}
.qty-input::-webkit-outer-spin-button, .qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qty-unit { font-size: .67rem; margin-top: 2px; }
.line-warn { font-size: .68rem; color: var(--warning-ink); display: flex; align-items: center; gap: 3px; margin-top: 2px; }
.line-warn svg { width: 12px; height: 12px; }

/* Bill summary */
.pos-right { position: sticky; top: calc(var(--topbar-h) + var(--navbar-h) + 1.5rem); }
.summary-card { background: #fff; border: 1px solid var(--border); border-radius: var(--r-md); padding: 1.1rem; }
.summary-store { font-size: .95rem; font-weight: 700; }
.summary-cashier { font-size: .72rem; color: var(--text-muted); margin-bottom: .9rem; padding-bottom: .75rem; border-bottom: 1px dashed var(--border); }
.summary-line { display: flex; justify-content: space-between; font-size: .84rem; padding: .28rem 0; color: var(--text-secondary); }
.summary-line span:last-child { font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.summary-line.change span:last-child { font-size: 1rem; color: var(--success-ink); }
.summary-line.change span:last-child.short { color: var(--danger-ink); }
.summary-field { display: block; margin: .6rem 0; }
.summary-field > span { display: block; font-size: .72rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }

.summary-grand {
    display: flex; justify-content: space-between; align-items: baseline;
    /* Flat brand violet. This used to be a 315° sweep aimed so the small "TOTAL"
       label landed on the deep end (the bright red corner measured 3.0:1 under it).
       Flat #360185 is 14.0:1 everywhere, so the label and the amount are both safe
       and the sweep is no longer needed. */
    background: var(--theme-color);
    color: var(--theme-contrast); border-radius: var(--r-md);
    padding: .7rem .85rem; margin: .75rem 0;
}
.summary-grand span:first-child { font-size: .72rem; letter-spacing: .1em; opacity: .8; }
.summary-grand span:last-child { font-size: 1.3rem; font-weight: 700; font-variant-numeric: tabular-nums; }

.quick-cash { display: flex; flex-wrap: wrap; gap: 5px; margin: .4rem 0 .5rem; }
.cash-btn {
    flex: 1 1 auto; min-width: 62px; border: 1px solid var(--border); background: #fff;
    border-radius: var(--r-sm); padding: .3rem .4rem; font-size: .76rem; cursor: pointer;
    font-weight: 600; color: var(--text-secondary);
}
.cash-btn:hover { border-color: var(--theme-muted); background: var(--theme-light); color: var(--theme-ink); }

.btn-finalize { width: 100%; justify-content: center; padding: .75rem; font-size: .95rem; font-weight: 600; margin-top: .5rem; }
/* The till sits at "disabled" between customers, so its primary action has to stay
   readable rather than wash out. The base .btn[disabled] 60% opacity would fade the
   violet fill to mush, so this state gets its own pale-violet treatment — ink on
   --theme-light2 is 7.5:1 and still reads clearly as "not ready yet". */
.btn-finalize[disabled] { opacity: 1; background: var(--theme-light2); color: var(--theme-ink); }
/* The shortcut isn't live while the button is disabled, so drop the key chip's
   wash — it would otherwise darken the pale background under the label to 3.8:1. */
.btn-finalize[disabled] kbd { background: transparent; }
.pos-keys { display: flex; justify-content: center; gap: .8rem; margin-top: .6rem; font-size: .68rem; color: var(--text-muted); }
.pos-keys kbd { background: var(--body-bg); border: 1px solid var(--border); color: var(--text-secondary); }

.sale-done { text-align: center; }
.done-number { font-family: 'Consolas', monospace; font-size: .85rem; color: var(--text-muted); letter-spacing: .06em; }
.done-total { font-size: 2rem; font-weight: 700; color: var(--theme-ink); margin: .2rem 0 1rem; }
.done-grid { text-align: left; border-top: 1px dashed var(--border); padding-top: .75rem; }
.done-grid > div { display: flex; justify-content: space-between; font-size: .84rem; padding: .2rem 0; }
.done-grid span { color: var(--text-secondary); }
.done-change strong { color: var(--success-ink); font-size: 1.05rem; }

/* ── BILL DETAIL / CORRECTION ────────────────────────────────── */
.bill-lock {
    display: flex; gap: .7rem; align-items: flex-start;
    background: var(--theme-light); border: 1px solid var(--theme-light2);
    border-radius: var(--r-md); padding: .7rem .9rem; font-size: .84rem;
}
.bill-lock.voided { background: var(--danger-soft); border-color: var(--danger-line); }
.bill-lock svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--theme-ink); margin-top: 1px; }
.bill-lock.voided svg { color: var(--danger-ink); }

.bill-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: .6rem; margin-top: 1rem; }
.bill-grid > div { background: var(--body-bg); border-radius: var(--r-sm); padding: .5rem .7rem; }
.bill-grid span { display: block; font-size: .68rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
.bill-grid strong { font-size: .84rem; }

.mini-table thead th { padding: .5rem .7rem; font-size: .68rem; }
.mini-table tbody td { padding: .5rem .7rem; font-size: .82rem; }
.mini-table .form-control { padding: .25rem .4rem; font-size: .82rem; }

.bill-totals { margin-top: 1rem; margin-left: auto; max-width: 300px; }
.bill-totals > div { display: flex; justify-content: space-between; font-size: .84rem; padding: .22rem 0; color: var(--text-secondary); }
.bill-totals > div span:last-child { font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.bill-totals .grand { border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); margin: .3rem 0; padding: .45rem 0; }
.bill-totals .grand span { font-size: 1rem; font-weight: 700; color: var(--theme-ink); }

.audit-block { margin-top: 1.25rem; border-top: 1px solid var(--border); padding-top: .9rem; }
.audit-title { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); margin-bottom: .6rem; }
.audit-row { display: flex; gap: .7rem; align-items: flex-start; padding: .45rem 0; font-size: .82rem; border-bottom: 1px dashed var(--border); }
.audit-row:last-child { border-bottom: none; }

/* ── PURCHASE ENTRY ──────────────────────────────────────────── */
/* The card that appears under the scanner once a barcode resolves. Master details
   are presentational (read-only by construction — they are not inputs); only the
   transaction fields are editable. */
.entry-card {
    background: #fff; border: 1px solid var(--theme-light2); border-left: 3px solid var(--theme-ink);
    border-radius: var(--r-md); padding: .85rem 1rem; margin-bottom: .75rem;
    box-shadow: 0 2px 10px rgba(204,0,0,.07);
}
.entry-card.new-product { border-left-color: var(--warning-ink); }
.entry-master { display: flex; flex-wrap: wrap; gap: .75rem 1.5rem; align-items: flex-start; }
.entry-name { font-size: 1rem; font-weight: 700; }
.entry-meta { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; margin-left: auto; }
.entry-meta span { font-size: .82rem; font-weight: 600; }
.entry-meta small {
    display: block; font-size: .64rem; font-weight: 600; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: .05em;
}
.entry-already {
    flex-basis: 100%; display: flex; align-items: center; gap: 5px;
    font-size: .74rem; color: var(--warning-ink);
}
.entry-already svg { width: 13px; height: 13px; flex-shrink: 0; }

.entry-newhead { display: flex; gap: .6rem; align-items: flex-start; margin-bottom: .75rem; }
.entry-newhead svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--warning-ink); margin-top: 2px; }

.entry-fields {
    display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end;
    margin-top: .85rem; padding-top: .75rem; border-top: 1px dashed var(--border);
}
.entry-fields label { display: block; flex: 1 1 110px; }
.entry-fields.wide label { flex: 1 1 150px; }
.entry-fields label > span {
    display: block; font-size: .7rem; font-weight: 600;
    color: var(--text-secondary); margin-bottom: 4px;
}
.entry-fields .btn { flex: 0 0 auto; height: 34px; }

/* ── BARCODE FIELD STATUS ────────────────────────────────────── */
/* Sits under a barcode input and reports what the scan found, without ever moving
   the caret out of the field. */
.barcode-status {
    display: flex; align-items: flex-start; gap: 5px;
    font-size: .74rem; line-height: 1.45; margin-top: 5px; min-height: 1rem;
}
.barcode-status:empty { display: none; }
.barcode-status svg { width: 13px; height: 13px; flex-shrink: 0; margin-top: 1px; }
.barcode-status.checking { color: var(--text-muted); }
.barcode-status.ok { color: var(--success-ink); }
.barcode-status.bad { color: var(--danger-ink); flex-wrap: wrap; }
.barcode-status.bad .link-btn { color: var(--danger-ink); text-decoration: underline; }

/* ── EXCEL IMPORT ────────────────────────────────────────────── */
.import-intro {
    display: flex; gap: 1rem; align-items: flex-start; justify-content: space-between;
    background: var(--theme-light); border: 1px solid var(--theme-light2);
    border-radius: var(--r-md); padding: .7rem .9rem; font-size: .84rem; margin-bottom: 1rem;
}
.import-intro .btn { flex-shrink: 0; }

/* Click target and drop target are the same element, so the label wraps the input. */
.dropzone {
    display: block; text-align: center; cursor: pointer;
    border: 2px dashed var(--border); border-radius: var(--r-md);
    padding: 1.5rem 1rem; transition: all .15s; background: var(--body-bg);
}
.dropzone:hover, .dropzone.over { border-color: var(--theme-muted); background: var(--theme-light); }
.dropzone.has-file { border-style: solid; border-color: var(--theme-muted); background: var(--theme-light); }
.dz-icon svg { width: 26px; height: 26px; color: var(--theme-ink); margin-bottom: .4rem; }
.dz-main { font-size: .88rem; font-weight: 600; word-break: break-all; }
.dz-sub { font-size: .72rem; color: var(--text-muted); margin-top: 2px; }

.im-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; margin: 1rem 0 .75rem; }
.im-tile { border: 1px solid var(--border); border-radius: var(--r-md); padding: .5rem .7rem; text-align: center; }
.im-tile .im-n { font-size: 1.25rem; font-weight: 700; line-height: 1.1; }
.im-tile .im-l { font-size: .68rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
.im-tile.ok  { background: var(--success-soft); border-color: var(--success-line); }
.im-tile.ok  .im-n { color: var(--success-ink); }
.im-tile.upd { background: var(--theme-light); border-color: var(--theme-light2); }
.im-tile.upd .im-n { color: var(--theme-ink); }
.im-tile.bad { background: var(--danger-soft); border-color: var(--danger-line); }
.im-tile.bad .im-n { color: var(--danger-ink); }

.im-note {
    display: flex; gap: .55rem; align-items: flex-start;
    background: var(--theme-light); border: 1px solid var(--theme-light2);
    border-radius: var(--r-md); padding: .55rem .75rem; font-size: .78rem; margin-bottom: .75rem;
}
.im-note svg { width: 15px; height: 15px; flex-shrink: 0; margin-top: 1px; color: var(--theme-ink); }
.im-note.bad { background: var(--danger-soft); border-color: var(--danger-line); }
.im-note.bad svg { color: var(--danger-ink); }

/* The preview can run to thousands of rows — keep it scrolling inside the modal
   rather than growing it past the viewport. */
.im-table { max-height: 320px; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--r-md); }
.im-table thead th { position: sticky; top: 0; z-index: 2; }
.im-msg { font-size: .75rem; color: var(--danger-ink); }
tr.im-bad td { background: var(--danger-soft); }

.import-fatal {
    display: flex; gap: .6rem; align-items: flex-start; margin-top: 1rem;
    background: var(--danger-soft); border: 1px solid var(--danger-line); border-radius: var(--r-md);
    padding: .7rem .9rem; font-size: .82rem; color: var(--danger-ink);
}
.import-fatal svg { width: 17px; height: 17px; flex-shrink: 0; color: var(--danger-ink); margin-top: 1px; }

@media (max-width: 640px) { .im-tiles { grid-template-columns: 1fr 1fr; } }

/* ── REPORTS ─────────────────────────────────────────────────── */
.report-layout { display: grid; grid-template-columns: 252px minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.report-menu {
    background: #fff; border: 1px solid var(--border); border-radius: var(--r-md); padding: .5rem;
    position: sticky; top: calc(var(--topbar-h) + var(--navbar-h) + 1.5rem);
}
.rm-group + .rm-group { margin-top: .5rem; border-top: 1px solid var(--border); padding-top: .5rem; }
.rm-title { font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted); padding: .35rem .6rem; }
.rm-item { display: block; width: 100%; text-align: left; border: none; background: none; cursor: pointer; padding: .45rem .6rem; border-radius: var(--r-sm); }
.rm-item:hover { background: var(--body-bg); }
.rm-item.active { background: var(--theme-light); }
.rm-item.active .rm-name { color: var(--theme-ink); }
.rm-name { display: block; font-size: .84rem; font-weight: 600; color: var(--text-primary); }
.rm-desc { display: block; font-size: .68rem; color: var(--text-secondary); line-height: 1.35; margin-top: 1px; }

.report-head { margin-bottom: 1rem; }
.report-title { font-size: 1.15rem; font-weight: 700; }
.report-period { padding: .6rem 1.25rem 0; font-size: .76rem; color: var(--text-muted); }
.report-tile { padding: .9rem 1rem; }
.report-tile .stat-value { font-size: 1.25rem; }
.report-table tbody td { padding: .55rem 1rem; font-size: .82rem; }
.report-table thead th { padding: .55rem 1rem; }
.report-table td.ta-right, .report-table th.ta-right { font-variant-numeric: tabular-nums; }

/* ── STORE PROFILE ───────────────────────────────────────────── */
.profile-layout { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 1.25rem; align-items: start; }
.preview-pane { background: var(--body-bg); display: flex; justify-content: center; }
/* Shown at true 82 mm, so what you see is what the roll prints. */
.receipt-preview {
    width: 82mm; background: #fff; padding: 3mm;
    box-shadow: 0 3px 14px rgba(0,0,0,.14);
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: 11px; line-height: 1.35; color: #000;
}
.receipt-preview .feed { display: none; }

/* ── RESPONSIVE ──────────────────────────────────────────────── */
/* The POS is a desktop / terminal screen first. It only stacks below tablet width,
   so a narrower monitor never squeezes the cashier's workflow. */
@media (max-width: 1180px) {
    .pos { grid-template-columns: 1fr; }
    .pos-right { position: static; }
    .pos-cart .table-wrap { max-height: none; }
    .profile-layout { grid-template-columns: 1fr; }
    .report-layout { grid-template-columns: 1fr; }
    .report-menu { position: static; }
}
@media (max-width: 900px) {
    .bill-grid { grid-template-columns: 1fr 1fr; }
    .picker-row { grid-template-columns: 1fr 90px; row-gap: .2rem; }
}
@media print {
    #topbar, #navbar, #toast-container, .modal-overlay { display: none !important; }
    #main-content { padding-top: 0; }
}

/* ── Operations module (stores, transfers, returns, audit) ──────────────
   Small shared pieces the newer screens lean on: a footer strip for a card
   that ends in actions, a read-only label/value grid for document detail,
   and a callout for the one line of context a screen needs to state. */
.card-footer {
    padding: .9rem 1.25rem;
    border-top: 1px solid var(--border);
    background: var(--bg-subtle, #fafafa);
    border-radius: 0 0 10px 10px;
}

.detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .75rem 1.5rem;
}
.detail-grid > div { font-size: .88rem; font-weight: 600; }
.detail-grid small {
    display: block; font-size: .68rem; font-weight: 600; letter-spacing: .04em;
    text-transform: uppercase; color: var(--text-muted); margin-bottom: .15rem;
}

.callout {
    padding: .7rem .9rem; border-radius: var(--r-md); font-size: .82rem;
    background: var(--theme-light); border-left: 3px solid var(--theme-color);
    color: var(--text-secondary);
}
.callout.warn { background: var(--warning-soft); border-left-color: var(--warning-ink); }

.text-danger { color: var(--danger-ink); }
.text-success { color: var(--success-ink); }

.badge-info { background:var(--info-soft); color:var(--info); }
.badge-warn { background:var(--warning-soft); color:var(--warning-ink); }

/* Audit feed — a chronological list reads better than a dense grid. */
.audit-row { display: grid; grid-template-columns: 132px 1fr; gap: .9rem; align-items: baseline; }
.audit-row .a-when { font-size: .74rem; color: var(--text-muted); white-space: nowrap; }
.audit-row .a-what { font-size: .86rem; }
.audit-row .a-what b { font-weight: 600; }
.audit-row .a-note { font-size: .76rem; color: var(--text-muted); margin-top: .1rem; }

/* Dashboard charts are hand-drawn inline SVG — there is no chart library here. */
.chart-card svg { display: block; width: 100%; height: auto; }

/* The two dashboard charts share one compact row. Placing them side by side in
   grid-2 halves each SVG's width and therefore its height, so they read compact
   without any height hack (a max-height on a width:100% SVG can collapse it to
   nothing in a flex item — do not reintroduce that). They stack on narrow
   screens via grid-2's own ≤640px breakpoint. */
.chart-row .chart-card { margin-bottom: 0; }
.chart-legend { display: flex; flex-wrap: wrap; gap: .35rem .9rem; margin-top: .6rem; font-size: .74rem; color: var(--text-secondary); }
.chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: .35rem; vertical-align: -1px; }

/* Segmented toggle — used to pick a purchase document type (Order vs Invoice).
   Two mutually exclusive modes read better as one control than as two buttons. */
.seg-toggle {
    display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-md);
    overflow: hidden; background: #fff;
}
.seg-toggle .seg {
    border: none; background: none; cursor: pointer;
    padding: .45rem .95rem; font-size: .8rem; font-weight: 600;
    color: var(--text-secondary);
}
.seg-toggle .seg + .seg { border-left: 1px solid var(--border); }
.seg-toggle .seg:hover { background: var(--theme-light); }
.seg-toggle .seg.active {
    background: var(--theme-color);
    color: var(--theme-contrast, #fff);
}

/* ═══════════════════════════════════════════════════════════════════════
   APP SHELL — the page itself never scrolls, only its content does

   Before this, the BODY was the scroller. The two bars were position:fixed so
   they LOOKED pinned, but the scrollbar belonged to the document, so a long
   product list scrolled the whole page underneath them — the chrome moved,
   the scrollbar ran the full height of the window, and every sticky panel had
   to subtract the height of the bars to find its place.

   Now the viewport is the frame and #main-content is the ONLY scroller. The
   markup is untouched; this is purely where the overflow lives.
   ═══════════════════════════════════════════════════════════════════════ */
html, body {
    height: 100%;
    overflow: hidden;            /* the page can never scroll — only its content can */
}

/* The one scroller. Pinned to the gap beneath the two fixed bars, so no amount
   of content can push, drag or hide the top bar or the menus. */
#main-content {
    position: fixed;
    top: calc(var(--topbar-h) + var(--navbar-h));
    left: 0;
    right: 0;
    bottom: 0;
    padding-top: 0;              /* the offset is `top` now, not padding */
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;/* reaching the end must not start scrolling anything else */
}

/* Sticky panels used to measure from the top of the PAGE, so each one had to
   subtract both bars to clear them. Inside the new scroller those bars are
   outside the container entirely, so the offset is just the page padding. */
.pos-right,
.report-menu { top: 1.5rem; }

/* A dialog owns the screen. While one is open the content behind it must not
   scroll away underneath — which is exactly what setting body overflow used to
   achieve while the body was the scroller. The lock moves to whatever actually
   scrolls now. (If :has() is unavailable the only cost is that the background
   can still be scrolled behind a dialog; nothing breaks.) */
body:has(.modal-overlay) #main-content { overflow: hidden; }

/* The sign-in screen renders without the shell, so it has no #main-content to
   scroll inside. It needs its own scroller, or on a short window the card is
   clipped with no way to reach the Sign In button.

   Two traps here, both hit while testing this:
     • `height: 100%` is IGNORED — it resolves against #app, which has no height
       of its own, so the wrap just grew past the clipped body. It has to be a
       viewport unit.
     • `align-items: center` centres the card, but once the card is TALLER than
       the window it overflows equally in both directions and the top half
       becomes unreachable — a scroller cannot scroll above its own start.
       `margin: auto` on the child centres it while leaving both ends reachable. */
.login-wrap {
    height: 100vh;
    overflow-y: auto;
    align-items: flex-start;
    /* The split-screen sign-in floats an elevated card on a soft neutral field,
       not the flat accent fill the base app.css gives it. */
    background: var(--body-bg);
    padding: 1.5rem;
}
.login-card { margin: auto; }

/* ── Topbar brand: real logo artwork ──────────────────────────────────────
   Swaps the placeholder "M" tile + text lockup for the M+ mark and the
   MartPLUS wordmark. app.css stays untouched; these classes live only here. */
.brand-mark { width: 36px; height: 36px; object-fit: contain; display: block; flex-shrink: 0; }
.brand-wordmark { height: 24px; width: auto; object-fit: contain; display: block; }

/* ── Split-screen sign-in ─────────────────────────────────────────────────
   Left: the white form panel. Right: a brand welcome panel washed cyan→purple
   in the two MartPlus logo colours. The login screen sits outside the app shell
   and is a deliberate, self-contained departure from the "flat, no shadow,
   accent-is-rare" chrome rules — those govern the working UI, not the splash. */
.login-split {
    margin: auto;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    width: 100%;
    max-width: 940px;
    background: var(--card-bg);
    border-radius: var(--r-md);
    overflow: hidden;
    box-shadow: 0 24px 70px rgba(54, 1, 133, 0.18);
}

/* Left — the form */
.login-form-panel {
    padding: 3rem 3rem 2.5rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.login-logo {
    height: 46px;
    width: auto;
    object-fit: contain;
    object-position: left center;
    margin-bottom: 2rem;
    align-self: flex-start;
}
.login-form { margin-top: .25rem; }
.login-form .form-control { height: 44px; }
.login-remember {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .82rem;
    color: var(--text-secondary);
    margin: .25rem 0 1.5rem;
    cursor: pointer;
    user-select: none;
}
.login-remember input { width: 16px; height: 16px; accent-color: var(--theme-color); }
.login-submit {
    width: 100%;
    justify-content: center;
    height: 46px;
    font-size: 14px;
    letter-spacing: .04em;
    text-transform: uppercase;
    border-radius: var(--r-pill);
}
.login-help {
    margin-top: 1.5rem;
    font-size: .8rem;
    color: var(--text-muted);
    text-align: center;
}
.login-help a { color: var(--theme-ink); font-weight: 700; text-decoration: none; }
.login-help a:hover { text-decoration: underline; }

/* Right — the brand welcome panel */
.login-welcome-panel {
    position: relative;
    overflow: hidden;
    background: linear-gradient(140deg, #44D0EB 0%, #6A2AC9 55%, #360185 100%);
    color: #fff;
    display: flex;
    align-items: center;
    padding: 3rem;
    min-height: 460px;
}
/* The M+ mark, oversized and faint — the reference's watermark motif. */
.login-welcome-mark {
    position: absolute;
    right: -46px;
    bottom: -40px;
    width: 320px;
    height: auto;
    opacity: .16;
    pointer-events: none;
}
/* A soft dark scrim on the lower/left so the heading keeps its contrast over
   the bright cyan end of the wash. */
.login-welcome-panel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(120deg, rgba(54, 1, 133, 0) 40%, rgba(41, 1, 101, 0.35) 100%);
    pointer-events: none;
}
.login-welcome-body { position: relative; z-index: 1; }
.login-welcome-eyebrow {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .28em;
    text-transform: uppercase;
    opacity: .9;
    margin-bottom: .6rem;
}
.login-welcome-title {
    font-size: 2.4rem;
    font-weight: 800;
    line-height: 1.1;
    margin: 0 0 1rem;
    color: #fff;
}
.login-welcome-title::after {
    content: "";
    display: block;
    width: 54px;
    height: 3px;
    background: rgba(255, 255, 255, 0.85);
    border-radius: 2px;
    margin-top: 1rem;
}
.login-welcome-sub { font-size: .95rem; opacity: .92; margin: 0; }

/* Stack on narrow screens: the welcome panel becomes a slim brand banner on top
   so the whole form stays reachable on a phone. */
@media (max-width: 760px) {
    .login-split { grid-template-columns: 1fr; max-width: 440px; }
    .login-welcome-panel { order: -1; min-height: 0; padding: 2rem; }
    .login-welcome-mark { width: 180px; right: -30px; bottom: -30px; }
    .login-welcome-title { font-size: 1.9rem; }
    .login-form-panel { padding: 2.25rem 1.75rem; }
}

@media print {
    /* Printing has to lay out the whole document. A fixed, clipped scroller
       would put exactly one screenful on the paper and drop the rest. */
    html, body { height: auto; overflow: visible; }
    #main-content {
        position: static;
        height: auto;
        overflow: visible;
        padding-top: 0;
    }
    .pos-right, .report-menu { position: static; }
}

/* A sticky panel taller than the window can never stick — it just scrolls away
   with everything else, which is what the Reports menu (26 entries, ~1565px)
   was doing. Bound it to the visible area and let it scroll inside itself, so
   the menu stays put and stays usable while you read the report beside it.
   Same principle as the shell above: the scrollbar belongs to the child. */
.report-menu {
    max-height: calc(100vh - var(--topbar-h) - var(--navbar-h) - 3rem);
    overflow-y: auto;
}

@media print {
    /* On paper it is a list, not a panel. */
    .report-menu { max-height: none; overflow: visible; }
}

/* ═══════════════════════════════════════════════════════════════════════
   TAX
   ═══════════════════════════════════════════════════════════════════════ */

/* Splits a long form into labelled sections. The product form grew past the point
   where an unbroken column of fields could be scanned. */
.form-section-title {
    font-size: .8125rem; font-weight: 700; color: var(--text-primary);
    padding-bottom: .4rem; margin: 1.25rem 0 .9rem;
    border-bottom: 1px solid var(--border);
}

/* The read-only "this is what the profile will charge" strip on the product form.
   Read-only on purpose: the rates belong to the profile, not to the product. */
.tax-preview {
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm); padding: .6rem .75rem; margin-bottom: 1rem;
    font-size: .8125rem;
}
.tax-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.tax-chip {
    background: #fff; border: 1px solid var(--border); border-radius: var(--r-sm);
    padding: 3px 8px; font-size: .75rem; color: var(--text-secondary);
}
.tax-chip strong { color: var(--theme-ink); }
.tax-flags { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .5rem; }
.tax-flags:empty { display: none; }

/* The till's tax block. Sits between the discounts and the grand total, in the same
   order the arithmetic runs, so the panel reads top-to-bottom as the calculation:
   subtotal -> discounts -> taxable -> each head -> TOTAL. */
.summary-tax {
    border-top: 1px dashed var(--border);
    margin-top: .5rem; padding-top: .5rem;
}
.summary-tax .summary-line { font-size: .78rem; }
.summary-tax .total-tax {
    font-weight: 700; color: var(--text-primary);
    border-top: 1px solid var(--border); margin-top: .3rem; padding-top: .3rem;
}
