/* Scrapy-AI — web frontend stylesheet.
   Design language mirrors the desktop's QSS: navy primary (#2c5d80),
   muted blue-grey background, card surfaces, generous padding for
   operator-grade readability. */

/* Palette and metrics mirror Windows_ver:
   - AppConstants.app_stylesheet (_invoice_shared.py)
   - TopBar (pages/main.py:45)
   - SecondaryBar (pages/_secondary_bar.py:73)
   - QGroupBox/PhotoBox styling inside RightPanel */
:root {
  --bg:           #f4f6f9;
  --card:         #ffffff;
  --primary:      #2c5d80;
  --primary-dk:   #1a3c54;
  --primary-light:#e1ecf4;
  --gold:         #f1c40f;
  --save:         #f39c12;
  --save-dk:      #d68910;
  --accent:       #00a65a;
  --accent-dk:    #008c4d;
  --warning:      #f39c12;
  --danger:       #dd4b39;
  --danger-dk:    #c0392b;
  --muted-bg:     #e8edf2;
  --text:         #2c3e50;
  --muted:        #7f8c8d;
  --muted-dk:     #444;
  --border:       #d8d8d8;
  --table-head:   #e0e7ed;
  --row-alt:      #f4f6f9;
  --topbar-h:     52px;
  --secbar-h:     42px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  line-height: 1.4;
  height: 100%;
  overflow: hidden;     /* outer never scrolls; inner panels do */
}

#app-root { height: 100%; }

/* Custom scrollbars (WebKit/Blink). Match Qt's QScrollBar styling. */
::-webkit-scrollbar         { width: 12px; height: 12px; }
::-webkit-scrollbar-track   { background: var(--bg); }
::-webkit-scrollbar-thumb   { background: var(--border); border-radius: 4px;
                              min-height: 24px; }
::-webkit-scrollbar-thumb:hover { background: var(--primary); }
::-webkit-scrollbar-corner  { background: var(--bg); }
* { scrollbar-width: thin; scrollbar-color: var(--border) var(--bg); }

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

/* ── Top bar ──────────────────────────────────────────────────── */

.topbar {
  background: linear-gradient(180deg, var(--primary) 0%, var(--primary-dk) 100%);
  color: #fff;
  height: var(--topbar-h);
  display: flex;
  align-items: stretch;
  padding: 0 12px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.18);
  border-bottom: 2px solid var(--save);
  flex: 0 0 auto;
  font-size: 12px;
}
.topbar .brand {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  padding: 0 12px 0 4px;
  flex: 0 0 auto;
}
.topbar .brand .brand-banner {
  height: 20px;
  width: auto;
  display: block;
  flex: 0 0 auto;
}
.topbar .brand .sub {
  font-size: 9px;
  opacity: 0.7;
  font-weight: 400;
  margin-top: 2px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  font-style: italic;
}
.topbar .vsep {
  width: 1px;
  background: rgba(255,255,255,0.2);
  margin: 8px 4px;
}
.topbar .nav {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-width: 0;
  /* Must NOT clip overflow — the .dropdown popover renders absolute
     below the topbar and gets cut off if .nav has overflow:hidden.
     With the consolidated Manage tab the nav stays narrow enough to
     fit on a typical 1280+ viewport without horizontal scroll anyway. */
  overflow: visible;
}
.topbar .section,
.topbar .manage-slot {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 0 2px;
  flex: 0 0 auto;
}
.topbar .section + .section {
  border-left: 1px solid rgba(255,255,255,0.18);
  margin-left: 4px;
  padding-left: 8px;
}
.topbar .item {
  position: relative;
  color: rgba(255,255,255,0.92);
  background: transparent;
  border: none;
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 3px;
  border-bottom: 3px solid transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  white-space: nowrap;
  flex: 0 0 auto;
}
.topbar .item:hover { background: rgba(255,255,255,0.10); color: #fff; }
.topbar .item.active {
  border-bottom-color: var(--save);
  color: #fff;
  background: rgba(0,0,0,0.15);
}
.topbar .right {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-left: 6px;
  border-left: 1px solid rgba(255,255,255,0.18);
  margin-left: 6px;
  flex: 0 0 auto;
}
.topbar .right .me {
  font-size: 11px;
  color: rgba(255,255,255,0.85);
  padding: 0 4px;
  white-space: nowrap;
}
.topbar .right button {
  font-size: 11px;
  padding: 4px 8px;
}

/* Hover-dropdown nav items.
   - .has-dropdown: the parent (clickable), shows a caret on the right
   - .dropdown:     the popover, hidden by default; appears on hover
   - Click on parent → navigates to its href (default page)
   - Click on a dropdown item → navigates to that page */
.topbar .has-dropdown { padding-right: 18px; }
.topbar .has-dropdown::after {
  content: "▾";
  position: absolute;
  right: 5px;
  top: 50%;
  transform: translateY(-40%);
  font-size: 8px;
  opacity: 0.7;
}
.topbar .dropdown {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  background: #fff;
  color: var(--text);
  min-width: 200px;
  border-radius: 0 0 6px 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.18);
  border: 1px solid var(--border);
  border-top: none;
  z-index: 110;
  flex-direction: column;
  padding: 4px;
}
.topbar .has-dropdown:hover .dropdown,
.topbar .dropdown:hover { display: flex; }
.topbar .dropdown a {
  color: var(--text);
  text-decoration: none;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 4px;
  border-bottom: none;
  white-space: nowrap;
}
.topbar .dropdown a:hover {
  background: var(--primary-light);
  color: var(--primary);
}

/* "⋯ More" overflow trigger — folds nav items that don't fit on
   narrow viewports (priority+ pattern; see applyNavOverflow in
   main.js). Anchor the dropdown to the right of its trigger so it
   doesn't spill off the viewport edge. Highlight the trigger in the
   active palette when an overflowed item matches the current route. */
.topbar .nav-more-section { margin-left: auto; }
.topbar .nav-more-section .nav-more.active {
  border-bottom-color: var(--save);
  color: #fff;
  background: rgba(0,0,0,0.15);
}
.topbar .nav-more-section .nav-more-dropdown {
  left: auto;
  right: 0;
  border-radius: 6px 0 6px 6px;
}
.topbar .nav-more-section .nav-more-dropdown a.active {
  color: var(--primary);
  background: var(--primary-light);
}

/* ── Secondary bar ───────────────────────────────────────────── */

.secondary-bar {
  background: var(--primary-dk);
  color: #fff;
  height: var(--secbar-h);
  display: flex;
  align-items: stretch;
  padding: 0 18px;
  flex: 0 0 auto;
}
.secondary-bar .title {
  display: flex;
  align-items: center;
  font-size: 16px;
  font-weight: 900;
  letter-spacing: 1.5px;
  color: var(--gold);
  padding: 0 14px 0 0;
  margin-right: 0;
  text-transform: uppercase;
  border-right: 1px solid rgba(255,255,255,0.18);
}
.secondary-bar .tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  /* Reset the generic `.tabs` rule (border-bottom + margin-bottom)
     which paints a light-gray underline and 16px gap below the tab
     strip. Inside the secondary bar we want the active tab's gold
     border to be the only line; the bar itself owns the bottom edge. */
  border-bottom: none;
  margin-bottom: 0;
}
/* Use .tabs in the selector chain so the generic `.tabs .tab.active`
   rule lower in the file (primary-color text + transparent bg) does
   NOT win for the secondary bar — equal class count would let it
   override. */
.secondary-bar .tabs .tab {
  color: rgba(255,255,255,0.75);
  text-decoration: none;
  padding: 0 14px;
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  display: flex;
  align-items: center;
  background: transparent;
  border: none;
  box-shadow: inset 0 0 0 0 transparent;
  transition: color 0.15s ease, box-shadow 0.15s ease;
}
/* Active marker uses inset box-shadow instead of border-bottom so it
   paints inside the tab and can't be clipped by the bar's flex height
   or hidden behind the page-body when the bar sits flush. */
.secondary-bar .tabs .tab.active {
  color: var(--gold);
  background: transparent;
  box-shadow: inset 0 -4px 0 0 var(--gold);
}
.secondary-bar .tabs .tab:hover,
.secondary-bar .tabs .tab:focus {
  text-decoration: none;
  color: var(--gold);
  box-shadow: inset 0 -4px 0 0 rgba(241, 196, 15, 0.4);
}
.secondary-bar .tabs .tab.active:hover,
.secondary-bar .tabs .tab.active:focus {
  /* Hover on the already-active tab keeps the solid gold marker. */
  box-shadow: inset 0 -4px 0 0 var(--gold);
}
.secondary-bar .back-link {
  display: flex;
  align-items: center;
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 0 14px 0 0;
  margin-right: 14px;
  border-right: 1px solid rgba(255, 255, 255, 0.18);
  transition: color 0.12s;
}
.secondary-bar .back-link:hover { color: var(--gold); }

/* Sync chip — right-pinned connection-state indicator. State class
   (.sync-chip--online/syncing/offline/degraded) drives dot colour. */
.secondary-bar .sync-chip {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-left: auto;
  padding: 0 16px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.65);
  border-left: 1px solid rgba(255, 255, 255, 0.14);
  white-space: nowrap;
}
.secondary-bar .sync-chip-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 0 3px rgba(74, 222, 128, 0.18);
  transition: background 0.15s, box-shadow 0.15s;
}
.secondary-bar .sync-chip--offline .sync-chip-dot {
  background: #ef4444;
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18);
}
.secondary-bar .sync-chip--syncing .sync-chip-dot,
.secondary-bar .sync-chip--degraded .sync-chip-dot {
  background: #f1c40f;
  box-shadow: 0 0 0 3px rgba(241, 196, 15, 0.18);
}
@media (max-width: 600px) {
  /* Phones — drop the label, keep the dot. Saves horizontal space
     so the tab strip retains its full scroll budget. */
  .secondary-bar .sync-chip { padding: 0 10px; border-left: none; }
  .secondary-bar .sync-chip-label { display: none; }
}

