/* ============================================================================
   Drivaza Vendor Portal — distinctive re-skin, layered on top of admin.css.
   Scoped entirely under body.vp-portal so the Admin/Agent apps (which reuse
   the same .adm-* classes) are completely untouched.

   Direction: an ink-first, editorial dashboard — Poppins throughout, a warm
   paper background instead of cold SaaS-gray, confident near-black primary
   buttons (green is reserved for genuine positive state, not decoration),
   status communicated with a dot + micro-label instead of pastel pill chips,
   crisp 1px borders instead of diffuse drop-shadows, uppercase small-caps
   section labels, and tabular numerals wherever money/counts appear.
   ========================================================================== */

body.vp-portal {
  --vp-font: 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
  --vp-bg: #f7f5f0;
  --vp-surface: #ffffff;
  --vp-ink: #17191c;
  --vp-ink-soft: #40444b;
  --vp-muted: #767a82;
  --vp-faint: #a4a8b0;
  --vp-line: #e6e2d8;
  --vp-line-strong: #d7d2c3;
  --vp-brand: #16a34a;
  --vp-brand-ink: #0d6b34;
  --vp-amber: #c2660f;
  --vp-red: #c0341f;
  --vp-blue: #2251c9;
  --vp-radius-sm: 8px;
  --vp-radius: 13px;
  --vp-radius-lg: 20px;
  --vp-shadow-lg: 0 24px 60px -18px rgba(20, 22, 18, .32), 0 4px 14px rgba(20, 22, 18, .08);
  font-family: var(--vp-font);
  background: var(--vp-bg);
  -webkit-font-smoothing: antialiased;
  --adm-bg: var(--vp-bg);
  --adm-line: var(--vp-line);
  --adm-line-soft: #efece3;
  --adm-ink: var(--vp-ink);
  --adm-muted: var(--vp-muted);
  --adm-faint: var(--vp-faint);
  --adm-shadow: none;
  --adm-shadow-md: none;
}
body.vp-portal button,
body.vp-portal input,
body.vp-portal select,
body.vp-portal textarea { font-family: var(--vp-font); }

