/* Dx3 — small overrides on top of Tabler defaults. */

/* Tighten sidebar nav to match the plan's "comfortable" density. */
.navbar-vertical .nav-link {
  padding: .5rem .75rem;
}

/* Visually disable nav items that point at "#" (not-yet-built pages).
   The dropdown toggle itself is also href="#" but must stay clickable, so we
   exclude .dropdown-toggle. Dropdown menu leaves (.dropdown-item[href="#"])
   also get the disabled treatment. */
.navbar-vertical .nav-link[href="#"]:not(.dropdown-toggle),
.navbar-vertical .dropdown-item[href="#"] {
  opacity: .55;
  pointer-events: none;
}

/* Active sidebar item indicator. Tabler ships .active styling for vertical
   navs already; we just nudge the highlight a touch stronger for the
   dropdown leaves so the current page reads at a glance. */
.navbar-vertical .dropdown-menu .dropdown-item.active {
  background-color: rgba(32, 107, 196, .12);
  color: var(--tblr-primary, #206bc4);
  font-weight: 500;
}

/* Status badge palette mapping (Tabler badges + plan colors). */
.badge-state-draft     { background:#adb5bd; color:#fff; }
.badge-state-submitted { background:#206bc4; color:#fff; }
.badge-state-partial   { background:#f59f00; color:#fff; }
.badge-state-posted    { background:#2fb344; color:#fff; }
.badge-state-cancelled { background:#d63939; color:#fff; }

/* Hide Alpine-managed elements until Alpine boots, prevents flash-of-all-images. */
[x-cloak] { display: none !important; }

/* Product gallery + lightbox. */
.gallery-main {
  position: relative;
  background: var(--tblr-bg-surface-secondary, #f8fafc);
  border-radius: 8px;
  min-height: 360px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.gallery-main img { cursor: zoom-in; transition: transform .15s ease; }
.gallery-main img:hover { transform: scale(1.01); }
.gallery-nav-btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  border: none; background: rgba(255,255,255,.85);
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(0,0,0,.12);
  cursor: pointer; color: #1d273b;
}
.gallery-nav-btn:hover { background:#fff; }
.gallery-nav-btn.prev { left: 12px; }
.gallery-nav-btn.next { right: 12px; }

.gallery-counter {
  position: absolute; top: 10px; right: 10px;
  background: rgba(0,0,0,.55); color: #fff;
  font-size: .75rem; padding: 2px 8px; border-radius: 999px;
  font-feature-settings: "tnum";
}

.gallery-thumbs {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: center; margin-top: 12px;
}
.gallery-thumb {
  width: 64px; height: 64px; border: 2px solid transparent;
  border-radius: 6px; padding: 0; cursor: pointer;
  background: none; overflow: hidden;
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-thumb.is-active { border-color: var(--tblr-primary, #206bc4); }

/* Lightbox. */
.lightbox {
  position: fixed; inset: 0; z-index: 1080;
  background: rgba(0,0,0,.92);
  display: flex; align-items: center; justify-content: center;
}
.lightbox-image { max-width: 92vw; max-height: 86vh; border-radius: 6px; }
.lightbox-close,
.lightbox-nav {
  position: absolute; border: none; background: rgba(255,255,255,.12);
  color: #fff; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 1.25rem;
}
.lightbox-close:hover, .lightbox-nav:hover { background: rgba(255,255,255,.22); }
.lightbox-close { top: 18px; right: 18px; }
.lightbox-nav.prev { left: 18px; top: 50%; transform: translateY(-50%); }
.lightbox-nav.next { right: 18px; top: 50%; transform: translateY(-50%); }
.lightbox-counter {
  position: absolute; top: 22px; left: 22px;
  color: rgba(255,255,255,.85); font-size: .9rem;
  font-feature-settings: "tnum";
}
.lightbox-caption {
  position: absolute; bottom: 22px; left: 0; right: 0;
  text-align: center; color: rgba(255,255,255,.9);
  font-size: .95rem; padding: 0 1rem;
}

/* Tom Select product picker — compact, single-line options. */
.ts-wrapper .ts-control { padding: .25rem .5rem; min-height: 32px; }
.ts-dropdown {
  font-size: .85rem;
  min-width: 32em;
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #dadcde);
  border-radius: 6px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .12);
  z-index: 1080;
}
.ts-dropdown .ts-dropdown-content {
  background: inherit;
  max-height: 320px;
}
.ts-dropdown .option { padding: .3rem .6rem; background: transparent; }
.ts-dropdown .option.active { background-color: rgba(32, 107, 196, .14); }
.ts-dropdown .no-results { padding: .5rem .65rem; color: var(--tblr-secondary, #626976); }
[data-bs-theme="dark"] .ts-dropdown { background: var(--tblr-bg-surface-dark, #1a2234); }
.dx3-pick-opt {
  display: flex; align-items: baseline; gap: .5rem;
  line-height: 1.3; min-width: 0;
}
.dx3-pick-sku {
  flex: 0 0 auto;
  font-size: .72rem;
  color: var(--tblr-secondary, #626976);
  background: rgba(0,0,0,.04);
  padding: .05rem .35rem;
  border-radius: 3px;
}
.dx3-pick-text {
  flex: 1 1 auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Invoice charge-row tinting — direction at a glance. */
.charge-row.charge-deduction { background: rgba(220, 53, 69, .04); }
.charge-row.charge-deduction > td:first-child { border-left: 3px solid rgba(220, 53, 69, .55); }
.charge-row.charge-addition  { background: rgba(40, 167, 69, .06); }
.charge-row.charge-addition > td:first-child { border-left: 3px solid rgba(40, 167, 69, .65); }

/* ============================================================
   Dx3 Design System — porcelain + ink + amber.
   Tokens live under :root with dx3- prefix to coexist with Tabler.
   New components also dx3-prefixed; Tabler classes left untouched.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@1,9..144,400;1,9..144,500&family=Manrope:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');

:root {
  /* Paper & ink */
  --dx3-paper:   #FCFCF9;
  --dx3-paper-2: #F4F3EE;
  --dx3-paper-3: #EAE8E2;
  --dx3-paper-4: #D9D6CD;
  --dx3-ink:     #16161A;
  --dx3-ink-2:   #2C2C30;
  --dx3-ink-3:   #6E6E6A;
  --dx3-ink-4:   #A0A09B;
  --dx3-rule:    #E4E2DB;
  --dx3-rule-2:  #CBC8C0;
  /* Signature amber */
  --dx3-amber:   #B8601C;
  --dx3-amber-2: #D17B2E;
  --dx3-amber-3: #ECD8C0;
  --dx3-amber-4: #F3E6D0;
  /* Document status */
  --dx3-green:   #1F5B3B;
  --dx3-green-3: #CEDAC6;
  --dx3-red:     #8A2A2A;
  --dx3-red-3:   #E8CFCA;
  --dx3-gold:    #B5821C;
  /* Type families */
  --dx3-sans:    'Manrope', system-ui, -apple-system, sans-serif;
  --dx3-display: 'Manrope', system-ui, sans-serif;
  --dx3-mono:    'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;
  --dx3-serif:   'Fraunces', 'Times New Roman', serif;
  /* Tell Tabler to use Manrope too */
  --tblr-font-sans-serif: 'Manrope', system-ui, -apple-system, sans-serif;
}

body {
  font-family: var(--dx3-sans);
  background: var(--dx3-paper);
}

/* Breathing room around the main content panel — equal padding on both
   sides so the page reads as a balanced column instead of being shoved
   against the right edge. Container's auto-margin is killed so the
   page-wrapper padding actually shifts the content rather than being
   absorbed by Bootstrap's centering. */
.page-wrapper {
  padding-left: 0.5in;
  padding-right: 0.5in;
}
.page-wrapper .container-xl {
  margin-left: 0 !important;
  margin-right: 0 !important;
  max-width: none;
}

/* === Sidebar: ink black with new brand lockup =================== */

.navbar-vertical[data-bs-theme="dark"] {
  --tblr-bg-surface: var(--dx3-ink);
  --tblr-body-bg: var(--dx3-ink);
  background: var(--dx3-ink) !important;
}

/* Sidebar inner padding — match the 0.25in margin-top set on .navbar-brand
   so the brand block has a visually consistent square corner: 0.25in top
   inset AND 0.25in left inset. Shifts the whole sidebar content (brand +
   nav items) by the same amount so the logo and menu icons stay aligned. */
.navbar-vertical > .container-fluid {
  padding-left: 0.18in !important;
  display: flex;
  flex-direction: column;
  height: 100vh;
  align-items: stretch;
}
/* Nav menu scrolls when it overflows; user block always stays in view. */
.navbar-vertical .navbar-collapse {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}
.dx3-sidebar-user { flex-shrink: 0; }

/* Tabler defaults the vertical navbar-brand to justify-content: center, which
   centers the anchor inside the h1. Our lockup needs to be flush-left so the
   logo image and the SALES & INVENTORY tag both align with the nav icons
   below. Override at the same specificity (0,3,0) Tabler uses. */
.navbar-vertical.navbar-expand-sm .navbar-brand,
.navbar-vertical.navbar-expand-md .navbar-brand,
.navbar-vertical.navbar-expand-lg .navbar-brand,
.navbar-vertical.navbar-expand-xl .navbar-brand,
.navbar-vertical.navbar-expand-xxl .navbar-brand,
.navbar-vertical.navbar-expand   .navbar-brand {
  justify-content: flex-start !important;
  width: 100%;
}

.navbar-vertical[data-bs-theme="dark"] .nav-link {
  color: rgba(252, 252, 249, 0.72);
}
.navbar-vertical[data-bs-theme="dark"] .nav-link:hover,
.navbar-vertical[data-bs-theme="dark"] .nav-link.active {
  color: var(--dx3-paper);
}
.navbar-vertical[data-bs-theme="dark"] .nav-link.active .nav-link-icon {
  color: var(--dx3-amber-2);
}
.navbar-vertical[data-bs-theme="dark"] .dropdown-menu {
  background: var(--dx3-ink-2);
}

/* Collapsible section grouping in the sidebar (mockup pattern).
   <details><summary>…</summary> wraps each multi-item group; click the
   summary to open/close. Active group has `open` attribute set so the
   group containing the current page expands on load. */
.navbar-vertical .dx3-nav-section { list-style: none; }
.navbar-vertical .dx3-nav-details { padding: 0; }
.navbar-vertical .dx3-nav-section-label {
  padding: 16px 1rem 4px;
  font-size: 10px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(252, 252, 249, 0.40);
  font-weight: 700;
  margin-top: 4px;
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  user-select: none;
}
/* Hide the default disclosure marker on <summary>. */
.dx3-nav-section-label::-webkit-details-marker { display: none; }
.dx3-nav-section-label::marker { content: ''; }
.dx3-nav-section-label:hover { color: rgba(252, 252, 249, 0.70); }
.dx3-nav-chevron {
  font-size: 14px;
  color: rgba(252, 252, 249, 0.40);
  transition: transform 160ms ease;
}
.dx3-nav-details[open] > .dx3-nav-section-label .dx3-nav-chevron { transform: rotate(180deg); }
.dx3-nav-details[open] > .dx3-nav-section-label { color: rgba(252, 252, 249, 0.65); }
.dx3-nav-section-items { padding-bottom: 6px; }
.dx3-nav-section:first-child .dx3-nav-section-label { margin-top: 0; padding-top: 4px; }

/* User block at the bottom of the sidebar — mockup pattern.
   Amber circle initial + name + role label in small caps tracked. */
.dx3-sidebar-user {
  border-top: 1px solid rgba(252, 252, 249, 0.08);
  padding: 14px 1rem;
  margin: 12px 0.18in 0;
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 12.5px;
  color: rgba(252, 252, 249, 0.85);
}
.dx3-sidebar-user-avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--dx3-amber-2);
  color: var(--dx3-ink);
  display: grid;
  place-items: center;
  font-family: var(--dx3-sans);
  font-weight: 700;
  font-size: 12px;
  flex-shrink: 0;
}
.dx3-sidebar-user-who { line-height: 1.2; }
.dx3-sidebar-user-who small {
  display: block;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.20em;
  color: rgba(252, 252, 249, 0.40);
  font-weight: 600;
  margin-top: 2px;
}

/* Topbar — hairline breadcrumb + meta strip above the page content.
   Replaces the visual prominence of Tabler's default navbar header. */
.dx3-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 0 16px;
  border-bottom: 1px solid var(--dx3-rule);
  font-size: 11px;
}
.dx3-topbar-crumb {
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
}
.dx3-topbar-crumb span + span::before {
  content: '/';
  margin: 0 10px;
  color: var(--dx3-ink-4);
}
.dx3-topbar-crumb span:last-child { color: var(--dx3-ink); }
.dx3-topbar-meta {
  font-family: var(--dx3-mono);
  font-size: 11px;
  color: var(--dx3-ink-3);
  text-align: right;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  gap: 18px;
}
.dx3-topbar-meta i { font-size: 14px; color: var(--dx3-ink-4); }
.dx3-topbar-meta .dx3-meta-chip { display: inline-flex; align-items: center; gap: 6px; }

/* Brand lockup inside .navbar-brand */
/* Brand lockup inside .navbar-brand. Sized to match the design mockup
   exactly (38px mark / 17px name / 10px gap). The mark's left edge is
   nudged 4px right to compensate for Tabler's .nav-link-icon, which
   centers its glyph inside a 1.5rem min-width span (the menu icon's
   visible left edge sits ~4px to the right of its containing span). */
.dx3-brand-lockup {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dx3-brand-mark {
  width: 49px !important;
  height: 49px !important;
  max-width: 49px !important;
  object-fit: contain;
  flex-shrink: 0;
}
.dx3-brand-name {
  font-family: var(--dx3-sans);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.018em;
  color: var(--dx3-paper);
  line-height: 1.1;
}
.dx3-brand-tag {
  font-family: var(--dx3-sans);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.28em;
  color: rgba(252, 252, 249, 0.5);
  margin-top: 10px;
  font-weight: 600;
  display: block;
}

/* === Page-level utilities (phase 2 uses these per page) ========== */

.dx3-eyebrow {
  font-size: 11px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  margin-bottom: 12px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.dx3-eyebrow::before {
  content: '';
  width: 18px;
  height: 1.5px;
  background: var(--dx3-amber);
}

.dx3-display {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif !important;
  font-weight: 800 !important;
  letter-spacing: -0.035em !important;
  line-height: 1 !important;
  color: var(--dx3-ink) !important;
}
.dx3-display-lg { font-size: 52px !important; }
.dx3-display-md { font-size: 42px !important; }
.dx3-display-sm { font-size: 28px !important; }

.dx3-text-mono { font-family: var(--dx3-mono); font-variant-numeric: tabular-nums; }
.dx3-text-amber { color: var(--dx3-amber); }
.dx3-text-muted { color: var(--dx3-ink-3); }

/* KPI tile */
.dx3-kpi {
  border: 1px solid var(--dx3-rule);
  padding: 26px 24px 24px;
  background: var(--dx3-paper);
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: inherit;
  position: relative;
  text-decoration: none;
  transition: background 140ms ease, border-color 140ms ease;
}
.dx3-kpi:hover { background: var(--dx3-paper-2); border-color: var(--dx3-ink-3); color: inherit; text-decoration: none; }
.dx3-kpi:hover .dx3-kpi-value { color: var(--dx3-amber); }
.dx3-kpi-label {
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
}
.dx3-kpi-value {
  font-family: var(--dx3-display);
  font-weight: 800;
  /* Fluid sizing: shrinks from 38px (≥~1500px viewport) down to 22px on
     narrow screens so long peso amounts like ₱1,234,567.89 don't punch
     through the tile. min-width:0 lets it shrink inside the flex column. */
  font-size: clamp(22px, 2.6vw, 38px);
  line-height: 1;
  color: var(--dx3-ink);
  letter-spacing: -0.035em;
  transition: color 150ms ease;
  margin-top: 6px;
  font-variant-numeric: tabular-nums;
  /* Reserve room for the corner icon (30px circle at right:22, top:22). */
  padding-right: 44px;
  min-width: 0;
  word-break: keep-all;
  overflow-wrap: normal;
}
.dx3-kpi-value .peso {
  font-size: clamp(14px, 1.6vw, 22px);
  vertical-align: 3px;
  color: var(--dx3-ink-3);
  margin-right: 2px;
  font-weight: 600;
}
.dx3-kpi-meta {
  font-size: 11.5px;
  color: var(--dx3-ink-3);
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  letter-spacing: 0.02em;
}
.dx3-kpi-meta .pill {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  padding: 2px 6px;
  background: var(--dx3-paper-3);
}
.dx3-kpi .ico {
  position: absolute;
  top: 22px; right: 22px;
  width: 30px; height: 30px;
  border: 1px solid var(--dx3-rule-2);
  display: grid; place-items: center;
  color: var(--dx3-ink-3);
  border-radius: 50%;
  font-size: 13px;
}

/* Section number badge (replaces Roman numerals) */
.dx3-section-num {
  font-family: var(--dx3-mono);
  font-weight: 600;
  font-size: 11px;
  color: var(--dx3-amber);
  letter-spacing: 0.06em;
  padding: 2px 6px;
  border: 1px solid var(--dx3-amber-3);
  background: var(--dx3-paper-2);
  margin-right: 6px;
}

/* Rubber-stamp status indicator */
.dx3-stamp {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border: 1.5px solid currentColor;
  font-size: 10.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  font-weight: 700;
  font-family: var(--dx3-sans);
  transform: rotate(-1.5deg);
  background: var(--dx3-paper);
}
.dx3-stamp::before {
  content: '';
  width: 5px; height: 5px;
  background: currentColor;
  border-radius: 50%;
}
.dx3-stamp.posted    { color: var(--dx3-green); }
.dx3-stamp.draft     { color: var(--dx3-ink-3); }
.dx3-stamp.cancelled { color: var(--dx3-red); text-decoration: line-through; }
.dx3-stamp.partial   { color: var(--dx3-gold); }

/* Ledger card (porcelain, hairline rule) */
.dx3-card {
  background: var(--dx3-paper);
  border: 1px solid var(--dx3-rule);
  margin-bottom: 24px;
}
.dx3-card-head {
  padding: 16px 22px 14px;
  border-bottom: 1px solid var(--dx3-rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.dx3-card-head h3,
.dx3-card-head .h3 {
  font-family: var(--dx3-sans);
  font-size: 10.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--dx3-ink-2);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
.dx3-card-head .pill {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-family: var(--dx3-mono);
}
.dx3-card-body { padding: 22px 24px; }
.dx3-card-body.tight { padding: 0; }
.dx3-card-foot {
  border-top: 1px solid var(--dx3-rule);
  padding: 14px 22px;
  font-size: 11.5px;
  color: var(--dx3-ink-3);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Ledger-style table (for transaction/movement rows) */
.dx3-ledger-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.dx3-ledger-table th {
  text-align: left;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  padding: 14px 22px 10px;
  border-bottom: 1.5px solid var(--dx3-ink-2);
  white-space: nowrap;
}
.dx3-ledger-table td {
  padding: 14px 22px;
  border-bottom: 1px solid var(--dx3-rule);
  vertical-align: middle;
}
.dx3-ledger-table tr:last-child td { border-bottom: 0; }
.dx3-ledger-table tbody tr:hover td { background: rgba(184, 96, 28, 0.04); }
.dx3-ledger-table .num,
.dx3-ledger-table th.num {
  text-align: right;
  font-family: var(--dx3-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.dx3-sku-chip {
  font-family: var(--dx3-mono);
  font-size: 11.5px;
  color: var(--dx3-ink-2);
  background: var(--dx3-paper-2);
  padding: 3px 7px;
  letter-spacing: 0.02em;
  border: 1px solid var(--dx3-rule);
}

/* Marginalia (small italic editorial accents) */
.dx3-marginalia {
  font-family: var(--dx3-serif);
  font-style: italic;
  font-size: 13px;
  color: var(--dx3-ink-3);
  line-height: 1.4;
}

/* === Dashboard ===================================================
   Page-header replacement: eyebrow + display h1 + narrative greeting */
.dx3-page-head {
  padding: 28px 0 32px;
  border-bottom: 1px solid var(--dx3-rule);
  margin-bottom: 32px;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 32px;
  align-items: end;
}
.dx3-narrative {
  font-family: var(--dx3-sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--dx3-ink-2);
  max-width: 64ch;
  margin: 10px 0 0;
  font-weight: 400;
}
.dx3-narrative em { color: var(--dx3-amber); font-style: normal; font-weight: 600; }
.dx3-narrative strong { font-weight: 700; color: var(--dx3-ink); }

/* Secondary tile (smaller than KPI) */
.dx3-tile2 {
  border: 1px solid var(--dx3-rule);
  padding: 20px 22px;
  background: var(--dx3-paper);
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: inherit;
  position: relative;
  text-decoration: none;
  transition: background 120ms ease;
}
.dx3-tile2:hover { background: var(--dx3-paper-2); color: inherit; text-decoration: none; }
.dx3-tile2:hover .dx3-tile2-value { color: var(--dx3-amber); }
.dx3-tile2-label {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
}
.dx3-tile2-value {
  font-family: var(--dx3-display);
  font-weight: 800;
  font-size: 28px;
  line-height: 1.05;
  color: var(--dx3-ink);
  letter-spacing: -0.030em;
  transition: color 140ms ease;
  margin-top: 6px;
  font-variant-numeric: tabular-nums;
}
.dx3-tile2-value .peso { font-size: 16px; color: var(--dx3-ink-3); vertical-align: 3px; font-weight: 600; }
.dx3-tile2-meta {
  font-size: 11.5px;
  color: var(--dx3-ink-3);
  margin-top: 6px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.dx3-tile2-meta i { font-size: 12px; color: var(--dx3-ink-4); }

/* Recent-movements coloured kind cells */
.dx3-move-kind {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 500;
}
.dx3-move-kind-receipt { color: var(--dx3-green); }
.dx3-move-kind-sale { color: var(--dx3-red); }
.dx3-move-kind-transfer { color: var(--dx3-amber); }
.dx3-move-kind-return { color: var(--dx3-ink-3); }
.dx3-move-kind-other { color: var(--dx3-ink-3); }
.dx3-qty-up { color: var(--dx3-green); }
.dx3-qty-down { color: var(--dx3-red); }
.dx3-when {
  color: var(--dx3-ink-3);
  font-family: var(--dx3-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.dx3-wh-tag {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--dx3-ink-3);
}

/* Top sellers — ranked list */
.dx3-ranked .dx3-rank-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 16px;
  align-items: center;
  padding: 14px 22px;
  border-bottom: 1px solid var(--dx3-rule);
}
.dx3-ranked .dx3-rank-row:last-child { border-bottom: 0; }
.dx3-ranked .dx3-rank-row:hover { background: rgba(184, 96, 28, 0.04); }
.dx3-ranked .dx3-rank {
  font-family: var(--dx3-mono);
  font-weight: 600;
  font-size: 13px;
  color: var(--dx3-amber);
  letter-spacing: 0.06em;
  line-height: 1;
  padding: 4px 6px;
  border: 1px solid var(--dx3-amber-3);
  background: var(--dx3-paper-2);
  text-align: center;
}
.dx3-ranked .dx3-name { font-size: 13px; color: var(--dx3-ink-2); }
.dx3-sku-tiny {
  display: block;
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  color: var(--dx3-ink-3);
  margin-top: 2px;
  letter-spacing: 0.04em;
}
.dx3-ranked .dx3-units {
  font-family: var(--dx3-mono);
  font-size: 16px;
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.dx3-ranked .dx3-units small {
  font-size: 10px;
  color: var(--dx3-ink-3);
  margin-left: 4px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 500;
}

/* Alerts panel — amber-tinted sticky-note feel */
.dx3-alerts {
  background: linear-gradient(180deg, var(--dx3-amber-4) 0%, var(--dx3-paper-3) 100%);
  border: 1px solid var(--dx3-amber-3);
  position: relative;
  overflow: hidden;
}
.dx3-alerts .dx3-card-head {
  background: transparent;
  border-bottom-color: var(--dx3-amber-3);
}
.dx3-alerts-section { padding: 18px 22px; }
.dx3-alerts-section + .dx3-alerts-section { border-top: 1px dashed var(--dx3-amber-3); }
.dx3-alerts-section .dx3-alerts-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--dx3-ink-2);
  font-weight: 700;
  margin-bottom: 12px;
}
.dx3-alerts-head i { color: var(--dx3-amber); font-size: 13px; }
.dx3-alerts-list { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.dx3-alerts-list li {
  padding: 7px 0;
  border-bottom: 1px dotted var(--dx3-amber-3);
  display: flex;
  align-items: center;
  gap: 10px;
}
.dx3-alerts-list li:last-child { border-bottom: 0; }
.dx3-alerts-list .dx3-lead { flex: 1; color: var(--dx3-ink-2); }
.dx3-alerts-list .dx3-qty {
  font-family: var(--dx3-mono);
  font-weight: 600;
  color: var(--dx3-ink);
  font-size: 13px;
}
.dx3-alerts-list .dx3-qty-warn { color: var(--dx3-gold); }
.dx3-alerts-list .dx3-qty-danger { color: var(--dx3-red); }

/* Tiny pulse for fresh data */
@keyframes dx3-pulse-amber {
  0%   { box-shadow: 0 0 0 0 rgba(184, 96, 28, 0.40); }
  100% { box-shadow: 0 0 0 8px rgba(184, 96, 28, 0); }
}
.dx3-fresh-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--dx3-amber);
  margin-right: 6px;
  animation: dx3-pulse-amber 1.6s ease-out infinite;
}

/* === POS (sheet 02) ===========================================
   Two-column counter layout: scan + cart left, checkout panel right. */

.dx3-pos-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 24px; }

/* Black scan bar — the focal point of the counter */
.dx3-scan {
  background: var(--dx3-ink);
  color: var(--dx3-paper);
  padding: 20px 24px;
  display: flex;
  align-items: center;
  gap: 20px;
  border: 1px solid var(--dx3-ink);
  position: relative;
}
.dx3-scan .dx3-scan-label {
  font-size: 10px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--dx3-ink-4);
  font-weight: 600;
  white-space: nowrap;
}
.dx3-scan .dx3-scan-icon { font-size: 22px; color: var(--dx3-amber-2); }
.dx3-scan input {
  flex: 1;
  background: transparent;
  color: var(--dx3-paper);
  border: 0;
  padding: 0;
  font-family: var(--dx3-mono);
  font-size: 19px;
  letter-spacing: 0.04em;
}
.dx3-scan input::placeholder { color: var(--dx3-ink-4); }
.dx3-scan input:focus { background: transparent; outline: none; box-shadow: none; }
.dx3-scan .dx3-scan-hint {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  color: var(--dx3-ink-4);
  letter-spacing: 0.06em;
  white-space: nowrap;
  padding-left: 16px;
  border-left: 1px solid rgba(252, 252, 249, 0.1);
}
.dx3-scan kbd {
  font-family: var(--dx3-mono);
  background: rgba(252, 252, 249, 0.1);
  padding: 2px 6px;
  border-radius: 2px;
  font-size: 10px;
  color: var(--dx3-paper);
  letter-spacing: 0.04em;
  border: 0;
}

/* Live suggestion dropdown */
.dx3-suggest {
  position: absolute;
  top: calc(100% + 4px);
  left: 0; right: 0;
  background: var(--dx3-paper);
  border: 1px solid var(--dx3-ink);
  z-index: 20;
  max-height: 360px;
  overflow-y: auto;
}
.dx3-suggest .dx3-suggest-item {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 14px;
  align-items: center;
  padding: 11px 18px;
  border-bottom: 1px solid var(--dx3-rule);
  cursor: pointer;
  background: transparent;
  border-left: 0; border-right: 0; border-top: 0;
  width: 100%;
  text-align: left;
}
.dx3-suggest .dx3-suggest-item:last-child { border-bottom: 0; }
.dx3-suggest .dx3-suggest-item:hover { background: var(--dx3-paper-2); }
.dx3-suggest .dx3-suggest-sku {
  font-family: var(--dx3-mono);
  font-size: 11.5px;
  color: var(--dx3-ink-2);
}
.dx3-suggest .dx3-suggest-name { color: var(--dx3-ink); }
.dx3-suggest .dx3-suggest-name small {
  display: block;
  font-size: 11px;
  color: var(--dx3-ink-3);
  margin-top: 1px;
}
.dx3-suggest .dx3-suggest-px {
  font-family: var(--dx3-mono);
  font-size: 14px;
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
}

/* Cart table */
.dx3-cart-empty {
  text-align: center;
  padding: 80px 24px;
  color: var(--dx3-ink-3);
}
.dx3-cart-empty .dx3-glyph {
  font-family: var(--dx3-mono);
  font-weight: 500;
  font-size: 36px;
  color: var(--dx3-paper-4);
  line-height: 1;
  margin-bottom: 14px;
  letter-spacing: 0.04em;
}
.dx3-cart-empty .dx3-head {
  font-family: var(--dx3-display);
  font-weight: 700;
  font-size: 16px;
  color: var(--dx3-ink-2);
  margin-bottom: 4px;
  letter-spacing: -0.01em;
}
.dx3-cart-empty p { font-size: 13px; color: var(--dx3-ink-3); margin: 0; }

.dx3-cart-input {
  width: 100%;
  padding: 7px 10px;
  font-family: var(--dx3-mono);
  font-size: 13px;
  text-align: right;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  font-variant-numeric: tabular-nums;
}
.dx3-cart-input:focus {
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
  outline: none;
}
/* Hide native number-input spinner arrows so the right-aligned digits
   are fully visible in narrow cart columns. */
.dx3-cart-input::-webkit-outer-spin-button,
.dx3-cart-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.dx3-cart-input[type="number"] { -moz-appearance: textfield; }

.dx3-line-total {
  font-family: var(--dx3-mono);
  font-weight: 600;
  font-size: 15px;
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
}

/* Availability caption under each cart-row qty input. Reads from the
   sohBySku map and the currently-selected warehouseId, both passed to
   posApp() from the view. */
.dx3-cart-avail {
  font-family: var(--dx3-mono);
  font-size: 10px;
  color: var(--dx3-amber);
  letter-spacing: 0.02em;
  margin-top: 4px;
  white-space: nowrap;
  text-align: right;
}
.dx3-cart-avail.danger { color: var(--dx3-red); font-weight: 600; }

/* === Entry forms — invoice / SO / SR / expense / etc. =============
   Shared scaffolding for the "drafting an entry" pattern: prominent
   customer/payee field, document header card, formset tables (lines +
   charges), live-reckoning totals card, big save button. New classes
   only — no existing rules modified. */

.dx3-entry-grid { display: grid; grid-template-columns: 1.7fr 1fr; gap: 24px; }

/* Promoted prominent field (Customer / Payee / Supplier) */
.dx3-customer-field {
  background: var(--dx3-paper-2);
  border: 1px solid var(--dx3-rule);
  padding: 18px 22px;
  margin-bottom: 16px;
}
.dx3-customer-field > label {
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
  margin-bottom: 6px;
  display: block;
}
.dx3-customer-field > input {
  border: 0 !important;
  background: transparent !important;
  width: 100%;
  font-family: var(--dx3-display);
  font-weight: 700;
  font-size: 20px;
  color: var(--dx3-ink);
  letter-spacing: -0.015em;
  padding: 4px 0;
  box-shadow: none !important;
}
.dx3-customer-field > input:focus { outline: none; }
.dx3-customer-field > input::placeholder { color: var(--dx3-ink-4); font-weight: 500; }
.dx3-customer-field .dx3-hint {
  font-size: 11px;
  color: var(--dx3-ink-3);
  margin-top: 4px;
}

/* Document-header field grid */
.dx3-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
  margin-bottom: 16px;
}
.dx3-meta-grid.two { grid-template-columns: 1fr 1fr; }
.dx3-meta-grid .dx3-field-label {
  display: block;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  margin-bottom: 6px;
  font-weight: 600;
}
.dx3-meta-grid input,
.dx3-meta-grid select,
.dx3-meta-grid textarea {
  width: 100%;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  padding: 8px 10px;
  font-family: var(--dx3-sans);
  font-size: 13px;
  color: var(--dx3-ink);
  border-radius: 0;
}
.dx3-meta-grid input:focus,
.dx3-meta-grid select:focus,
.dx3-meta-grid textarea:focus {
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
  outline: none;
}

/* Notes textarea inside an entry card */
.dx3-notes-field { margin-top: 4px; }
.dx3-notes-field > label {
  display: block;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  margin-bottom: 6px;
  font-weight: 600;
}
.dx3-notes-field textarea {
  width: 100%;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  padding: 10px 12px;
  font-family: var(--dx3-sans);
  font-size: 13px;
  color: var(--dx3-ink);
  resize: vertical;
  min-height: 60px;
}
.dx3-notes-field textarea:focus {
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
  outline: none;
}

/* Formset tables — lines + charges, ledger-style with dx3 inputs.
   table-layout: fixed pins column widths so a long Tom Select item or note
   can't expand the table and force the page to scroll horizontally. */
.dx3-formset-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  table-layout: fixed;
}
.dx3-formset-table th {
  text-align: left;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  padding: 12px 12px 8px;
  border-bottom: 1.5px solid var(--dx3-ink-2);
  white-space: nowrap;
  background: var(--dx3-paper-2);
}
.dx3-formset-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--dx3-rule);
  vertical-align: top;
  /* No overflow:hidden here — qty hint + product description below the picker
     are allowed to wrap inside the fixed-width cell. Widget-level clamps
     below stop the Tom Select control from inflating the column. */
}

/* Tom Select widget inside a formset cell — clamp to the cell so a long
   selected item ellipses instead of pushing the table wider. */
.dx3-formset-table .ts-wrapper {
  width: 100%;
  min-width: 0;
  max-width: 100%;
}
.dx3-formset-table .ts-control {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  flex-wrap: nowrap;
  overflow: hidden;
}
.dx3-formset-table .ts-control > .item {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dx3-formset-table .ts-control .dx3-pick-opt {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}
.dx3-formset-table .ts-control .dx3-pick-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dx3-formset-table tbody tr:last-child td { border-bottom: 0; }
.dx3-formset-table tbody tr:hover td { background: rgba(184, 96, 28, 0.03); }
.dx3-formset-table .num,
.dx3-formset-table th.num { text-align: right; font-family: var(--dx3-mono); font-variant-numeric: tabular-nums; }
/* Re-skin every form widget rendered inside the table */
.dx3-formset-table input.form-control,
.dx3-formset-table input.form-control-sm,
.dx3-formset-table input[type="text"],
.dx3-formset-table input[type="number"],
.dx3-formset-table input[type="date"],
.dx3-formset-table select.form-select,
.dx3-formset-table select.form-select-sm,
.dx3-formset-table select,
.dx3-formset-table textarea {
  width: 100%;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  padding: 7px 9px;
  font-family: var(--dx3-sans);
  font-size: 13px;
  color: var(--dx3-ink);
  border-radius: 0;
  box-shadow: none;
}
.dx3-formset-table input[type="number"] {
  text-align: right;
  font-family: var(--dx3-mono);
  font-variant-numeric: tabular-nums;
}
.dx3-formset-table input:focus,
.dx3-formset-table select:focus,
.dx3-formset-table textarea:focus {
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
  outline: none;
}
.dx3-formset-table input[type="number"]::-webkit-outer-spin-button,
.dx3-formset-table input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.dx3-formset-table input[type="number"] { -moz-appearance: textfield; }

/* Availability caption beneath the qty input.
   white-space: normal lets "Available: 5 at JANE" wrap to a second line
   inside a narrow qty column instead of being clipped. */
.dx3-formset-table .availability,
.dx3-formset-table .dx3-avail {
  display: block;
  font-family: var(--dx3-mono);
  font-size: 10px;
  line-height: 1.25;
  color: var(--dx3-amber);
  margin-top: 4px;
  letter-spacing: 0.02em;
  text-align: right;
  min-height: 1.1em;
  white-space: normal;
  word-spacing: -1px;
  /* Defend against Bootstrap's .placeholder utility — if a state class
     called `placeholder` ever sneaks back onto the element, Tabler's
     loading-skeleton style would otherwise dim it to opacity:0.2 and
     paint a currentcolor background bar. */
  opacity: 1;
  background-color: transparent;
}
.dx3-formset-table .dx3-avail.danger { color: var(--dx3-red); font-weight: 600; }
.dx3-formset-table .dx3-avail.is-empty { color: var(--dx3-ink-4); }

/* Inline field error rendered directly under a formset input. The
   error banner at the top of the form is the primary surface; this is
   the in-row confirmation so the user sees exactly which cell tripped. */
.dx3-formset-table .dx3-field-error {
  display: block;
  margin-top: 4px;
  font-family: var(--dx3-mono);
  font-size: 10px;
  line-height: 1.25;
  color: var(--dx3-red);
  font-weight: 600;
  text-align: right;
  white-space: normal;
}

/* Product description shown beneath the Tom Select picker — full
   description in muted, wrappable small text so the picker chip can
   stay compact and the cell width stays disciplined. */
.dx3-product-desc {
  display: block;
  font-size: 11px;
  line-height: 1.35;
  color: var(--dx3-ink-3);
  margin-top: 6px;
  font-style: italic;
  white-space: normal;
  word-break: break-word;
  max-width: 100%;
  /* Cap to 2 lines on cards/lists, let it grow if the cell allows. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dx3-product-desc:empty { display: none; }

/* Per-line live total */
.dx3-line-total-preview {
  display: inline-block;
  text-align: right;
  font-family: var(--dx3-mono);
  font-weight: 600;
  font-size: 13px;
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
  padding-top: 7px;
  /* Defensive override of Bootstrap/Tabler `.placeholder` utility — same
     trap as the availability hint had. State modifier uses `.is-empty`. */
  opacity: 1;
  background-color: transparent;
}
.dx3-line-total-preview.is-empty { color: var(--dx3-ink-4); }

/* Trash button on formset rows */
.dx3-trash-btn {
  background: transparent;
  border: 0;
  color: var(--dx3-ink-4);
  cursor: pointer;
  padding: 6px;
  font-size: 16px;
  display: inline-flex;
  align-items: center;
}
.dx3-trash-btn:hover { color: var(--dx3-red); }
.dx3-trash-btn input[type="checkbox"] { display: none; }

/* Add-line row (button + hint) */
.dx3-add-line-row {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 12px 14px;
}

/* Charge-row tinting — scoped to dx3-formset-table so legacy tables
   still get the existing .charge-row styling unchanged. */
.dx3-formset-table tr.charge-row.charge-deduction {
  background: rgba(138, 42, 42, 0.04);
}
.dx3-formset-table tr.charge-row.charge-deduction > td:first-child {
  border-left: 3px solid var(--dx3-red);
}
.dx3-formset-table tr.charge-row.charge-addition {
  background: rgba(31, 91, 59, 0.04);
}
.dx3-formset-table tr.charge-row.charge-addition > td:first-child {
  border-left: 3px solid var(--dx3-green);
}

/* Charge-direction legend */
.dx3-charge-legend {
  display: flex;
  gap: 18px;
  align-items: center;
  font-size: 11px;
  color: var(--dx3-ink-3);
}
.dx3-charge-legend .dx3-swatch { display: inline-flex; align-items: center; gap: 6px; }
.dx3-charge-legend .dx3-swatch::before { content: ''; width: 12px; height: 3px; flex-shrink: 0; }
.dx3-charge-legend .dx3-swatch.minus::before { background: var(--dx3-red); }
.dx3-charge-legend .dx3-swatch.plus::before { background: var(--dx3-green); }

/* Right sticky column for entry pages */
.dx3-entry-sticky-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: sticky;
  top: 24px;
  align-self: start;
}

/* Big save button for entry pages */
.dx3-entry-save-btn {
  width: 100%;
  padding: 18px;
  border: 0;
  background: var(--dx3-ink);
  color: var(--dx3-paper);
  font-family: var(--dx3-sans);
  font-size: 13px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  transition: background 100ms ease;
}
.dx3-entry-save-btn:hover:not(:disabled) { background: var(--dx3-amber); }
.dx3-entry-save-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.dx3-entry-cancel-link {
  display: block;
  text-align: center;
  margin-top: 10px;
  color: var(--dx3-ink-3);
  text-decoration: none;
  font-size: 12px;
  padding: 8px;
}
.dx3-entry-cancel-link:hover { color: var(--dx3-ink); text-decoration: underline; }

/* Live totals preview — mirror of the detail-page Reckoning card */
.dx3-totals-preview { padding: 18px 22px; }
.dx3-totals-preview .row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 7px 0;
  font-size: 12.5px;
}
.dx3-totals-preview .row .l { color: var(--dx3-ink-3); letter-spacing: 0.04em; }
.dx3-totals-preview .row .v {
  font-family: var(--dx3-mono);
  color: var(--dx3-ink-2);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
}
.dx3-totals-preview .row.minus .v { color: var(--dx3-red); }
.dx3-totals-preview .row.plus  .v { color: var(--dx3-green); }
.dx3-totals-preview .rule { height: 1px; background: var(--dx3-rule); margin: 6px 0; }
.dx3-totals-preview .rule.strong { background: var(--dx3-ink-2); height: 1.5px; margin: 10px 0 4px; }
.dx3-totals-preview .grand {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 12px 0 6px;
}
.dx3-totals-preview .grand .l {
  font-family: var(--dx3-sans);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--dx3-ink);
}
.dx3-totals-preview .grand .v {
  font-family: var(--dx3-display);
  font-weight: 800;
  font-size: 24px;
  color: var(--dx3-ink);
  letter-spacing: -0.025em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.dx3-totals-preview .grand .v .peso { font-size: 15px; color: var(--dx3-ink-3); vertical-align: 3px; font-weight: 600; margin-right: 2px; }

/* Invoice-wide % discount input inside the reckoning panel — compact,
   right-aligned numeric input that sits between the line discount row
   and the document grand total. */
.dx3-invoice-discount {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 8px 0 6px;
  padding: 6px 0;
}
.dx3-invoice-discount label {
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--dx3-ink-3);
  text-transform: uppercase;
  margin: 0;
}
.dx3-invoice-discount input {
  width: 80px;
  padding: 5px 8px;
  text-align: right;
  font-family: var(--dx3-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  color: var(--dx3-ink);
  border-radius: 0;
}
.dx3-invoice-discount input:focus {
  outline: none;
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
}

/* Live preview tag (pulsing amber dot) */
.dx3-live-tag {
  font-family: var(--dx3-mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  color: var(--dx3-amber);
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 14px;
}
.dx3-live-tag::before {
  content: '';
  width: 6px; height: 6px;
  background: var(--dx3-amber);
  border-radius: 50%;
  animation: dx3-pulse-amber 1.6s ease-out infinite;
}

/* === Invoice detail (sheet 03) =================================
   Doc hero, parties (Bill to / Ship from), totals/reckoning,
   timeline. Same layout idiom as sr-detail will reuse later. */

.dx3-doc-grid { display: grid; grid-template-columns: 1.7fr 1fr; gap: 24px; }

/* Doc hero — big mono-numeric document identifier */
.dx3-doc-hero {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 32px;
  margin-bottom: 36px;
  padding-bottom: 24px;
  border-bottom: 2px solid var(--dx3-ink);
}
.dx3-doc-hero h1 {
  font-family: var(--dx3-display);
  font-weight: 800;
  font-size: 42px;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--dx3-ink);
  margin: 0;
  font-feature-settings: 'tnum' 1;
  font-variant-numeric: tabular-nums;
}
.dx3-doc-hero h1 .seg { color: var(--dx3-ink); font-weight: 800; }
.dx3-doc-hero h1 .num { color: var(--dx3-amber); }
.dx3-doc-hero .dx3-doc-meta {
  font-family: var(--dx3-mono);
  font-size: 11.5px;
  color: var(--dx3-ink-3);
  letter-spacing: 0.05em;
  text-align: right;
  line-height: 1.8;
}
.dx3-doc-hero .dx3-doc-meta strong {
  font-family: var(--dx3-sans);
  font-weight: 700;
  color: var(--dx3-ink);
}
.dx3-doc-hero .dx3-stamp { margin-bottom: 12px; }

/* Party blocks (Bill to / Ship from) with an amber arrow between */
.dx3-parties {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 32px;
  align-items: center;
  margin-bottom: 28px;
}
.dx3-party {
  padding: 18px 22px;
  border: 1px solid var(--dx3-rule);
  background: var(--dx3-paper);
}
.dx3-party .dx3-party-lab {
  font-size: 10px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
  margin-bottom: 8px;
}
.dx3-party .dx3-party-name {
  font-family: var(--dx3-display);
  font-weight: 700;
  font-size: 17px;
  color: var(--dx3-ink);
  letter-spacing: -0.018em;
}
.dx3-party .dx3-party-sub {
  font-size: 12px;
  color: var(--dx3-ink-3);
  margin-top: 4px;
  line-height: 1.5;
}
.dx3-party .dx3-party-sub .tin {
  font-family: var(--dx3-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
}
.dx3-party-arrow {
  font-family: var(--dx3-mono);
  font-size: 22px;
  color: var(--dx3-amber);
  line-height: 1;
  text-align: center;
  font-weight: 500;
}

/* Definition list — header card pairs (small-caps label : value) */
.dx3-dl {
  display: grid;
  grid-template-columns: 1fr 2.2fr;
  gap: 12px 18px;
}
.dx3-dl dt {
  font-size: 10.5px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
  padding-top: 2px;
  margin: 0;
}
.dx3-dl dd {
  margin: 0;
  font-size: 13px;
  color: var(--dx3-ink-2);
}
.dx3-dl dd code,
.dx3-dl dd .mono { font-family: var(--dx3-mono); font-size: 12.5px; }
.dx3-dl dd em,
.dx3-dl dd .italic {
  font-family: var(--dx3-serif);
  font-style: italic;
  color: var(--dx3-ink-3);
  font-size: 13px;
}

/* Lines table — invoice / SR specific cell types */
.dx3-doc-lines td.qty,
.dx3-doc-lines td.px,
.dx3-doc-lines td.net {
  font-family: var(--dx3-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  font-size: 13.5px;
}
.dx3-doc-lines td.disc {
  font-family: var(--dx3-mono);
  text-align: right;
  font-size: 12px;
  color: var(--dx3-ink-3);
}
.dx3-doc-lines td.net { font-weight: 600; color: var(--dx3-ink); font-size: 14px; }
.dx3-doc-lines td.cogs {
  font-family: var(--dx3-mono);
  text-align: right;
  font-size: 11.5px;
  color: var(--dx3-ink-3);
}

/* Status card action buttons — full-width stacked */
.dx3-actions-card .btn {
  width: 100%;
  justify-content: center;
  margin-bottom: 8px;
}
.dx3-actions-card .btn:last-child { margin-bottom: 0; }

/* Totals / Reckoning — the right-column accounting block */
.dx3-totals { padding: 20px 24px 22px; }
.dx3-totals .row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 9px 0;
  font-size: 13px;
}
.dx3-totals .row .l { color: var(--dx3-ink-3); letter-spacing: 0.04em; }
.dx3-totals .row .v {
  font-family: var(--dx3-mono);
  color: var(--dx3-ink-2);
  font-variant-numeric: tabular-nums;
  font-size: 13.5px;
}
.dx3-totals .row.minus .v { color: var(--dx3-red); }
.dx3-totals .row.plus  .v { color: var(--dx3-green); }
.dx3-totals .rule { height: 1px; background: var(--dx3-rule); margin: 6px 0; }
.dx3-totals .rule.strong { background: var(--dx3-ink-2); height: 1.5px; margin: 10px 0 4px; }
.dx3-totals .grand {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 12px 0 8px;
}
.dx3-totals .grand .l {
  font-family: var(--dx3-sans);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--dx3-ink);
}
.dx3-totals .grand .v {
  font-family: var(--dx3-mono);
  font-size: 22px;
  font-weight: 500;
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
}
.dx3-totals .grand.outstanding .v { color: var(--dx3-red); }
.dx3-totals .grand.outstanding.zero .v { color: var(--dx3-green); }

/* Charge breakdown — itemized fees list inside the totals card */
.dx3-charge-breakdown {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--dx3-rule-2);
  font-size: 12px;
}
.dx3-charge-breakdown .head {
  font-size: 9.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 700;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.dx3-charge-breakdown .head i { font-size: 12px; color: var(--dx3-amber); }
.dx3-charge-breakdown ul { list-style: none; padding: 0; margin: 0; }
.dx3-charge-breakdown li {
  display: flex;
  justify-content: space-between;
  padding: 5px 0;
  border-bottom: 1px dotted var(--dx3-rule);
  font-size: 12px;
}
.dx3-charge-breakdown li:last-child { border-bottom: 0; }
.dx3-charge-breakdown li .lab { color: var(--dx3-ink-2); }
.dx3-charge-breakdown li .lab small { color: var(--dx3-ink-3); }
.dx3-charge-breakdown li .v {
  font-family: var(--dx3-mono);
  font-variant-numeric: tabular-nums;
}
.dx3-charge-breakdown li .v.minus { color: var(--dx3-red); }
.dx3-charge-breakdown li .v.plus  { color: var(--dx3-green); }

/* Timeline — vertical thread with bullets */
.dx3-timeline {
  padding: 6px 22px 22px;
  position: relative;
}
.dx3-timeline::before {
  content: '';
  position: absolute;
  left: calc(22px + 80px + 8px);
  top: 18px;
  bottom: 30px;
  width: 1px;
  background: var(--dx3-rule-2);
}
.dx3-timeline-row {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px dotted var(--dx3-rule);
  position: relative;
}
.dx3-timeline-row:last-child { border-bottom: 0; }
.dx3-timeline-row .when {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  color: var(--dx3-ink-3);
  letter-spacing: 0.04em;
  padding-top: 1px;
}
.dx3-timeline-row .what {
  font-size: 12.5px;
  padding-left: 4px;
  color: var(--dx3-ink-2);
}
.dx3-timeline-row .what .arrow {
  font-family: var(--dx3-mono);
  color: var(--dx3-amber);
  font-style: normal;
  font-size: 14px;
  margin: 0 4px;
}
.dx3-timeline-row .what .actor {
  font-family: var(--dx3-mono);
  font-size: 10.5px;
  color: var(--dx3-ink-3);
  display: block;
  margin-top: 2px;
}
.dx3-timeline-row .what .note {
  font-style: italic;
  font-family: var(--dx3-serif);
  color: var(--dx3-ink-3);
  display: block;
  margin-top: 4px;
  font-size: 12.5px;
}
.dx3-timeline-row::before {
  content: '';
  position: absolute;
  left: 88px;
  top: 18px;
  width: 9px;
  height: 9px;
  background: var(--dx3-paper);
  border: 1.5px solid var(--dx3-ink-3);
  border-radius: 50%;
  z-index: 1;
}
.dx3-timeline-row.active::before {
  background: var(--dx3-amber);
  border-color: var(--dx3-amber);
}
.dx3-cart-trash {
  background: transparent;
  border: 0;
  color: var(--dx3-ink-4);
  cursor: pointer;
  padding: 6px;
}
.dx3-cart-trash:hover { color: var(--dx3-red); }

/* Right column — checkout panel */
.dx3-checkout { position: sticky; top: 24px; }
.dx3-checkout .dx3-section {
  padding: 22px 24px;
  border-bottom: 1px solid var(--dx3-rule);
}
.dx3-checkout .dx3-section:last-child { border-bottom: 0; }

.dx3-totals-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dx3-totals-stack .dx3-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13px;
  color: var(--dx3-ink-3);
}
.dx3-totals-stack .dx3-line .v {
  font-family: var(--dx3-mono);
  color: var(--dx3-ink);
  font-variant-numeric: tabular-nums;
}
.dx3-totals-stack .dx3-line .v.minus { color: var(--dx3-green); }
.dx3-totals-stack .dx3-grand {
  margin-top: 8px;
  padding-top: 16px;
  border-top: 2px solid var(--dx3-ink-2);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.dx3-totals-stack .dx3-grand .lab {
  font-family: var(--dx3-sans);
  font-weight: 700;
  font-size: 12px;
  color: var(--dx3-ink);
  letter-spacing: 0.20em;
  text-transform: uppercase;
}
.dx3-totals-stack .dx3-grand .v {
  font-family: var(--dx3-display);
  font-weight: 800;
  font-size: 34px;
  color: var(--dx3-ink);
  letter-spacing: -0.030em;
  font-feature-settings: 'tnum' 1;
  line-height: 1;
}
.dx3-totals-stack .dx3-grand .v .peso {
  font-size: 20px;
  color: var(--dx3-ink-3);
  vertical-align: 4px;
  margin-right: 2px;
  font-weight: 600;
}

/* Cash-tendered pad */
.dx3-cash-pad input {
  font-family: var(--dx3-mono);
  font-size: 24px;
  text-align: right;
  padding: 14px 16px;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  color: var(--dx3-ink);
  width: 100%;
}
.dx3-change-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 14px;
}
.dx3-change-row .lab {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
}
.dx3-change-row .v {
  font-family: var(--dx3-mono);
  font-size: 26px;
  font-weight: 500;
  color: var(--dx3-green);
  font-variant-numeric: tabular-nums;
}
.dx3-change-row .v.danger { color: var(--dx3-red); }

/* Big charge button */
.dx3-charge-btn {
  width: 100%;
  padding: 22px;
  border: 0;
  background: var(--dx3-ink);
  color: var(--dx3-paper);
  font-family: var(--dx3-sans);
  font-size: 14px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: background 100ms ease;
}
.dx3-charge-btn:hover:not(:disabled) { background: var(--dx3-amber); }
.dx3-charge-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.dx3-charge-btn .amt {
  font-family: var(--dx3-mono);
  font-size: 18px;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.dx3-charge-btn i { font-size: 18px; }

/* 4-button payment method selector */
.dx3-pay-method {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border: 1px solid var(--dx3-rule-2);
}
.dx3-pay-method button {
  border: 0;
  background: var(--dx3-paper);
  padding: 12px 8px;
  font-family: var(--dx3-sans);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--dx3-ink-3);
  cursor: pointer;
  border-right: 1px solid var(--dx3-rule-2);
  transition: background 80ms ease;
}
.dx3-pay-method button:last-child { border-right: 0; }
.dx3-pay-method button:hover { background: var(--dx3-paper-2); color: var(--dx3-ink); }
.dx3-pay-method button.on { background: var(--dx3-ink); color: var(--dx3-paper); }
.dx3-pay-method button i { display: block; font-size: 14px; margin-bottom: 4px; color: inherit; }

.dx3-meta-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 18px;
  font-size: 11px;
}
.dx3-meta-row .dx3-cell .dx3-l {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  font-weight: 600;
  margin-bottom: 4px;
}
.dx3-meta-row .dx3-cell .dx3-v {
  font-family: var(--dx3-mono);
  color: var(--dx3-ink);
  font-size: 12.5px;
}

/* Cart-wide discount row */
.dx3-cart-disc-row {
  background: var(--dx3-paper-2);
  padding: 12px 16px;
  border: 1px dashed var(--dx3-rule-2);
  display: flex;
  gap: 12px;
  align-items: end;
  margin-bottom: 16px;
}
.dx3-cart-disc-row label { margin-bottom: 4px; }
.dx3-cart-disc-row input {
  padding: 7px 10px;
  font-family: var(--dx3-mono);
  width: 80px;
  text-align: right;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  font-variant-numeric: tabular-nums;
}
.dx3-cart-disc-row button {
  padding: 8px 14px;
  font-size: 10.5px;
  letter-spacing: 0.16em;
}

/* Small labels in checkout panel */
.dx3-checkout .dx3-field-label {
  display: block;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--dx3-ink-3);
  margin-bottom: 6px;
  font-weight: 600;
}
.dx3-checkout select,
.dx3-checkout input[type="text"] {
  width: 100%;
  border: 1px solid var(--dx3-rule-2);
  background: var(--dx3-paper);
  padding: 10px 12px;
  font-family: var(--dx3-sans);
  font-size: 13.5px;
  color: var(--dx3-ink);
}
.dx3-checkout select:focus,
.dx3-checkout input[type="text"]:focus {
  border-color: var(--dx3-ink);
  background: var(--dx3-paper-2);
  outline: none;
}

/* ============================================================
   MOBILE OVERRIDES — Phase F-mobile-1 (dx3 design-system base)
   ─────────────────────────────────────────────────────────────
   Single source of mobile mods for the dx3 design system.
   Targets ≤768px (covers iPhone Pro Max + most Android phones
   in portrait), with extra tightening at ≤480px.

   Why this block exists:
     The desktop primitives use fixed 22–24px paddings, 13.5px
     ledger-table fonts, and a 1fr+auto page-head grid that all
     break or overflow on phone widths. Before this block,
     dx3.css had ZERO @media queries — every dx3-* template
     rendered at desktop sizes regardless of viewport.

   Covers known iOS Safari + Chrome Mobile quirks:
     - 16px min font on form inputs (prevents iOS focus zoom)
     - touch-action: manipulation (kills 300ms tap delay)
     - -webkit-tap-highlight-color: transparent (no gray flash)
     - safe-area-inset gutters for iPhone notch / home indicator

   When you need to add new mobile rules: put them in THIS
   block (or the ≤480px block below), not scattered across
   the file. Keeps mobile behaviour auditable in one place.
============================================================ */

@media (max-width: 768px) {

  /* ----- Page chrome ----- */
  .dx3-page-head {
    padding: 18px 0 22px;
    margin-bottom: 22px;
    grid-template-columns: 1fr;  /* stack title and actions */
    gap: 14px;
    align-items: start;
  }
  .dx3-topbar {
    padding: 12px 0 10px;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 11px;
  }
  /* Meta row (date chip + hostname chip): at this width both chips
     squeezed onto one line, forcing each to wrap internally — the
     hostname breaks mid-word at its hyphen (e.g. "dx3-" / "latest.on
     render.com"), stranding the icon on the wrapped second line.
     Let the two chips wrap onto their own lines instead, and keep
     each chip's icon+text as one unbreakable unit so it never splits
     mid-word — worst case a chip wraps whole, never internally. */
  .dx3-topbar-meta {
    flex-wrap: wrap;
    row-gap: 4px;
  }
  .dx3-topbar-meta .dx3-meta-chip {
    white-space: nowrap;
  }

  /* Empty-state list tables ("No invoices yet", etc. — used across ~30
     list views): the only tbody row is a single colspan'd message cell,
     but the browser's table auto-layout still sizes columns from the
     <thead>'s separate <th> cells, forcing the table (and the centered
     empty-state content inside it) wider than the viewport — the
     message reads as cut off on the right edge instead of centered.
     Scoped to :has(td[colspan]) so this can never affect a table that
     actually has data rows (those never render a colspan cell). */
  .table-responsive table:has(tbody > tr > td[colspan]) {
    table-layout: fixed;
    width: 100%;
  }
  /* Forcing equal fixed-width columns above fixes the message's own
     width, but now squeezes the thead's normal per-column labels into
     the same narrow slices, overlapping illegibly. With zero data rows
     the header conveys nothing anyway — hide it in this case. */
  .table-responsive table:has(tbody > tr > td[colspan]) thead {
    display: none;
  }

  /* ----- Cards (the workhorse primitive) ----- */
  .dx3-card        { margin-bottom: 16px; }
  .dx3-card-head   {
    padding: 12px 14px;
    gap: 8px;
    flex-wrap: wrap;
  }
  /* h3 inside card-head has heavy tracking (letter-spacing: 0.26em) at desktop.
     That makes a 16-char title like "RECENT MOVEMENTS" ~210px wide — wider
     than the card head on a 360px phone, so it wraps onto two lines and
     pushes the right-side action link below. Tighten both font and tracking
     for mobile so titles stay on a single line. */
  .dx3-card-head h3,
  .dx3-card-head .h3 {
    font-size: 10px;
    letter-spacing: 0.10em;
    gap: 6px;
  }
  .dx3-card-body   { padding: 16px 14px; }
  .dx3-card-body.tight {
    padding: 12px 14px;
    /* Tables inside .tight bodies (dashboard widgets) can still overflow
       horizontally at very narrow widths — allow scroll inside the card
       rather than clipping content past the right edge. */
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .dx3-card-foot   {
    padding: 12px 14px;
    align-items: flex-start;  /* multi-line text reads better top-aligned */
  }

  /* ----- Totals / Reckoning panel (SR + invoice detail) ----- */
  .dx3-totals          { padding: 14px 14px 16px; }
  .dx3-totals .row     { padding: 7px 0; font-size: 12.5px; }
  .dx3-totals .grand   { padding: 10px 0 6px; }
  .dx3-totals .grand .v { font-size: 18px; }

  /* ----- Ledger tables (recent movements, account ledger) -----
     Desktop column headers use letter-spacing: 0.22em which is gorgeous on
     a 1280px screen and brutal on 360px. Drop tracking + tighten padding
     + drop cell font so all five columns (When/Kind/SKU/WH/Qty) fit
     without horizontal scroll on most phones. The chips inside
     (dx3-when, dx3-sku-chip, dx3-move-kind, dx3-wh-tag) get their own
     tightening below. */
  .dx3-ledger-table { font-size: 11px; }
  .dx3-ledger-table th {
    font-size: 9px;
    letter-spacing: 0.10em;
    padding: 10px 8px;
  }
  .dx3-ledger-table td { padding: 9px 8px; }
  .dx3-ledger-table th:first-child,
  .dx3-ledger-table td:first-child { padding-left: 12px !important; }
  .dx3-ledger-table th:last-child,
  .dx3-ledger-table td:last-child  { padding-right: 12px !important; }

  /* ----- Inline chips/tags used inside ledger rows ----- */
  .dx3-when      { font-size: 10px; letter-spacing: 0.02em; }
  .dx3-move-kind { font-size: 10px; letter-spacing: 0.04em; }
  .dx3-wh-tag    { font-size: 10px; letter-spacing: 0.04em; }
  .dx3-sku-chip  { font-size: 10.5px; padding: 2px 5px; letter-spacing: 0.01em; }

  /* ----- KPI tiles (dashboard) ----- */
  .dx3-kpi   { padding: 16px 14px; }
  .dx3-tile2 { padding: 16px 14px; }

  /* ----- Section number pills ("01" "02" markers) ----- */
  .dx3-section-num { font-size: 10px; padding: 1px 5px; }

  /* ----- Hero block / page header variants ----- */
  .dx3-hero {
    padding: 18px 14px;
    grid-template-columns: 1fr;
    gap: 12px;
  }

  /* ----- Form inputs: prevent iOS Safari focus auto-zoom -----
     Anything below 16px causes iOS to zoom the whole page on
     focus. Bumping every input to 16px keeps the layout stable.
     Trade-off: form-control-sm looks slightly larger on phones,
     but better than the viewport jumping every tap. */
  input[type="text"], input[type="number"], input[type="date"],
  input[type="email"], input[type="password"], input[type="search"],
  input[type="tel"],  input[type="url"], textarea, select,
  .form-control, .form-select {
    font-size: 16px;
  }
  .form-control-sm, .form-select-sm {
    font-size: 16px;
    min-height: 38px;
  }

  /* ----- Touch targets: 40px floor for taps ----- */
  .btn {
    min-height: 40px;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }
  .btn-sm { min-height: 36px; font-size: 13px; }
  .pill   { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }

  /* ----- Tables: smooth momentum scroll inside .table-responsive ----- */
  .table-responsive { -webkit-overflow-scrolling: touch; }

  /* ----- iPhone safe-area (notch + home indicator) ----- */
  /* Only add gutter if the device actually reports an inset; env()
     returns 0 on non-notch browsers so this is a no-op for them. */
  @supports (padding: max(0px)) {
    body {
      padding-left:  max(0px, env(safe-area-inset-left));
      padding-right: max(0px, env(safe-area-inset-right));
    }
  }

  /* ----- Misc tightening ----- */
  .dx3-fresh-dot { left: 4px; }  /* re-anchor the leading-row dot now that cells are tighter */
  .dx3-move-kind { letter-spacing: 0.06em; }  /* tighter wide tracking saves px */

}

/* ============================================================
   ≤991.98px — TABLER NAVBAR-VERTICAL MOBILE FIX
   ─────────────────────────────────────────────────────────────
   The sidebar (<aside class="navbar navbar-vertical navbar-expand-lg">)
   is fixed full-height at every breakpoint in Tabler's default
   CSS. On phones it claims the entire viewport: brand pinned
   top, user-identity card pinned bottom, nav items hidden in
   the middle until the hamburger fires — looks empty and
   "scattered" because there's no content where you'd expect it.

   Below the lg breakpoint (992px) we collapse the sidebar into
   a proper mobile top-bar:
     - position: relative (no longer covers viewport)
     - height: auto (only as tall as visible content)
     - container-fluid laid out row-wise: hamburger + brand
     - Tabler's .collapse keeps the nav items hidden until tap;
       when shown they drop below the brand
     - user-identity card hidden while collapsed; shown when
       hamburger reveals the nav (so it stays accessible without
       claiming bottom space when closed)
     - .page-wrapper no longer reserves left space for sidebar

   This matches Tabler's expand-lg semantic: at ≥lg the sidebar
   is the fixed left chrome; below lg it behaves like a normal
   collapsible top navbar.
============================================================ */
@media (max-width: 991.98px) {
  .navbar.navbar-vertical {
    position: relative !important;
    width: 100% !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    border-right: 0 !important;
    border-bottom: 1px solid rgba(252, 252, 249, 0.08);
  }
  .navbar.navbar-vertical .container-fluid {
    padding: 8px 12px;
    flex-direction: row !important;
    height: auto !important;
    flex-wrap: wrap;
    align-items: center;
  }

  /* Brand: shrink the desktop 0.25in top margin + sidebar padding.
     Hide the "Sales & Inventory" subtitle on mobile — it eats two
     lines of vertical space for a tagline. */
  .navbar.navbar-vertical .navbar-brand {
    margin: 0 !important;
    padding: 0 !important;
    width: auto !important;
    flex: 1 1 auto;
    text-align: left;
  }
  .navbar.navbar-vertical .navbar-brand a {
    padding-left: 8px !important;
  }
  .navbar.navbar-vertical .dx3-brand-tag { display: none !important; }
  .navbar.navbar-vertical .dx3-brand-name { font-size: 15px; }
  .navbar.navbar-vertical .dx3-brand-mark { width: 28px; height: 28px; }

  /* Hamburger sits beside brand on a single 56px-tall row. */
  .navbar.navbar-vertical .navbar-toggler {
    order: 1;
    margin-right: 8px;
    padding: 6px 10px;
  }
  .navbar.navbar-vertical .navbar-brand { order: 2; }
  .navbar.navbar-vertical .navbar-collapse  { order: 3; flex-basis: 100%; }
  .navbar.navbar-vertical .dx3-sidebar-user { order: 4; flex-basis: 100%; }

  /* Page wrapper: stop reserving sidebar width on the left.
     padding-right must go too. The desktop rule sets 0.5in on BOTH sides
     for a balanced column; zeroing only the left left 48px of dead gutter
     down the right of every page on a phone, squeezing the content into
     342px of a 390px viewport. The container-xl inside still supplies its
     own 8px gutters, which is the right amount at this width. */
  .page-wrapper {
    margin-left: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }

  /* User identity: only visible when the nav drawer is expanded.
     Otherwise it'd float orphaned below the closed top-bar. */
  .navbar.navbar-vertical .dx3-sidebar-user { display: none; }
  .navbar.navbar-vertical .navbar-collapse.show ~ .dx3-sidebar-user,
  .navbar.navbar-vertical .navbar-collapse.collapsing ~ .dx3-sidebar-user {
    display: flex;
    margin: 8px 0 0 !important;
  }

  /* Nav drawer when open: cap height so it doesn't push the page
     content way down on devices with lots of nav groups. Adds
     internal scroll if there's overflow. */
  .navbar.navbar-vertical .navbar-collapse {
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .navbar.navbar-vertical .navbar-nav { padding-top: 4px !important; }

  /* Make nav section labels readable in the dark drawer. */
  .dx3-nav-section-label {
    padding: 10px 12px 4px;
    letter-spacing: 0.14em;
    font-size: 9px;
  }
}

/* ============================================================
   ≤480px — extra-small phones (iPhone SE-class, older Android)
   Only tightens where 768px wasn't enough. Don't put new
   behaviour here; just nudge the values defined above.
============================================================ */
@media (max-width: 480px) {
  .dx3-card-head, .dx3-card-body, .dx3-card-foot, .dx3-totals {
    padding-left: 12px;
    padding-right: 12px;
  }
  .dx3-card-body.tight {
    padding: 10px 0;  /* edge-to-edge so the table's own cell padding owns the gutters */
  }
  .dx3-totals .row,
  .dx3-totals .grand   { font-size: 12px; }
  .dx3-totals .grand .v { font-size: 17px; }

  /* Recent-movements widget: drop tracking to zero, shrink chips one more
     notch so all 5 columns fit at iPhone-SE width (~320px). */
  .dx3-ledger-table          { font-size: 10.5px; }
  .dx3-ledger-table th       { font-size: 8.5px; letter-spacing: 0.06em; padding: 9px 6px; }
  .dx3-ledger-table td       { padding: 8px 6px; }
  .dx3-ledger-table th:first-child,
  .dx3-ledger-table td:first-child { padding-left: 10px !important; }
  .dx3-ledger-table th:last-child,
  .dx3-ledger-table td:last-child  { padding-right: 10px !important; }

  .dx3-when      { font-size: 9.5px; }
  .dx3-move-kind { font-size: 9.5px; letter-spacing: 0.02em; }
  .dx3-wh-tag    { font-size: 9.5px; letter-spacing: 0.02em; }
  .dx3-sku-chip  { font-size: 10px; padding: 1px 4px; }
  .dx3-fresh-dot { width: 5px; height: 5px; margin-right: 4px; }
}

/* ===================================================================
   Mobile fixes found by measuring real pages at phone viewports
   (.claude/skills/mobile-ui-review). Each rule below records the
   measurement that justified it, because these look arbitrary later.
   =================================================================== */

@media (max-width: 991.98px) {
  /* Data-entry pages (invoice, SO, GRN, adjustment, transfer, expense,
     POS...) lay out as a two-column grid: the form on the left, a sticky
     save/summary column on the right. There was no mobile override, so on a
     390px phone both columns stayed side by side and nothing could shrink -
     sales:pos needed 940px, inv_add 723px. Every one of the 13 entry screens
     scrolled sideways. Stack them instead, and drop the stickiness: a column
     pinned to the top of a narrow screen covers the field being typed in. */
  .dx3-entry-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .dx3-entry-sticky-col {
    position: static;
    top: auto;
  }
  /* Grid items default to min-width:auto, i.e. they refuse to shrink below
     their own content. Stacking the grid was not enough on its own: the
     summary column still measured 494px inside a 390px track because a wide
     table inside it set the floor. Letting the tracks shrink is what
     actually lands the fix. */
  .dx3-entry-grid > * {
    min-width: 0;
  }

  /* Document meta (date / reference / warehouse) is a 3-up grid. Three
     ~120px tracks at phone width is too narrow for a date input and pushed
     so_add 21px past the viewport. Two tracks fit comfortably and keep the
     form short; min-width:0 stops a long label setting the floor. */
  .dx3-meta-grid,
  .dx3-meta-grid.two {
    grid-template-columns: 1fr 1fr;
  }
  .dx3-meta-grid > * {
    min-width: 0;
  }

  /* Entry forms use Tabler's -sm control sizing, which renders 38px tall.
     That is fine under a mouse and marginal under a thumb - the guideline
     is 44px, and a receiving clerk tapping through 20 line items feels
     every missed hit. Taller controls make the form longer, which is the
     right trade on a touch screen. */
  .dx3-entry-grid .form-control,
  .dx3-entry-grid .form-select,
  .dx3-pos-grid .form-control,
  .dx3-pos-grid .form-select,
  .dx3-formset-table input,
  .dx3-formset-table select,
  .dx3-entry-grid .ts-control,
  .dx3-pos-grid .ts-control {
    min-height: 44px;
  }
  .dx3-entry-grid .btn,
  .dx3-pos-grid .btn,
  .dx3-formset-table .btn {
    min-height: 44px;
  }

  /* The POS counter screen has its own 2fr/1fr grid with the same problem:
     product search beside the cart, 940px of content in a 390px viewport.
     It is mostly used on a till or tablet, but a phone should still be able
     to render it rather than scroll in two directions. */
  .dx3-pos-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .dx3-pos-grid > * {
    min-width: 0;
  }
  /* The scan hint is nowrap mono text sitting beside the barcode input -
     237px of it hung off the side. Let it wrap; it is advisory copy, not a
     label that has to stay on one line. */
  .dx3-scan {
    /* label + input + hint on one non-wrapping flex row does not fit a
       phone. Let the row wrap and give the input the full width below. */
    flex-wrap: wrap;
    gap: 8px 12px;
    padding: 14px 16px;
  }
  .dx3-scan input {
    min-width: 0;
    flex: 1 1 100%;
  }
  .dx3-scan .dx3-scan-hint {
    white-space: normal;
    padding-left: 0;
  }
  /* Inputs and selects inside the entry/POS grids must not set their own
     floor from a size attribute or long placeholder. */
  .dx3-entry-grid input, .dx3-entry-grid select,
  .dx3-pos-grid input, .dx3-pos-grid select {
    max-width: 100%;
  }

  /* The hamburger is the only way to reach the menu on a phone and it
     measured 32x32 — under the 44px iOS/WCAG target. Grow the hit area
     without moving the glyph. */
  .navbar.navbar-vertical .navbar-toggler {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Account menu measured 113x20 — a real control, too short to hit
     reliably. Padding rather than font-size so the chrome stays compact. */
  .navbar.navbar-vertical .dx3-sidebar-user > a,
  .navbar.navbar-vertical .dx3-sidebar-user .dropdown-toggle {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
}

@media (max-width: 480px) {
  /* Tabler styles data-table headers at 10px uppercase. That is a
     deliberate density choice on a desktop grid, but it falls below the
     ~12px readability floor on a handset. Nudged rather than overridden,
     so the table still reads as a table. */
  .table-responsive > table > thead > tr > th,
  .card-table > thead > tr > th {
    font-size: 12px;
    letter-spacing: 0.04em;
  }
}

/* ===================================================================
   Stacked list tables below the tablet breakpoint.

   A seven-column invoice list cannot be read at 390px. Scrolling it
   sideways works but costs the reader their place; shrinking it makes
   every value illegible. So below 768px each row becomes a small card of
   "Label: value" pairs that reads top-to-bottom like everything else on
   the page, and the horizontal scroll disappears entirely.

   Labels come from each table's own <thead>, copied onto the cells as
   data-label by the script in base.html. Nothing is hard-coded per table,
   so a column rename keeps its label automatically.

   Opt out with data-no-stack on the wrapper where comparing columns
   matters more than reading a single row.
   =================================================================== */
@media (max-width: 768px) {
  /* The wrapper no longer needs to scroll - nothing is wider than the card. */
  .table-responsive:has(> table.dx3-stackable),
  .table-responsive:has(> table.dx3-summary) {
    overflow-x: visible;
  }

  /* ---- Summary cards: the screens used on a handset ----------------
     The row becomes a wrapping flex line. Roles come from data-mobile,
     set by the template on each <th>. Anything unmarked is hidden: the
     point of this mode is that a phone shows what you scan for, and the
     rest lives one tap away in the record. */
  table.dx3-summary,
  table.dx3-summary > tbody {
    display: block;
    width: 100%;
  }
  table.dx3-summary > thead {
    display: none;
  }
  table.dx3-summary > tbody > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 3px 10px;
    padding: 13px 15px;
    border-bottom: 1px solid var(--dx3-rule);
  }
  table.dx3-summary > tbody > tr > td {
    border: 0;
    padding: 0;
    width: auto !important;
    white-space: normal;
  }
  /* Unmarked columns are deliberately dropped on a phone. */
  table.dx3-summary > tbody > tr > td:not([data-mobile]),
  table.dx3-summary > tbody > tr > td[data-mobile="hide"] {
    display: none;
  }
  table.dx3-summary td[data-mobile="title"] {
    order: 1;
    font-size: 15px;
    font-weight: 600;
  }
  table.dx3-summary td[data-mobile="badge"] {
    order: 2;
    margin-left: auto;
  }
  table.dx3-summary td[data-mobile="subtitle"] {
    order: 3;
    flex: 1 1 100%;   /* forces its own line */
    font-size: 14px;
  }
  table.dx3-summary td[data-mobile="meta"] {
    order: 4;
    font-size: 12px;
    color: var(--dx3-ink-3);
  }
  table.dx3-summary td[data-mobile="amount"] {
    order: 5;
    margin-left: auto;
    font-size: 16px;
    font-weight: 700;
    white-space: nowrap;
  }
  table.dx3-summary td[data-mobile="flag"] {
    order: 6;
    flex: 1 1 100%;
    font-size: 11.5px;
    font-weight: 600;
  }
  table.dx3-summary > tbody > tr > td[colspan] {
    display: block;
    flex: 1 1 100%;
    text-align: center;
  }
  table.dx3-summary > tfoot {
    display: block;
  }
  table.dx3-summary > tfoot > tr {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 15px;
    border-top: 2px solid var(--dx3-ink);
  }
  table.dx3-summary > tfoot > tr > td {
    border: 0;
    padding: 0;
  }

  table.dx3-stackable,
  table.dx3-stackable > tbody {
    display: block;
    width: 100%;
  }
  /* Column headings are repeated into every cell, so the row of them is
     now noise. */
  table.dx3-stackable > thead {
    display: none;
  }
  table.dx3-stackable > tbody > tr {
    display: block;
    padding: 12px 14px;
    border-bottom: 1px solid var(--dx3-rule);
  }
  table.dx3-stackable > tbody > tr:last-child {
    border-bottom: 0;
  }
  table.dx3-stackable > tbody > tr > td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    width: auto !important;
    padding: 3px 0;
    border: 0;
    text-align: right;
  }
  table.dx3-stackable > tbody > tr > td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--dx3-ink-3);
    font-weight: 600;
  }
  /* A cell with no heading (action buttons, icons) gets no label row. */
  table.dx3-stackable > tbody > tr > td:not([data-label])::before {
    content: none;
  }
  /* The first column is the identifier - read it as the card's title
     rather than another label/value pair. */
  table.dx3-stackable > tbody > tr > td:first-child {
    justify-content: flex-start;
    text-align: left;
    font-size: 15px;
    font-weight: 600;
    padding-bottom: 8px;
  }
  table.dx3-stackable > tbody > tr > td:first-child::before {
    content: none;
  }
  /* Empty-state rows span the table and already read as a sentence. */
  table.dx3-stackable > tbody > tr > td[colspan] {
    display: block;
    text-align: center;
  }
  table.dx3-stackable > tbody > tr > td[colspan]::before {
    content: none;
  }
  /* Footer totals keep their own layout. */
  table.dx3-stackable > tfoot {
    display: block;
  }
  table.dx3-stackable > tfoot > tr {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 14px;
    border-top: 2px solid var(--dx3-ink);
  }
  table.dx3-stackable > tfoot > tr > td {
    border: 0;
    padding: 0;
  }
}
