/* ================================================================
   Bakery ERP — shared design system
   -----------------------------------------------------------------
   Palette     teal (#0d9488) on slate, paper-white surfaces, quiet
               #f1f5f9 canvas. Numbers are the product here, so money
               and quantities always use tabular figures.
   Type        System UI stack only (this ERP runs offline in the
               field — no webfont dependency). Hierarchy is carried
               by weight, size, case and letter-spacing instead.
   Layout      Fluid main column; sidebar is a fixed rail on desktop
               and an off-canvas drawer (hamburger) below 992px.
   ================================================================ */

:root {
  /* palette */
  --erp-ink:        #0f172a;
  --erp-body:       #334155;
  --erp-muted:      #64748b;
  --erp-faint:      #94a3b8;
  --erp-bg:         #eef2f7;
  --erp-surface:    #ffffff;
  --erp-border:     #e2e8f0;
  --erp-border-hi:  #cbd5e1;

  --erp-accent:       #0d9488;
  --erp-accent-700:   #0f766e;
  --erp-accent-800:   #115e59;
  --erp-accent-soft:  #ccfbf1;
  --erp-accent-tint:  #f0fdfa;

  --erp-danger:  #dc2626;
  --erp-success: #059669;
  --erp-warning: #d97706;
  --erp-info:    #2563eb;

  --erp-sidebar:  #0f172a;
  --erp-sidebar-2:#0b1322;
  --erp-sidebar-text:   #a7b3c6;
  --erp-sidebar-muted:  #5c6b83;

  /* geometry */
  --erp-radius:    .55rem;
  --erp-radius-sm: .4rem;
  --erp-sidebar-w: 244px;
  --erp-topbar-h:  56px;
  --erp-shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);
  --erp-shadow-md: 0 10px 30px -12px rgba(15, 23, 42, .25);

  /* type */
  --erp-font: "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --erp-font-ui: "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--erp-bg);
  color: var(--erp-body);
  font-family: var(--erp-font);
  font-size: .875rem;
  line-height: 1.5;
}
a { color: var(--erp-accent); }
a:hover { color: var(--erp-accent-700); }
::selection { background: var(--erp-accent-soft); }
:focus-visible { outline: 2px solid var(--erp-accent); outline-offset: 2px; }
kbd {
  background: #e2e8f0; color: #334155;
  border: 1px solid #cbd5e1; border-bottom-width: 2px;
  border-radius: 4px; padding: .05rem .38rem;
  font-family: inherit; font-size: .7rem; font-weight: 600;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 6px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; border: 2px solid transparent; background-clip: content-box; }

/* ================================================================
   App shell — sidebar + topbar + content
   ================================================================ */
.erp-shell { display: flex; align-items: stretch; min-height: 100vh; }