/* ── Sidebar / topbar — same structure, tightened type ─────────────────── */
body.vp-portal .adm-sidebar { background: linear-gradient(180deg, #10201a 0%, #142a20 100%); }
body.vp-portal .adm-sb-item { font-weight: 500; letter-spacing: .01em; border-radius: 10px; }
body.vp-portal .adm-sb-item.active { box-shadow: none; }
body.vp-portal .adm-sb-group-label { font-weight: 700; }
body.vp-portal .adm-topbar { background: rgba(247, 245, 240, .86); border-bottom-color: var(--vp-line); }
body.vp-portal .adm-topbar h1 { font-weight: 700; letter-spacing: -.015em; }
body.vp-portal .adm-content { max-width: 1280px; }

/* ── Buttons — the headline change: ink-first, no glow, confident weight ── */
body.vp-portal .adm-btn {
  background: var(--vp-ink);
  color: #fff;
  border-radius: var(--vp-radius-sm);
  padding: 10px 17px;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .003em;
  box-shadow: none;
  transition: transform .14s cubic-bezier(.2, .7, .2, 1), background .14s, box-shadow .14s;
}
body.vp-portal .adm-btn:hover { background: #000; box-shadow: 0 8px 18px -6px rgba(23, 25, 28, .38); transform: translateY(-1px); }
body.vp-portal .adm-btn:active { transform: translateY(0); box-shadow: none; }
body.vp-portal .adm-btn:disabled { box-shadow: none; transform: none; }
body.vp-portal .adm-btn-ghost {
  background: transparent; color: var(--vp-ink); border: 1.5px solid var(--vp-line-strong);
}
body.vp-portal .adm-btn-ghost:hover { background: #fff; border-color: var(--vp-ink); box-shadow: none; }
body.vp-portal .adm-btn-danger { background: transparent; color: var(--vp-red); border: 1.5px solid #ecc7bd; box-shadow: none; }
body.vp-portal .adm-btn-danger:hover { background: var(--vp-red); color: #fff; border-color: var(--vp-red); box-shadow: 0 8px 18px -8px rgba(192, 52, 31, .4); }
body.vp-portal .adm-btn-sm { padding: 6px 12px; font-size: .76rem; border-radius: 7px; }
/* A button that IS the positive/confirm action (picked up, save & such money
   states) can opt into the brand green explicitly via .vp-btn-brand. */
body.vp-portal .adm-btn.vp-btn-brand { background: var(--vp-brand); }
body.vp-portal .adm-btn.vp-btn-brand:hover { background: var(--vp-brand-ink); box-shadow: 0 8px 18px -6px rgba(22, 163, 74, .38); }

/* ── Status — dot + uppercase micro-label instead of pastel pill chips ──── */
body.vp-portal .adm-badge {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; padding: 0;
  font-weight: 700; font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--vp-ink-soft);
}
body.vp-portal .adm-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; flex: 0 0 6px; background: var(--vp-faint); }
body.vp-portal .adm-badge.ok    { color: #146534; } body.vp-portal .adm-badge.ok::before    { background: var(--vp-brand); }
body.vp-portal .adm-badge.wait  { color: #92400e; } body.vp-portal .adm-badge.wait::before  { background: var(--vp-amber); }
body.vp-portal .adm-badge.bad   { color: #991b1b; } body.vp-portal .adm-badge.bad::before   { background: var(--vp-red); }
body.vp-portal .adm-badge.info  { color: #1d4ed8; } body.vp-portal .adm-badge.info::before  { background: var(--vp-blue); }
body.vp-portal .adm-badge.muted { color: var(--vp-muted); } body.vp-portal .adm-badge.muted::before { background: var(--vp-faint); }

/* ── Cards — crisp border, uppercase micro-label titles, no drop-shadow ─── */
body.vp-portal .adm-card { border-color: var(--vp-line); border-radius: var(--vp-radius); box-shadow: none; }
body.vp-portal .adm-card-title {
  font-weight: 700; font-size: .7rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--vp-muted); margin-bottom: 10px;
}
body.vp-portal .adm-card-sub { color: var(--vp-muted); }
body.vp-portal .adm-empty { border-color: var(--vp-line-strong); background: #fdfcf9; border-radius: var(--vp-radius); }

/* ── Tables — bolder small-caps header, tabular figures ──────────────────── */
body.vp-portal .adm-table { border-color: var(--vp-line); box-shadow: none; border-radius: var(--vp-radius); }
body.vp-portal .adm-table th {
  background: #faf8f3; letter-spacing: .07em; font-weight: 700; color: var(--vp-muted);
  border-bottom-color: var(--vp-line);
}
body.vp-portal .adm-table td { border-bottom-color: var(--vp-line); font-variant-numeric: tabular-nums; }
body.vp-portal .adm-table tbody tr:hover { background: #faf9f5; }
body.vp-portal .adm-table a { color: var(--vp-brand-ink); }

/* ── Inputs — everywhere (adm-toolbar / adm-form-grid / vac-f / vp-field) ── */
body.vp-portal .adm-toolbar input, body.vp-portal .adm-toolbar select,
body.vp-portal .adm-form-grid input, body.vp-portal .adm-form-grid select,
body.vp-portal .adm-card input, body.vp-portal .adm-card select, body.vp-portal .adm-card textarea,
body.vp-portal .vac-f input, body.vp-portal .vac-f select, body.vp-portal .vac-f textarea,
body.vp-portal .vp-field select, body.vp-portal .vp-field input,
body.vp-portal .vp-mini input, body.vp-portal .vp-mini select {
  border-color: var(--vp-line-strong); border-radius: var(--vp-radius-sm); color: var(--vp-ink);
}
body.vp-portal .adm-toolbar input:focus, body.vp-portal .adm-toolbar select:focus,
body.vp-portal .adm-form-grid input:focus, body.vp-portal .adm-form-grid select:focus,
body.vp-portal .adm-card input:focus, body.vp-portal .adm-card select:focus, body.vp-portal .adm-card textarea:focus,
body.vp-portal .vac-f input:focus, body.vp-portal .vac-f select:focus, body.vp-portal .vac-f textarea:focus,
body.vp-portal .vp-field select:focus, body.vp-portal .vp-field input:focus {
  border-color: var(--vp-ink); box-shadow: 0 0 0 3.5px rgba(23, 25, 28, .08);
}
body.vp-portal .vac-form { border-color: var(--vp-line); border-radius: var(--vp-radius-lg); box-shadow: none; }
body.vp-portal .vac-head h3 { font-family: var(--vp-font); }
body.vp-portal .vac-sec { color: var(--vp-muted); font-weight: 700; }
body.vp-portal .vac-actions { border-top-color: var(--vp-line); }

/* ── Alerts — flat card with a coloured left rule, not a pastel fill ───────
   Block, not style.css's flex row: that row exists for an icon + text, and the
   portal's alerts have no icon — they are sentences with a bold figure in the
   middle, which as flex items split into columns ("Outstanding balance: |
   AED 1,840.50 | — please settle…" as three ragged blocks on a phone). */
body.vp-portal .alert {
  display: block;
  background: #fff; color: var(--vp-ink); border: 1px solid var(--vp-line);
  border-left: 3px solid var(--vp-faint); border-radius: 10px; font-weight: 500;
}
body.vp-portal .alert-ok   { border-left-color: var(--vp-brand); }
body.vp-portal .alert-err  { border-left-color: var(--vp-red); }
body.vp-portal .alert-warn { border-left-color: var(--vp-amber); }

/* ── Sub-tabs (CarDetail workspace) — ink underline, not brand-colour ──────
   Defined in full here (not in the shared admin.css) because these classes
   exist only in the vendor portal. */
.vp-subtabs {
  display: flex; gap: 2px; flex-wrap: wrap; margin: 0 0 18px;
  border-bottom: 1.5px solid var(--vp-line, #e6e2d8);
}
.vp-subtab {
  position: relative; border: none; background: none; cursor: pointer;
  padding: 10px 14px; font-size: .84rem; font-weight: 600; letter-spacing: .01em;
  color: var(--vp-muted, #767a82); border-bottom: 2px solid transparent; margin-bottom: -1.5px;
  font-family: inherit; display: inline-flex; align-items: center; gap: 6px;
  transition: color .12s, border-color .12s;
}
.vp-subtab:hover { color: var(--vp-ink, #17191c); }
.vp-subtab.active { color: var(--vp-ink, #17191c); border-bottom-color: var(--vp-ink, #17191c); }
.vp-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
.vp-dot.bad  { background: #dc2626; }
.vp-dot.warn { background: #f59e0b; }

/* ── Stat tiles — number-forward, thin brand rule, no icon chip ──────────── */
body.vp-portal .vp-stat {
  border-color: var(--vp-line); border-radius: var(--vp-radius); box-shadow: none;
  flex-direction: column; align-items: flex-start; gap: 3px; position: relative; overflow: hidden; padding: 16px 18px 15px;
}
body.vp-portal .vp-stat::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--vp-brand); opacity: .55; }
body.vp-portal .vp-stat:hover { transform: none; box-shadow: none; border-color: var(--vp-line-strong); }
body.vp-portal .vp-stat-ico { width: 32px; height: 32px; border-radius: 9px; flex: 0 0 32px; margin-bottom: 6px; }
/* clamp() is the shipped 1.55rem at any width above ~460px; below that it keeps
   "AED 172,350" on one line inside a half-width phone tile. */
body.vp-portal .vp-stat-val { font-weight: 800; font-size: clamp(1.15rem, 5.4vw, 1.55rem); font-variant-numeric: tabular-nums; }
body.vp-portal .vp-stat-label { font-weight: 700; text-transform: uppercase; letter-spacing: .06em; font-size: .64rem; color: var(--vp-muted); }

/* ── Settlement panel & mini fields (BookingDesk) ─────────────────────────── */
.vp-settle {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px;
  background: #faf8f3; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); padding: 14px; margin-bottom: 12px;
}
.vp-settle > div { display: flex; flex-direction: column; gap: 2px; }
.vp-settle span {
  font-size: .68rem; font-weight: 700; color: var(--vp-muted, #767a82);
  text-transform: uppercase; letter-spacing: .05em;
}
.vp-settle strong { font-size: .95rem; font-variant-numeric: tabular-nums; }
.vp-settle > div.warn strong { color: #b45309; }
.vp-settle > div.ok strong { color: #16a34a; }

.vp-mini { display: flex; flex-direction: column; gap: 4px; font-size: .68rem; color: var(--vp-muted, #767a82); }
.vp-mini span { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.vp-mini input, .vp-mini select {
  padding: 8px 10px; border: 1.5px solid var(--vp-line-strong, #d7d2c3);
  border-radius: var(--vp-radius-sm, 8px); font-size: .84rem; font-family: inherit;
  background: #fff; color: var(--vp-ink, #17191c);
}

/* ── Gallery ──────────────────────────────────────────────────────────────── */
.vp-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.vp-gitem {
  position: relative; border-radius: var(--vp-radius-sm, 8px); overflow: hidden;
  border: 1px solid var(--vp-line, #e6e2d8); background: #faf8f3;
}
.vp-gitem img { width: 100%; height: 130px; object-fit: cover; display: block; }
.vp-gcover {
  position: absolute; top: 8px; left: 8px; background: var(--vp-brand, #16a34a); color: #fff;
  font-size: .62rem; font-weight: 800; letter-spacing: .06em; padding: 3px 8px; border-radius: 6px;
}
.vp-gactions { display: flex; gap: 4px; padding: 6px; justify-content: center; background: #fff; }
.vp-gactions button {
  border: 1px solid var(--vp-line-strong, #d7d2c3); background: #fff; border-radius: 6px;
  cursor: pointer; padding: 4px 9px; font-size: .8rem; line-height: 1.2; font-family: inherit;
}
.vp-gactions button:hover:not(:disabled) { background: #f3f2ee; }
.vp-gactions button:disabled { opacity: .35; cursor: default; }

/* ── Sticky form action bar ────────────────────────────────────────────────
   Primary action pinned bottom-right, draft controls bottom-left, so a long
   form never hides its own Save button below the fold. Sticks to the bottom
   of whichever ancestor scrolls (page for inline forms, the overlay for
   modals) and sits flush with the container edge via negative margins. */
.vp-formbar {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: rgba(255, 255, 255, .94); backdrop-filter: blur(8px);
  border-top: 1px solid var(--vp-line, #e6e2d8);
}
/* Sticks to the bottom of .vp-modal-body's scrollport, which is bounded — so
   it always sits on the modal's bottom edge, never over its content. */
.vp-modal-body .vp-formbar {
  margin: 22px -26px -22px; padding: 14px 26px;
  border-radius: 0 0 var(--vp-radius-lg, 20px) var(--vp-radius-lg, 20px);
}
.vac-form .vp-formbar {
  margin: 22px -22px -22px; padding: 14px 22px;
  border-radius: 0 0 var(--vp-radius-lg, 20px) var(--vp-radius-lg, 20px);
}
.vp-formbar-left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.vp-formbar-right { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.vp-draft-note { font-size: .74rem; color: var(--vp-muted, #767a82); }
.vp-draft-note.ok { color: #146534; font-weight: 600; }
.vp-draft-note button {
  background: none; border: none; padding: 0; cursor: pointer; font: inherit;
  color: var(--vp-ink, #17191c); text-decoration: underline;
}
@media (max-width: 560px) {
  .vp-formbar-right { width: 100%; margin-left: 0; }
  .vp-formbar-right .adm-btn { flex: 1; justify-content: center; }
}

/* ── Modal chrome (see shared.tsx Modal) ─────────────────────────────────── */
.vp-modal-overlay {
  position: fixed; inset: 0; background: rgba(15, 18, 15, .55); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 24px 16px;
  z-index: 200; overflow-y: auto; animation: vp-fade .16s ease both;
}
/* The modal is a BOUNDED flex column that scrolls its own body. This is what
   keeps the sticky footer inside the dialog: a sticky element resolves against
   its nearest scrolling ancestor, so if the modal has no height limit the
   scroller is the full-viewport overlay and the bar pins to the viewport
   bottom — i.e. floating over the middle of a tall form. */
.vp-modal {
  background: #fff; border-radius: var(--vp-radius-lg); width: 100%; max-width: 640px;
  max-height: min(88vh, 940px);
  display: flex; flex-direction: column; min-height: 0;
  padding: 0; box-shadow: var(--vp-shadow-lg, 0 24px 60px -18px rgba(0, 0, 0, .35));
  animation: vp-modal-in .2s cubic-bezier(.2, .8, .2, 1) both; font-family: var(--vp-font);
}
.vp-modal.wide { max-width: 960px; }
.vp-modal-head {
  flex: 0 0 auto;
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  margin: 0; padding: 22px 26px 16px; border-bottom: 1px solid var(--vp-line, #e6e2d8);
}
.vp-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 26px 22px; }
.vp-modal-head h3 { font-weight: 700; font-size: 1.02rem; margin: 0; letter-spacing: -.01em; color: var(--vp-ink, #17191c); }
.vp-modal-close {
  width: 32px; height: 32px; border-radius: 9px; border: 1.5px solid var(--vp-line-strong, #d7d2c3);
  background: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--vp-muted, #767a82); flex: 0 0 32px; transition: background .12s, color .12s, border-color .12s;
}
.vp-modal-close:hover { background: var(--vp-ink, #17191c); color: #fff; border-color: var(--vp-ink, #17191c); }
@keyframes vp-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes vp-modal-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }

/* ── Toggle switch (My Cars → Online/Offline) ────────────────────────────── */
.vp-toggle {
  cursor: pointer; border: 1.5px solid transparent; border-radius: 20px; font-family: var(--vp-font);
  padding: 5px 13px 5px 11px; font-weight: 700; font-size: .72rem; letter-spacing: .02em;
  display: inline-flex; align-items: center; gap: 6px; transition: background .14s, border-color .14s, color .14s;
}
.vp-toggle::before { content: ''; width: 7px; height: 7px; border-radius: 50%; }
.vp-toggle.on  { background: #eafaef; color: #146534; border-color: #bfe8cc; }
.vp-toggle.on::before  { background: var(--vp-brand, #16a34a); }
.vp-toggle.off { background: #f3f2ee; color: #6b7280; border-color: var(--vp-line-strong, #d7d2c3); }
.vp-toggle.off::before { background: #a4a8b0; }
.vp-toggle:disabled { opacity: .55; cursor: not-allowed; }

/* ── Auth (login) — inherits Poppins automatically via body font-family ──── */
body.vp-portal .auth-badge { font-family: var(--vp-font); }

@media (max-width: 900px) {
  .vp-modal { max-height: 92vh; }
  .vp-modal-head { padding: 18px 18px 14px; }
  .vp-modal-body { padding: 16px 18px 18px; }
  .vp-modal-body .vp-formbar { margin: 18px -18px -18px; padding: 12px 18px; }
}

/* ── Accounts workspace ────────────────────────────────────────────────────── */
.vp-acc-bar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 18px; padding-bottom: 0; border-bottom: 1.5px solid var(--vp-line, #e6e2d8);
}
.vp-acc-range { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding-bottom: 8px; }
.vp-acc-range select, .vp-acc-range input, .vp-acc-select {
  padding: 7px 10px; border: 1.5px solid var(--vp-line-strong, #d7d2c3);
  border-radius: var(--vp-radius-sm, 8px); font-size: .82rem; font-family: inherit;
  background: #fff; color: var(--vp-ink, #17191c);
}
.vp-acc-note { font-size: .76rem; color: var(--vp-muted, #767a82); margin-top: 14px; line-height: 1.6; }

/* Profit & loss sheet */
.vp-pl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 14px; }
.vp-pl-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--adm-line-soft, #efece3); font-size: .86rem;
}
.vp-pl-row:last-child { border-bottom: none; }
.vp-pl-row > span { color: var(--vp-ink-soft, #40444b); min-width: 0; }
.vp-pl-row > span em {
  display: block; font-style: normal; font-size: .72rem; color: var(--vp-faint, #a4a8b0); margin-top: 2px;
}
.vp-pl-row > strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
.vp-pl-row.total {
  border-top: 1.5px solid var(--vp-line-strong, #d7d2c3); border-bottom: none;
  margin-top: 4px; padding-top: 12px; font-weight: 700;
}
.vp-pl-row.total > span { color: var(--vp-ink, #17191c); font-weight: 700; }

.vp-net {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin-top: 14px; padding: 16px 20px; border-radius: var(--vp-radius, 13px);
  border: 1px solid var(--vp-line, #e6e2d8); border-left: 4px solid var(--vp-faint, #a4a8b0);
  background: #fff;
}
.vp-net > span { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--vp-muted, #767a82); }
.vp-net > strong { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.vp-net.ok  { border-left-color: var(--vp-brand, #16a34a); }
.vp-net.ok  > strong { color: #146534; }
.vp-net.bad { border-left-color: var(--vp-red, #c0341f); }
.vp-net.bad > strong { color: var(--vp-red, #c0341f); }

/* Table footer totals */
.vp-tfoot td {
  background: #faf8f3; font-weight: 700; font-variant-numeric: tabular-nums;
  border-top: 1.5px solid var(--vp-line-strong, #d7d2c3);
}

/* Per-car contribution bar */
.vp-sparkbar { height: 6px; border-radius: 3px; background: #efece3; overflow: hidden; }
.vp-sparkbar span { display: block; height: 100%; border-radius: 3px; }
.vp-sparkbar span.ok  { background: var(--vp-brand, #16a34a); }
.vp-sparkbar span.bad { background: var(--vp-red, #c0341f); }

/* Print: the Overview becomes a clean period statement on paper. */
.vp-print-head { display: none; }
@media print {
  /* admin.css blanks the whole page for printing — `body * { visibility:
     hidden !important }` — and only un-hides `.acc-print-area`, a wrapper the
     ADMIN accounting screens use. The vendor portal has no such wrapper, so
     every print here (invoice, P&L, statement, ledger) came out as a blank
     sheet. Undo the blanket hide for this portal; `body.vp-portal *` outranks
     `body *`, so this wins even against the !important. What must not print is
     then removed explicitly with display:none below, which is the right tool —
     visibility:hidden leaves the element occupying the page. */
  body.vp-portal * { visibility: visible !important; }

  .adm-sidebar, .adm-topbar, .adm-sb-backdrop, .vp-noprint, .vp-stats { display: none !important; }
  .adm-main { margin-left: 0 !important; }
  .adm-content { padding: 0 !important; max-width: none !important; }
  body.vp-portal { background: #fff; }
  .vp-print-head { display: block; margin-bottom: 20px; }
  .vp-print-head h2 { font-size: 1.4rem; font-weight: 800; margin: 0 0 4px; }
  .vp-print-head p { color: #555; font-size: .9rem; margin: 0; }
  .adm-card, .vp-net { break-inside: avoid; box-shadow: none; }
  .vp-pl-grid { grid-template-columns: 1fr 1fr; }
}

/* ── Ledgers (statement / customer ledger / aging / day book) ──────────────── */
.vp-ledger-open td {
  background: #faf8f3; font-weight: 700; font-size: .78rem;
  text-transform: uppercase; letter-spacing: .05em; color: var(--vp-muted, #767a82);
}
.vp-ledger-sub td { background: #fdfcf9; font-size: .8rem; }
.vp-acc-sheet .adm-table { font-variant-numeric: tabular-nums; }

/* ── Dispatch board ────────────────────────────────────────────────────────── */
.vp-dgroup { margin-bottom: 26px; }
.vp-dgroup-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.vp-dgroup-count {
  font-family: var(--vp-font); font-weight: 800; font-size: 1.05rem;
  font-variant-numeric: tabular-nums; color: var(--vp-ink, #17191c);
}
.vp-dgroup-hint { font-size: .78rem; color: var(--vp-muted, #767a82); }
.vp-dlist { display: flex; flex-direction: column; gap: 8px; }
.vp-drow {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); padding: 12px 14px;
}
.vp-drow > img, .vp-drow-noimg {
  width: 62px; height: 44px; object-fit: cover; border-radius: 8px; flex: 0 0 62px;
  background: #efece3;
}
.vp-drow-main { flex: 1 1 260px; min-width: 0; }
.vp-drow-title { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; font-size: .9rem; font-weight: 600; }
.vp-drow-title .linklike { font-weight: 800; color: var(--vp-ink, #17191c); }
.vp-drow-plate {
  font-family: ui-monospace, Menlo, monospace; font-size: .7rem; letter-spacing: .04em;
  border: 1px solid var(--vp-line-strong, #d7d2c3); border-radius: 5px; padding: 1px 6px; color: var(--vp-muted, #767a82);
}
.vp-drow-sub { font-size: .8rem; color: var(--vp-muted, #767a82); margin-top: 3px; }
.vp-drow-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-left: auto; }

/* ── Availability calendar ─────────────────────────────────────────────────── */
/* background-COLOR, not the shorthand: the scroller also carries .adm-scroll-x,
   whose edge shadows are background-images — the "this pans sideways" cue a
   phone gets instead of a scrollbar — and the shorthand wiped them out. */
.vp-cal-scroll { overflow-x: auto; border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius, 13px); background-color: #fff; }
.vp-cal { min-width: 760px; }
.vp-cal-head, .vp-cal-row { display: grid; grid-template-columns: 210px 1fr; align-items: stretch; }
.vp-cal-head { position: sticky; top: 0; z-index: 3; background: #faf8f3; border-bottom: 1px solid var(--vp-line, #e6e2d8); }
.vp-cal-corner {
  padding: 8px 12px; font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--vp-muted, #767a82); display: flex; align-items: center;
  position: sticky; left: 0; background: #faf8f3; z-index: 2;
}
.vp-cal-head { grid-template-columns: 210px repeat(var(--days), 1fr); }
.vp-cal-day {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 6px 2px; font-size: .68rem; color: var(--vp-muted, #767a82);
  border-left: 1px solid var(--vp-line-soft, #efece3);
}
.vp-cal-day .num { font-weight: 700; font-size: .8rem; color: var(--vp-ink, #17191c); font-variant-numeric: tabular-nums; }
.vp-cal-day.weekend { background: #f4f1e9; }
.vp-cal-day.today { background: var(--vp-ink, #17191c); }
.vp-cal-day.today .num, .vp-cal-day.today .dow { color: #fff; }
.vp-cal-row { border-bottom: 1px solid var(--vp-line-soft, #efece3); }
.vp-cal-row:last-child { border-bottom: none; }
.vp-cal-car {
  display: flex; align-items: center; gap: 9px; padding: 8px 12px; min-width: 0;
  position: sticky; left: 0; background: #fff; z-index: 2; border-right: 1px solid var(--vp-line, #e6e2d8);
}
.vp-cal-car img { width: 38px; height: 27px; object-fit: cover; border-radius: 5px; flex: 0 0 38px; }
.vp-cal-car .t { font-size: .78rem; font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vp-cal-car .p { font-size: .68rem; color: var(--vp-faint, #a4a8b0); }
.vp-cal-track { position: relative; height: 46px; }
.vp-cal-cell {
  position: absolute; top: 0; bottom: 0; border: none; background: transparent; cursor: pointer;
  border-left: 1px solid var(--vp-line-soft, #efece3); padding: 0;
}
.vp-cal-cell:hover { background: rgba(23, 25, 28, .05); }
.vp-cal-cell.today { background: rgba(23, 25, 28, .035); }
.vp-cal-cell.dragging { background: rgba(194, 102, 15, .22); }
.vp-cal-bar {
  position: absolute; top: 8px; height: 30px; border: none; border-radius: 6px; cursor: pointer;
  font-family: var(--vp-font); font-size: .7rem; font-weight: 600; color: #fff;
  padding: 0 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left;
  display: flex; align-items: center; z-index: 1;
}
.vp-cal-bar:hover { filter: brightness(1.12); }
.vp-cal-bar.confirmed { background: #2f6f4a; }
.vp-cal-bar.active    { background: var(--vp-brand, #16a34a); }
.vp-cal-bar.overdue   { background: var(--vp-red, #c0341f); }
.vp-cal-bar.wait      { background: #b58230; }
.vp-cal-bar.done      { background: #9aa39d; }
.vp-cal-bar.blocked {
  background: repeating-linear-gradient(45deg, #6d6a63, #6d6a63 5px, #57544e 5px, #57544e 10px);
  font-size: .66rem; text-transform: uppercase; letter-spacing: .04em;
}
.vp-cal-legend { display: flex; align-items: center; gap: 7px; font-size: .72rem; color: var(--vp-muted, #767a82); flex-wrap: wrap; }
.vp-cal-legend i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; margin-left: 6px; }
.vp-cal-legend i.confirmed { background: #2f6f4a; }
.vp-cal-legend i.active { background: var(--vp-brand, #16a34a); }
.vp-cal-legend i.overdue { background: var(--vp-red, #c0341f); }
.vp-cal-legend i.blocked { background: #6d6a63; }

@media (max-width: 700px) {
  /* Two selectors, two templates. The head used to share the rows' `140px 1fr`
     here, which dropped its day columns: every day cell after the first
     wrapped onto its own line down the car column. */
  .vp-cal-row { grid-template-columns: 140px 1fr; }
  .vp-cal-head { grid-template-columns: 140px repeat(var(--days), 1fr); }
  .vp-cal-car img { display: none; }
  .vp-drow-actions { width: 100%; margin-left: 0; }
}
/* 62px photo + 14px gap + a 260px text basis is exactly 336px — a 390px
   phone's content box — so at 375/360 the photo sat alone on its own line. */
@media (max-width: 480px) {
  .vp-drow-main { flex-basis: 180px; }
}

/* ── Booking timeline ──────────────────────────────────────────────────────── */
.vp-timeline { display: flex; flex-direction: column; gap: 2px; }
.vp-tl-item { display: grid; grid-template-columns: 18px 1fr; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--vp-line-soft, #efece3); }
.vp-tl-item:last-child { border-bottom: none; }
.vp-tl-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--vp-brand, #16a34a); margin: 6px auto 0; }
.vp-tl-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: .88rem; text-transform: capitalize; }
.vp-tl-who { font-size: .76rem; color: var(--vp-muted, #767a82); text-transform: none; }
.vp-tl-detail { font-size: .8rem; color: var(--vp-ink-soft, #40444b); margin-top: 2px; }
.vp-tl-when { font-size: .72rem; color: var(--vp-faint, #a4a8b0); margin-top: 3px; font-variant-numeric: tabular-nums; }

/* ── Handover wizard (full-screen, phone-first) ────────────────────────────── */
.vp-ho {
  position: fixed; inset: 0; z-index: 300; background: var(--vp-bg, #f7f5f0);
  display: flex; flex-direction: column; font-family: var(--vp-font);
}
.vp-ho-head { display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: #fff; border-bottom: 1px solid var(--vp-line, #e6e2d8); }
.vp-ho-title { font-weight: 700; font-size: .96rem; }
.vp-ho-sub { font-size: .78rem; color: var(--vp-muted, #767a82); }
.vp-ho-steps { display: flex; gap: 2px; background: #fff; border-bottom: 1px solid var(--vp-line, #e6e2d8); overflow-x: auto; }
.vp-ho-step {
  flex: 1; min-width: 84px; border: none; background: none; cursor: pointer; font-family: inherit;
  padding: 10px 8px; font-size: .78rem; font-weight: 600; color: var(--vp-muted, #767a82);
  border-bottom: 2px solid transparent; display: flex; align-items: center; justify-content: center; gap: 6px;
}
.vp-ho-step .n {
  width: 19px; height: 19px; border-radius: 50%; background: #efece3; color: var(--vp-muted, #767a82);
  display: grid; place-items: center; font-size: .68rem; font-weight: 700;
}
.vp-ho-step.active { color: var(--vp-ink, #17191c); border-bottom-color: var(--vp-ink, #17191c); }
.vp-ho-step.active .n { background: var(--vp-ink, #17191c); color: #fff; }
.vp-ho-step.done .n { background: var(--vp-brand, #16a34a); color: #fff; }
.vp-ho-body { flex: 1; overflow-y: auto; padding: 18px 16px; max-width: 720px; width: 100%; margin: 0 auto; }
.vp-ho-hint { font-size: .82rem; color: var(--vp-muted, #767a82); margin: 0 0 14px; line-height: 1.55; }
.vp-ho-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
.vp-ho-tile {
  position: relative; aspect-ratio: 4/3; border: 1.5px dashed var(--vp-line-strong, #d7d2c3); border-radius: 10px;
  background: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center;
  cursor: pointer; overflow: hidden;
}
.vp-ho-tile.filled { border-style: solid; border-color: var(--vp-brand, #16a34a); }
.vp-ho-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.vp-ho-tile-icon { font-size: 1.5rem; color: var(--vp-faint, #a4a8b0); }
.vp-ho-tile-label {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 4px 7px; font-size: .7rem; font-weight: 600;
  background: rgba(255,255,255,.92); color: var(--vp-ink, #17191c);
}
.vp-ho-diagram { display: flex; justify-content: center; margin-bottom: 14px; }
.vp-ho-diagram svg { width: 190px; height: auto; }
.vp-ho-damages { display: flex; flex-direction: column; gap: 8px; }
.vp-ho-damage { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; background: #fff; border: 1px solid var(--vp-line, #e6e2d8); border-radius: 9px; padding: 9px 11px; font-size: .82rem; }
.vp-ho-damage select, .vp-ho-damage input { padding: 5px 8px; border: 1.5px solid var(--vp-line-strong, #d7d2c3); border-radius: 7px; font-family: inherit; font-size: .8rem; }
.vp-ho-damage input { flex: 1; min-width: 110px; }
.vp-ho-sigwrap { position: relative; margin-bottom: 14px; }
.vp-ho-sig, .vp-sign-pad canvas {
  width: 100%; height: 160px; background: #fff; border: 1.5px solid var(--vp-line-strong, #d7d2c3);
  border-radius: 10px; touch-action: none; display: block;
}
.vp-ho-sigclear { position: absolute; top: 8px; right: 8px; }
.vp-ho-summary { list-style: none; padding: 0; margin: 0; display: flex; gap: 16px; flex-wrap: wrap; font-size: .82rem; color: var(--vp-muted, #767a82); }
.vp-ho-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; background: #fff; border-top: 1px solid var(--vp-line, #e6e2d8);
}

/* ── Public signing page ───────────────────────────────────────────────────── */
.vp-sign { min-height: 100vh; background: var(--vp-bg, #f7f5f0); padding: 20px 14px 60px; font-family: var(--vp-font); }
.vp-sign-card { max-width: 760px; margin: 0 auto; background: #fff; border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius-lg, 20px); overflow: hidden; }
.vp-sign-head { padding: 22px 24px 16px; border-bottom: 1px solid var(--vp-line, #e6e2d8); }
.vp-sign-vendor { font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--vp-muted, #767a82); }
.vp-sign-head h1 { font-size: 1.35rem; margin: 4px 0 0; letter-spacing: -.02em; }
.vp-sign-meta { font-size: .82rem; color: var(--vp-muted, #767a82); margin: 5px 0 0; }
.vp-sign-doc { max-height: 46vh; overflow-y: auto; border-bottom: 1px solid var(--vp-line, #e6e2d8); background: #fdfcf9; }
.vp-sign-actions { padding: 20px 24px 26px; display: flex; flex-direction: column; gap: 14px; }
.vp-sign-pad { position: relative; }
.vp-sign-padlabel { display: block; font-size: .75rem; font-weight: 600; color: var(--vp-muted, #767a82); margin-bottom: 5px; }
.vp-sign-pad .adm-btn { position: absolute; top: 26px; right: 8px; }
/* The renter's signing page (/contract/sign/) loads no admin.css, so none of
   its touch floors reach this "Clear" — a ~30px target on the one page a
   renter uses with a finger. */
@media (max-width: 900px) { .vp-sign-pad .adm-btn { min-height: 40px; } }
.vp-sign-agree { display: flex; gap: 9px; align-items: flex-start; font-size: .86rem; line-height: 1.5; }
.vp-sign-submit { width: 100%; justify-content: center; height: 48px; font-size: .95rem; }
.vp-sign-fine { font-size: .74rem; color: var(--vp-faint, #a4a8b0); text-align: center; margin: 0; }
.vp-sign-done { padding: 46px 24px; text-align: center; }
.vp-sign-tick { width: 58px; height: 58px; border-radius: 50%; background: #eafaef; color: #146534; font-size: 1.9rem; display: grid; place-items: center; margin: 0 auto 16px; }
.vp-sign-done h2 { margin: 0 0 8px; font-size: 1.2rem; }
.vp-sign-done p { color: var(--vp-muted, #767a82); font-size: .9rem; max-width: 42ch; margin: 0 auto; }

/* ── Remember me ───────────────────────────────────────────────────────────── */
.vp-remember {
  display: flex; align-items: center; gap: 9px; margin: 4px 0 18px;
  font-size: .84rem; color: rgba(255, 255, 255, .62); cursor: pointer;
}
.vp-remember input { width: 16px; height: 16px; accent-color: #16a34a; cursor: pointer; }

/* ── Printable document (tax invoice / receipt / credit note) ──────────────── */
.vp-doc { background: #fff; color: #111; font-size: 12.5px; line-height: 1.55; }
.vp-doc-head { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  border-bottom: 2px solid #111; padding-bottom: 14px; margin-bottom: 16px; }
.vp-doc-logo { max-height: 44px; margin-bottom: 8px; display: block; }
.vp-doc-co { font-size: 1.05rem; font-weight: 800; letter-spacing: -.01em; }
.vp-doc-ar { font-size: .86rem; color: #444; }
.vp-doc-meta { font-size: .74rem; color: #555; }
.vp-doc-label { font-size: .62rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #777; margin-bottom: 3px; }
.vp-doc-type { font-size: .9rem; font-weight: 800; letter-spacing: .07em; }
.vp-doc-no { font-family: ui-monospace, Menlo, monospace; font-size: .84rem; margin-top: 3px; }
.vp-doc-parties { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 20px; margin-bottom: 16px; }
.vp-doc-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.vp-doc-table th { text-align: left; background: #f3f1ea; padding: 7px 8px; font-size: .66rem;
  text-transform: uppercase; letter-spacing: .06em; color: #555; border-bottom: 1px solid #ddd; }
.vp-doc-table td { padding: 7px 8px; border-bottom: 1px solid #eee; vertical-align: top; font-variant-numeric: tabular-nums; }
.vp-doc-totals { margin: 14px 0 0 auto; max-width: 300px; font-variant-numeric: tabular-nums; }
.vp-doc-totals > div { display: flex; justify-content: space-between; gap: 20px; padding: 5px 0; font-size: 12.5px; }
.vp-doc-totals .grand { border-top: 1.5px solid #111; margin-top: 4px; padding-top: 8px; font-size: 14px; font-weight: 800; }
.vp-doc-totals .due strong { color: #c2660f; }
.vp-doc-notes { margin-top: 16px; padding-top: 10px; border-top: 1px solid #eee; font-size: .78rem; color: #444; }
.vp-doc-foot { margin-top: 18px; font-size: .68rem; color: #888; text-align: center; }

@media print {
  .vp-modal-overlay { position: static !important; background: none !important; padding: 0 !important; overflow: visible !important; }
  .vp-modal { max-height: none !important; box-shadow: none !important; border-radius: 0 !important; max-width: none !important; }
  .vp-modal-head, .vp-modal-body { overflow: visible !important; padding: 0 !important; }
  .vp-modal-head { display: none !important; }

  /* The modal plays a scale-in entrance. A transform on an ancestor scales the
     A4 page with it and makes it the containing block for anything positioned
     inside — so a print fired mid-animation came out fractionally short and
     mis-paginated. Paper has no animations. */
  .vp-modal { animation: none !important; transform: none !important; }

  /* Printing a document prints ONLY that document. The modal is portalled to
     <body>, so the tab behind it (the documents table) is a sibling and would
     otherwise print first and push the invoice onto page 2. The class is set
     for the duration of the print job by printDocument() in shared.tsx. */
  body.vp-printing-doc .adm-shell { display: none !important; }

  /* Coloured bands, table header fills and the total block ARE the design.
     Browsers drop background fills when printing unless told otherwise, which
     turned a branded invoice into bare text on white. */
  .vp-doc, .vp-doc *, .vp-doc-canvas, .vp-doc-canvas * {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
}

/* ── Document designs: gallery + drag-and-drop builder ──────────────────────
   The builder is a three-rail workspace (palette / page / properties). The
   page itself is painted by the real renderer at a transform scale, with a
   transparent hit-box overlay in SCREEN pixels on top — so outlines and
   handles stay 1px crisp at every zoom instead of scaling down with the page.
   ------------------------------------------------------------------------- */

/* Gallery */
.vp-tg {
  display: grid; gap: 18px; margin: 0 0 22px;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
}
.vp-tg-h {
  font-family: var(--vp-font); font-size: .74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; color: var(--vp-muted, #767a82);
  margin: 26px 0 12px;
}
.vp-tg-card {
  background: var(--vp-surface, #fff); border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); overflow: hidden;
  display: flex; flex-direction: column; transition: border-color .14s, transform .14s;
}
.vp-tg-card:hover { border-color: var(--vp-line-strong, #d7d2c3); transform: translateY(-2px); }
.vp-tg-card.is-default { border-color: var(--vp-brand, #16a34a); box-shadow: 0 0 0 1px var(--vp-brand, #16a34a); }
.vp-tg-thumb {
  height: 316px; overflow: hidden; background: #efece4;
  display: flex; justify-content: center; padding: 12px 0 0;
  border-bottom: 1px solid var(--vp-line, #e6e2d8);
}
.vp-tg-thumb > div { box-shadow: 0 6px 20px -8px rgba(0, 0, 0, .3); }
.vp-tg-blank { color: var(--vp-faint, #a4a8b0); font-size: .8rem; align-self: center; }
.vp-tg-meta { padding: 12px 14px 4px; display: flex; flex-direction: column; gap: 2px; }
.vp-tg-meta strong { font-size: .92rem; color: var(--vp-ink, #17191c); }
.vp-tg-meta span { font-size: .75rem; color: var(--vp-muted, #767a82); }
.vp-tg-acts { display: flex; gap: 6px; flex-wrap: wrap; padding: 10px 14px 14px; margin-top: auto; }

/* Workspace shell */
.vp-tb { display: flex; flex-direction: column; gap: 12px; }
.vp-tb-top {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 12px; background: var(--vp-surface, #fff);
  border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius, 13px);
}
.vp-tb-sp { flex: 1 1 auto; }
.vp-tb-name {
  font-family: var(--vp-font); font-weight: 700; font-size: .95rem; color: var(--vp-ink, #17191c);
  border: 1px solid transparent; background: transparent; padding: 6px 10px;
  border-radius: var(--vp-radius-sm, 8px); min-width: 150px; max-width: 260px;
}
.vp-tb-name:hover { border-color: var(--vp-line, #e6e2d8); }
.vp-tb-name:focus { border-color: var(--vp-ink, #17191c); outline: none; background: #fff; }
.vp-tb-zoom {
  display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius-sm, 8px); padding: 2px;
}
.vp-tb-zoom button {
  border: none; background: none; cursor: pointer; width: 26px; height: 24px;
  font-size: 1rem; line-height: 1; color: var(--vp-ink-soft, #40444b); border-radius: 5px;
}
.vp-tb-zoom button:hover { background: var(--vp-bg, #f7f5f0); }
.vp-tb-zoom b {
  font-size: .74rem; font-variant-numeric: tabular-nums; color: var(--vp-muted, #767a82);
  min-width: 38px; text-align: center;
}
.adm-btn.is-on { background: var(--vp-ink, #17191c); color: #fff; border-color: var(--vp-ink, #17191c); }
.vp-tb-msg { margin: 0; }

.vp-tb-body { display: grid; grid-template-columns: 216px minmax(0, 1fr) 268px; gap: 12px; align-items: start; }
.vp-tb.is-preview .vp-tb-body { grid-template-columns: minmax(0, 1fr); }
.vp-tb.is-preview .vp-tb-rail { display: none; }

.vp-tb-rail {
  background: var(--vp-surface, #fff); border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); padding: 14px;
  max-height: calc(100vh - 210px); overflow-y: auto; position: sticky; top: 12px;
}
.vp-tb-rail h4 {
  font-family: var(--vp-font); font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--vp-muted, #767a82);
  margin: 0 0 9px; display: flex; justify-content: space-between; align-items: baseline;
}
.vp-tb-rail h4:not(:first-child) { margin-top: 20px; }
.vp-tb-rail h5 {
  font-family: var(--vp-font); font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--vp-muted, #767a82);
  margin: 18px 0 8px; padding-top: 12px; border-top: 1px solid var(--vp-line, #e6e2d8);
}
.vp-tb-count { font-weight: 500; letter-spacing: 0; text-transform: none; font-size: .7rem; color: var(--vp-faint, #a4a8b0); }
.vp-tb-help { font-size: .72rem; line-height: 1.5; color: var(--vp-muted, #767a82); margin: 8px 0 0; }
.vp-tb-help code { font-size: .68rem; background: var(--vp-bg, #f7f5f0); padding: 1px 4px; border-radius: 4px; }

/* Palette + presets */
.vp-tb-palette, .vp-tb-presets { display: flex; flex-direction: column; gap: 5px; }
.vp-tb-chip {
  display: flex; flex-direction: column; gap: 1px; text-align: left; cursor: pointer;
  border: 1px solid var(--vp-line, #e6e2d8); background: var(--vp-surface, #fff);
  border-radius: var(--vp-radius-sm, 8px); padding: 7px 10px; font-family: inherit;
  transition: border-color .12s, background .12s;
}
.vp-tb-chip:hover { border-color: var(--vp-ink, #17191c); background: var(--vp-bg, #f7f5f0); }
.vp-tb-chip strong { font-size: .8rem; font-weight: 600; color: var(--vp-ink, #17191c); }
.vp-tb-chip em { font-style: normal; font-size: .68rem; color: var(--vp-faint, #a4a8b0); }

/* Layer list */
.vp-tb-layers { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.vp-tb-layers button {
  display: flex; align-items: center; gap: 7px; width: 100%; text-align: left; cursor: pointer;
  border: none; background: none; font-family: inherit; font-size: .76rem;
  color: var(--vp-ink-soft, #40444b); padding: 5px 7px; border-radius: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vp-tb-layers button:hover { background: var(--vp-bg, #f7f5f0); }
.vp-tb-layers button.on { background: var(--vp-ink, #17191c); color: #fff; }
.vp-tb-dot { width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto; background: var(--vp-faint, #a4a8b0); }
.vp-tb-dot[data-t="text"] { background: #2251c9; }
.vp-tb-dot[data-t="logo"], .vp-tb-dot[data-t="image"] { background: #c2660f; }
.vp-tb-dot[data-t="items_table"] { background: #16a34a; }
.vp-tb-dot[data-t="totals"] { background: #0d6b34; }
.vp-tb-dot[data-t="divider"] { background: #a4a8b0; }
.vp-tb-dot[data-t="spacer"] { background: #17191c; }

/* Canvas */
.vp-tb-canvas {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 20px; background: #efece4; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); overflow: auto;
}
.vp-tb-stage { position: relative; flex: 0 0 auto; }
.vp-tb-paper { position: absolute; inset: 0; overflow: hidden; box-shadow: 0 10px 34px -14px rgba(0, 0, 0, .45); }
.vp-tb-overlay { position: absolute; inset: 0; }
.vp-tb-box {
  position: absolute; cursor: move; border: 1px solid transparent; border-radius: 2px;
  transition: border-color .1s, background .1s;
}
.vp-tb-box:hover { border-color: rgba(34, 81, 201, .5); background: rgba(34, 81, 201, .06); }
.vp-tb-box.is-sel { border: 1.5px solid #2251c9; background: rgba(34, 81, 201, .07); }
.vp-tb-handle {
  position: absolute; right: -5px; bottom: -5px; width: 11px; height: 11px;
  background: #fff; border: 1.5px solid #2251c9; border-radius: 2px; cursor: nwse-resize;
}
.vp-tb-tip { font-size: .74rem; color: var(--vp-muted, #767a82); margin: 0; text-align: center; }

/* Properties */
.vp-tb-panel { display: flex; flex-direction: column; }
.vp-tb-panel > h4 { margin-bottom: 12px; }
.vp-tb-geom { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; }
.vp-tb-actions { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 12px; }
.vp-tb-danger { color: var(--vp-red, #c0341f) !important; }
.vp-tb-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 30px; font-size: .76rem; color: var(--vp-ink-soft, #40444b);
}
.vp-tb-row > span:first-child { flex: 0 0 auto; }
.vp-tb-row-in { display: inline-flex; align-items: center; gap: 5px; justify-content: flex-end; min-width: 0; }
.vp-tb-row select, .vp-tb-row input[type="text"], .vp-tb-row input:not([type]) {
  font-family: inherit; font-size: .76rem; padding: 4px 6px; max-width: 132px;
  border: 1px solid var(--vp-line, #e6e2d8); border-radius: 6px; background: #fff; color: var(--vp-ink, #17191c);
}
.vp-tb-num { display: inline-flex; align-items: center; gap: 3px; }
.vp-tb-num input {
  width: 58px; font-family: inherit; font-size: .76rem; padding: 4px 6px; text-align: right;
  font-variant-numeric: tabular-nums; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: 6px; background: #fff; color: var(--vp-ink, #17191c);
}
.vp-tb-num i { font-style: normal; font-size: .66rem; color: var(--vp-faint, #a4a8b0); }
.vp-tb-colour { display: inline-flex; align-items: center; gap: 5px; }
.vp-tb-colour input[type="color"] {
  width: 26px; height: 22px; padding: 0; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: 5px; background: none; cursor: pointer;
}
.vp-tb-colour code { font-size: .64rem; color: var(--vp-faint, #a4a8b0); font-variant-numeric: tabular-nums; }
.vp-tb-mini {
  border: 1px solid var(--vp-line, #e6e2d8); background: #fff; cursor: pointer;
  border-radius: 5px; font-size: .66rem; padding: 2px 5px; color: var(--vp-muted, #767a82); font-family: inherit;
}
.vp-tb-mini:hover { border-color: var(--vp-ink, #17191c); color: var(--vp-ink, #17191c); }
.vp-tb-seg { display: inline-flex; border: 1px solid var(--vp-line, #e6e2d8); border-radius: 6px; overflow: hidden; }
.vp-tb-seg button {
  border: none; background: #fff; cursor: pointer; font-family: inherit; font-size: .7rem;
  padding: 4px 8px; color: var(--vp-muted, #767a82); border-right: 1px solid var(--vp-line, #e6e2d8);
}
.vp-tb-seg button:last-child { border-right: none; }
.vp-tb-seg button.on { background: var(--vp-ink, #17191c); color: #fff; }
.vp-tb-check {
  display: flex; align-items: center; gap: 7px; font-size: .76rem;
  color: var(--vp-ink-soft, #40444b); min-height: 28px; cursor: pointer;
}
.vp-tb-check input { width: 14px; height: 14px; accent-color: var(--vp-ink, #17191c); }
.vp-tb-content {
  width: 100%; font-family: inherit; font-size: .78rem; line-height: 1.6; resize: vertical;
  border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius-sm, 8px);
  padding: 8px 10px; color: var(--vp-ink, #17191c); background: #fff; box-sizing: border-box;
}
.vp-tb-content:focus { border-color: var(--vp-ink, #17191c); outline: none; }

/* Token picker */
.vp-tb-tokens { display: flex; flex-direction: column; gap: 7px; margin-top: 9px; }
.vp-tb-tokens > div { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; }
.vp-tb-tokgroup {
  flex: 0 0 100%; font-size: .62rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--vp-faint, #a4a8b0);
}
.vp-tb-tokens button {
  border: 1px solid var(--vp-line, #e6e2d8); background: var(--vp-bg, #f7f5f0); cursor: pointer;
  border-radius: 20px; font-family: inherit; font-size: .68rem; padding: 3px 9px;
  color: var(--vp-ink-soft, #40444b); transition: background .12s, color .12s, border-color .12s;
}
.vp-tb-tokens button:hover { background: var(--vp-ink, #17191c); border-color: var(--vp-ink, #17191c); color: #fff; }

/* Columns editor */
.vp-tb-cols { display: flex; flex-direction: column; gap: 5px; }
.vp-tb-col { display: flex; align-items: center; gap: 4px; }
.vp-tb-col.off { opacity: .45; }
.vp-tb-col input:not([type]) { flex: 1 1 auto; min-width: 0; max-width: none; }
.vp-tb-col .vp-tb-num input { width: 42px; }
.vp-tb-eye {
  border: none; background: none; cursor: pointer; font-size: .78rem; padding: 2px; line-height: 1;
}
.vp-tb-addcol { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }

/* Designed document inside the viewer modal */
.vp-doc-canvas { overflow-x: auto; display: flex; justify-content: center; }
.vp-doc-canvas > div { flex: 0 0 auto; box-shadow: 0 0 0 1px var(--vp-line, #e6e2d8); }

@media print {
  .vp-doc-canvas { overflow: visible !important; display: block !important; }
  .vp-doc-canvas > div { box-shadow: none !important; }
}

@media (max-width: 1180px) {
  .vp-tb-body { grid-template-columns: 180px minmax(0, 1fr) 240px; }
}
@media (max-width: 900px) {
  .vp-tb-body { grid-template-columns: minmax(0, 1fr); }
  .vp-tb-rail { position: static; max-height: none; }
  .vp-tb-right { order: -1; }
}

/* ── Book Now: incoming requests (VendorRequests) ────────────────────────────
   Cards, not a table. Every other tab in this portal is a
   <div style="overflow-x:auto"><table>, which on a phone is a sideways scroll
   — and a request answered standing in a car park cannot be that. Everything
   below is scoped under body.vp-portal and coloured only from the --vp-*
   tokens, because the Admin and Agent apps reuse the same .adm-* chrome and
   must not inherit a line of it. */
body.vp-portal .vp-req-list { display: grid; gap: 10px; }
body.vp-portal .vp-req {
  display: grid; grid-template-columns: 64px 1fr; gap: 12px;
  padding: 12px; border: 1px solid var(--vp-line, #e6e2d8);
  border-radius: var(--vp-radius, 13px); background: #fff;
}
/* Unread earns a rule, not a fill — in this portal green is genuine state. */
body.vp-portal .vp-req.unread { border-left: 3px solid var(--vp-brand, #16a34a); }
body.vp-portal .vp-req-thumb {
  width: 64px; height: 48px; object-fit: cover;
  border: 1px solid var(--vp-line, #e6e2d8); border-radius: var(--vp-radius-sm, 8px);
  background: var(--vp-bg, #f7f5f0);
}
/* min-width:0, or one long car title stretches the 1fr track and pushes the
   card's own actions off the right edge of the phone. */
body.vp-portal .vp-req-main { min-width: 0; }
body.vp-portal .vp-req-title {
  font-weight: 600; font-size: .92rem; letter-spacing: -.01em; color: var(--vp-ink, #17191c);
}
body.vp-portal .vp-req-meta { margin-top: 2px; font-size: .78rem; color: var(--vp-muted, #767a82); }
body.vp-portal .vp-req-money {
  margin-top: 6px; font-size: .82rem; color: var(--vp-ink-soft, #40444b);
  font-variant-numeric: tabular-nums;
}
body.vp-portal .vp-req-warn {
  margin-top: 6px; font-size: .78rem; font-weight: 600; color: var(--vp-amber, #c2660f);
}
body.vp-portal .vp-req-acts { display: flex; gap: 8px; margin-top: 10px; }
@media (max-width: 700px) {
  /* Confirm / Counter are the whole point of the card and they are hit with a
     thumb — full width, and never under the 44px touch target. */
  body.vp-portal .vp-req-acts .adm-btn { flex: 1; min-height: 44px; justify-content: center; }
}

/* ── Book Now: mobile bottom tab bar (VendorBottomBar) ───────────────────────
   Five destinations — Today · Requests · Bookings · Cars · More. Desktop keeps
   the sidebar; this only exists under 900px, where .adm-sidebar has already
   become an off-canvas drawer and the burger is the only way to change tab. */
body.vp-portal .vp-bbar { display: none; }
@media (max-width: 900px) {
  body.vp-portal .vp-bbar {
    display: grid; grid-template-columns: repeat(5, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 470;
    background: var(--vp-surface, #fff); border-top: 1px solid var(--vp-line, #e6e2d8);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  body.vp-portal .vp-bbar-i {
    min-height: 56px; position: relative;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    border: none; background: none; cursor: pointer; font-family: inherit;
    font-size: .64rem; font-weight: 600; letter-spacing: .01em;
    color: var(--vp-muted, #767a82);
  }
  body.vp-portal .vp-bbar-i .ico { display: flex; align-items: center; justify-content: center; }
  body.vp-portal .vp-bbar-i.active { color: var(--vp-ink, #17191c); }
  /* admin.css styles .badge-count only inside .adm-sb-item, so the tab bar's
     own counter needs its own rule or it renders as bare digits. */
  body.vp-portal .vp-bbar-i .badge-count {
    position: absolute; top: 6px; left: 50%; margin-left: 6px;
    background: var(--vp-red, #c0341f); color: #fff;
    font-size: .6rem; font-weight: 700; line-height: 1; padding: 3px 5px; border-radius: 20px;
  }

  /* MANDATORY, same reasoning as the /cars/ toolbar reserve at style.css:630-637:
     a fixed control must never cover a tappable one. Without this the bar sits
     on top of the last row of every table in the portal. */
  body.vp-portal .adm-content { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }

  /* …and the same rule read the other way: the bar is above the shell (470 vs
     the sidebar's 50 and the modal overlay's 200), so anything that takes over
     the screen has to take the bar with it, or it floats over that surface's
     own buttons instead. Dropped whole by browsers without :has(), which only
     costs the overlap it was added to prevent. */
  body.vp-portal:has(.vp-modal-overlay) .vp-bbar,
  body.vp-portal:has(.vp-ho) .vp-bbar,
  body.vp-portal:has(.adm-sidebar.open) .vp-bbar { display: none; }

  /* A request thread is a phone chat, not a dialog — full-screen, the pattern
     .vp-ho already uses. 100vh first so a browser without dvh still gets a
     bounded box (the modal must stay a bounded flex column or its sticky
     .vp-formbar resolves against the overlay and pins to the viewport); the
     overlay's own 24px/16px padding and the 640px cap have to go with it or
     the 100dvh box simply overflows its container. */
  body.vp-portal .vp-modal-overlay { padding: 0; }
  body.vp-portal .vp-modal {
    inset: 0; width: 100%; max-width: none;
    max-height: 100vh; height: 100dvh; border-radius: 0;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   Poster Studio — the vendor's social-media image maker.

   The canvas is the product here, so everything else stays quiet: a neutral
   stage, controls in one column beside it, and no surface that competes with
   the poster for attention. All sizing is driven off the canvas's own
   intrinsic ratio (1080x1080, 1080x1920, …) rather than hardcoded boxes, so a
   new poster size needs no CSS at all.
   ══════════════════════════════════════════════════════════════════════════ */

/* The studio is mounted in TWO shells: the vendor portal (body.vp-portal, which
   defines the --vp-* palette) and the admin (body.adm-body, which does not).
   Every rule below is therefore unscoped, and the tokens it needs are declared
   here on the component root — same values, same convention as .vp-modal's
   var(--vp-x, literal) fallbacks. Without this the admin studio rendered with
   no layout at all: an untamed 1080px canvas running off the side of a phone.
   Inside the portal these shadow identical inherited values, so nothing there
   changes. */
.vp-posters, .vp-poster-editor {
  --vp-surface: #ffffff;
  --vp-ink: #17191c;
  --vp-ink-soft: #40444b;
  --vp-muted: #767a82;
  --vp-faint: #a4a8b0;
  --vp-line: #e6e2d8;
  --vp-line-strong: #d7d2c3;
  --vp-brand: #16a34a;
  --vp-brand-ink: #0d6b34;
  --vp-amber: #c2660f;
  --vp-red: #c0341f;
  --vp-radius-sm: 8px;
  --vp-radius: 13px;
}

.vp-posters { display: flex; flex-direction: column; gap: 16px; }

.vp-poster-hero {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 20px 22px; flex-wrap: wrap;
}
.vp-poster-hero h3 { margin: 0 0 4px; font-size: 1.05rem; font-weight: 700; letter-spacing: -.01em; }
.vp-poster-hero p { margin: 0; color: var(--vp-muted); font-size: .86rem; line-height: 1.55; max-width: 62ch; }

.vp-poster-empty {
  padding: 34px 26px; text-align: center; color: var(--vp-muted); font-size: .9rem; line-height: 1.6;
}
.vp-poster-empty .big { font-size: 1.05rem; font-weight: 700; color: var(--vp-ink); margin-bottom: 6px; }
.vp-poster-empty p { max-width: 54ch; margin: 0 auto 16px; }

.vp-poster-note {
  padding: 10px 14px; border-radius: var(--vp-radius-sm); font-size: .84rem; cursor: pointer;
  background: #eef7f1; color: var(--vp-brand-ink); border: 1px solid #cfe8d9;
}
.vp-poster-note.bad { background: #fdf0ed; color: var(--vp-red); border-color: #f0cdc4; }

.vp-poster-hint { color: var(--vp-muted); font-size: .8rem; line-height: 1.55; margin: 0 0 12px; }
.vp-poster-warn {
  margin: 12px 0 0; padding: 10px 14px; border-radius: var(--vp-radius-sm);
  background: #fdf6e8; border: 1px solid #f0e0bd; color: #7a5a12; font-size: .8rem; line-height: 1.55;
}

/* ── Saved posters ─────────────────────────────────────────────────────── */
.vp-poster-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.vp-poster-card {
  background: var(--vp-surface); border: 1px solid var(--vp-line);
  border-radius: var(--vp-radius); overflow: hidden; display: flex; flex-direction: column;
}
/* A fixed-height well, so a story and a banner sit in the same grid row
   without one card being three times the height of its neighbour. */
.vp-poster-thumb {
  height: 210px; display: flex; align-items: center; justify-content: center;
  background: #eceae4; padding: 10px;
}
.vp-poster-thumb img { max-width: 100%; max-height: 100%; border-radius: 6px; display: block; }
.vp-poster-thumb span { color: var(--vp-faint); font-size: .8rem; }
.vp-poster-meta { padding: 11px 13px 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vp-poster-meta strong {
  font-size: .88rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vp-poster-meta span { font-size: .72rem; color: var(--vp-faint); font-variant-numeric: tabular-nums; }
.vp-poster-actions {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 11px 13px 13px; margin-top: auto;
}
.vp-poster-actions .adm-btn { text-decoration: none; }

/* ── Car picker ────────────────────────────────────────────────────────── */
.vp-poster-search {
  width: 100%; padding: 11px 14px; border: 1.5px solid var(--vp-line-strong);
  border-radius: var(--vp-radius-sm); font-size: .9rem; margin-bottom: 14px;
}
.vp-poster-cars { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.vp-poster-car {
  display: flex; gap: 12px; align-items: center; text-align: left; cursor: pointer;
  padding: 9px; border: 1.5px solid var(--vp-line); border-radius: var(--vp-radius-sm);
  background: var(--vp-surface); transition: border-color .14s, background .14s;
}
.vp-poster-car:hover { border-color: var(--vp-ink); background: #fffdf8; }
.vp-poster-car .pic {
  width: 76px; height: 54px; flex: 0 0 auto; border-radius: 6px; overflow: hidden;
  background: #eceae4; display: flex; align-items: center; justify-content: center;
}
.vp-poster-car .pic img { width: 100%; height: 100%; object-fit: cover; }
.vp-poster-car .pic i { font-size: .62rem; color: var(--vp-faint); font-style: normal; }
.vp-poster-car .txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vp-poster-car strong { font-size: .85rem; font-weight: 600; }
.vp-poster-car small { font-size: .73rem; color: var(--vp-muted); }
.vp-poster-car .warn { font-size: .68rem; color: var(--vp-amber); font-style: normal; }

/* ── Editor shell ──────────────────────────────────────────────────────── */
.vp-poster-editor { display: flex; flex-direction: column; gap: 14px; }
.vp-poster-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.vp-poster-title {
  flex: 1 1 200px; min-width: 140px; padding: 8px 12px; font-size: .9rem; font-weight: 600;
  border: 1.5px solid transparent; border-radius: var(--vp-radius-sm); background: transparent;
}
.vp-poster-title:hover { border-color: var(--vp-line); }
.vp-poster-title:focus { border-color: var(--vp-ink); background: var(--vp-surface); outline: none; }
.vp-poster-bar-right { display: flex; gap: 7px; margin-left: auto; }

.vp-poster-work { display: grid; grid-template-columns: minmax(0, 1fr) 384px; gap: 18px; align-items: start; }

/* ── The stage ─────────────────────────────────────────────────────────── */
.vp-poster-stage {
  background: var(--vp-surface); border: 1px solid var(--vp-line);
  border-radius: var(--vp-radius); padding: 18px;
  position: sticky; top: 12px;
}
.vp-poster-frame {
  display: flex; align-items: center; justify-content: center;
  background: #e9e7e1; border-radius: var(--vp-radius-sm); padding: 16px; min-height: 220px;
}
/* The canvas carries its own intrinsic ratio, so capping both axes is all the
   sizing it needs — a story shrinks to the height cap, a banner to the width. */
.vp-poster-canvas {
  max-width: 100%; max-height: 62vh; width: auto; height: auto;
  border-radius: 4px; box-shadow: 0 10px 34px -12px rgba(20, 22, 18, .42);
  display: block;
  /* The QR block is dragged on the canvas; without this a drag selects the
     page instead, and on a phone it scrolls the view. */
  touch-action: none;
}
/* The whole canvas is draggable now — the photo everywhere, the Drivaza block
   where it sits — so the default cursor says so. */
.vp-poster-canvas { cursor: grab; }
.vp-poster-canvas.grabbable { cursor: grab; }
.vp-poster-canvas.dragging { cursor: grabbing; }

.vp-poster-draghint {
  display: flex; align-items: center; gap: 8px; justify-content: center;
  margin: 10px 0 0; text-align: center;
}
.vp-poster-link {
  border: none; background: none; padding: 0; cursor: pointer;
  color: var(--vp-brand-ink); font-size: .8rem; font-weight: 600; text-decoration: underline;
}

.vp-poster-sizes { display: flex; gap: 7px; margin-top: 14px; flex-wrap: wrap; }
.vp-poster-size {
  display: flex; align-items: center; gap: 7px; cursor: pointer; padding: 7px 11px;
  border: 1.5px solid var(--vp-line); border-radius: var(--vp-radius-sm); background: var(--vp-surface);
  font-size: .76rem; font-weight: 600; color: var(--vp-ink-soft);
}
.vp-poster-size:hover { border-color: var(--vp-line-strong); }
.vp-poster-size.on { border-color: var(--vp-ink); color: var(--vp-ink); background: #fffdf8; }
/* A miniature of the shape being chosen — quicker to read than "1080x1920". */
.vp-poster-size .box { border: 1.5px solid currentColor; border-radius: 2px; opacity: .72; flex: 0 0 auto; }
.vp-poster-size .box.square { width: 14px; height: 14px; }
.vp-poster-size .box.portrait { width: 12px; height: 15px; }
.vp-poster-size .box.story { width: 9px; height: 16px; }
.vp-poster-size .box.landscape { width: 18px; height: 10px; }

/* ── The control panel ─────────────────────────────────────────────────── */
.vp-poster-panel {
  background: var(--vp-surface); border: 1px solid var(--vp-line);
  border-radius: var(--vp-radius); padding: 16px 18px 20px;
}
.vp-poster-tabs {
  display: flex; gap: 3px; margin: -4px -4px 16px; padding: 4px;
  background: #f1efe9; border-radius: 10px;
}
.vp-poster-tabs button {
  flex: 1; padding: 8px 6px; border: none; background: transparent; cursor: pointer;
  border-radius: 7px; font-size: .78rem; font-weight: 600; color: var(--vp-muted);
}
.vp-poster-tabs button.on { background: var(--vp-surface); color: var(--vp-ink); box-shadow: 0 1px 3px rgba(20, 22, 18, .1); }

.vp-poster-h {
  margin: 20px 0 10px; font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--vp-faint);
}
.vp-poster-h:first-child { margin-top: 0; }

.vp-poster-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 13px; }
.vp-poster-field > span { font-size: .76rem; font-weight: 600; color: var(--vp-ink-soft); }
.vp-poster-field input {
  padding: 9px 12px; border: 1.5px solid var(--vp-line-strong); border-radius: var(--vp-radius-sm); font-size: .85rem;
}
.vp-poster-field small { font-size: .7rem; color: var(--vp-faint); line-height: 1.45; }

.vp-poster-toggle { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; cursor: pointer; font-size: .82rem; }
.vp-poster-toggle input { width: 17px; height: 17px; accent-color: var(--vp-brand); cursor: pointer; }

.vp-poster-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: .8rem; margin-top: 12px; }
.vp-poster-colour { display: flex; align-items: center; gap: 6px; }
.vp-poster-colour input[type=color] {
  width: 42px; height: 30px; padding: 2px; border: 1.5px solid var(--vp-line-strong);
  border-radius: 7px; background: var(--vp-surface); cursor: pointer;
}
.vp-poster-mini {
  border: 1.5px solid var(--vp-line-strong); background: var(--vp-surface); cursor: pointer;
  border-radius: 6px; width: 26px; height: 26px; line-height: 1; color: var(--vp-muted); flex: 0 0 auto;
}
.vp-poster-mini:hover { border-color: var(--vp-red); color: var(--vp-red); }

/* ── Template picker ───────────────────────────────────────────────────── */
.vp-poster-templates { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.vp-poster-tpl {
  display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer;
  padding: 6px 4px; border: 1.5px solid var(--vp-line); border-radius: 10px;
  background: var(--vp-surface); transition: border-color .14s;
}
.vp-poster-tpl:hover { border-color: var(--vp-line-strong); }
.vp-poster-tpl.on { border-color: var(--vp-ink); background: #fffdf8; }
.vp-poster-tpl span {
  font-size: .63rem; font-weight: 600; color: var(--vp-muted); text-align: center; line-height: 1.25;
}
.vp-poster-tpl.on span { color: var(--vp-ink); }
/* Height-capped so the four columns stay level whichever poster shape is
   selected; the canvas keeps its own ratio inside that. */
.vp-poster-tpl-canvas {
  max-width: 100%; max-height: 92px; width: auto; height: auto; border-radius: 3px; display: block;
}

/* ── Palettes ──────────────────────────────────────────────────────────── */
.vp-poster-palettes { display: flex; flex-wrap: wrap; gap: 7px; }
.vp-poster-pal {
  display: flex; width: 46px; height: 30px; padding: 0; cursor: pointer; overflow: hidden;
  border: 2px solid var(--vp-line); border-radius: 8px; background: none;
}
.vp-poster-pal:hover { border-color: var(--vp-line-strong); }
.vp-poster-pal.on { border-color: var(--vp-ink); }
.vp-poster-pal i { flex: 1; display: block; }

/* ── Price ─────────────────────────────────────────────────────────────── */
.vp-poster-rates { display: flex; gap: 7px; margin-bottom: 9px; }
.vp-poster-rate {
  flex: 1; display: flex; flex-direction: column; gap: 2px; cursor: pointer; padding: 8px 6px;
  border: 1.5px solid var(--vp-line); border-radius: var(--vp-radius-sm); background: var(--vp-surface);
}
.vp-poster-rate:hover:not(:disabled) { border-color: var(--vp-line-strong); }
.vp-poster-rate.on { border-color: var(--vp-ink); background: #fffdf8; }
.vp-poster-rate:disabled { opacity: .45; cursor: not-allowed; }
.vp-poster-rate b { font-size: .7rem; font-weight: 700; color: var(--vp-muted); }
.vp-poster-rate span { font-size: .78rem; font-weight: 600; font-variant-numeric: tabular-nums; }

.vp-poster-seg { display: flex; gap: 0; border: 1.5px solid var(--vp-line-strong); border-radius: var(--vp-radius-sm); overflow: hidden; margin-bottom: 8px; }
.vp-poster-seg button {
  flex: 1; padding: 8px 6px; border: none; background: var(--vp-surface); cursor: pointer;
  font-size: .75rem; font-weight: 600; color: var(--vp-muted);
}
.vp-poster-seg button + button { border-left: 1.5px solid var(--vp-line-strong); }
.vp-poster-seg button.on { background: var(--vp-ink); color: #fff; }
/* Locked by the QR code, not broken — see the hint printed under it. */
.vp-poster-seg button:disabled { opacity: .42; cursor: not-allowed; }
.vp-poster-seg button:disabled:hover { background: var(--vp-surface); }
.vp-poster-field input[readonly] {
  background: #f4f2ec; color: var(--vp-muted); cursor: default;
}

/* ── Chips ─────────────────────────────────────────────────────────────── */
.vp-poster-chips { display: flex; flex-direction: column; gap: 6px; }
.vp-poster-chip { display: flex; gap: 6px; align-items: center; }
.vp-poster-chip input {
  flex: 1; min-width: 0; padding: 8px 11px; border: 1.5px solid var(--vp-line-strong);
  border-radius: var(--vp-radius-sm); font-size: .82rem;
}

/* ── Photo pane ────────────────────────────────────────────────────────── */
.vp-poster-shots { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 4px; }
.vp-poster-shot {
  position: relative; padding: 0; cursor: pointer; overflow: hidden; aspect-ratio: 4 / 3;
  border: 2px solid var(--vp-line); border-radius: 8px; background: #eceae4;
}
.vp-poster-shot.on { border-color: var(--vp-ink); }
.vp-poster-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vp-poster-shot i {
  position: absolute; left: 3px; bottom: 3px; font-style: normal; font-size: .55rem; font-weight: 700;
  background: rgba(23, 25, 28, .82); color: #fff; border-radius: 4px; padding: 1px 5px;
}

.vp-poster-slider { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.vp-poster-slider > span { display: flex; justify-content: space-between; font-size: .76rem; font-weight: 600; color: var(--vp-ink-soft); }
.vp-poster-slider i { font-style: normal; color: var(--vp-faint); font-variant-numeric: tabular-nums; font-weight: 500; }
.vp-poster-slider input[type=range] { width: 100%; accent-color: var(--vp-ink); cursor: pointer; }

/* ── Caption ───────────────────────────────────────────────────────────── */
.vp-poster-caption {
  width: 100%; padding: 12px 14px; border: 1.5px solid var(--vp-line-strong);
  border-radius: var(--vp-radius-sm); font-size: .84rem; line-height: 1.6; resize: vertical;
}
.vp-poster-caption-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 9px; }
.vp-poster-caption-foot span { font-size: .72rem; color: var(--vp-faint); }
.vp-poster-caption-foot div { display: flex; gap: 6px; }

/* ── Narrow screens ────────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  /* minmax(0, 1fr), NOT 1fr. A bare `1fr` track is minmax(auto, 1fr), and its
     auto floor is the column's max-content width — the template grid and the
     rate buttons were holding the stacked layout open at 405px inside a 347px
     phone, clipping the right edge off the canvas and every control under it. */
  .vp-poster-work { grid-template-columns: minmax(0, 1fr); }
  /* Same reason, one level down: a grid item's min-width is auto by default. */
  .vp-poster-stage, .vp-poster-panel { min-width: 0; }
  /* Sticky is only useful while the panel scrolls PAST the stage. Stacked,
     it would pin the poster over the controls the vendor is reaching for. */
  .vp-poster-stage { position: static; }
  .vp-poster-canvas { max-height: 52vh; }
}

/* ── Phones ────────────────────────────────────────────────────────────────
   The studio is a phone tool first: the photos are on the phone, the Instagram
   app is on the phone, and the person posting is standing next to the car. So
   below 780px the layout is rebuilt rather than merely narrowed —

     · the poster is sized against the VISIBLE viewport (dvh, which excludes
       the iOS toolbars that vh happily hides content behind),
     · Save / Download / Share leave the top bar for a fixed footer over the
       thumb, clear of the iOS home indicator,
     · every control is at least 44px in its short axis, and
     · every text input is 16px, because anything smaller makes iOS Safari zoom
       the page on focus and leaves it zoomed — which is most of what "not
       mobile friendly" felt like.
   ────────────────────────────────────────────────────────────────────────── */
@media (max-width: 780px) {
  .vp-poster-editor { gap: 10px; }

  /* Title on its own line: sharing a row with "← All posters" left it about
     nine characters wide. */
  .vp-poster-bar { gap: 8px; }
  .vp-poster-title { flex: 1 1 100%; order: 2; font-size: 16px; padding: 10px 12px; border-color: var(--vp-line); }

  .vp-poster-stage { padding: 10px; border-radius: var(--vp-radius-sm); }
  .vp-poster-frame { padding: 8px; min-height: 0; }
  /* 52vh of a 700px phone is a 5cm poster with the controls still off-screen.
     Give it the room, and let the panel below be the thing you scroll to. */
  .vp-poster-canvas { max-height: 58vh; max-height: 58dvh; }

  .vp-poster-draghint { flex-wrap: wrap; gap: 4px; font-size: .78rem; }

  /* Size chips scroll sideways instead of wrapping into three ragged rows. */
  .vp-poster-sizes {
    margin-top: 10px; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .vp-poster-sizes::-webkit-scrollbar { display: none; }
  .vp-poster-size { flex: 0 0 auto; min-height: 40px; }

  /* The clearance for the fixed action bar lives INSIDE the panel, not as
     padding on the editor: the panel is the last thing on the page, and this
     way the gap survives whatever the surrounding shell does with scrolling.
     64px of bar (46px buttons + 9px either side) plus air. */
  .vp-poster-panel {
    padding: 12px 13px calc(82px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--vp-radius-sm);
  }
  .vp-poster-tabs { position: sticky; top: 0; z-index: 3; margin: -4px -4px 12px; }
  .vp-poster-tabs button { min-height: 44px; font-size: .82rem; }

  /* iOS zooms the whole page in on any focused input under 16px and never
     zooms back out. Every typing surface in the studio, therefore: */
  .vp-poster-field input,
  .vp-poster-chip input,
  .vp-poster-caption,
  .vp-poster-search { font-size: 16px; }
  .vp-poster-field input, .vp-poster-chip input { padding: 11px 12px; }

  .vp-poster-toggle { min-height: 40px; margin-bottom: 8px; }
  .vp-poster-toggle input { width: 21px; height: 21px; }
  .vp-poster-rate { min-height: 52px; }
  .vp-poster-seg button { min-height: 44px; }
  .vp-poster-mini { width: 34px; height: 34px; }
  .vp-poster-pal { width: 52px; height: 36px; }
  /* A 4px rail is not hittable with a fingertip. */
  .vp-poster-slider input[type=range] { height: 34px; }

  /* The actions follow the thumb to the bottom of the screen and stay there,
     so "Save" is never a scroll away from whatever you just changed. */
  .vp-poster-bar-right {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    margin: 0; gap: 8px; padding: 9px 12px calc(9px + env(safe-area-inset-bottom));
    background: rgba(255, 255, 255, .94);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border-top: 1px solid var(--vp-line);
    box-shadow: 0 -6px 20px -12px rgba(20, 22, 18, .5);
  }
  .vp-poster-bar-right .adm-btn { flex: 1; justify-content: center; min-height: 46px; padding: 0 10px; }
  /* A note about a failed save has to clear it too. */
  .vp-poster-note { position: relative; z-index: 41; }

  .vp-poster-grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 10px; }
  .vp-poster-thumb { height: 150px; }
  .vp-poster-actions { gap: 5px; }
  .vp-poster-actions .adm-btn { min-height: 38px; }
  .vp-poster-cars { grid-template-columns: 1fr; }
  .vp-poster-car { min-height: 64px; }
  .vp-poster-hero { padding: 15px 16px; gap: 12px; }
  .vp-poster-hero .adm-btn { width: 100%; justify-content: center; min-height: 46px; }

  /* The vendor portal already owns the bottom of a phone screen: .vp-bbar is a
     fixed five-tab bar, 56px tall plus the safe-area inset, at z-index 470. So
     in that shell the poster actions sit directly ON TOP of it instead of
     underneath it, where they would be invisible and untappable. The admin has
     no bottom bar, which is why this is an override and not the default. */
  body.vp-portal .vp-poster-bar-right {
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-bottom: 9px;
  }
  /* …and the panel clears BOTH bars in that shell: 64px of actions on top of a
     56px tab bar. */
  body.vp-portal .vp-poster-panel { padding-bottom: calc(138px + env(safe-area-inset-bottom, 0px)); }
}

@media (max-width: 620px) {
  .vp-poster-templates { grid-template-columns: repeat(3, 1fr); }
}

/* Very small phones (SE-class, 320-360px): four photo thumbs per row leaves
   each one 58px wide behind its 2px border, so drop to three. */
@media (max-width: 400px) {
  .vp-poster-shots { grid-template-columns: repeat(3, 1fr); }
  .vp-poster-tabs button { font-size: .76rem; padding: 8px 2px; }
  .vp-poster-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Landscape on a phone: the poster and the controls genuinely do fit side by
   side, and the canvas cap has to come off the height instead. */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 520px) {
  .vp-poster-work { grid-template-columns: minmax(0, 1fr) minmax(260px, 42%); }
  .vp-poster-canvas { max-height: 76vh; max-height: 76dvh; }
  .vp-poster-bar-right { position: static; padding: 0; background: none; border: none; box-shadow: none; backdrop-filter: none; }
  .vp-poster-panel { padding-bottom: 16px; }
  /* Same again for the portal — but its tab bar is still fixed down there in
     landscape, so the page keeps that much clearance. */
  body.vp-portal .vp-poster-bar-right { position: static; bottom: auto; padding: 0; }
  body.vp-portal .vp-poster-panel { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
}
/* The iOS focus-zoom rule again, keyed on the POINTER rather than the width.
   Zooming in on a sub-16px input is a property of the touch keyboard, not of
   the screen: a phone held sideways is 844px wide and misses every width
   breakpoint above, and it is exactly where someone crops a photo. */
@media (pointer: coarse) {
  .vp-poster-field input,
  .vp-poster-chip input,
  .vp-poster-caption,
  .vp-poster-title,
  .vp-poster-search { font-size: 16px; }
}

/* Poster picker: the admin studio lists rental cars AND for-sale ads, so each
   row says which it is. The vendor payload has no `kind`, so nothing renders
   there and the picker is byte-identical to what it was. */
.vp-poster-kinds { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 4px; }
.vp-kind {
  display: inline-block; font-style: normal; font-size: .62rem; font-weight: 800;
  letter-spacing: .05em; text-transform: uppercase; vertical-align: middle;
  color: #15803d; background: rgba(34,197,94,.12); border: 1px solid rgba(34,197,94,.26);
  border-radius: 999px; padding: 2px 7px; margin-right: 7px;
}
.vp-kind.sale { color: #b45309; background: rgba(245,158,11,.13); border-color: rgba(245,158,11,.3); }

/* ══════════════════════════════════════════════════════════════════════════
   MOBILE PARITY WITH THE ADMIN
   The screens now use admin.css's responsive contract (.adm-table-wrap +
   .adm-cards, .adm-rowactions, .adm-td-num, …; see its RESPONSIVE FOUNDATION
   block). What follows is only what the portal needs on top of that: its own
   look for the cards, and the places where a vendor.css rule or an inline
   style was quietly beating a shared phone rule.
   ══════════════════════════════════════════════════════════════════════════ */

/* Drawer chrome — the ✕ that exists only while the sidebar is a drawer, and
   the kill switch under "Log out". Both sit on the dark sidebar, so neither can
   use the light-surface button styles. */
body.vp-portal .vp-sb-close {
  margin-left: auto; background: none; cursor: pointer; font-size: 1rem;
  color: rgba(255, 255, 255, .72); border: 1px solid rgba(255, 255, 255, .14); border-radius: 10px;
}
body.vp-portal .vp-sb-close:hover { color: #fff; border-color: rgba(255, 255, 255, .32); }
.vp-sb-everywhere {
  width: 100%; margin-top: 6px; padding: 6px 0; background: none; border: none; cursor: pointer;
  color: rgba(255, 255, 255, .45); font-size: .72rem; font-family: inherit;
}
.vp-sb-everywhere:hover { color: rgba(255, 255, 255, .8); text-decoration: underline; }
/* "Log out" is a ghost button, and the portal's ghost is ink-on-transparent —
   which on this dark sidebar made it invisible, drawer and desktop alike. */
body.vp-portal .adm-sb-foot .adm-btn-ghost { color: rgba(255, 255, 255, .86); border-color: rgba(255, 255, 255, .22); }
body.vp-portal .adm-sb-foot .adm-btn-ghost:hover { color: #fff; background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .42); }

/* style.css reserves 56px under <body> on phones for the PUBLIC site's bottom
   bar, which this page never renders — the portal keeps its own tab bar clear
   through .adm-content's padding instead. Left in, it added a dead band under
   every screen: a beige strip below the dark sign-in card. */
body.vp-portal { padding-bottom: 0; }

/* iOS zooms the page on focus for any control under 16px and never zooms
   back. admin.css already sets 16px below 900px, but in the portal it loses
   twice over: vendor.css's own field rules (.vp-mini, .vp-acc-select, …) come
   later in the cascade, and dozens of controls carry an inline fontSize. Hence
   !important, and hence the pointer query too — a phone on its side is 844px
   wide and misses the width breakpoint, same reasoning as the poster studio
   rule above. */
@media (max-width: 900px), (pointer: coarse) {
  body.vp-portal input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
  body.vp-portal select,
  body.vp-portal textarea { font-size: 16px !important; }
}

/* A link styled as a button inside a table (WhatsApp, Call, Open) — admin.css
   grows every table <a> into a 40px hit area with padding and an EQUAL
   NEGATIVE MARGIN, which is right for a text link and wrong for a button: in a
   card's action footer the margin pulled it over its neighbours. The table
   link colour also beat the button's own colour, so the text came out green. */
body.vp-portal .adm-table a.adm-btn { margin: 0; text-decoration: none; }
body.vp-portal .adm-table a.adm-btn-ghost { color: var(--vp-ink); }
body.vp-portal .adm-table a.adm-btn:not(.adm-btn-ghost):not(.adm-btn-danger) { color: #fff; }

/* Desktop keeps the shipped one-line button cells. .adm-rowactions wraps, which
   is right in a phone card's footer, but in a tight desktop table it let the
   browser squeeze the action column and drop "Cancel" onto a second line —
   the old nowrap cells always kept their column wide enough. A cell that
   wrapped on purpose before (My Cars) says so inline. */
@media (min-width: 721px) {
  body.vp-portal .adm-table td[data-card-actions] > .adm-rowactions { flex-wrap: nowrap; }
  body.vp-portal .adm-table td[data-card-actions] { white-space: nowrap; }
}

/* Phone cards in the portal's palette rather than the admin's cool grey. */
@media (max-width: 720px) {
  body.vp-portal .adm-table.adm-cards > tbody > tr,
  body.vp-portal .adm-table.adm-cards > tfoot > tr {
    border-color: var(--vp-line); border-radius: var(--vp-radius); box-shadow: none;
  }
  body.vp-portal .adm-table.adm-cards td[data-card-head],
  body.vp-portal .adm-table.adm-cards > tfoot > tr { background: #faf8f3; }
  body.vp-portal .adm-table.adm-cards td[data-card-head] { letter-spacing: -.01em; }
  /* The desktop column caps are inline (`maxWidth: 190` on a car title,
     `width: 30` on a checkbox cell), and an inline style beats every card
     rule — so a capped cell became a 190px row inside a 358px card, its value
     wrapped into a narrow column and its divider stopped short. A card row is
     always the card's full width. */
  body.vp-portal .adm-table.adm-cards td { max-width: none !important; min-width: 0 !important; width: auto !important; }
}

/* Inline row editors (My Cars → Edit prices / + Plate). Desktop is the shipped
   wrapping row; on a phone the fields become a two-up grid and the inline
   `width: 90` on each input has to give way to the column. */
.vp-inline-edit { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
@media (max-width: 720px) {
  .vp-inline-edit { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; align-items: end; }
  .vp-inline-edit .vp-mini input,
  .vp-inline-edit .vp-mini select { width: 100% !important; min-width: 0 !important; box-sizing: border-box; }
  .vp-inline-edit > .adm-btn { justify-content: center; }
}

/* Portal forms. style.css turns .vac-grid into `1fr 1fr` under 560px, and a
   plain 1fr track floors at its content's min-content width — a date input or
   a long select option pushed the second column off the card. */
.vac-grid > * { min-width: 0; }
@media (max-width: 560px) {
  .vac-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Sub-tab strips (car workspace, booking desk, accounts, ledgers, money…):
   one swipeable line instead of three wrapped rows of tabs above the content.
   The tabs lose their -1.5px overlap with the strip's rule, because the
   scroller would clip it; the active underline then simply sits on the line. */
@media (max-width: 640px) {
  .vp-subtabs {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; min-width: 0; max-width: 100%;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    scroll-snap-type: x proximity; scrollbar-width: none;
  }
  .vp-subtabs::-webkit-scrollbar { display: none; }
  .vp-subtab { flex: 0 0 auto; scroll-snap-align: start; white-space: nowrap; margin-bottom: 0; min-height: 44px; }
  /* Accounts/Ledgers put the strip beside the period picker with an inline
     flex:1 — a zero basis that never wraps, so the strip was squeezed to
     whatever the picker left over. Give it its own line. */
  .vp-acc-bar > .vp-subtabs { flex: 1 1 100% !important; }
}

/* Touch floors for the portal's own small controls (admin.css covers .adm-*). */
@media (max-width: 900px) {
  .vp-modal-close { width: 40px; height: 40px; flex-basis: 40px; }
  .vp-gactions button { min-width: 40px; min-height: 40px; }
  .vp-toggle { min-height: 36px; padding: 7px 14px 7px 12px; }
  .vp-remember { min-height: 40px; }
}