/* ── Settings landing tile grid ───────────────────────────────── */
.settings-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  max-width: 1280px;
  margin: 0 auto;
}
.settings-tile {
  display: block;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 18px 16px;
  text-decoration: none;
  color: inherit;
  box-shadow: 0 1px 0 rgba(15, 25, 50, 0.03);
  transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
}
.settings-tile:hover {
  border-color: var(--primary);
  box-shadow: 0 8px 18px -8px rgba(44, 93, 128, 0.3);
  transform: translateY(-1px);
}
.settings-tile .tile-ic {
  width: 38px;
  height: 38px;
  border-radius: 9px;
  background: var(--primary-light);
  color: var(--primary);
  display: grid;
  place-items: center;
  font-size: 18px;
  font-weight: 800;
  margin-bottom: 10px;
}
.settings-tile .tile-name {
  font-size: 14px;
  font-weight: 800;
  color: var(--primary-dk);
  margin: 0 0 2px;
}
.settings-tile .tile-desc {
  font-size: 12px;
  color: var(--muted, #6b7280);
  line-height: 1.4;
  margin: 0;
}
@media (max-width: 600px) {
  .settings-tile-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .settings-tile { padding: 14px; }
}

/* ── Layout shell ─────────────────────────────────────────────── */

#app-root > div {
  /* The router host: topbar + main, fills viewport, doesn't scroll. */
  display: flex;
  flex-direction: column;
  height: 100%;
}
main#page-host {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* The router renders inside main: secondary-bar + page-body.
   The render's outer div should also be a flex column. */
main#page-host > div {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.page-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 18px 24px;
  width: 100%;
}
/* Pages that own the entire viewport (Buy/Sell with 3-col splits)
   add this modifier: no padding, no inner scroll — children fill. */
.page-body.full {
  padding: 0;
  overflow: hidden;
}
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  gap: 16px;
  flex-wrap: wrap;
}
.page-title {
  font-size: 20px;
  font-weight: 700;
  color: var(--primary);
  margin: 0;
}

/* ── Card surface ─────────────────────────────────────────────── */

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 18px 22px;
  margin-bottom: 16px;
}
.card .card-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--primary);
  margin: 0 0 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* ── Forms ────────────────────────────────────────────────────── */

label { font-weight: 600; font-size: 13px; color: var(--muted-dk); }

input, textarea, select, button {
  font-family: inherit;
  font-size: 14px;
}

input[type="text"], input[type="number"], input[type="password"],
input[type="email"], input[type="date"], textarea, select {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  width: 100%;
  max-width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary-light);
}

.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row > * { margin: 0; }
.row label { white-space: nowrap; }

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.form-grid .field { display: flex; flex-direction: column; gap: 4px; }
.form-grid .field.span-2 { grid-column: span 2; }

/* ── Buttons ──────────────────────────────────────────────────── */