/* ---------- Sidebar ---------- */
.erp-sidebar {
  width: var(--erp-sidebar-w);
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--erp-sidebar) 0%, var(--erp-sidebar-2) 100%);
  color: var(--erp-sidebar-text);
  overflow-y: auto;
  z-index: 1050;
}
.erp-brand {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .95rem 1rem;
  min-height: var(--erp-topbar-h);
  color: #fff;
  border-bottom: 1px solid rgba(148, 163, 184, .14);
  white-space: nowrap;
  overflow: hidden;
}
.erp-brand .brand-mark {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: .5rem;
  background: linear-gradient(135deg, #14b8a6, var(--erp-accent-700));
  color: #fff;
  font-weight: 800; font-size: .95rem;
  box-shadow: 0 3px 10px rgba(20, 184, 166, .4);
}
.erp-brand .brand-text {
  min-width: 0;
  font-weight: 700; font-size: .97rem; line-height: 1.15;
}
/* The uploaded logo, in place of the letter mark (Settings → General → Show in header).
   No plate behind it: the file is drawn straight on the dark rail, so whatever
   background it has — or hasn't — is what shows.  A transparent PNG therefore sits
   flush on the sidebar, exactly as it does on the login card.

   Every size below is the design's own multiplied by --brand-scale, which the page
   sets from Master Settings → General → “Logo size”.  One percentage, one variable,
   and the sidebar, its collapsed rail and the login page always agree. */
.erp-brand .brand-logo {
  flex: 0 0 auto;
  max-height: calc(32px * var(--brand-scale, 1));
  max-width: calc(150px * var(--brand-scale, 1));
  object-fit: contain;
}
/* The uploaded logo on its own (Settings → General → Show in header = Logo). The file
   is usually far bigger than the 32px mark it sat in, so it read as a smudge on the
   dark rail: centre it in the brand row and let it use the room. */
.erp-brand.brand-solo {
  justify-content: center;
  padding: .55rem .75rem;
}
.erp-brand.brand-solo .brand-logo {
  max-height: calc(46px * var(--brand-scale, 1));
  max-width: 100%;
}
.erp-brand small {
  display: block;
  color: #71809a;
  font-size: .62rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
}
.erp-nav-close {
  display: none;
  margin-left: auto;
  flex: 0 0 auto;
  width: 30px; height: 30px;
  padding: 0;
  border: 0;
  border-radius: .4rem;
  background: rgba(255, 255, 255, .08);
  color: #cbd5e1;
  align-items: center; justify-content: center;
}
.erp-nav-close:hover { background: rgba(255, 255, 255, .16); color: #fff; }

.erp-nav { flex: 1 1 auto; padding: .5rem 0 .8rem; }
.erp-nav .nav-sep {
  padding: 1rem .9rem .3rem;
  font-size: .63rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--erp-sidebar-muted);
}
.erp-nav a {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 1px .5rem;
  padding: .46rem .7rem;
  border-radius: .45rem;
  border-left: 3px solid transparent;
  color: var(--erp-sidebar-text);
  font-size: .85rem;
  text-decoration: none;
  transition: background-color .12s ease, color .12s ease;
}
.erp-nav a:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.erp-nav a.active {
  background: rgba(20, 184, 166, .14);
  border-left-color: #2dd4bf;
  color: #fff;
}
.erp-nav a.active i { color: #5eead4; }
.erp-nav a i { width: 1.15rem; text-align: center; font-size: .95rem; color: var(--erp-sidebar-muted); }
.erp-nav a:hover i, .erp-nav a.active i { color: inherit; }
.erp-nav a span { overflow: hidden; text-overflow: ellipsis; }

/* ---------- Sidebar submenu (Security Gate etc.) ---------- */
.erp-nav .nav-group-toggle .nav-caret { transition: transform .15s ease; font-size: .7rem; }
.erp-nav .nav-group.open .nav-group-toggle .nav-caret { transform: rotate(180deg); }
.erp-nav .nav-sub { display: none; padding: 2px 0 4px; }
.erp-nav .nav-group.open .nav-sub { display: block; }
.erp-nav .nav-sub a {
  display: flex;
  align-items: center;
  margin: 1px .5rem 1px 2.1rem;
  padding: .34rem .6rem;
  border-radius: .4rem;
  border-left: 2px solid transparent;
  color: var(--erp-sidebar-muted);
  font-size: .8rem;
  text-decoration: none;
}
.erp-nav .nav-sub a:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.erp-nav .nav-sub a.active { background: rgba(20, 184, 166, .14); border-left-color: #2dd4bf; color: #fff; }
/* Icons-only rail: submenu rows collapse to their dot; the label is in title. */
body.sidebar-collapsed .erp-nav .nav-sub a span { display: none; }
body.sidebar-collapsed .erp-nav .nav-sub a { margin-left: .5rem; justify-content: center; }
body.sidebar-collapsed .erp-nav .nav-sub a::before { content: "·"; font-size: .9rem; }
body.sidebar-collapsed .erp-nav .nav-group .nav-caret { display: none; }

.erp-sidebar .erp-foot {
  padding: .75rem 1rem;
  font-size: .7rem;
  color: var(--erp-sidebar-muted);
  border-top: 1px solid rgba(148, 163, 184, .12);
}
.erp-sidebar .erp-foot kbd { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.12); color: #94a3b8; }

/* Mobile off-canvas backdrop */
.erp-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1040;
  background: rgba(15, 23, 42, .55);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s ease;
}

/* ---------- Main column / topbar ---------- */
.erp-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.erp-topbar {
  position: sticky;
  top: 0;
  z-index: 1020;
  display: flex;
  align-items: center;
  gap: .65rem;
  min-height: var(--erp-topbar-h);
  padding: .45rem 1.1rem;
  background: var(--erp-surface);
  border-bottom: 1px solid var(--erp-border);
  box-shadow: var(--erp-shadow-sm);
}
.erp-topbar .page-title {
  font-size: 1.02rem;
  font-weight: 650;
  color: var(--erp-ink);
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.erp-topbar .btn { display: inline-flex; align-items: center; gap: .3rem; }
.erp-content {
  flex: 1 1 auto;
  padding: clamp(.9rem, 1.6vw, 1.35rem) clamp(.65rem, 1.4vw, 1.5rem) 3rem;
  /* No width cap: the content always fills the space right of the rail.  The old
     1700px cap left a dead band on the right whenever the sidebar was open, while
     the collapsed state (max-width: none below) filled the window — which is why
     the two states disagreed. */
  max-width: none;
  width: 100%;
}
.erp-content > .card, .erp-content > form > .card { box-shadow: var(--erp-shadow-sm); }
/* A dispatch voucher shown inside the app (dispatch/view): the printed A4 sheet,
   which is a fixed 841px wide, so a narrow window scrolls it instead of clipping. */
.vp-report { overflow-x: auto; }
.vp-report .page { flex: 0 0 auto; }
body.sidebar-open { overflow: hidden; }

/* ---------- Desktop rail: full menu ⇄ icons only ----------
   Folding the rail narrows it to the icons rather than removing it, so the menu stays
   reachable and the page gets the rest of the width. Each icon keeps its label in a
   title attribute while folded (set in app.js). Only wide screens use this — the
   mobile drawer rules below are untouched. */
@media (min-width: 992px) {
  :root { --erp-rail-w: 64px; }
  .erp-sidebar { transition: width .18s ease; }
  body.sidebar-collapsed .erp-sidebar { width: var(--erp-rail-w); }
  body.sidebar-collapsed .erp-brand { justify-content: center; padding: .8rem .35rem; }
  /* A bigger logo must not spill out of the 64px rail, so the scale is capped by it. */
  body.sidebar-collapsed .erp-brand .brand-logo {
    max-width: min(calc(38px * var(--brand-scale, 1)), 44px);
    max-height: min(calc(28px * var(--brand-scale, 1)), 34px);
  }
  body.sidebar-collapsed .erp-brand .brand-text,
  body.sidebar-collapsed .erp-nav .nav-sep,
  body.sidebar-collapsed .erp-nav a span,
  body.sidebar-collapsed .erp-foot { display: none; }
  body.sidebar-collapsed .erp-nav { padding: .6rem 0; }
  body.sidebar-collapsed .erp-nav a {
    justify-content: center;
    gap: 0;
    margin: 2px .5rem;
    padding: .5rem 0;
    border-left-width: 0;
  }
  body.sidebar-collapsed .erp-nav a i { flex: 0 0 auto; width: auto; font-size: 1.05rem; }
  /* The rail gave back 180px, so the reading cap has to come off with it, or that
     180px sits empty on the right while a wide report still scrolls sideways inside
     a half-empty page. */
  body.sidebar-collapsed .erp-content { max-width: none; }
}

/* ---------- Responsive: off-canvas drawer ---------- */
@media (max-width: 991.98px) {
  .erp-shell { display: block; }
  .erp-sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: min(280px, 88vw);
    height: 100vh; height: 100dvh;
    transform: translateX(-102%);
    transition: transform .22s ease;
    box-shadow: var(--erp-shadow-md);
  }
  .erp-sidebar.open { transform: translateX(0); }
  .erp-nav-close { display: inline-flex; }
  .erp-backdrop.show { opacity: 1; visibility: visible; }
  .erp-topbar { padding: .45rem .8rem; gap: .5rem; }
  .erp-content { padding-top: .9rem; }
}

/* ================================================================
   Cards / panels
   ================================================================ */
.card {
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  box-shadow: var(--erp-shadow-sm);
}
.card-header {
  background: var(--erp-surface);
  border-bottom: 1px solid var(--erp-border);
  padding: .68rem 1rem;
  font-size: .9rem;
  font-weight: 650;
  color: var(--erp-ink);
  gap: .5rem;
}
.card-header .btn { font-weight: 500; }
/* Let header toolbars (title + filters + actions) wrap on narrow screens */
.card-header.d-flex { flex-wrap: wrap; row-gap: .5rem; }
/* …and the toolbar nested inside one.  The rule above only matches the header
   element itself, which carries both classes; a child like
   <div class="d-flex gap-2"> holding the filters plus the action buttons stayed
   on one line, and because a flex item never shrinks below its content the last
   buttons (Returns, New Voucher) hung off the right edge of the card — visible
   whenever the viewport or the sidebar leaves the card narrower than the toolbar. */
.card-header .d-flex { flex-wrap: wrap; row-gap: .5rem; }
.card-footer {
  background: #fbfcfd;
  border-top: 1px solid var(--erp-border);
  padding: .55rem 1rem;
  font-size: .8rem;
  color: var(--erp-muted);
}
.card-body { padding: 1rem; }

/* ================================================================
   Tables
   ================================================================ */
.table { margin-bottom: 0; --bs-table-border-color: var(--erp-border); }
.table thead th {
  background: #f6f8fb;
  border-bottom: 1px solid var(--erp-border);
  color: var(--erp-muted);
  font-size: .67rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  white-space: nowrap;
  padding: .55rem .7rem;
}
.table td {
  padding: .5rem .7rem;
  vertical-align: middle;
  border-color: #eef1f6;
}
/* ---------- The payroll run: a dense money grid ----------
   This one table carries eighteen columns, six of them editable money boxes. At the
   roomy .7rem cell padding every other table gets, the padding alone came to ~200px
   across the row, which pushed Status / Pay / Slip past the right edge and left wide
   empty bands between the figures. Trimming the padding to .35rem gives the columns
   that room back, so the whole run — and its totals line — sits on one screen. */
/* With the table's default automatic layout the browser hands every spare pixel to
   the one column whose content could grow — the staff name — so on a wide screen the
   row huddled against the right edge behind a great empty band. The fixed layout plus
   the percentage widths in the view (every column carries its share) spreads the row
   across the whole card, and the money boxes take their column's width rather than a
   pixel width of their own. The floor keeps the columns usable on a narrow window,
   where the table scrolls sideways instead of squashing. */
#payrollTable { table-layout: fixed; min-width: 1150px; }
#payrollTable td .form-control { width: 100%; }
#payrollTable > thead > tr > th,
#payrollTable > tbody > tr > td,
#payrollTable > tfoot > tr > td { padding-left: .35rem; padding-right: .35rem; }
#payrollTable > thead > tr > th { padding-top: .4rem; padding-bottom: .4rem; }
#payrollTable > tbody > tr > td { padding-top: .4rem; padding-bottom: .4rem; }
.table-hover tbody tr:hover { background: var(--erp-accent-tint); }
.table-bordered > :not(caption) > * { border-color: var(--erp-border); }
.table .num, td.num, .num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---------- List pager ----------
   One bar per list: how many rows are showing, the remembered "Records per page"
   picker and the page buttons (‹ 1 2 3 … 12 ›). Renders above the table on screens
   that have one, so the picker is reachable without scrolling a long list. */
.pg-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1rem;
  padding: .55rem .85rem;
  border-bottom: 1px solid var(--erp-border);
  background: var(--erp-surface, #fff);
}
.pg-info { font-size: .8rem; color: var(--erp-muted); }
.pg-info strong { color: var(--erp-ink); font-weight: 700; }
.pg-size { display: flex; align-items: center; gap: .45rem; margin-left: auto; }
.pg-size-label { font-size: .8rem; color: var(--erp-muted); white-space: nowrap; margin: 0; }
.pg-size .form-select { width: auto; min-width: 76px; }
.pg-pages { margin: 0; flex-wrap: wrap; }
.pg-bar .page-link { border-color: var(--erp-border); color: var(--erp-ink); }
.pg-bar .page-item.active .page-link { background: var(--erp-accent); border-color: var(--erp-accent); color: #fff; }
.pg-bar .page-item.disabled .page-link { color: var(--erp-muted); }
/* The bar is chrome, not content: it never belongs on paper. */
@media print { .pg-bar { display: none !important; } }

/* ================================================================
   Forms
   ================================================================ */
.form-label {
  font-size: .76rem;
  font-weight: 650;
  color: #44506b;
  letter-spacing: .02em;
  margin-bottom: .3rem;
}
.form-control, .form-select { font-size: .88rem; color: var(--erp-ink); }
.form-control:focus, .form-select:focus {
  border-color: var(--erp-accent);
  box-shadow: 0 0 0 .18rem rgba(13, 148, 136, .14);
}
.form-control::placeholder { color: #a8b3c4; }
.form-select { padding-right: 2rem; }
.input-group-text { font-size: .85rem; background: #f6f8fb; }
.form-text { font-size: .72rem; color: var(--erp-muted); }
.required::after { content: " *"; color: var(--erp-danger); }
.form-check-input:checked { background-color: var(--erp-accent); border-color: var(--erp-accent); }
.form-check-input:focus { border-color: var(--erp-accent); box-shadow: 0 0 0 .18rem rgba(13, 148, 136, .14); }
textarea.form-control { font-family: var(--erp-font); }
@media (max-width: 575.98px) {
  /* Prevent iOS auto-zoom when focusing fields */
  .form-control, .form-select, .btn, input[type="date"], input[type="number"], input[type="text"], input[type="search"], input[type="password"] { font-size: 16px; }
}

/* ================================================================
   Buttons
   ================================================================ */
.btn { border-radius: var(--erp-radius-sm); font-size: .855rem; }
.btn i:first-child:not(:last-child) { margin-right: .35rem; }
.btn i:only-child { vertical-align: -.1em; }
.btn-primary {
  --bs-btn-bg: var(--erp-accent);
  --bs-btn-border-color: var(--erp-accent);
  --bs-btn-hover-bg: var(--erp-accent-700);
  --bs-btn-hover-border-color: var(--erp-accent-700);
  --bs-btn-active-bg: var(--erp-accent-800);
  --bs-btn-active-border-color: var(--erp-accent-800);
  --bs-btn-disabled-bg: var(--erp-accent);
  --bs-btn-disabled-border-color: var(--erp-accent);
}
.btn-outline-primary {
  --bs-btn-color: var(--erp-accent-700);
  --bs-btn-border-color: var(--erp-accent);
  --bs-btn-hover-bg: var(--erp-accent);
  --bs-btn-hover-border-color: var(--erp-accent);
  --bs-btn-active-bg: var(--erp-accent-700);
  --bs-btn-active-border-color: var(--erp-accent-700);
}
.btn-outline-secondary {
  --bs-btn-color: #526078;
  --bs-btn-border-color: var(--erp-border-hi);
  --bs-btn-hover-bg: #eef2f7;
  --bs-btn-hover-border-color: var(--erp-border-hi);
  --bs-btn-hover-color: #334155;
}
.btn-success {
  --bs-btn-bg: var(--erp-success);
  --bs-btn-border-color: var(--erp-success);
  --bs-btn-hover-bg: #047857;
  --bs-btn-hover-border-color: #047857;
}
.btn-xs { padding: .12rem .5rem; font-size: .74rem; border-radius: .35rem; }
.btn-danger {
  --bs-btn-bg: var(--erp-danger);
  --bs-btn-border-color: var(--erp-danger);
}
.kbd-hint { font-size: .72rem; color: var(--erp-muted); }
.kbd-hint kbd { margin: 0 .1rem; }

/* ================================================================
   Status badges (class set is shared across every module)
   ================================================================ */
.badge { font-weight: 600; font-size: .68rem; letter-spacing: .02em; padding: .38em .6em; border-radius: 999px; }
.badge-draft { background: #eef2f7; color: #526078; }
.badge-submitted, .badge-planned, .badge-open { background: #dbeafe; color: #1d4ed8; }
.badge-received, .badge-pending { background: #fef3c7; color: #b45309; }
.badge-in_progress, .badge-in_production, .badge-partially_fulfilled { background: #fef3c7; color: #b45309; }
.badge-ready, .badge-confirmed, .badge-approved, .badge-completed, .badge-active, .badge-available, .badge-paid { background: #d1fae5; color: #047857; }
.badge-dispatched, .badge-closed, .badge-issued { background: #e0e7ff; color: #4338ca; }
.badge-cancelled, .badge-rejected, .badge-disabled, .badge-inactive, .badge-left, .badge-maintenance { background: #fee2e2; color: #b91c1c; }
.badge-on_route { background: #ede9fe; color: #6d28d9; }
/* A merged report line whose rows do not all agree — neither one status nor a failure. */
.badge-mixed { background: #f1f5f9; color: #64748b; }

/* ================================================================
   Dashboard stat cards
   ================================================================ */
.stat-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  background: var(--erp-surface);
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  padding: .95rem 1rem;
  box-shadow: var(--erp-shadow-sm);
  min-height: 86px;
}
.stat-card .stat-label {
  font-size: .7rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--erp-muted);
}
.stat-card .stat-value {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--erp-ink);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.stat-card .stat-icon {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: .65rem;
  background: var(--erp-accent-tint);
  color: var(--erp-accent-700);
  font-size: 1.15rem;
}

/* ================================================================
   Editable entry grids (js-grid helper used by several screens)
   ================================================================ */
.js-grid input, .js-grid select { min-width: 0; }
.js-grid .qty-cell { width: 130px; }
.grid-total { background: var(--erp-accent-tint) !important; font-weight: 700; }
.grid-total td { border-top: 2px solid var(--erp-accent-soft) !important; }
/* The heading a band of lines sits under in a grouped report (a section-wise sheet). */
.grid-section td { background: #eef1f6 !important; font-weight: 700; font-size: .72rem;
                   color: var(--erp-ink); border-top: 1px solid var(--erp-border) !important; }

/* ================================================================
   Manual dispatch voucher (fast keyboard entry)
   ================================================================ */
/* No width cap: a page wrapper must fill the space right of the rail (see .erp-content). */
.ve-page { max-width: none; }
.ve-page .card { border-color: var(--erp-border); }
.ve-card-head { border-bottom: 1px solid var(--erp-border); }
.ve-title-icon {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: .6rem;
  background: linear-gradient(135deg, #14b8a6, var(--erp-accent-700));
  color: #fff;
  font-size: 1.15rem;
  box-shadow: 0 4px 12px rgba(13, 148, 136, .3);
}
.ve-title { font-size: 1rem; font-weight: 700; color: var(--erp-ink); line-height: 1.2; }
.ve-subtitle { font-size: .74rem; color: var(--erp-muted); }
.ve-legend { display: flex; flex-wrap: wrap; gap: .3rem .6rem; align-items: center; font-size: .7rem; color: var(--erp-muted); }

/* salesman info chips */
.ve-chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: .5rem;
  margin: .75rem 0 1.1rem;
}
.ve-chip {
  display: flex;
  align-items: center;
  gap: .6rem;
  background: var(--erp-surface);
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  padding: .55rem .75rem;
  box-shadow: var(--erp-shadow-sm);
}
.ve-chip > i {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: .45rem;
  background: var(--erp-accent-tint);
  color: var(--erp-accent-700);
  font-size: .95rem;
}
.ve-chip .k {
  font-size: .6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--erp-faint);
  line-height: 1.4;
}
.ve-chip .v { font-weight: 700; font-size: .82rem; color: var(--erp-ink); line-height: 1.35; }

/* products section */
.ve-section-title { font-size: .86rem; font-weight: 700; color: var(--erp-ink); }
.ve-section-sub { font-size: .74rem; color: var(--erp-muted); }

/* grid */
.ve-grid { min-width: 1120px; }
.ve-grid thead th { background: #f6f8fb; }
.ve-grid td { padding: .45rem .5rem; }
.ve-grid .ve-c-no { width: 3.5%; }
.ve-grid .ve-c-prod { width: 25%; }
.ve-grid .ve-c-price { width: 8%; }
.ve-grid .ve-c-qty { width: 9%; }
.ve-grid .ve-c-amt { width: 9%; }
.ve-grid .ve-c-ret { width: 8%; }
.ve-grid .ve-c-unsold { width: 8%; }
.ve-grid .ve-c-rprice { width: 8%; }
.ve-grid .ve-c-retamt { width: 9%; }
.ve-grid .ve-c-tot { width: 11%; }
.ve-grid .ve-c-del { width: 4%; }
.ve-grid td:first-child { text-align: center; color: var(--erp-muted); font-size: .78rem; }
.ve-grid .js-prod { font-size: .86rem; }
.ve-grid input[type="number"] { min-width: 0; font-size: .86rem; text-align: right; }
.ve-grid .js-qty, .ve-grid .js-ret { width: 100%; max-width: 110px; }
.ve-grid .js-del { opacity: .5; }
.ve-grid tr:hover .js-del { opacity: 1; }
.ve-grid .muted { color: var(--erp-faint); }

/* product search + dropdown */
.ve-search { position: relative; }
.ve-dd {
  position: fixed;
  z-index: 3000;
  display: none;
  min-width: 320px;
  max-height: 300px;
  overflow-y: auto;
  background: var(--erp-surface);
  border: 1px solid var(--erp-border);
  border-radius: .5rem;
  box-shadow: var(--erp-shadow-md);
  padding: .3rem;
}
.ve-dd.open { display: block; }
.ve-pi {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .48rem .6rem;
  border-radius: .35rem;
  cursor: pointer;
  font-size: .85rem;
  color: var(--erp-ink);
}
.ve-pi:hover, .ve-pi.active { background: var(--erp-accent-tint); }
.ve-pi .code { color: var(--erp-faint); font-size: .72rem; margin-left: .3rem; }
.ve-pi .tray {
  display: inline-block;
  margin-left: .3rem;
  padding: .08rem .4rem;
  border-radius: 999px;
  background: var(--erp-accent-soft);
  color: var(--erp-accent-800);
  font-size: .68rem;
  font-weight: 600;
}
.ve-pi .num { color: var(--erp-ink); font-weight: 700; white-space: nowrap; }
.ve-dd-empty { padding: .6rem; color: var(--erp-faint); font-size: .8rem; }

/* voucher closing */
.ve-close-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: .75rem; }
.ve-close-panel {
  background: var(--erp-surface);
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  padding: .85rem .9rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.ve-close-panel .panel-head { display: flex; align-items: center; gap: .45rem; }
.ve-close-panel .panel-head i { color: var(--erp-accent); font-size: 1rem; }
.ve-close-panel .panel-head .t { font-size: .78rem; font-weight: 700; color: var(--erp-ink); }
.ve-close-panel .panel-head .hint { margin-left: auto; font-size: .68rem; color: var(--erp-faint); font-weight: 500; }
.ve-cash { border-color: #99f6e4; background: linear-gradient(180deg, #f0fdfa, #ffffff); }
.ve-cash .panel-head i { color: var(--erp-success); }
.ve-cash input { font-size: 1.12rem; font-weight: 700; }
.tray-ret-row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.tray-ret-row .t-label { font-size: .78rem; color: var(--erp-muted); }
.tray-ret-row .t-label strong { color: var(--erp-ink); font-variant-numeric: tabular-nums; }
.tray-ret-row .js-tret { width: 130px; }
.exp-row { display: flex; gap: .4rem; }
.exp-row .exp-desc { flex: 1 1 auto; min-width: 0; }
.exp-row .exp-amt { width: 120px; flex: 0 0 auto; text-align: right; }

/* live totals strip under the grid */
.ve-totals-band {
  display: flex;
  flex-wrap: wrap;
  margin-top: .55rem;
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  background: #fff;
  box-shadow: var(--erp-shadow-sm);
  overflow: hidden;
}
.ve-totals-band .vt {
  flex: 1 1 132px;
  min-width: 132px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .05rem;
  padding: .5rem .85rem;
  border-left: 1px solid #eef2f7;
}
.ve-totals-band .vt:first-child { border-left: 0; }
.ve-totals-band .vt .k {
  font-size: .58rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--erp-muted);
  white-space: nowrap;
}
.ve-totals-band .vt .v {
  font-size: .95rem;
  font-weight: 800;
  color: var(--erp-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  line-height: 1.25;
}
.ve-totals-band .vt small {
  font-size: .66rem;
  font-weight: 700;
  color: var(--erp-faint);
}
.ve-totals-band .vt-pay {
  background: var(--erp-accent-tint);
  border-left: 3px solid var(--erp-accent);
}
.ve-totals-band .vt-pay .k { color: var(--erp-accent-700); }
.ve-totals-band .vt-pay .v { color: var(--erp-accent-800); font-size: 1.08rem; }

/* voucher print preview (hidden #print-doc only exists on this page) */
#print-doc { display: none; }
@media print {
  body * { visibility: hidden; }
  #print-doc, #print-doc * { visibility: visible; }
  #print-doc { display: block; position: absolute; left: 0; top: 0; width: 100%; }
}

/* ================================================================
   Dispatch voucher — create (mode chooser)
   ================================================================ */
.mode-card .card-body { display: flex; flex-direction: column; }
.mode-card .mode-icon {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: .85rem;
  font-size: 1.5rem;
}
.mode-card .mode-icon.i-neutral {
  background: #eef2f7;
  color: #526078;
}
.mode-card .mode-icon.i-brand {
  background: linear-gradient(135deg, #14b8a6, var(--erp-accent-700));
  color: #fff;
  box-shadow: 0 6px 16px rgba(13, 148, 136, .3);
}
.mode-card h5 { font-size: 1rem; font-weight: 700; color: var(--erp-ink); }
.mode-card p { font-size: .8rem; color: var(--erp-muted); }
.mode-card .mode-cta { margin-top: auto; }

/* ================================================================
   Reports launchpad cards
   ================================================================ */
.launch-card { transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease; }
.launch-card:hover {
  border-color: var(--erp-accent-soft);
  box-shadow: 0 8px 24px -12px rgba(13, 148, 136, .35);
  transform: translateY(-2px);
}
.launch-card .card-body { display: flex; flex-direction: column; gap: .5rem; }
.launch-card .lc-icon {
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: .7rem;
  background: var(--erp-accent-tint);
  color: var(--erp-accent-700);
  font-size: 1.2rem;
}
.launch-card h6 { font-size: .9rem; font-weight: 700; color: var(--erp-ink); margin: 0; }
.launch-card p { font-size: .76rem; color: var(--erp-muted); margin: 0; }
.launch-card .lc-cta { margin-top: auto; padding-top: .5rem; }

/* ================================================================
   Login
   ================================================================ */
.login-wrap {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background:
    radial-gradient(900px 480px at 85% -10%, rgba(13, 148, 136, .35), transparent 60%),
    radial-gradient(700px 420px at -10% 110%, rgba(13, 148, 136, .25), transparent 55%),
    linear-gradient(150deg, #0b1220 0%, #0f172a 55%, #134e4a 130%);
}
.login-card {
  width: 100%;
  max-width: 400px;
  border: 0;
  border-radius: 1rem;
  box-shadow: 0 30px 70px -20px rgba(2, 6, 23, .6);
  overflow: hidden;
}
.login-card .auth-brand { text-align: center; margin-bottom: 1.4rem; }
.login-card .auth-brand .mark {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  margin: 0 auto .75rem;
  border-radius: .9rem;
  background: linear-gradient(135deg, #14b8a6, var(--erp-accent-700));
  color: #fff; font-size: 1.5rem; font-weight: 800;
  box-shadow: 0 8px 22px rgba(13, 148, 136, .45);
}
.login-card .auth-brand .logo {
  display: block;
  max-height: calc(84px * var(--brand-scale, 1));
  max-width: calc(230px * var(--brand-scale, 1));
  margin: 0 auto .85rem;
  object-fit: contain;
}
.login-card .auth-brand h4 { font-weight: 750; color: var(--erp-ink); margin-bottom: .15rem; }
.login-card .auth-brand p { color: var(--erp-muted); font-size: .82rem; margin: 0; }
.login-card .btn-primary { padding: .55rem 1rem; font-weight: 600; }

/* ================================================================
   Error pages
   ================================================================ */
.error-page { min-height: 100vh; min-height: 100dvh; }
.error-page .code {
  font-size: 5rem;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1;
  background: linear-gradient(135deg, var(--erp-accent), var(--erp-accent-800));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ================================================================
   Misc / helpers (hooks used across views)
   ================================================================ */
.offline-banner {
  display: none;
  background: #fffbeb;
  color: #92400e;
  text-align: center;
  padding: .35rem .75rem;
  font-size: .8rem;
  font-weight: 600;
  border-bottom: 1px solid #fde68a;
}
body.offline .offline-banner { display: block; }
.text-muted-sm { color: var(--erp-muted); font-size: .78rem; }
.mono { font-variant-numeric: tabular-nums; font-family: ui-monospace, "Cascadia Mono", Consolas, "Segoe UI Mono", monospace; }
.cursor-pointer { cursor: pointer; }

/* A table row that opens something of its own (a merged report line opening back up onto
   the records behind it).  The pointer and the tint say the row is a door; app.js does the
   walking, and a click that lands on a control inside the row is left to that control. */
tr[data-href] { cursor: pointer; }
tr[data-href]:hover > td { background-color: var(--bs-tertiary-bg, #f8f9fa); }
.nowrap { white-space: nowrap; }
.summary-box { background: #f6f8fb; border: 1px dashed var(--erp-border-hi); border-radius: var(--erp-radius-sm); padding: .7rem .9rem; }
.toast-container { position: fixed; top: .9rem; right: .9rem; z-index: 5000; }
.toast-container .toast { border-radius: var(--erp-radius-sm); box-shadow: var(--erp-shadow-md); }
.alert { border-radius: var(--erp-radius-sm); }
.alert-danger { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.alert-success { background: #ecfdf5; border-color: #a7f3d0; color: #065f46; }
.alert-warning { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.alert-info { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }

/* ---------- Print: screen chrome off, content clean ---------- */
@media print {
  .erp-sidebar, .erp-topbar, .no-print, .offline-banner, .erp-backdrop { display: none !important; }
  .erp-main { display: block; }
  .erp-content { padding: 0; max-width: none; }
  body { background: #fff; }
  .card { border: none; box-shadow: none; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ================================================================
   Manual voucher — compact spreadsheet layout (small text everywhere)
   ================================================================ */
.ve-page { font-size: .72rem; }
.ve-title { font-size: .95rem; }
.ve-subtitle, .ve-section-sub, .ve-legend { font-size: .68rem; }
.ve-chip .k { font-size: .56rem; }
.ve-chip .v { font-size: .76rem; }

.ve-grid { min-width: 1180px; font-size: .68rem; }
.ve-grid thead th { font-size: .6rem; text-transform: uppercase; letter-spacing: .04em; padding: .38rem .45rem; }
.ve-grid td { padding: .28rem .4rem; }
.ve-grid .js-prod { font-size: .76rem; }
.ve-grid input[type="number"] { font-size: .76rem; }
.ve-grid .ve-c-prod { width: 25%; }
.ve-grid .ve-c-price, .ve-grid .ve-c-amt, .ve-grid .ve-c-rprice, .ve-grid .ve-c-retamt { width: 8%; }
.ve-grid .ve-c-qty { width: 8.5%; }
.ve-grid .ve-c-ret { width: 7.5%; }
.ve-grid .ve-c-unsold { width: 7%; }
.ve-grid .ve-c-trays { width: 6%; }
.ve-grid .ve-c-tot { width: 9.5%; }
.ve-grid td:first-child { font-size: .66rem; }
.ve-grid .js-qty, .ve-grid .js-ret, .ve-grid .js-unsold { max-width: 90px; }
.ve-grid tfoot th { background: #f1f5f9; font-size: .68rem; font-weight: 700; padding: .3rem .4rem; color: var(--erp-ink); }
.ve-grid .js-total-cell { font-weight: 700; }

.ve-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: .4rem;
}
.ve-summary .vs {
  background: #fff;
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  padding: .38rem .5rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: .2rem;
  min-width: 0;
}
.ve-summary .vs .k {
  font-size: .55rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--erp-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ve-summary .vs .v {
  font-size: .78rem;
  font-weight: 800;
  color: var(--erp-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ve-summary .vs .v.neg { color: var(--erp-danger); }
.ve-summary .vs input { font-size: .76rem; padding: .2rem .4rem; }
.ve-summary .vs-net { border-color: var(--erp-accent); background: var(--erp-accent-tint); }
.ve-summary .vs-net .v { color: var(--erp-accent-800); }
.ve-summary .vs-bal { border-color: #fcd34d; background: #fffbeb; }
.ve-summary .vs-bal .v { color: #b45309; }
.ve-summary-foot {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.4rem;
  margin-top: .45rem;
  font-size: .66rem;
  color: var(--erp-muted);
}
.ve-summary-foot span { font-variant-numeric: tabular-nums; }

.ve-summary .tray-ret-row { display: flex; flex-direction: column; gap: .15rem; }
.ve-summary .tray-ret-row .t-label { font-size: .6rem; color: var(--erp-faint); }
.ve-summary .tray-ret-row .t-label strong { color: var(--erp-ink); }
.ve-summary .tray-ret-row .js-tret { width: 100%; max-width: none; padding: .2rem .4rem; font-size: .76rem; }

/* Misc cell: amount-only rows (no names, no add/delete buttons) */
.ve-summary .exp-row { display: flex; gap: .3rem; margin-bottom: .3rem; }
.ve-summary .exp-row:last-child { margin-bottom: 0; }
.ve-summary .exp-row .exp-amt { flex: 1 1 auto; width: 100%; max-width: none; min-width: 0; text-align: right; font-size: .76rem; padding: .2rem .4rem; }

.ve-exp-panel {
  background: var(--erp-surface);
  border: 1px solid var(--erp-border);
  border-radius: var(--erp-radius);
  padding: .55rem .7rem;
}
.ve-exp-panel .panel-head { display: flex; align-items: center; gap: .45rem; margin-bottom: .4rem; }
.ve-exp-panel .panel-head i { color: var(--erp-accent); }
.ve-exp-panel .panel-head .t { font-size: .72rem; font-weight: 700; color: var(--erp-ink); }
.ve-exp-panel .panel-head button { margin-left: auto; }
.ve-exp-panel .exp-row { display: flex; gap: .4rem; margin-bottom: .35rem; }
.ve-exp-panel .exp-row .exp-desc { flex: 1 1 auto; min-width: 0; font-size: .74rem; }
.ve-exp-panel .exp-row .exp-amt { width: 110px; flex: 0 0 auto; text-align: right; font-size: .74rem; }
.ve-exp-panel .exp-row .btn-xs { padding: .15rem .3rem; line-height: 1; }

.ve-pi { font-size: .78rem; padding: .38rem .5rem; }

/* ==================================================================
   Staff photographs
   A face lives in a BOX, not a circle: the file is a rectangle and the
   disc crop threw away a third of it.  On the card the box is also the
   button that opens the full picture (the plain Bootstrap modal).
   ================================================================== */
.staff-photo-box {
  width: 110px; height: 110px; object-fit: cover;
  border: 1px solid var(--erp-border, #dee2e6);
  border-radius: 10px; background: #fff; display: block;
}
.staff-photo-empty { background: #eef2f7; color: #64748b; font-weight: 700; }
.staff-photo-btn { line-height: 0; cursor: zoom-in; }
.staff-photo-btn:focus-visible { outline: 2px solid var(--erp-accent, #0d9488); outline-offset: 2px; border-radius: 10px; }
/* The small one on the list keeps its size, only the shape changes. */
.staff-photo-sm.staff-photo-box { width: 34px; height: 34px; border-radius: 6px; }

/* ============ Settings page tabs ============ */
/* One row of tabs under the page title: the chosen tab is underlined in the
   accent color and the rest stay quiet — the same idea as the reference
   screenshot (Profile / Database Cleanup / Settings / APIs / Email / Dashboard). */
.erp-tabs {
  border-bottom: 2px solid var(--bs-border-color, #dee2e6);
  gap: .25rem;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: thin;
}
.erp-tabs .nav-link {
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  color: var(--bs-secondary-color, #6c757d);
  white-space: nowrap;
  padding: .5rem .9rem;
}
.erp-tabs .nav-link:hover { color: var(--bs-body-color, #212529); }
.erp-tabs .nav-link.active {
  color: var(--bs-primary, #0d6efd);
  border-bottom-color: var(--bs-primary, #0d6efd);
  background: transparent;
  font-weight: 600;
}

/* ---- Master search (top bar) ---- */
.erp-search-input { width: 300px; max-width: 34vw; border-radius: 20px; padding-left: 14px; }
.erp-search-menu { position: absolute; top: 100%; right: 0; min-width: 380px; max-width: 92vw; max-height: 70vh; overflow-y: auto; z-index: 1055; }
.erp-search-mobile { position: absolute; right: 0; top: 0; width: min(78vw, 340px) !important; z-index: 1056; box-shadow: 0 4px 16px rgba(0,0,0,.15); }