button, .btn {
  font-family: inherit;
  background: var(--primary);
  color: #fff;
  /* Transparent border so variants that DO have a visible border
     (.secondary) are the same height as those that don't. */
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 8px 16px;
  font-weight: 700;
  font-size: 13px;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  white-space: nowrap;
}
button:hover, .btn:hover { background: var(--primary-dk); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
button.secondary, .btn.secondary {
  background: var(--muted-bg);
  color: var(--text);
  border-color: var(--border);
}
button.secondary:hover, .btn.secondary:hover { background: #d6dde6; }
/* Use --accent-dk (darker green) for default state — bumps contrast
   ratio with white text from ~3.4:1 (borderline) to ~4.6:1 (WCAG AA). */
button.success, .btn.success { background: var(--accent-dk); color: #fff; }
button.success:hover, .btn.success:hover { background: #00703d; }
button.warning, .btn.warning { background: var(--warning); color: #fff; }
button.warning:hover, .btn.warning:hover { background: #d68910; }
button.danger, .btn.danger { background: var(--danger); color: #fff; }
button.danger:hover, .btn.danger:hover { background: #c0392b; }
button.small, .btn.small { padding: 4px 10px; font-size: 12px; }

/* ── Tables ───────────────────────────────────────────────────── */

table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
}
table th, table td {
  text-align: left;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
table th {
  background: var(--table-head);
  font-weight: 700;
  color: var(--text);
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
table tbody tr:nth-child(even) { background: var(--row-alt); }
table tbody tr:hover { background: var(--primary-light); }
table td.num, table th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Price tags shown in the Products list — one chip per department. */
.price-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.price-tag {
  display: inline-block;
  background: var(--row-alt);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 2px 8px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: nowrap;
}

/* ── Pills / status chips ─────────────────────────────────────── */

.pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 12px;
  letter-spacing: 0.3px;
}
.pill.active   { background: #fff3cd; color: #7c5e00; }
.pill.sent     { background: #d1ecf1; color: #0c5460; }
.pill.finished { background: #d4edda; color: #155724; }
.pill.void     { background: #f8d7da; color: #721c24; }

/* ── Totals strip ─────────────────────────────────────────────── */

.totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}
.totals .pill-card {
  background: #f0f3f7;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 14px 18px;
}
.totals .pill-card .label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
}
.totals .pill-card .value {
  font-size: 22px;
  font-weight: 800;
  color: var(--primary);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}

/* ── Login screen ─────────────────────────────────────────────── */

.login-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dk) 100%);
}
.login-card {
  background: #fff;
  border-radius: 8px;
  padding: 36px 40px;
  width: 360px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.2);
}
.login-card h1 {
  margin: 0 0 6px;
  font-size: 24px;
  color: var(--primary);
}
.login-card .login-logo {
  display: block;
  width: 100%;
  max-width: 320px;
  height: auto;
  margin: 0 auto 12px;
}
.login-card .tagline {
  color: var(--muted);
  font-size: 13px;
  margin-bottom: 24px;
}
.login-card .field { margin-bottom: 14px; display: flex; flex-direction: column; gap: 4px; }
.login-card button { width: 100%; padding: 10px; font-size: 15px; }

/* ── Status messages ──────────────────────────────────────────── */

.error   { color: var(--danger);  font-size: 13px; margin-top: 8px; }
.success { color: var(--accent);  font-size: 13px; margin-top: 8px; }
.muted   { color: var(--muted);   font-size: 12px; }
.notice  { background: var(--primary-light); border-left: 3px solid var(--primary);
           padding: 10px 14px; border-radius: 4px; margin: 12px 0; font-size: 13px; }

.hidden { display: none !important; }

/* ── Tabs ─────────────────────────────────────────────────────── */

.tabs {
  display: flex;
  gap: 2px;
  border-bottom: 2px solid var(--border);
  margin-bottom: 16px;
}
.tabs .tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  border-radius: 0;
}
.tabs .tab:hover { background: var(--muted-bg); color: var(--text); }
.tabs .tab.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
  background: transparent;
}

/* ── Reports / Summaries ──────────────────────────────────────── */

.report-output { margin: 0 18px 24px; }

.report-letterhead {
  display: grid;
  grid-template-columns: 220px 1fr 180px;
  gap: 16px;
  padding: 14px 18px;
  margin: 0 0 0 0;
  border-bottom: 2px solid var(--primary);
  background: #fafcff;
  border-radius: 8px 8px 0 0;
  align-items: center;
}
.report-letterhead .lh-brand {
  font-size: 18px; font-weight: 700; color: var(--primary);
}
.report-letterhead .lh-title {
  text-align: center; font-size: 16px; font-weight: 700;
  color: var(--text);
}
.report-letterhead .lh-filters {
  text-align: center; font-size: 11px;
}
.report-letterhead .lh-right { text-align: right; font-size: 11px; }

.report-table { width: 100%; border-collapse: collapse; }
.report-table th, .report-table td {
  padding: 6px 10px; border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.report-table th {
  background: #2c5d80; color: #fff; text-align: left; font-weight: 600;
}
.report-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.report-table th.num { text-align: right; }
.report-table tr.detail-banner td {
  background: #2c5d80; color: #fff; font-weight: 700;
  padding: 8px 10px; font-size: 13px;
}
.report-table tr.detail-total td {
  background: #eaf3fa; color: #1a3c54; font-weight: 700;
}

.report-summary { margin-top: 12px; }
.report-summary .summary-kv { width: 100%; }
.report-summary .summary-kv td.k {
  width: 200px; color: var(--muted); padding: 4px 8px;
}
.report-summary .summary-kv td.v {
  font-weight: 600; padding: 4px 8px;
}

.report-footer {
  text-align: center; padding: 10px; font-size: 11px;
  border-top: 1px solid var(--border); margin-top: 12px;
}

.req-star { font-weight: 700; margin-left: 2px; }

/* Daily Accounts — Daily Entry 2-column layout */
.da-grid {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 8px;
  height: 100%;
  padding: 0;
}
.da-main, .da-right {
  min-width: 0; min-height: 0; overflow-y: auto;
}
.da-main .da-stack { padding: 12px; display: flex; flex-direction: column; gap: 12px; }
.da-right { padding: 12px; display: flex; flex-direction: column; gap: 12px; }
.da-right .summary-kv td.k { width: 60%; }
.da-right .summary-kv td.v { text-align: right; font-variant-numeric: tabular-nums; }
.da-section-head:hover { background: var(--muted-bg, #f4f7fa); }
input.locked-imported, select.locked-imported {
  background: #f4f7fa; color: #5b6877;
  cursor: not-allowed;
}
.import-group-head:hover { background: #e8eef5 !important; }
.import-detail-row td { background: #fafcff; font-size: 12.5px; }

/* AI Assistant drawer */
aside.ai-drawer {
  position: fixed; right: 0; top: 0; bottom: 0;
  width: min(520px, 95vw); background: #fff;
  box-shadow: -4px 0 16px rgba(0,0,0,0.18);
  transform: translateX(0); transition: transform 0.18s ease;
  z-index: 900; display: flex; flex-direction: column;
}
.ai-header {
  padding: 10px 12px; background: #2c5d80; color: #fff;
  border-bottom: 1px solid #d6dde6;
  display: flex; align-items: center; gap: 8px;
}
.ai-header .ai-title { font-size: 14px; }
.ai-header .ai-tabs { display: flex; gap: 4px; flex: 1; justify-content: center; }
.ai-header .ai-tab {
  background: transparent; color: #cce0ec; border: none;
  padding: 4px 10px; border-radius: 4px; cursor: pointer;
  font-size: 12px;
}
.ai-header .ai-tab:hover { background: rgba(255,255,255,0.08); }
.ai-header .ai-tab.active { background: rgba(255,255,255,0.15); color: #fff; }
.ai-body { flex: 1; display: flex; flex-direction: column;
  min-height: 0; overflow: hidden; }
.ai-log {
  flex: 1; overflow-y: auto; padding: 12px 16px;
  background: #f4f7fa;
}
.ai-msg {
  margin: 6px 0; padding: 10px 14px; border-radius: 8px;
  max-width: 92%; font-size: 13.5px; line-height: 1.5;
}
.ai-msg-user {
  background: #2c5d80; color: #fff;
  margin-left: auto; border-bottom-right-radius: 2px;
  display: block;
}
.ai-msg-assistant {
  background: #fff; color: #1a1a1a;
  border: 1px solid #d6dde6;
  border-bottom-left-radius: 2px;
}
.ai-msg-assistant pre {
  background: #f4f7fa; padding: 6px 8px;
  border-radius: 4px; font-size: 12px; overflow-x: auto;
}
.ai-msg-assistant code {
  background: #f4f7fa; padding: 1px 4px;
  border-radius: 3px; font-size: 12px;
}
.ai-inline-link {
  color: #2c5d80; font-weight: 600; text-decoration: underline;
}
.ai-latency {
  font-size: 10.5px; margin-top: 4px; text-align: right;
  color: #5b6877;
}
.ai-status {
  padding: 0 16px 6px; font-size: 11px; color: #5b6877;
}
.ai-composer {
  border-top: 1px solid #d6dde6; background: #fff;
  padding: 8px 12px; display: flex; flex-direction: column; gap: 6px;
}
.ai-composer-row { display: flex; gap: 6px; }
.ai-composer-input {
  resize: vertical; flex: 1; padding: 8px;
  border-radius: 4px; border: 1px solid #d6dde6;
  font-family: inherit;
}
.ai-attach-strip {
  display: flex; gap: 6px; flex-wrap: wrap;
}
.ai-attach-thumb {
  position: relative; width: 60px; height: 60px;
  border: 1px solid #d6dde6; border-radius: 4px; overflow: hidden;
}
.ai-attach-thumb img {
  width: 100%; height: 100%; object-fit: cover;
}
.ai-attach-thumb button {
  position: absolute; top: 2px; right: 2px;
  font-size: 10px; padding: 0 4px;
}
.ai-section-head {
  padding: 12px 16px; border-bottom: 1px solid #d6dde6;
  display: flex; flex-direction: column; gap: 2px; background: #fafcff;
}
.ai-list {
  flex: 1; overflow-y: auto; padding: 8px 12px;
}
.ai-alert-card, .ai-history-card {
  background: #fff; border: 1px solid #d6dde6; border-radius: 6px;
  padding: 8px 10px; margin-bottom: 6px; font-size: 13px;
}
.ai-history-card:hover { background: #f4f7fa; }

/* User-name dropdown in the topbar right cluster */
.topbar .user-menu {
  font-weight: 600;
  cursor: pointer;
}
/* User dropdown lives at the far right; anchoring left:0 makes it
   spill off-screen and clip. Anchor right instead so it fans in. */
.topbar .user-menu .dropdown {
  left: auto;
  right: 0;
  min-width: 220px;
  border-radius: 6px 0 6px 6px;
}
.topbar .user-menu .dropdown a:last-child {
  color: #c0392b;     /* Sign out — destructive */
}

/* Session-expiry warning banner */
.session-warn-banner {
  position: fixed; bottom: 16px; right: 16px; z-index: 1500;
  background: #fff8dc; border: 1px solid #f39c12;
  border-radius: 6px; padding: 10px 14px;
  display: flex; align-items: center; gap: 10px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.18);
  font-size: 13px;
}

/* Audit log diff panel */
.audit-json {
  background: #f4f7fa; padding: 8px; border-radius: 4px;
  font-size: 11px; max-height: 360px; overflow: auto;
  white-space: pre-wrap; word-break: break-all;
}

/* hold_until chip — appears on Buy line items under a LawAndReg hold */
.hold-chip {
  display: inline-block; margin-left: 6px;
  padding: 1px 6px; font-size: 10.5px; font-weight: 600;
  background: #fde2e1; color: #8b3a39;
  border: 1px solid #f5b7b1; border-radius: 10px;
}
.held-cell {
  color: #8b3a39; font-weight: 600;
  background: rgba(253, 226, 225, 0.4);
}

/* Settings → Employees: list pane on the left, detail on the right.
   Each pane scrolls independently to mirror the buy/sell layout. */
.emp-page {
  display: grid;
  grid-template-columns: minmax(280px, 360px) 1fr;
  gap: 16px;
  align-items: start;
  height: calc(100vh - 160px);
}
.emp-list, .emp-detail {
  height: 100%; overflow-y: auto;
}
.emp-list-bar {
  display: flex; gap: 8px; align-items: center;
  margin-bottom: 8px;
}
.emp-search { flex: 1; }
.emp-list-card { padding: 0; }
.emp-table { width: 100%; }
.emp-table th { text-align: left; }
.emp-table tbody tr { cursor: pointer; }
.emp-table tbody tr:hover { background: #f4f7fa; }
.emp-table tbody tr.selected { background: #e3eef9; }
.emp-empty {
  display: flex; align-items: center; justify-content: center;
  min-height: 200px; text-align: center;
}
.emp-detail-card { padding: 16px 20px; }
.emp-section {
  border-top: 1px solid #e5e9ee; padding-top: 14px; margin-top: 14px;
}
.emp-section:first-of-type {
  border-top: none; padding-top: 0; margin-top: 8px;
}
.emp-section h3 {
  margin: 0 0 8px; font-size: 14px;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: #5d6470;
}
.emp-actions {
  margin-top: 18px; padding-top: 14px;
  border-top: 1px solid #e5e9ee;
  gap: 10px;
}

/* Permission tree + dept grid */
.perm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 4px 16px;
}
.perm-box {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; user-select: none;
}
.perm-tree {
  border: 1px solid #e5e9ee; border-radius: 6px;
  padding: 8px;
  background: #fafbfc;
}
.perm-row {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 6px; border-radius: 4px;
}
.perm-row:hover { background: #eef2f6; }
.perm-label  { user-select: none; }
.perm-parent { font-weight: 600; }

/* Toggle switch — used for permission rows. */
.toggle {
  position: relative; display: inline-block;
  width: 38px; height: 20px; flex-shrink: 0;
}
.toggle input {
  opacity: 0; width: 0; height: 0;
}
.toggle .slider {
  position: absolute; cursor: pointer;
  top: 0; left: 0; right: 0; bottom: 0;
  background-color: #c8cdd4;
  transition: background-color .15s ease;
  border-radius: 20px;
}
.toggle .slider::before {
  content: ""; position: absolute;
  height: 14px; width: 14px;
  left: 3px; bottom: 3px;
  background: white; border-radius: 50%;
  transition: transform .15s ease;
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.toggle input:checked + .slider {
  background-color: #2c5d80;
}
.toggle input:checked + .slider::before {
  transform: translateX(18px);
}
.toggle input:disabled + .slider {
  opacity: 0.5; cursor: not-allowed;
}

/* Ticket Search — CBIR promoted-match highlighting */
.ticket-row-promoted td {
  background: #fff8dc !important;
  border-left: 3px solid #f39c12;
}
.score-chip {
  display: inline-block; padding: 1px 6px; margin-left: 6px;
  font-size: 11px; font-weight: 700; border-radius: 10px;
  background: #2c5d80; color: #fff;
  vertical-align: middle;
}
.score-chip-weak { background: #95a5a6; }

/* AI voice-mode buttons */
.ai-composer-row button.toggled-on {
  background: var(--primary, #2c5d80) !important;
  color: #fff !important;
  border-color: var(--primary, #2c5d80);
}
.ai-composer-row button.recording {
  background: #c0392b !important;
  color: #fff !important;
  animation: ai-pulse 1.0s ease-in-out infinite;
}
@keyframes ai-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(192, 57, 43, 0.6); }
  50%      { box-shadow: 0 0 0 6px rgba(192, 57, 43, 0); }
}

/* Money Count grid — dense 10-row layout in the right panel. */
.money-count-table { width: 100%; font-size: 12px; }
.money-count-table td { padding: 1px 4px; line-height: 1.2; }
.money-count-table td:first-child { width: 50px; color: var(--muted); }
.money-count-table td.num {
  text-align: right; font-variant-numeric: tabular-nums;
}
.money-count-table input[type="number"] {
  padding: 1px 4px; font-size: 12px; height: 22px;
  text-align: right;
}

/* Inventory — Active view 2-column layout (boxes | Locations panel) */
.active-inv-grid {
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: 8px;
  height: 100%;
  padding: 8px;
}
.active-inv-main, .active-inv-right {
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
}
.active-inv-right .compact-table { width: 100%; font-size: 13px; }
.active-inv-right .compact-table th,
.active-inv-right .compact-table td { padding: 4px 6px; }

/* Inventory — age-based row coloring + scan input */
td.age-green  { color: #1a7f3c; font-weight: 600; }
td.age-yellow { color: #b08800; font-weight: 600; }
td.age-red    { color: #c0392b; font-weight: 700; }
input.scan-input {
  border: 2px solid var(--accent);
  border-radius: 6px;
  padding: 6px 10px;
  font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
  font-size: 13px;
}

/* Searchable single-select. The list is teleported to <body> with
   position:fixed so it escapes overflow:hidden/auto scroll containers
   (items grids, dialogs). Coordinates are set in JS from the input's
   bounding rect on open + on every scroll/resize. */
.ss-wrap { display: inline-block; min-width: 200px; }
.ss-wrap .ss-input { width: 100%; }
.ss-list {
  z-index: 1100;   /* sit above dialog backdrops (z-index: 1000) */
  background: #fff; border: 1px solid var(--border);
  max-height: 240px; overflow-y: auto;
  box-shadow: 0 4px 12px rgba(0,0,0,0.18);
  border-radius: 4px;
}
.ss-item { padding: 6px 10px; cursor: pointer; font-size: 13px; }
.ss-item:hover,
.ss-item.active { background: var(--muted-bg); }

@media print {
  body.printing-report .topbar,
  body.printing-report .secondary-bar,
  body.printing-report .tabs,
  body.printing-report .page-header,
  body.printing-report .filter-row,
  body.printing-report .row > button,
  body.printing-report .field {
    display: none !important;
  }
  body.printing-report .card { box-shadow: none; border: none; }
  body.printing-report .report-output {
    margin: 0; padding: 0;
  }
  body.printing-report .report-letterhead {
    background: #fff;
  }
}

/* ── Dialog / modal ───────────────────────────────────────────── */

.dialog-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.dialog {
  background: #fff;
  border-radius: 8px;
  max-width: 720px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  padding: 24px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}
/* Manage popup — Products / Customers / Vehicles / Trailers open as
   a large dialog over whatever page the operator is currently on,
   instead of navigating away. .dialog-large overrides the form-shaped
   720 px max-width so the table-heavy pages have room. */
.dialog-large {
  max-width: 95vw;
  width: 95vw;
  max-height: 92vh;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.manage-dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.manage-dialog-head h2 { margin: 0; }
.manage-dialog-close {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  width: 32px; height: 32px;
  font-size: 16px;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  color: var(--muted);
}
.manage-dialog-close:hover { background: #fdecea; color: var(--danger); border-color: var(--danger); }
.manage-dialog-body {
  flex: 1;
  overflow-y: auto;
  padding: 0;
}

/* Inline 🔍 Browse button next to right-panel inputs on Buy / Sell —
   opens the matching Manage popup pre-filtered by the field value. */
.input-with-browse { display: flex; gap: 4px; align-items: center; }
.input-with-browse > input,
.input-with-browse > select { flex: 1; min-width: 0; }
.browse-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  width: 28px; height: 28px;
  font-size: 14px;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  flex-shrink: 0;
}
.browse-btn:hover {
  background: var(--primary-light);
  border-color: var(--primary);
}

/* Manage-page header — filter inputs on the left, action buttons on
   the right, all on one row that wraps gracefully on narrow widths. */
.manage-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px;
  padding: 12px 18px;
  flex-wrap: wrap;
}
.manage-filters {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  flex-wrap: wrap;
  flex: 1;
  min-width: 0;
}
.manage-filters .field { min-width: 0; }
/* Desktop cap on filter text inputs — keeps a row of four filters
   from stretching out of proportion. Phone widths override this to
   full-width below (the cap was previously an inline maxWidth which
   the mobile CSS couldn't beat). */
.filter-input { max-width: 140px; }
/* Mobile-only filter toggle button. Hidden on desktop — the manage
   pages show filters inline there. On phone widths the mobile
   @media block flips this to inline-block and starts the filter
   block collapsed (rendered by `manageFiltersToggle` in util.js). */
.manage-filters-toggle { display: none; }
.manage-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-shrink: 0;
}

/* Image lightbox — full-screen view of an authenticated image.
   Sits on top of .dialog-backdrop instead of inside .dialog so it
   isn't cropped by the form-shaped 720 px max-width. */
.image-lightbox-img {
  max-width: 95vw;
  max-height: 90vh;
  object-fit: contain;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
  cursor: default;
}

.dialog h2 { margin: 0 0 16px; color: var(--primary); }
.dialog .actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

/* ── Buy / Sell — 3-column QSplitter-style layout ─────────────── */

/* The grid fills the page-body (which itself fills the viewport
   under topbar + secondary-bar). Each column owns its own scrollbar.
   Proportions mirror Windows splitter.setSizes([280, 800, 420]). */
.buy-grid {
  display: grid;
  /* Custom properties drive the 1st and 5th columns; the splitters
     in slots 2 and 4 are 6px wide drag handles. Operator can drag
     the seams to resize; widths persist via localStorage. Default
     right is 260px — just enough for the customer block (name /
     company / contact) on three lines per invoice. */
  grid-template-columns:
    var(--buy-left-w, 220px) 6px 1fr 6px var(--buy-right-w, 260px);
  height: 100%;
  padding: 8px;
  background: var(--bg);
}
.buy-left, .buy-center, .buy-right {
  min-width: 0;
  min-height: 0;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
}
.buy-center {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 4px;       /* breathing room from inner scrollbar */
}

.buy-splitter {
  cursor: col-resize;
  background: transparent;
  border-left:  1px solid var(--border);
  border-right: 1px solid var(--border);
  user-select: none;
  position: relative;
  z-index: 5;
}
.buy-splitter:hover,
.buy-splitter.dragging {
  background: var(--primary);
  border-color: var(--primary);
}

@media (max-width: 1280px) {
  /* Tighter defaults for smaller laptops; user can still drag. */
  .buy-grid {
    grid-template-columns:
      var(--buy-left-w, 200px) 6px 1fr 6px var(--buy-right-w, 240px);
  }
}
@media (max-width: 1024px) {
  .buy-grid { grid-template-columns: 220px 1fr; }
  .buy-right {
    grid-column: 1 / -1;
    height: auto;
    max-height: 50vh;
  }
}


/* ── Mobile / tablet-portrait chrome (≤1023px) ──────────────────
   Instagram-style two-row top panel (brand + AI/Settings/User on top;
   secondary bar with page name + tabs immediately below). Bottom nav
   replaces the desktop horizontal nav. Desktop (≥1024px) stays
   exactly as it is — every rule here is gated on the @media block. */
@media (max-width: 1023px) {
  /* Row 1 — compact topbar. Keep brand left, AI + ⚙ + User right.
     Drop everything else (nav, manage, vsep, subtitle, current-
     company desktop label). */
  .topbar {
    height: 48px;
    padding: 0 10px;
    gap: 8px;
    align-items: center;
    border-bottom: none;
    box-shadow: 0 1px 0 rgba(0,0,0,0.18);
  }
  .topbar .brand { padding: 0 0 0 4px; flex: 0 0 auto; }
  .topbar .brand .brand-banner { height: 20px; }
  .topbar .brand .sub { display: none; }
  .topbar .vsep,
  .topbar .nav,
  .topbar .manage-slot,
  .topbar .current-company { display: none; }

  /* Right cluster — three compact buttons in this visual order:
     AI · Settings · User. JSX already emits them in that order.   */
  .topbar .right {
    margin-left: auto;
    padding-left: 0;
    border-left: none;
    gap: 8px;
  }
  /* AI button — rounded square, translucent. */
  .topbar .right > button {
    width: 34px;
    height: 34px;
    min-height: 34px;
    padding: 0;
    border-radius: 8px;
    background: rgba(255,255,255,0.12);
    border: 1px solid rgba(255,255,255,0.18);
    color: #fff;
    font-size: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Settings cog — same shape as the AI button. The desktop renders
     it as an `.item` anchor at `href="#/settings"`; here we restyle
     the same element. */
  .topbar .right > a[href="#/settings"] {
    width: 34px;
    height: 34px;
    min-height: 34px;
    padding: 0;
    border-radius: 8px;
    background: rgba(255,255,255,0.12);
    border: 1px solid rgba(255,255,255,0.18);
    color: #fff;
    font-size: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* User-menu — initials circle. The dropdown's items are unchanged
     (Change user info / Change theme / Switch company / Switch mode
     / Sign out); only the trigger is restyled. */
  .topbar .user-menu {
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--primary-dk);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .topbar .user-menu .um-label { display: none; }    /* mobile hides text */
  .topbar .user-menu .um-avatar { display: inline-flex; }
  /* Caret pseudo-element from the desktop `has-dropdown` rule looks
     wrong inside a circle button — drop it. */
  .topbar .user-menu::after { display: none; }
  /* User dropdown panel — anchor to the right edge of the avatar
     instead of stretching left-to-right beneath the topbar. */
  .topbar .user-menu .dropdown {
    right: 0;
    left: auto;
    top: 100%;
    min-width: 220px;
    max-width: 80vw;
  }

  /* Row 2 — secondary bar sits flush against Row 1. The component
     itself already renders title + tabs; we just tighten it to read
     as part of the same panel. */
  .secondary-bar {
    padding: 0 12px;
    border-bottom: 1px solid rgba(0,0,0,0.25);
  }
  .secondary-bar .title {
    font-size: 14px;
    padding: 0 12px 0 0;
    margin-right: 8px;
    letter-spacing: 1px;
  }
  .secondary-bar .tabs .tab {
    padding: 0 12px;
    font-size: 11px;
  }
  /* Allow the tab strip to scroll horizontally on phone if it
     doesn't fit — important for Inventory's 3-tab strip or any
     page that grows a 4th tab later. `overflow-y: hidden` is
     explicit so the CSS spec doesn't implicitly promote it to
     `auto` (which paints an unwanted vertical scrollbar in
     non-WebKit browsers). */
  .secondary-bar .tabs {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .secondary-bar .tabs::-webkit-scrollbar { display: none; }

  /* Desktop hover-dropdown becomes tap-toggle on touch devices. The
     main.js click handler toggles `.open` on the user-menu wrap;
     this rule reveals the dropdown when that class is set. */
  .has-dropdown.open .dropdown { display: flex; }

  /* Push page content clear of the fixed bottom nav (56px + iOS
     home-indicator safe-area). */
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }
}

/* ── Tap-to-open user menu on any touch device, regardless of
   viewport. Same as the @media block's rule but unconditional on
   `(hover: none)` so it covers iPad-with-mouse edge cases. */
@media (hover: none) and (pointer: coarse) {
  .has-dropdown .dropdown { display: none; }
  .has-dropdown.open .dropdown { display: flex; }
}

/* ── Bottom nav — mounted by main.js when mobile chrome is active.
   Default-hidden on desktop (`display:none`) so the element class
   stays available for the JS that renders it, but it never shows
   above 1024px. */
.bottom-nav { display: none; }
@media (max-width: 1023px) {
  .bottom-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(56px + env(safe-area-inset-bottom, 0px));
    background: #fff;
    border-top: 1px solid var(--border);
    z-index: 1000;
    justify-content: space-around;
    align-items: stretch;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-shadow: 0 -1px 4px rgba(0,0,0,0.06);
  }
  .bottom-nav .bn-tab {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    font-size: 11px;
    color: #8a96a3;
    text-decoration: none;
    position: relative;
  }
  .bottom-nav .bn-tab .bn-icon { font-size: 20px; line-height: 1; }
  .bottom-nav .bn-tab.active {
    color: var(--primary-dk);
    font-weight: 600;
    box-shadow: inset 0 3px 0 var(--gold);
  }

  /* Bottom sheet for the "More" overflow. Slides up above the
     bottom nav; tapping its backdrop closes it. */
  .bn-sheet-backdrop { z-index: 1090; }
  .bottom-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    background: #fff;
    border-top: 1px solid var(--border);
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
    z-index: 1100;
    max-height: 60vh;
    overflow-y: auto;
    padding: 6px 0;
    box-shadow: 0 -4px 14px rgba(0,0,0,0.18);
  }
  .bottom-sheet .bn-sheet-handle {
    width: 40px;
    height: 4px;
    margin: 6px auto 10px;
    background: #cbd1da;
    border-radius: 2px;
  }
  .bottom-sheet .bn-sheet-list {
    display: flex;
    flex-direction: column;
  }
  .bottom-sheet .bn-sheet-item {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    color: var(--primary-dk);
    text-decoration: none;
    font-size: 15px;
    border-top: 1px solid var(--border);
  }
  .bottom-sheet .bn-sheet-item:first-child { border-top: none; }
  .bottom-sheet .bn-sheet-item .bn-icon { font-size: 18px; }
}

/* Drawer/sheet backdrop — shared by the More sheet and any other
   modal-style overlay added later. */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 1080;
}


/* ── Side drawers (mobile ≤1023px) ─────────────────────────────────
   Edge-anchored handle + slide-in panel for pages whose desktop
   layout has a left and/or right side column. attachSideDrawer()
   in components/side_drawer.js hoists the panel out of its host
   grid into a `.side-drawer` wrapper and sets `data-mobile-drawer`
   on it; the `:not([data-mobile-drawer])` rules below collapse the
   panel's empty grid slot. Outside the @media block everything is
   hidden defensively in case a stale artefact lingers after a
   viewport flip. */

.side-drawer,
.side-drawer-handle,
.side-drawer-backdrop { display: none; }

@media (max-width: 1023px) {
  /* Collapse the multi-column grids → single column. The hoisted
     side panels live in the drawer, not in the grid. */
  .buy-grid          { grid-template-columns: 1fr; }
  /* The splitter element's class is `.buy-splitter` (created by
     buyGridSplitter() in util.js). The earlier `.col-splitter`
     rule targeted a class that doesn't exist, so the splitter
     handles still stacked as visible 6-px bars on mobile. */
  .buy-grid .buy-splitter,
  .buy-grid .col-splitter { display: none; }
  .buy-left:not([data-mobile-drawer]),
  .buy-right:not([data-mobile-drawer])  { display: none; }
  /* Defensive: pin the secondary-bar to its declared height so
     `align-items: stretch` + horizontal tab overflow scroll can't
     let it grow on touch devices. */
  main#page-host .secondary-bar {
    height: var(--secbar-h);
    min-height: var(--secbar-h);
    flex: 0 0 var(--secbar-h);
  }

  .da-grid           { grid-template-columns: 1fr; }
  .da-right:not([data-mobile-drawer])   { display: none; }
  /* Keep the main column inside the viewport even when a row has a
     long product name / customer name. Without this, a wide table
     cell pushes the whole `.da-main` past 100% and the page-body
     scrolls horizontally on phones. Combining `min-width: 0` (so the
     grid item can shrink below its content) with table overflow:
     auto containment lets the table scroll inside its card.
     `width: auto; min-width: 100%` on the table lets long content
     expand the table beyond the card width and the card's own
     `overflow-x: auto` provides the scroll — `width: 100%` alone
     would have clipped the table at the card edge and the inner
     cells would have visually leaked past the card.
     `box-sizing: border-box + max-width: 100%` on the card stops
     the card itself from being the overflowing element. */
  .da-main { min-width: 0; max-width: 100%; }
  .da-main .card {
    overflow-x: auto;
    max-width: 100%;
    box-sizing: border-box;
  }
  .da-main table { width: auto; min-width: 100%; }
  /* Section title bars (chevron + name + count + buttons) wrap on
     phone widths instead of forcing the card to grow. */
  .da-main .da-section-head { flex-wrap: wrap; gap: 4px; }

  /* Manage-page header — on desktop it's a single flex row with
     filters left, action buttons right. On phones the actions block
     was hogging ~50% of the row, squeezing the filter column to a
     few characters wide. Stack the whole header so filters and
     actions each get a full-width row. */
  .manage-header {
    flex-direction: column;
    align-items: stretch;
    padding: 10px 12px;
    gap: 10px;
  }
  /* Manage-page filter inputs (Products, Customers — purchase +
     sales, Vehicles, Trailers). On phones the filter block starts
     collapsed; the operator taps the "🔍 Filters" toggle button to
     reveal it. When open, each filter takes a full-width row so the
     operator can actually type into them. */
  .manage-filters-toggle {
    display: inline-block;
    width: 100%;
    text-align: left;
  }
  .manage-filters { display: none; }
  .manage-filters.is-open {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .manage-filters .field {
    width: 100%;
    flex: 1 1 100%;
  }
  .manage-filters .field input,
  .manage-filters .field select {
    width: 100%;
    max-width: none;
    box-sizing: border-box;
  }
  /* Buttons on their own row, equal-width so the touch targets
     line up cleanly under the filters. */
  .manage-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px;
  }

  /* Table card on the manage pages contains a wide table (5-7
     columns). Without overflow:auto here the card pushes past the
     viewport and the whole page scrolls horizontally. The adjacent
     selector (.manage-header + .card) scopes this to the table card
     directly under the manage-page filter row so cards in other
     layouts (Buy / Sell / Daily Accounts) aren't touched. */
  .manage-header + .card {
    overflow-x: auto;
    max-width: 100%;
    box-sizing: border-box;
  }
  .manage-header + .card table { min-width: 0; }

  /* Tighten the page-body padding on phones — the 18 × 24 px
     desktop margin eats too much of a 360 px viewport.
     `.page-body.full` (Buy / Sell three-column pages) overrides
     this back to 0 in its own rule so they're unaffected. */
  .page-body { padding: 10px 12px; }

  .active-inv-grid   { grid-template-columns: 1fr; }
  .active-inv-right:not([data-mobile-drawer]) { display: none; }

  /* Edge-anchored handle button — vertically centred. Translucent
     pill so the page content shows through faintly behind. */
  .side-drawer-handle {
    position: fixed;
    top: 50%;
    width: 32px;
    min-height: 96px;
    padding: 10px 4px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: rgba(26, 60, 84, 0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: #fff;
    cursor: pointer;
    z-index: 70;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.22);
    transition: opacity .18s ease, transform .22s ease;
  }
  .side-drawer-handle-left  {
    left: 0;
    border-radius: 0 14px 14px 0;
    transform: translateY(-50%);
  }
  .side-drawer-handle-right {
    right: 0;
    border-radius: 14px 0 0 14px;
    transform: translateY(-50%);
  }
  .side-drawer-handle.hidden {
    opacity: 0;
    pointer-events: none;
  }
  .side-drawer-handle-left.hidden  { transform: translate(-100%, -50%); }
  .side-drawer-handle-right.hidden { transform: translate( 100%, -50%); }
  .side-drawer-handle .sdh-chevron {
    font-size: 16px;
    line-height: 1;
  }
  .side-drawer-handle .sdh-label {
    writing-mode: vertical-rl;
    text-orientation: mixed;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    font-size: 10.5px;
  }
  .side-drawer-handle-left .sdh-label { transform: rotate(180deg); }

  /* Drawer panel — fixed, slides in from the screen edge. Top edge
     clears the 2-row mobile chrome (48 + ~40 = 88); bottom clears the
     56px bottom nav and any iOS home-indicator safe-area. */
  .side-drawer {
    position: fixed;
    top: 88px;
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    width: min(86vw, 360px);
    background: #fff;
    z-index: 1020;
    box-shadow: 0 4px 18px rgba(0,0,0,0.28);
    overflow: hidden;
    transition: transform .22s ease;
    display: flex;
    flex-direction: column;
  }
  .side-drawer-left  {
    left: 0;
    transform: translateX(-100%);
    border-top-right-radius: 12px;
    border-bottom-right-radius: 12px;
  }
  .side-drawer-right {
    right: 0;
    transform: translateX(100%);
    border-top-left-radius: 12px;
    border-bottom-left-radius: 12px;
  }
  .side-drawer.open { transform: translateX(0); }

  /* The hoisted panel fills the drawer container; its own inner
     scroll regions still work. */
  .side-drawer > .buy-left,
  .side-drawer > .buy-right,
  .side-drawer > .da-right,
  .side-drawer > .active-inv-right {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    background: #fff;
    padding: 10px;
    overflow-y: auto;
  }

  /* Backdrop dims everything behind the drawer (bottom nav included);
     tap closes. */
  .side-drawer-backdrop { z-index: 1010; }
  .side-drawer-backdrop.open { display: block; }

  /* ── Buy/Sell center column — one column scroll on mobile ──────
     Whole `.buy-center` is the single scroll context: photo strip
     (compact band on top) → items table (natural height, grows as
     lines are added) → action panel (sits at the bottom of the
     natural flow). When the operator adds a line the action panel
     drifts down; scrolling up reveals the photo strip again. No
     inner vertical scroll on items-card. `.buy-center` already has
     `overflow-y: auto` (from the desktop base rule) which becomes
     the one visible scrollbar. */

  /* Reclaim ~50 px of desktop-leftover chrome padding so the items
     table can claim that vertical space. Bottom-nav clearance stays. */
  .buy-grid {
    padding: 0;
    /* Switch from grid → flex column on mobile. With grid mode and
       a single auto-sized row, .buy-center { height: 100% } would
       resolve circularly to its own content height — actions-card
       { margin-top: auto } would then find no spare space to absorb,
       leaving the light-grey band visible above the bottom nav.
       Flex column forces buy-center to claim the full remaining
       height of the page-body, which is what every "stick to bottom"
       trick on the inside depends on. */
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
  .buy-grid .buy-center {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
    gap: 4px;
    padding-right: 0;
  }
  .buy-center {
    gap: 4px;
    padding-right: 0;
  }
  .buy-center .card { padding: 8px; }
  /* `.buy-grid` prefix bumps specificity to 0,2,0 so these mobile
     overrides beat the desktop `.buy-page-header` rule that lives
     later in the file (source order would otherwise win at equal
     specificity). Same trick for the actions-card margin glue. */
  .buy-grid .buy-page-header {
    padding: 2px 8px;
    margin: 0;
    border: none;
    border-radius: 0;
    min-height: 0;
  }
  .buy-grid .buy-page-header .page-title {
    font-size: 12px;
    font-weight: 600;
  }
  .buy-grid .buy-page-header .pill {
    font-size: 10px;
    padding: 1px 6px;
  }
  /* Glue the action panel to the bottom of buy-center while items
     are short; flexbox auto-margin collapses to 0 once items grow
     past the available space, restoring natural single-scroll. */
  .buy-grid .buy-center .actions-card { margin-top: auto; }

  .buy-center .photo-card {
    min-height: 0;
    max-height: 60px;
    padding: 4px 6px;
    display: flex;
    flex-direction: column;
  }
  .buy-center .photo-card .card-title { display: none; }
  .buy-center .photo-card .photo-strip-wrap {
    max-height: 44px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
  }

  /* Warehouse card (Sell) — actual `max-height` lives in the
     end-of-file `@media` block with a `.buy-grid` prefix so it
     beats the desktop `.buy-center .warehouse-card` rule that sits
     later in this file. `min-height: 0` so flex shrinking works. */
  .buy-center .warehouse-body { min-height: 0; }

  /* Items card grows with its content; the page-level scroll picks
     up the slack. Table itself still scrolls horizontally for its
     9 columns — vertical inherits the column scroll. */
  .buy-center .items-card { flex: 0 0 auto; }
  .buy-center .items-card-body {
    overflow-x: auto;
    overflow-y: visible;
  }

  /* Row 1 — Department + Payment side-by-side. Department shrinks
     to fit (text-overflow ellipsis on long company names), Payment
     gets a slim trailing slot. The desktop spacer is hidden. */
  .buy-center .actions-card .action-row {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: end;
    gap: 6px;
    overflow: visible;
  }
  .buy-center .actions-card .action-row > * {
    flex: 0 1 auto;
    min-width: 0;
  }
  .buy-center .actions-card .action-row select {
    max-width: 100%;
    text-overflow: ellipsis;
    font-size: 12px;
    padding: 4px 6px;
  }
  .buy-center .actions-card .action-row > div[style*="flex: 1"] {
    display: none;
  }

  /* Row 2 — wrap onto multiple lines rather than scrolling. The
     individual lifecycle buttons (Save/Finish/Void/Sent) hide
     on mobile via `.desktop-only`; the End Invoice trigger takes
     their place. */
  .buy-center .actions-card .action-row-2 {
    flex-wrap: wrap;
    overflow: visible;
    gap: 6px;
  }
  .buy-center .actions-card .action-row-2 > * {
    flex: 0 0 auto;
  }
  .buy-center .actions-card .action-row-2 > div[style*="flex: 1"] {
    display: none;
  }
  .buy-center .actions-card .action-row-2 button {
    padding: 6px 10px;
    font-size: 12px;
  }
  .buy-center .actions-card .desktop-only { display: none; }
}


/* End-Invoice menu — mobile-only button that opens a bottom sheet
   listing the lifecycle actions (Save / Finish / Void / Sent). The
   trigger is hidden on desktop; sheet items use the existing
   `.bottom-sheet` chrome from bottom_nav.js. */
.end-invoice-btn {
  flex: 0 0 auto;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.end-invoice-btn:hover { background: var(--accent-dk); }
.end-invoice-item {
  text-align: left;
  padding: 12px 18px;
  background: #fff;
  border: none;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  width: 100%;
  cursor: pointer;
}
.end-invoice-item:last-child { border-bottom: none; }
.end-invoice-item:hover { background: var(--primary-light); }

@media (min-width: 1024px) {
  .end-invoice-btn { display: none; }
}


/* Active Tickets list (left column) — mirrors LeftPanel QListWidget.
   Flat 3-line text per ticket, no borders, hover highlight only. */
.ticket-list {
  background: #fff;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  height: 100%;
}
.ticket-list-title {
  font-weight: 700;
  color: var(--text);
  padding: 10px 14px 6px;
  font-size: 14px;
  background: #fff;
  flex: 0 0 auto;
}
.ticket-list-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: block;
  padding: 0;
}
/* Sales-side: Active / Sent inline tabs above the ticket body. */
.ticket-tabs {
  display: flex;
  gap: 0;
  padding: 0 14px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.ticket-tabs .tab {
  background: transparent;
  color: var(--muted);
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.ticket-tabs .tab.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
}
.ticket-item {
  border: none;
  border-radius: 0;
  padding: 4px 14px 6px;
  cursor: pointer;
  background: transparent;
  font-size: 13px;
  line-height: 1.35;
  color: var(--text);
}
.ticket-item:hover { background: var(--primary-light); }
.ticket-item.selected { background: #cfe5f3; }
.ticket-line-1 { font-weight: 700; color: var(--text); font-size: 13px; }
.ticket-line-2, .ticket-line-3 {
  color: var(--text);
  font-size: 12px;
  font-weight: 400;
}
.ticket-item.finished {
  color: #808080;
  font-style: italic;
}
.ticket-item.finished .ticket-line-1,
.ticket-item.finished .ticket-line-2,
.ticket-item.finished .ticket-line-3 { color: #808080; }

/* Center cards — match Windows "SalesCard" objectName. */
.buy-center .card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  margin: 0;
}
.buy-center .card .card-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 8px;
  text-transform: none;
  letter-spacing: 0;
}
.buy-center .photo-card {
  flex: 0 0 auto;
  min-height: 180px;
}
.buy-center .warehouse-card {
  flex: 0 0 auto;
  max-height: 280px;
  display: flex;
  flex-direction: column;
}
.buy-center .warehouse-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.warehouse-table th { background: var(--table-head); }
.buy-center .items-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.buy-center .items-card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;       /* y for vertical, x for narrow viewports */
  margin-top: 8px;
}
.buy-center .actions-card {
  flex: 0 0 auto;
}

/* Photo strip — horizontal scroll only. */
.photo-strip-wrap {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px;
  min-height: 140px;
}
.photo-strip {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  align-items: center;
  min-height: 120px;
}
.photo-strip img {
  max-height: 110px;
  max-width: 160px;
  border-radius: 4px;
  border: 2px solid #2ecc71;
  flex-shrink: 0;
}

/* Items table cells — match Windows TransactionTable. */
.items-table { font-size: 13px; }
.items-table input[type="number"],
.items-table input[type="text"] { width: 100%; padding: 4px 6px; font-size: 13px; }
.items-table select { width: 100%; padding: 4px; font-size: 13px; }
.items-table th, .items-table td { padding: 5px 8px; }
.items-table th { font-size: 12px; }
.items-table .items-x-cell { width: 28px; padding: 0 4px; text-align: center; }
.items-table .items-photo-cell { width: 60px; text-align: center; padding: 4px; }

/* ✕ row delete (column 1, red marker like Windows). */
.items-x {
  background: var(--danger);
  color: #fff;
  border: none;
  border-radius: 3px;
  width: 22px; height: 22px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.items-x:hover { background: var(--danger-dk); }

/* "+ Detail" chip in description column. */
.detail-chip {
  background: transparent;
  color: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 3px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.detail-chip:hover { background: var(--primary-light); }

/* Photo button in row. */
.items-photo {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 2px 6px;
  font-size: 13px;
  cursor: pointer;
}
.items-photo:hover { background: var(--row-alt); }

/* Fixed_Prices bit (2) — Price column locked when dept setting on. */
.items-table input.locked-price {
  background: #f9f9f9;
  color: #555;
  cursor: not-allowed;
}

/* Read-only mode (Finished / Void invoices) — visual cue. Inputs
   still get HTML `disabled`; this just makes the page feel passive. */
.buy-grid.read-only input:disabled,
.buy-grid.read-only select:disabled,
.buy-grid.read-only textarea:disabled {
  background: #f5f5f5;
  color: #555;
  cursor: not-allowed;
  -webkit-text-fill-color: #555;   /* Safari renders disabled text faded */
  opacity: 1;
}
.buy-grid.read-only button:disabled { opacity: 0.55; cursor: not-allowed; }

/* Center-panel lock — applied when no department is selected.
   The dept dropdown lives in .action-row (row 1) which stays clickable
   so the operator can pick one. Photo / items / row 2 are dimmed. */
.buy-grid.center-locked .photo-card,
.buy-grid.center-locked .items-card,
.buy-grid.center-locked .actions-card .action-row-2 {
  pointer-events: none;
  opacity: 0.5;
  filter: grayscale(0.3);
}
.buy-grid.center-locked .items-card {
  position: relative;
}
.buy-grid.center-locked .items-card::after {
  content: "Pick a department to start.";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--gold);
  color: var(--text);
  padding: 10px 20px;
  border-radius: 4px;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  pointer-events: none;
  box-shadow: 0 4px 14px rgba(0,0,0,0.25);
}

/* Compliance sub-rows: Detail (required inputs), Alert (warning),
   Hold (info). Sit below the main item row, indented from col 1. */
.items-table tr.items-detail td {
  background: #fbfcff;
  border-bottom: 1px solid var(--border);
  padding: 6px 8px;
}
.items-table tr.items-detail .detail-row-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}
.items-table tr.items-detail .detail-input {
  display: flex;
  align-items: center;
  gap: 4px;
}
.items-table tr.items-detail .detail-input label {
  font-size: 11px;
  color: var(--muted-dk);
  font-weight: 700;
  white-space: nowrap;
}
.items-table tr.items-detail input {
  padding: 3px 6px;
  font-size: 12px;
  width: 160px;
  border: 1px solid var(--primary);
  background: #fff;
}
.items-table tr.items-alert td {
  background: #fff8e1;
  color: #7a5400;
  font-weight: 600;
  padding: 4px 8px;
  border-bottom: 1px solid #f1d77a;
}
.items-table tr.items-hold td {
  background: #f0f6fa;
  color: var(--primary);
  padding: 4px 8px;
  font-size: 12px;
  border-bottom: 1px solid var(--border);
}

/* Placeholder row — faint, click to add a new line (matches Windows). */
.items-table tr.items-placeholder {
  color: #b0b6bd;
  cursor: pointer;
  background: #fbfcfd;
}
.items-table tr.items-placeholder:hover { background: var(--primary-light); }
.items-table tr.items-placeholder td { border-bottom: 1px solid var(--border); }

/* Action buttons row — Save (orange) / Finish (green) / Void (red). */
.btn-save    { background: var(--save);   color: #fff; }
.btn-save:hover    { background: var(--save-dk); }
.btn-finish  { background: var(--accent); color: #fff; }
.btn-finish:hover  { background: var(--accent-dk); }
.btn-void    { background: var(--danger); color: #fff; }
.btn-void:hover    { background: var(--danger-dk); }

/* Bottom action row — Department / Payment / Read Scale / Total / buttons. */
.action-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.action-row .field {
  flex-direction: row;
  align-items: center;
  gap: 6px;
}
.action-row .field label {
  font-size: 12px;
  color: var(--muted);
}
.action-row .field select { min-width: 140px; }
.total-summary {
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
  white-space: nowrap;
  padding: 0 6px;
}
/* Second row of the action bar — Read Scale on the left, buttons right.
   Top-bordered to visually separate from Department/Payment row. */
.actions-card .action-row + .action-row-2 {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* Customer panel (right column) — QGroupBox-style collapsibles. */
.customer-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px 12px 24px;
}
.panel-group {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0 10px 10px;
  position: relative;
  margin-top: 12px;
}
.panel-group > summary {
  display: inline-block;
  margin: -10px 0 8px 6px;
  padding: 0 8px;
  background: #fff;
  font-size: 14px;
  font-weight: 700;
  color: var(--primary);
  cursor: pointer;
  user-select: none;
  list-style: none;
  position: relative;
  z-index: 1;
}
.panel-group > summary::-webkit-details-marker { display: none; }
.panel-group > summary::before {
  content: "▾ ";
  font-size: 9px;
  margin-right: 2px;
  color: var(--primary);
}
.panel-group:not([open]) > summary::before { content: "▸ "; }
.panel-group:not([open]) {
  padding-bottom: 4px;
}
.panel-group:not([open]) > summary { margin-bottom: 4px; }
.panel-group-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 4px 0;
}
.panel-row {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 8px;
  align-items: center;
}
.panel-row label { font-size: 12px; color: var(--muted); font-weight: 600; }
.panel-row input,
.panel-row select { padding: 4px 6px; font-size: 13px; width: 100%; }

/* ── Customer search typeahead (Buy panel) ───────────────────── */
.customer-search { position: relative; display: flex;
  flex-direction: column; gap: 4px; }
.customer-search-row-input { display: flex; gap: 6px; }
.customer-search-field { flex: 0 0 auto; padding: 4px 6px;
  font-size: 13px; }
.customer-search-input { flex: 1 1 auto; padding: 4px 6px;
  font-size: 13px; min-width: 0; }
.customer-search-picked { font-size: 12px; min-height: 1em;
  padding-left: 2px; }
.customer-search-panel {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 60;
  margin-top: 2px;
  background: var(--bg, #fff);
  border: 1px solid var(--border, #c5cfdc);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  max-height: 320px; overflow-y: auto;
}
.customer-search-header { padding: 6px 10px; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.5px;
  border-bottom: 1px solid var(--border, #e5e9ef); }
.customer-search-empty { padding: 12px; font-size: 13px;
  text-align: center; }
.customer-search-empty.error { color: #b54848; }
.customer-search-row { padding: 6px 10px; cursor: pointer;
  border-bottom: 1px solid var(--border, #eef1f5);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent; }
.customer-search-row:last-child { border-bottom: none; }
.customer-search-row:hover,
.customer-search-row.active { background: var(--accent-soft, #eaf2ff); }
.customer-search-row-name { font-weight: 600; font-size: 13px; }
.customer-search-row-meta { font-size: 11px; margin-top: 2px; }

/* Touch / coarse-pointer tweaks: bigger row + tap targets, panel
   capped to viewport width so it doesn't overflow on phones. */
@media (hover: none) and (pointer: coarse) {
  .customer-search-row { padding: 12px 14px; min-height: 44px; }
  .customer-search-row-name { font-size: 14px; }
  .customer-search-row-meta { font-size: 12px; }
  .customer-search-panel { max-width: calc(100vw - 16px); }
}
.panel-labeled { display: flex; flex-direction: column; gap: 4px; }
.panel-labeled-label {
  font-size: 11px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.4px;
}
.veh-readonly {
  color: var(--text);
  padding: 4px 6px;
  background: var(--row-alt);
  border-radius: 3px;
  font-size: 13px;
}

/* PhotoBox — mirrors Windows _invoice_shared.PhotoBox:
   - Empty: dashed gray border + "📁 No Image" placeholder; click to upload.
   - Filled: solid green border + image; hover darkens + reveals
     View / Replace / Clear icon buttons. */
.photo-slot { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.photo-preview {
  position: relative;
  min-height: 110px;
  background: #f0f0f0;
  border: 2px dashed #ccc;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  overflow: hidden;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.photo-preview:not(.filled):hover {
  background: #e8eef4;
  border-color: var(--primary);
}
.photo-preview.filled {
  background: #fff;
  border: 2px solid #2ecc71;
  cursor: default;
}
.photo-preview img {
  max-height: 100%;
  max-width: 100%;
  border-radius: 3px;
  display: block;
}
.photo-empty {
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  user-select: none;
}

/* Hover overlay — same reveal-on-hover behaviour for both states.
   Filled: 👁 / 📁 / 📷 / ✕ buttons. Empty: just 📷 (when the slot's
   kind has a bridge action). */
.photo-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(0,0,0,0);
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
  pointer-events: none;
}
.photo-preview:hover .photo-overlay,
.photo-preview:focus-within .photo-overlay {
  opacity: 1;
  background: rgba(0,0,0,0.55);
  pointer-events: auto;
}
.photo-ov-btn {
  background: rgba(255,255,255,0.95);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  width: 36px; height: 36px;
  font-size: 16px;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.photo-ov-btn:hover { background: #fff; }
.photo-ov-btn-x { color: var(--danger); }
.photo-ov-btn-x:hover { background: #fdecea; color: var(--danger-dk); }

/* Bio row — Face + Thumb side by side, compact 1:1 split.
   minmax(0, 1fr) lets cells shrink without overflowing. */
.bio-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 8px;
}
.bio-row .panel-labeled { min-width: 0; }
.bio-row .photo-preview { min-height: 100px; }
.bio-row .photo-preview img { max-height: 90px; }
.bio-row .photo-ov-btn { width: 30px; height: 30px; font-size: 14px; }

/* Docs section — combo type picker + required-doc highlighting.
   Mirrors desktop RightPanel.create_doc_section + _highlight_required. */
.doc-type-combo {
  width: 100%;
  padding: 4px 6px;
  font-size: 13px;
}
.doc-type-combo option.required-doc {
  color: var(--danger);
  font-weight: 700;
}
.panel-group > summary.has-required {
  color: var(--danger) !important;
}
/* doc-other-row visibility is controlled by JS via inline style.display.
   Don't add a CSS display rule here or the JS toggle won't show. */
.doc-upload-row {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* Document list inside Customer / Invoice docs. */
.doc-list {
  display: flex; flex-direction: column; gap: 4px;
  max-height: 180px; overflow-y: auto;
  border-top: 1px solid var(--border);
  padding-top: 6px;
  margin-top: 4px;
}
.doc-row {
  display: grid;
  grid-template-columns: 1fr 28px 28px;
  gap: 6px;
  align-items: center;
  padding: 4px 6px;
  background: var(--row-alt);
  border-radius: 3px;
  font-size: 12px;
}
.doc-row-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.doc-row-name {
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.doc-row-desc {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.doc-view {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: #fff;
  font-size: 13px;
}
.doc-view:hover { background: var(--primary-light); }

/* Page header on Buy/Sell — slimmer row docked into the center column. */
.buy-page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin: 0;
  flex: 0 0 auto;
}
.buy-page-header .page-title { font-size: 16px; }

/* History filter row. */
.filter-row {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
}
.filter-row .field { min-width: 0; }

/* Past Purchase / Sales Invoices view. */
.history-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin: 14px 18px 8px;
}
.history-filters {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  padding: 0 18px 12px;
  background: var(--bg);
}
.history-filters .field {
  flex-direction: row;
  align-items: center;
  gap: 6px;
}
.history-filters .field label {
  font-size: 12px;
  color: var(--muted-dk);
  font-weight: 600;
  white-space: nowrap;
}
.history-filters input { padding: 4px 8px; font-size: 12px; max-width: 130px; }
.history-filters select { padding: 4px 8px; font-size: 12px; }
.history-table { font-size: 12px; }
.history-table th { padding: 8px 10px; font-size: 12px; text-transform: none; }
.history-table td { padding: 4px 10px; }
.history-table .row-num {
  background: var(--table-head);
  font-weight: 700;
  text-align: center;
  width: 40px;
  color: var(--text);
}

/* ── Settings drill-in cards — list/detail flow ─────────────────
   Used by every settings page that requires the operator to pick
   something (a yard, a department, an employee) before showing the
   actual settings. The list step renders centred + full-width; the
   detail step replaces it with a Back button at the top. */

.drill-in-card {
  max-width: 920px;
  margin: 16px auto;
  padding: 12px 16px;
}
.drill-in-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.drill-in-list tr { cursor: pointer; }
.drill-in-list tr:hover { background: #f4f5f7; }
.drill-in-back { white-space: nowrap; }
.drill-in-body { padding-top: 4px; }

/* ── Executive yard filter — compact dropdown ─────────────────── */

.yard-filter-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.2;
  min-width: 140px;
  box-sizing: border-box;
  background: #fff;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  text-align: left;
  justify-content: space-between;
  vertical-align: middle;
}
.yard-filter-trigger:hover,
.yard-filter-trigger:focus {
  background: #fff;
  border-color: var(--primary);
  outline: none;
}
.yard-filter-label { flex: 1; white-space: nowrap;
                      overflow: hidden; text-overflow: ellipsis; }
.yard-filter-caret { color: var(--muted-dk); font-size: 10px; }
.yard-filter-pop {
  background: #fff;
  border: 1px solid #bbb;
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,.12);
  padding: 6px;
  max-height: 320px;
  overflow: auto;
  z-index: 9999;
}
.yard-filter-pop-actions {
  display: flex;
  gap: 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid #eee;
  margin-bottom: 4px;
}
.yard-filter-pop-list {
  display: flex;
  flex-direction: column;
}
.yard-filter-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  cursor: pointer;
  font-size: 12px;
  border-radius: 3px;
}
.yard-filter-item:hover { background: #f4f5f7; }

/* ── Settings → Hardware: device cards + agent banner ────────── */

.hw-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card-bg, #fff);
  margin-bottom: 14px;
}
.hw-banner.online        { border-color: #2ecc71; }
.hw-banner.offline       { border-color: #e67e22; background: #fef6ee; }
.hw-banner.unregistered  { border-color: #d4a017; background: #fff8e1; }
.hw-banner-icon          { font-size: 20px; }
.hw-banner-body          { flex: 1; }
.hw-banner-title         { font-weight: 700; font-size: 14px; }
.hw-banner-sub           { color: var(--muted); font-size: 12px; margin-top: 2px; }

/* Topbar warnings center — bell + numeric count badge + a dropdown
   listing live, self-clearing warnings (hardware agent down, invoices
   not compliant with the law, …). Replaces the old agent status dot.
   The panel reuses the shared .topbar .dropdown look (white, dark rows). */
.topbar .right .warnings-center {
  position: relative;
  font-size: 15px;
  line-height: 1;
  border-bottom: none;
}
.topbar .right .warnings-center.has-dropdown { padding-right: 10px; }
.topbar .right .warnings-center.has-dropdown::after { content: none; }
.topbar .right .warnings-center .warn-badge {
  position: absolute;
  top: 0; right: 0;
  min-width: 15px; height: 15px;
  padding: 0 3px;
  border-radius: 8px;
  background: #e74c3c; color: #fff;
  font-size: 10px; font-weight: 700; line-height: 15px;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
}
.topbar .right .warnings-center .warn-list {
  left: auto; right: 0;
  min-width: 300px; max-width: 380px;
  border-radius: 6px 0 6px 6px;
}
.warn-head {
  font-size: 11px; font-weight: 700; letter-spacing: 0.4px;
  text-transform: uppercase; color: var(--muted);
  padding: 6px 10px 2px;
}
.warn-empty { padding: 12px 10px; color: var(--muted); font-size: 13px; }
.topbar .right .warnings-center .warn-row { white-space: normal; }
.warn-row-title { font-size: 13px; font-weight: 600; }
.warn-row-detail {
  font-size: 11px; font-weight: 400; color: var(--muted); margin-top: 2px;
}
.warn-row-static { cursor: default; }
.warn-row-static:hover { background: transparent !important; color: inherit !important; }

.hw-section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  margin: 16px 0 8px;
}
.hw-section-head h3 { margin: 0; font-size: 15px; }

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.device-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  background: #fff;
  min-height: 200px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.device-card:hover {
  border-color: var(--primary);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.device-card-icon {
  font-size: 36px;
  text-align: center;
  margin-bottom: 8px;
  user-select: none;
}
.device-card-name {
  font-weight: 700;
  font-size: 14px;
  text-align: center;
  margin-bottom: 2px;
  word-break: break-word;
}
.device-card-sub {
  color: var(--muted);
  font-size: 11px;
  text-align: center;
  margin-bottom: 10px;
}
.device-card-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: center;
  margin-bottom: 10px;
}
.device-card-pills .pill {
  font-size: 10px;
  padding: 2px 6px;
}
.device-card-default {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: 3px;
  background: #fff8d4;
  color: #8a6d00;
  border: 1px solid #e8d875;
  margin: 0 auto 10px;
  text-align: center;
}
.device-card-actions {
  display: flex;
  justify-content: center;
  gap: 4px;
  margin-top: auto;
}
.device-card-actions button {
  font-size: 12px;
  padding: 4px 8px;
}

.hw-other-toggle {
  background: transparent;
  border: none;
  color: var(--primary);
  cursor: pointer;
  font-size: 13px;
  padding: 8px 0;
  margin-top: 18px;
}
.hw-other-toggle:hover { text-decoration: underline; }
.hw-other-list {
  list-style: none;
  padding: 0;
  margin: 8px 0;
}
.hw-other-list li {
  padding: 6px 0;
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: 10px;
}


/* ════════════════════════════════════════════════════════════════
   Mobile/tablet (≤1023px) — LAST-WORD OVERRIDES.
   Earlier mobile rules in this file were getting clobbered by
   desktop rules that come later in source. Putting these at the
   end means source-order naturally favours them at equal specificity.
   ════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {

  /* Pin the secondary bar at its 42 px chrome height — nothing in
     the later cascade can stretch it into the page-body. */
  .secondary-bar {
    height: var(--secbar-h);
    min-height: var(--secbar-h);
    max-height: var(--secbar-h);
    flex: 0 0 auto;
  }

  /* The grid paints its own background — without an explicit bg,
     empty space at the top of buy-center (no items yet) shows
     whatever lurks behind page-body, which on this build is the
     navy chrome colour. */
  .buy-grid {
    background: var(--bg);
    padding: 0;
    height: 100%;
  }

  /* Slim flush strip under the secondary bar. The `.buy-grid`
     prefix raises specificity to 0,2,0 so this beats the desktop
     `.buy-page-header` rule that sits later in this file. */
  .buy-grid .buy-page-header {
    padding: 2px 8px;
    margin: 0;
    border: none;
    border-radius: 0;
    min-height: 0;
    background: #fff;
  }
  .buy-grid .buy-page-header .page-title {
    font-size: 12px;
    font-weight: 600;
  }
  .buy-grid .buy-page-header .pill {
    font-size: 10px;
    padding: 1px 6px;
  }

  /* Glue actions to the bottom of buy-center while the items list
     is short. The flexbox auto-margin collapses to 0 once content
     grows past the column, restoring single-scroll behaviour. */
  .buy-grid .buy-center .actions-card { margin-top: auto; }

  /* Compact per-card padding — the desktop `.buy-center .card`
     rule later in this file was overriding the earlier mobile
     attempt at 10 px. */
  .buy-grid .buy-center .card { padding: 8px; }

  /* Photo strip (Buy) — same source-order trap as the warehouse
     card: the desktop `.buy-center .photo-card { min-height: 180px }`
     later in this file was winning over the mobile `min-height: 0`,
     so the previous `max-height: 60px` had no effect (min-height >
     max-height clamps to min). Specificity-bumped to 0,3,0 here so
     the slim band actually applies. */
  .buy-grid .buy-center .photo-card {
    min-height: 0;
    max-height: 60px;
  }
  .buy-grid .buy-center .photo-card .photo-strip-wrap { max-height: 44px; }

  /* Warehouse strip (Sell) — match the Buy page's photo-card band.
     The photo card renders at ~180 px on mobile due to a desktop
     `min-height: 180 px` winning the cascade (clamps the mobile
     `max-height: 60px` up to 180); we set warehouse to 180 here so
     the two pages feel visually paired. Specificity-bumped so the
     desktop `.buy-center .warehouse-card { max-height: 280px }`
     rule later in this file can't override. */
  .buy-grid .buy-center .warehouse-card { max-height: 280px; }
  

  /* Shrink the Department / Payment selects on phone widths so the
     first action row packs tighter under the existing horizontal
     scroll constraint. */
  .buy-grid .buy-center .actions-card .action-row select {
    min-width: 96px;
    font-size: 12px;
    padding: 4px 6px;
  }
}


/* Hide :disabled action-card buttons everywhere — when an invoice
   is locked (Finished / Void) the JS disables Save/Void/Finish/Sent;
   removing them from view (instead of greying out) keeps the action
   bar focused on what the operator can actually press. The trade-off
   is a brief disappearance while a request is in flight. */
.actions-card button:disabled { display: none; }

/* Vertical-scroll container for data tables. Keeps long tables inside
   their card instead of growing the page. The sticky header keeps
   column titles visible while the body scrolls. */
.table-scroll {
  max-height: 60vh;
  overflow-y: auto;
  overflow-x: auto;
}
.table-scroll table {
  margin: 0;
}
.table-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--table-head);
}

.hw-cap-list { list-style: none; padding: 0; margin: .5rem 0; }
.hw-cap-list li { padding: .35rem 0; }
.hw-pill { display: inline-block; padding: .1rem .5rem; border-radius: 999px; font-size: .85rem; }
.hw-pill-ok   { background: #e6f7e9; color: #0a7a2a; }
.hw-pill-warn { background: #fef6ee; color: #a05a00; }

/* Offline-unavailable placeholder card (P2.14) */
.offline-unavailable .card {
  padding: 24px;
  text-align: center;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: 8px;
}

/* ── PC authorization card — Settings → Hardware (P4.3) ─────────── */
.auth-pc-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  margin-bottom: 14px;
  background: var(--card);
}
.auth-pc-card.authorized   { border-color: var(--accent); }
.auth-pc-card.unauthorized { border-color: var(--warning); }

.auth-pc-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.auth-pc-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
  flex-shrink: 0;
}
.auth-pc-badge.authorized   { background: #e6f7e9; color: #0a7a2a; }
.auth-pc-badge.unauthorized { background: #fef6ee; color: #a05a00; }

.auth-pc-meta   { font-size: 12px; color: var(--muted); margin: 4px 0 0; }
.auth-pc-body   { font-size: 13px; margin: 6px 0 0; color: var(--muted-dk); }
.auth-pc-actions { margin-top: 10px; }

/* ── authorize_pc_modal error (P4.4) ────────────────────────────── */
.auth-pc-modal-error { margin-top: 8px; }

/* ── paired_pcs_list (P6.6) — admin fleet table ──────────────────── */
.paired-pcs-list   { margin-bottom: 16px; }
.paired-pcs-list h3 { margin: 0 0 8px; font-size: 14px; }
.paired-pcs-list table { width: 100%; border-collapse: collapse; }
.paired-pcs-list th,
.paired-pcs-list td {
  text-align: left; padding: 8px 6px; font-size: 13px;
  border-bottom: 1px solid var(--border, #d4dbe1);
}
.paired-pcs-list .status.online  { color: var(--accent, #2c5d80); }
.paired-pcs-list .status.offline { color: var(--muted, #7a8895); }
.paired-pcs-list .status.revoked { color: var(--danger, #b03a2e); }
.paired-pcs-list .empty { color: var(--muted, #7a8895); font-style: italic; }
.paired-pcs-list .meta  { font-size: 12px; color: var(--muted, #7a8895); }

