/* ════════════════════════════════════════════════════════════════════════════
   V3.2 visual port — theme overlay
   ════════════════════════════════════════════════════════════════════════════
   Founder direction 2026-06-03: revamp UI to match V3.2 (`Release/hornback-ims-v3.html`).
   The previous "industrial" V4 look (sharp corners, dark near-black topbar, dashed
   factory-tape stripe, warm cream body) is rejected. This overlay loads AFTER app.css
   in the page chain so it cleanly overrides without touching the original file.

   Reference token map (V3.2 → V4 override):
     --bg            #f1f5f9   →  --canvas
     --sidebar-bg    #1e2845   →  --ink-950 (topbar + sidebar)
     --radius        8px        →  default for buttons / cards / modals
     --primary       #f97316    →  already matches V4's --brand-orange
     --text          #1e293b    →  already close to V4's --ink-800
     fonts                       →  already aligned (Hanken Grotesk + Antonio + JetBrains Mono)

   Page-by-page rollout per project_v32_visual_overhaul_directive memory.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Surface palette ── V3.2 cool slate scale. */
  --canvas: #f1f5f9;          /* body bg (was warm cream #F2EFEA) */
  --paper:  #ffffff;
  --ink-950: #1e2845;         /* topbar + sidebar deep navy (was near-black #0A0F14) */
  --ink-900: #233152;         /* sidebar hover band */

  /* Borders softer. V3.2 uses #e2e8f0 everywhere; V4 had ink-200 = #D6DCE3.
     Override the alias V4 components use so cards / inputs land identically. */
  --border-default: #e2e8f0;
  --ink-200: #e2e8f0;

  /* Shadows — V3.2 is much softer + uses slate-toned alpha not pure black. */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 4px 6px -1px rgba(15, 23, 42, 0.07), 0 2px 4px -1px rgba(15, 23, 42, 0.04);
  --shadow-lg: 0 10px 15px -3px rgba(15, 23, 42, 0.09), 0 4px 6px -2px rgba(15, 23, 42, 0.05);
  --shadow-xl: 0 20px 25px -5px rgba(15, 23, 42, 0.10), 0 10px 10px -5px rgba(15, 23, 42, 0.04);
  --shadow-panel: -4px 0 18px rgba(15, 23, 42, 0.08);

  /* V3.2 standardises on 8px radius. Keep V4's --r-sm for tight tags + --r-pill for chips. */
  --r-md: 8px;
  --r-lg: 8px;
  --r-xl: 12px;
}

/* ── Body background — flips from warm cream to V3.2's cool slate. ── */
body {
  background: var(--canvas);
}

/* ════════════════════════════════════════════════════════════════════════════
   Topbar + sidebar — LIGHT theme (Zoho-Books style · 2026-06-15, founder direction).
   Replaces the industrial dark-navy chrome with a light surface, section sub-items
   indented FORWARD under their header, and a full orange pill on the active item.
   Overrides the app.css dark base (this stylesheet loads last).
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Topbar: white surface, dark text ── */
.app-topbar {
  background: #ffffff;
  color: var(--ink-900);
  border-bottom: 1px solid var(--ink-200);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
}
a.brand-mark, .brand-mark {
  color: var(--ink-900);
  letter-spacing: 0.04em;
  font-weight: 700;
}
a.brand-mark:hover { color: var(--brand-orange); }
.topbar-icon-btn { color: var(--ink-500); }
.topbar-icon-btn:hover { background: var(--ink-100); color: var(--ink-900); }
/* Search sits on the light topbar now — light field, dark text. */
.topbar-search-input {
  background: #ffffff;
  border-color: var(--ink-200);
  color: var(--ink-900);
}
.topbar-search-input::placeholder { color: var(--ink-400); }
.topbar-search-input:focus { background: #ffffff; border-color: var(--brand-orange); }
.topbar-search-icon { color: var(--ink-400); }
.topbar-search-clear { background: var(--ink-200); color: var(--ink-700); }
.topbar-search-clear:hover { background: var(--danger); color: #ffffff; }

/* ── Sidebar: light surface ── */
.app-sidebar {
  background: #f6f7f9;
  color: var(--ink-600);
  border-right: 1px solid var(--ink-200);
}
/* Section headers — readable sentence-case, not tiny mono-caps. */
.nav-group-label {
  font-family: var(--font-ui);
  font-size: 14px;                 /* +2 — section headers stand out from items */
  font-weight: 700;                /* bold */
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-700);
  padding: 6px var(--space-4);
  margin: 0 var(--space-2) var(--space-1);
  border-radius: 6px;
}
/* "You are here" — the section CONTAINING the active item gets a light-grey fill.
   (The selected item itself keeps its orange pill.) */
.nav-group:has(.nav-item.active) > summary.nav-group-label { background: #e3e6ec; }
/* Outline chevron (Zoho-style) instead of the filled ▸ triangle — better visibility. */
summary.nav-group-label::before {
  content: "";
  box-sizing: border-box;
  width: 7px;
  height: 7px;
  border: 0 solid var(--ink-500);
  border-right-width: 1.6px;
  border-bottom-width: 1.6px;
  transform: rotate(-45deg);       /* points right when collapsed */
  transition: transform 140ms ease;
}
details[open] > summary.nav-group-label::before { transform: rotate(45deg); }   /* points down when open */
summary.nav-group-label:hover { color: var(--ink-900); }

/* Nav items — light + pill-shaped; indented FORWARD under the section (expanded only). */
.app-sidebar .nav-item {
  color: var(--ink-600);
  border-left: none;
  border-radius: 7px;
  transition: background 0.13s ease, color 0.13s ease;
}
.app-shell:not(.sidebar-collapsed) .nav-item {
  padding: 7px var(--space-3) 7px var(--space-8);        /* forward indent under header */
  margin: 1px var(--space-2);
}
.app-sidebar .nav-item:hover {
  background: #e6e8ee;
  color: var(--ink-900);
}
.app-sidebar .nav-item.active {
  background: var(--brand-orange);
  color: #ffffff;
  border-left: none;
  font-weight: 600;
}
.app-sidebar .nav-item.active .nav-icon { color: #ffffff; }
/* Expanded sidebar = text-only nav items (Zoho style); leading icons hidden.
   The collapsed rail still shows them (the only glyph once labels are hidden). */
.app-shell:not(.sidebar-collapsed) .nav-icon { display: none; }
/* Deeper nested sub-item (if used) — a touch more indent. */
.app-shell:not(.sidebar-collapsed) .nav-item-sub {
  padding-left: calc(var(--space-8) + var(--space-4));
}

/* Collapse toggle, group separators + "dev" tag — light treatment. */
.sidebar-toggle { border-color: var(--ink-300); color: var(--ink-500); }
.sidebar-toggle:hover { background: var(--ink-100); color: var(--ink-900); border-color: var(--ink-400); }
.app-shell.sidebar-collapsed .nav-group { border-top-color: var(--ink-200); }
.nav-soon { background: var(--ink-100); color: var(--ink-500); }

/* ════════════════════════════════════════════════════════════════════════════
   Sidebar brand (moved from topbar) + collapsed rail (line icon + small label)
   · 2026-06-15 founder direction (Zoho-style collapsed nav).
   ════════════════════════════════════════════════════════════════════════════ */
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-5);   /* more breathing room from the left */
  border-bottom: 1px solid var(--ink-200);
  margin-bottom: var(--space-2);
}
.sidebar-brand { text-decoration: none; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.sidebar-logo {
  height: 26px;                 /* a touch bigger than the wordmark */
  width: auto;
  display: block;
  flex-shrink: 0;
}
.sidebar-brand-full {
  font-family: 'Poppins', var(--font-ui), sans-serif;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0;
  color: var(--ink-900);
  white-space: nowrap;
}
.sidebar-brand:hover .sidebar-brand-full { color: var(--brand-orange); }

/* Tighter gap between nav sections (founder: too much space between Overview / Purchases / …). */
.nav-group { margin-bottom: var(--space-2); }
.app-shell.sidebar-collapsed .nav-group { margin-bottom: var(--space-1); padding-top: var(--space-2); }

/* The nav-icon span wraps an inline SVG (Feather line icon). Size it; hidden when expanded. */
.nav-icon svg { display: block; width: 20px; height: 20px; }
.app-shell.sidebar-collapsed .nav-icon { display: flex; width: auto; align-items: center; justify-content: center; }

/* Collapsed rail: each item = icon on top + small short-label below (text-only expanded). */
.app-shell.sidebar-collapsed { grid-template-columns: var(--sidebar-w-collapsed) 1fr; }
.app-shell.sidebar-collapsed .nav-item {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 8px 2px;
  margin: 1px 6px;
}
.app-shell.sidebar-collapsed .nav-label { display: none; }
.app-shell.sidebar-collapsed .nav-label-short {
  display: block;
  font-size: 10px;
  line-height: 1.1;
  text-align: center;
  white-space: nowrap;
}
.app-shell:not(.sidebar-collapsed) .nav-label-short { display: none; }
/* Collapsed brand: hide the full name, show the compact HB mark, stack the head. */
.app-shell.sidebar-collapsed .sidebar-head { flex-direction: column-reverse; gap: var(--space-2); padding: var(--space-2) 0; }
.app-shell.sidebar-collapsed .sidebar-brand { justify-content: center; gap: 0; }
.app-shell.sidebar-collapsed .sidebar-brand-full { display: none; }   /* collapsed: logo only */
.app-shell.sidebar-collapsed .sidebar-logo { height: 30px; }          /* logo a touch bigger when it stands alone */

/* ── Section icons + collapsed hierarchy (founder 2026-06-15) ──
   Expanded: section header is the chevron + text (icon hidden).
   Collapsed: section header shows a BIG icon + small bold label, and its items show
   SMALLER icons — so the rail reads as section > items. */
.nav-group-icon { display: none; }
.nav-group-icon svg { display: block; width: 22px; height: 22px; }
.app-shell.sidebar-collapsed .nav-group-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 2px 6px;
  margin: 2px var(--space-2) 0;
  color: var(--ink-700);
}
.app-shell.sidebar-collapsed .nav-group-icon { display: flex; align-items: center; justify-content: center; }
.app-shell.sidebar-collapsed summary.nav-group-label::before { display: none; }   /* drop the disclosure chevron */
.app-shell.sidebar-collapsed .nav-group-text {
  display: block;
  font-size: 9.5px;
  font-weight: 700;
  line-height: 1.05;
  text-align: center;
  white-space: nowrap;
}
/* Items nested under a section — smaller icon than the section header (shows hierarchy). */
.app-shell.sidebar-collapsed .nav-item .nav-icon svg { width: 16px; height: 16px; }
.app-shell.sidebar-collapsed .nav-item { padding: 6px 2px; gap: 2px; }
.app-shell.sidebar-collapsed .nav-item .nav-label-short { font-size: 9px; color: var(--ink-500); }

/* ════════════════════════════════════════════════════════════════════════════
   Buttons — V3.2's clean 8px radius, soft hover, no industrial harshness.
   ════════════════════════════════════════════════════════════════════════════ */

.btn-primary, .btn-secondary, .btn-danger, .action-btn-primary, .seg-btn, .action-btn-secondary {
  border-radius: 8px;                                    /* unify default radius */
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn-primary, .action-btn-primary {
  background: var(--brand-orange);                       /* override industrial dark-navy bg */
  color: #ffffff;
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(249, 115, 22, 0.15);
  border: 1px solid var(--brand-orange);
}
.btn-primary:hover, .action-btn-primary:hover {
  background: var(--brand-orange-hover);
  border-color: var(--brand-orange-hover);
  color: #ffffff;
  box-shadow: 0 2px 4px rgba(249, 115, 22, 0.22);
}
/* Founder bugfix · 2026-06-12 — there was NO :disabled styling anywhere, so a blocked
   "Confirm & Save" looked fully clickable while clicks silently did nothing. M3 disabled
   state: greyed + not-allowed cursor. Applies app-wide to every button family. */
.btn-primary:disabled, .action-btn-primary:disabled,
.btn-secondary:disabled, .action-btn-secondary:disabled,
.btn-danger:disabled, .seg-btn:disabled {
  opacity: .45;
  filter: grayscale(45%);
  cursor: not-allowed;
  box-shadow: none;
}
.btn-primary:disabled:hover, .action-btn-primary:disabled:hover {
  background: var(--brand-orange);                       /* defeat the hover lift while disabled */
  border-color: var(--brand-orange);
  box-shadow: none;
}
.btn-secondary, .action-btn-secondary {
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  color: var(--ink-800);
  font-weight: 500;
}
.btn-secondary:hover, .action-btn-secondary:hover {
  background: #f1f5f9;
  border-color: #cbd5e1;
}

/* Segmented buttons (filter chips, tabs) take the V3.2 soft pill look. */
.seg-btn {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  color: var(--ink-700);
  border-radius: 8px;
  min-height: 38px;                 /* match .btn-secondary — was text-height, too short next to Columns */
  padding: 8px 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.seg-btn:hover {
  background: #f8fafc;
}
.seg-btn.active {
  background: var(--brand-orange);
  border-color: var(--brand-orange);
  color: #ffffff;
}

/* Salary structures — merged people-cost rollup (2026-07-09).
   Location header / group subheader / group subtotal / location subtotal / grand total rows. */
.data-table tr.cb-loc td    { background: var(--ink-100); font-weight: 700; color: var(--ink-900); border-top: 2px solid var(--ink-300); }
.data-table tr.cb-grp td    { background: var(--ink-50);  font-weight: 600; color: var(--ink-700); }
.data-table tr.cb-grp .cb-n { color: var(--ink-500); font-weight: 400; }
.data-table tr.cb-sub td    { border-top: 1px solid var(--ink-200); color: var(--ink-600); font-weight: 600; }
.data-table tr.cb-locsub td { border-top: 1px solid var(--ink-300); border-bottom: 2px solid var(--ink-300); font-weight: 700; color: var(--ink-900); }
.data-table tr.cb-grand td  { background: var(--ink-100); font-weight: 800; color: var(--ink-950); border-top: 2px solid var(--ink-400); }
.cb-dept { display: inline-block; margin-left: 8px; font-size: 11px; color: var(--ink-500);
           background: var(--paper); border: 1px solid var(--ink-200); border-radius: 10px; padding: 0 8px; vertical-align: middle; }
.data-table tr.cb-click { cursor: pointer; }
.data-table tr.cb-click:hover td { background: var(--ink-50); }
.cb-caret { display: inline-block; width: 14px; color: var(--ink-500); font-size: 11px; }
/* Pay-runs inside .fullbleed-page (2026-07-10, heading-jump fix): the layout's own fixed
   100vh height would overflow the fullbleed shell — flex-fill it instead. */
.fullbleed-page > .list-detail-layout { flex: 1 1 auto; min-height: 0; height: auto; }

/* Salary-structures master-detail (2026-07-10): rail and detail pane scroll INDEPENDENTLY.
   The old single .tab-panel-scroll scrolled both together, so picking another name from the
   rail dragged the open detail out of view (founder). */
.tab-panel-fill { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: var(--space-4) 4px 0; }
.tab-panel-fill > .vendors-shell { flex: 1; min-height: 0; }
.tab-panel-fill .list-pane { overflow-y: auto; min-height: 0; display: flex; flex-direction: column; }
.tab-panel-fill .list-rail { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.tab-panel-fill .list-rail-body { flex: 1; min-height: 0; overflow-y: auto; }
.tab-panel-fill .detail-pane { min-height: 0; }
.tab-panel-fill .detail-pane-body { flex: 1; min-height: 0; overflow-y: auto; }
.cb-info { color: var(--ink-500); cursor: help; font-size: 14px; margin-left: 4px; }
.cb-info:hover, .cb-info:focus-visible { color: var(--brand-orange); }

/* ════════════════════════════════════════════════════════════════════════════
   Round 2 fix · 2026-06-03 — Entity tab strip (Items: List / Anomalies / Price).
   Founder: "if the active tab can have more of something different". Lift the
   active tab with an orange bar + stronger weight + white card so it reads as
   the current view rather than just a button.
   ════════════════════════════════════════════════════════════════════════════ */

.entity-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid #e2e8f0;
  padding: 0 var(--space-4);
  /* White "shelf" so the selected tab's grey fill (var(--canvas) #f1f5f9) is VISIBLE against it.
     Previously transparent → on PO/Logistics/Items the strip showed the grey page canvas behind, so
     the grey active fill merged in and the selection vanished. Vendors looked right only because it
     set background:#fff inline. Making it the default fixes every entity-tab page at once, matching
     Vendors. 2026-06-15 founder. */
  background: #fff;
}
.entity-tab {
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  color: var(--ink-500);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
  margin-bottom: -1px;                                    /* overlap container border for clean join */
}
.entity-tab:hover {
  color: var(--ink-700);
  background: rgba(248, 250, 252, 0.6);
}
.entity-tab.active {
  color: var(--brand-orange);
  border-bottom-color: var(--brand-orange);
  background: #ffffff;
}

/* SubAssemblies tabbar uses `.sa-tabbar` + `.sa-tab-btn` — apply the same V3.2
   shape so it stops looking boxy. */
.sa-tabbar {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid #e2e8f0;
  padding: 0 var(--space-4);
  margin-bottom: var(--space-4);
  background: #fff;   /* white shelf so the grey active-tab fill shows (same fix as .entity-tabs) */
}
.sa-tab-btn {
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  color: var(--ink-500);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
  margin-bottom: -1px;
}
.sa-tab-btn:hover {
  color: var(--ink-700);
  background: rgba(248, 250, 252, 0.6);
}
.sa-tab-btn.active {
  color: var(--brand-orange);
  border-bottom-color: var(--brand-orange);
  background: #ffffff;
}
/* Unified active-tab look (2026-06-15 founder): the selected tab gets soft top corners + a subtle
   fill so it reads as a raised "folder tab", keeping the orange bottom-border — consistent across
   every tabbed surface (Inward, Logistics, Purchase Orders, Sub-Assemblies, …). */
.entity-tab, .sa-tab-btn { border-top-left-radius: 7px; border-top-right-radius: 7px; }
.entity-tab.active, .sa-tab-btn.active {
  background: var(--canvas);
  border-bottom-width: 3px;
}
/* Tab count = a live quantity for that section, not part of the heading — bracket + mute it
   ("List (36)", "Anomalies (3)"). 2026-06-15 founder. */
.entity-tab-count { color: var(--ink-500); font-weight: 500; margin-left: 4px; font-size: 12px; }
.entity-tab-count::before { content: "("; }
.entity-tab-count::after { content: ")"; }
.entity-tab.active .entity-tab-count { color: var(--brand-orange); }
/* Purchase Orders + Logistics emit `is-active` (not `active`) on the selected entity-tab, so the
   `.entity-tab.active` rules above never matched them — their active tab looked like plain text
   while Vendors/Items (which emit `active`) showed the orange folder. Alias `is-active` to the same
   computed look so every tabbed page is consistent regardless of which class the markup emits. This
   is CSS-only (no rebuild) — the founder's "PO/Logistics tabs don't match Vendors". 2026-06-15. */
.entity-tab.is-active {
  color: var(--brand-orange);
  border-bottom-color: var(--brand-orange);
  border-bottom-width: 3px;
  background: var(--canvas);
}
.entity-tab.is-active .entity-tab-count { color: var(--brand-orange); }

/* ════════════════════════════════════════════════════════════════════════════
   Cards / panels / modals — V3.2's calm paper-on-slate aesthetic.
   ════════════════════════════════════════════════════════════════════════════ */

.detail-pane, .modal, .card, .view-section, .form-section {
  border-radius: 8px;
}
.detail-pane {
  box-shadow: var(--shadow-panel);
}
.modal {
  border-radius: 12px;
  box-shadow: var(--shadow-xl);
  border: 1px solid #e2e8f0;
}
.modal-overlay {
  background: rgba(15, 23, 42, 0.45);
  backdrop-filter: blur(2px);
}

/* Section bars — restrained accent strip, not a brutal block.
   Round 3 fix · 2026-06-03 — first-letter clip on Daily Report. Cause: outer `.form-section`
   has its own 1px border + overflow that ate into the section-bar's left border-left + left
   padding. Switch to a positioned ::before marker so the orange accent doesn't consume any
   layout space, then put plenty of padding-left for the text. */
.section-bar {
  position: relative;
  background: #f8fafc;
  color: var(--ink-700);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 8px 14px 8px 22px;
  border-bottom: 1px solid #e2e8f0;
  border-left: none;
}
.section-bar::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  background: var(--brand-orange);
  border-radius: 2px;
  pointer-events: none;
}

/* ════════════════════════════════════════════════════════════════════════════
   Tables — V3.2's clean header band + soft alternating rows.
   Round 2 fix · 2026-06-03 — founder reported "double line on the header".
   Cause: `.table-wrap` had its own border + `.data-table` had its own border + the
   `.zsync-bulk-row` toolbar row had a border-bottom, stacking 2-3 horizontal lines.
   Fix: ONE source of truth for the visual frame — `.table-wrap` (because it spans
   the full content area). Suppress the table's own border + drop the toolbar's.
   ════════════════════════════════════════════════════════════════════════════ */

/* Default V3.2 card frame on every .data-table. Pages with their own .table-wrap get
   the frame from the wrap instead (rules below suppress the redundant inner frame). */
.data-table {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  margin: 0 0 12px;
  width: 100%;
  border-collapse: separate;                             /* preserves radius corners */
}
/* When wrapped in .table-wrap, the wrap is the visible frame. */
.table-wrap {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  margin-bottom: 12px;
}
.table-wrap .data-table {
  border: none;
  border-radius: 0;
  box-shadow: none;
  margin: 0;
}
.data-table thead th {
  background: #f8fafc;
  color: var(--ink-700);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: none;
  border-bottom: 1px solid #e2e8f0;
  border-top: none;                                      /* avoid double-line at top */
}
.data-table tbody tr {
  border-bottom: 1px solid #f1f5f9;
}
.data-table tbody tr:last-child {
  border-bottom: none;                                   /* wrap bottom border replaces it */
}
.data-table tbody tr:hover {
  background: #f8fafc;
}
.data-table.clickable-rows tbody tr:hover {
  cursor: pointer;
}

/* Pre-table toolbar rows (.zsync-bulk-row is the one above the table on Vendors / Items /
   Consumables). Drop the bottom border — the table's own card frame replaces the separation. */
.zsync-bulk-row {
  border-bottom: none;
  padding: 8px 14px 12px;
}

/* ════════════════════════════════════════════════════════════════════════════
   Form controls — softer focus, 8px corners.
   ════════════════════════════════════════════════════════════════════════════ */

.field, input.field, select.field, textarea.field, input[type="text"], input[type="number"], input[type="date"], input[type="email"], input[type="password"], select, textarea {
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  /* 2026-06-10 founder NON-NEGOTIABLE rule (feedback_standard_input_size memory) — every
     input / select / textarea on every modal + form must be standard size, not cramped.
     Founder has asked 10+ times. These three properties make the .field class the
     reference standard. Local overrides (e.g. table-cell qty inputs) may tighten width
     but must preserve padding + min-height. */
  padding: 8px 12px;
  min-height: 38px;
  font-size: 13px;
}
.field-row .field, .form-grid .field, .modal .field {
  /* Modal + form fields: fill the column they live in. Stops "thin column" cropping. */
  width: 100%;
  box-sizing: border-box;
}
textarea.field, textarea {
  min-height: 64px;
  padding: 10px 12px;
}
.modal .modal-actions button, .modal .form-actions button,
.modal > div > button.btn-primary, .modal > div > button.btn-secondary {
  /* Same memory rule applied to action-bar buttons. */
  min-width: 110px;
  padding: 8px 16px;
  min-height: 38px;
}
.field:focus, input.field:focus, select.field:focus, textarea.field:focus,
input[type="text"]:focus, input[type="number"]:focus, input[type="date"]:focus,
input[type="email"]:focus, input[type="password"]:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand-orange);
  box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.15);
}

/* ════════════════════════════════════════════════════════════════════════════
   Page chrome — title row, toolbars, KPI stats, empty states.
   ════════════════════════════════════════════════════════════════════════════ */

.page-toolbar h1, .page-title {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  line-height: 0.95;
  color: var(--ink-800);
}
/* Note: the orange left-accent strip is already painted by `.page-toolbar::before`
   in app.css. Do NOT add a `border-left` here — see Round 3 fix at the bottom of
   this file for the duplicate-bar bug this caused on every page title. */

/* Stat cards — soft white surface, not heavy borders. */
.page-stat {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 10px 14px;
  box-shadow: var(--shadow-sm);
}
.page-stat-label {
  font-size: 10px;
  font-weight: 600;
  color: var(--ink-500);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.page-stat-value {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Stock Ledger banner groups (founder 2026-07-13) — the same total broken up two ways.
   A group is ONE flex child of .page-stats: tiny caption on top, its cards in a row below,
   so "By process" / "By location" wrap together instead of scattering. */
.sl-stat-group { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sl-stat-group-cap {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;   /* micro section label — allowed caps, same family as .page-stat-label */
  color: var(--ink-400);
  padding-left: 2px;
}
.sl-stat-group-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* Page filter bar — V3.2 floats the bar inside a white card. */
.page-filter-bar {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 10px 14px;
  margin: 0 var(--space-4) var(--space-3);
  box-shadow: var(--shadow-sm);
}

/* Filter field cluster — small label above a select for clarity. Replaces the
   segmented chip strips on Dispatch Log, Items Anomalies, etc. */
.filter-field {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
}
.filter-field-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--ink-500);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.filter-field .field {
  min-width: 160px;
  padding: 6px 28px 6px 10px;
  font-size: 13px;
}

/* Empty state lifted to V3.2's centered comfort. */
.empty-state {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 48px 24px;
  text-align: center;
  color: var(--ink-500);
}
.empty-state h3 {
  color: var(--ink-800);
  font-weight: 600;
  margin-bottom: 6px;
}

/* ════════════════════════════════════════════════════════════════════════════
   Status pills — V3.2 soft pastel chips on white background.
   ════════════════════════════════════════════════════════════════════════════ */

.pill {
  border-radius: 10px;
  padding: 2px 9px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: none;
}
.pill-color-green   { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; }
.pill-color-orange  { background: #ffedd5; color: #9a3412; border: 1px solid #fed7aa; }
.pill-color-blue    { background: #dbeafe; color: #1e40af; border: 1px solid #bfdbfe; }
.pill-color-purple  { background: #ede9fe; color: #5b21b6; border: 1px solid #ddd6fe; }
.pill-color-yellow  { background: #fef3c7; color: #92400e; border: 1px solid #fde68a; }
.pill-color-red     { background: #fee2e2; color: #991b1b; border: 1px solid #fecaca; }
.pill-color-gray    { background: #f1f5f9; color: var(--ink-700); border: 1px solid #e2e8f0; }
.pill-color-teal    { background: #ccfbf1; color: #115e59; border: 1px solid #99f6e4; }
.pill-warn          { background: #fffbeb; color: #92400e; border: 1px solid #fde68a; }

/* ════════════════════════════════════════════════════════════════════════════
   Subtle polish — scrollbars, code/mono treatment, link colour.
   ════════════════════════════════════════════════════════════════════════════ */

a { color: var(--brand-orange); }
a:hover { color: var(--brand-orange-hover); }

code, kbd, pre, samp {
  font-family: var(--font-mono);
  background: #f1f5f9;
  color: var(--ink-700);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 11.5px;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; border: 2px solid transparent; background-clip: content-box; }

/* ════════════════════════════════════════════════════════════════════════════
   Round 2 fix · 2026-06-03 — SubAssemblies boxy accordion fix.
   Founder: "subassembly table is still boxy, like, rounded edges on the other
   tables, but subassembly still has boxy kind of a shape." The page uses
   <details> accordions + custom record rows that bypass `.data-table` styling.
   Round their corners + give them the same soft white card frame.
   ════════════════════════════════════════════════════════════════════════════ */

/* The actual SubAssemblies page wraps content in `.sa-tab-body` and uses
   <details open style="border:1px solid …; border-radius:0; …"> directly with
   INLINE styles. CSS specificity won't beat inline styles for non-!important
   properties — so we use !important for border-radius + softer border colour. */
.sa-tab-body details {
  border-radius: 8px !important;
  border-color: #e2e8f0 !important;
  overflow: hidden;
  margin-bottom: 12px !important;
  box-shadow: var(--shadow-sm);
  background: #ffffff !important;
}
.sa-tab-body details > summary {
  border-radius: 0 !important;
  padding: 10px 14px !important;
  background: #f8fafc !important;
  border-bottom: 1px solid #e2e8f0;
}
/* Nested sub-group details (Fork / Lock / Suspension) — softer treatment. */
.sa-tab-body details details {
  border: 1px solid #e2e8f0 !important;
  background: #ffffff !important;
  margin: 0 0 8px 0 !important;
}
/* Per-record row hover. The Razor outputs each record as a div without a class
   inside the inner details — match by descendant. */
.sa-tab-body details details > div > div:hover,
.sa-tab-body details > div > div:hover {
  background: #f8fafc;
}

/* `.sa-tab-body` itself: the bordered wrapper holding the tabs' content.
   Match the V3.2 soft card frame instead of sharp ink-200 lines. */
.sa-tab-body {
  border: 1px solid #e2e8f0 !important;
  border-top: none !important;
  border-radius: 0 0 8px 8px !important;
  background: #ffffff !important;
  padding: 14px !important;
}

/* The full-page table on Sub-Assemblies (frame-pipeline-table) inherits .data-table
   when it has that class; force the same rounded card frame on the wrapper. */
.frame-pipeline-table thead th {
  background: #f8fafc;
  color: var(--ink-700);
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0.02em;
  border-bottom: 1px solid #e2e8f0;
}

/* ════════════════════════════════════════════════════════════════════════════
   Round 3 fix · 2026-06-03 — double orange vertical-bar bug on page titles.
   Cause: app.css already paints an orange bar via `.page-toolbar::before` (the V3.2
   left-accent strip). My earlier rule added a SECOND orange `border-left` on the h1
   itself, sitting next to the ::before at a different height = visible "two bars".
   Fix: rely on the existing `.page-toolbar::before` only — strip the h1 border-left,
   restore default h1 padding so the title spacing reads cleanly.
   ════════════════════════════════════════════════════════════════════════════ */

.page-toolbar h1, .page-title {
  border-left: none;
  padding-left: 0;
}

/* ════════════════════════════════════════════════════════════════════════════
   U34 — Sticky table header. Keeps column headers visible while the table body
   scrolls. Per Rules-V4 U34: position:sticky with solid bg + bottom shadow, on a
   table that uses border-spacing:0 (not collapse) so sticky engages cleanly.
   ════════════════════════════════════════════════════════════════════════════ */
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: #f8fafc;
  box-shadow: 0 1px 0 #e2e8f0;
}
.table-wrap {
  max-height: calc(100vh - 250px);
  overflow: auto;
}

/* Batch-4c · 2026-06-13 — Frame Pipeline table: visible divider above each colour group
   (founder: "no divider between painted frames on the left side"). tr borders don't render
   with border-spacing, so the line goes on the row's cells. The fab column cell spans the
   whole frame type, so the divider runs from the colour column rightward — intended. */
.pl-pipeline tr.pl-colour-first > td {
  border-top: 2px solid #f3d1e3;
}

/* Batch-4b · 2026-06-12 — the Batch-4 `.dispatch-log-table { min-width: 1480px }` scroll
   fix is REMOVED (founder: "columns stop resizing at some length which is too much").
   The table-level floor meant shrinking one column just redistributed width to the others
   — total never went below 1480px. The column resizer writes width+min+max inline on each
   TH (app.js initColumnResize), so once any column is sized the table's intrinsic minimum
   = Σ column widths, and .table-wrap's overflow:auto produces the horizontal scrollbar
   whenever that sum exceeds the window. Default (unresized) view shares width with U35
   ellipsis like every other page. */

/* ════════════════════════════════════════════════════════════════════════════
   U35 — Uniform row height + ellipsis truncation. Long content gets `…` instead
   of wrapping the row. Pages can opt out per cell with `.cell-multiline`.
   ════════════════════════════════════════════════════════════════════════════ */
.data-table td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 320px;
  height: 44px;
  vertical-align: middle;
}
.data-table th {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.data-table td.cell-multiline {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  height: auto;
  max-width: none;
}
/* Allow nested .muted helper text to wrap inside the cell while the main row
   stays on one line — used by Customer (with phone below) and IMS (date below). */
.data-table td .muted {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* MR-V32-ProdLogXref · 2026-06-04 — Period KPI pairs on Production Log.
   Inline rate strip (MTD + FY by stage) — small / dense / read-only. */
.prod-kpi-pair {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 3px 10px;
  background: #fff;
  border: 1px solid var(--ink-100);
  font-size: 12px;
}
.prod-kpi-pair .prod-kpi-stage {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .3px;
  margin-right: 4px;
}
.prod-kpi-pair .prod-kpi-num {
  font-size: 15px;
  font-weight: 800;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
.prod-kpi-pair .prod-kpi-label {
  font-size: 10px;
  color: var(--ink-500);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  margin-left: 1px;
}
.prod-kpi-pair .prod-kpi-sep {
  color: var(--ink-300);
  font-weight: 400;
}

/* ════════════════════════════════════════════════════════════════════════════
   M3-UI-Overhaul Batch A.2 · 2026-06-08 — Global keyboard focus indicator (G1)
   ════════════════════════════════════════════════════════════════════════════
   Before this rule the entire stylesheet had only two :focus-visible rules
   (.data-table th + .user-avatar), so every other button / tab / nav item /
   dropdown / chip / icon-action was invisible on keyboard focus. The handoff
   doc (M3-UI-REVIEW-HANDOFF-2026-06-08.md §2 G1) calls this "the highest-
   leverage single fix" — one rule that lights up every keyboard-interactive
   control across all 28 pages.

   Specificity is intentionally low — :where() gives 0,0,0 so any component
   that wants a richer focus style can still override with a plain selector.

   Outline color uses the M3 secondary role (= --accent #1E40AF) so it stands
   out cleanly against orange brand surfaces and dark navy chrome alike.
   3px width clears WCAG SC 2.4.7 (Focus Visible) comfortably.

   border-radius is intentionally NOT set — modern browsers (Chromium 94+,
   Firefox 88+, Safari 16.4+) auto-curve outline to match the element's own
   border-radius, so the focus ring follows whatever shape the button has.
   ════════════════════════════════════════════════════════════════════════════ */
:where(
  .btn-primary, .btn-secondary, .btn-danger,
  .btn-icon, .btn-icon-danger,
  .seg-btn, .entity-tab, .sa-tab-btn,
  .pagination-btn, .dropdown-item,
  .list-menu-btn, .col-settings-btn,
  .nav-item, .icon-action-btn,
  .tfd-trigger, .tfd-menu-item,
  .bulk-btn, .bulk-clear,
  a.brand-mark, .topbar-icon-btn,
  .user-avatar,
  .filter-chip, .topbar-search-clear
):focus-visible {
  outline: 3px solid var(--md-sys-color-secondary);
  outline-offset: 2px;
}

/* ════════════════════════════════════════════════════════════════════════════
   M3-UI-Overhaul Batch A.3 · 2026-06-08 — Contrast token fixes (G3)
   ════════════════════════════════════════════════════════════════════════════
   Per M3-UI-REVIEW-HANDOFF §2 G3. Four WCAG-failing colour pairs across the
   app:

   1. .btn-primary text — #fff on #F97316 = 2.9:1 (fails 4.5:1 body, fails
      3:1 even as a UI affordance). Swap to M3 on-primary role (#2A1500
      dark brown) for 7.2:1 AAA contrast. The brand orange stays unchanged.

   2. .field:focus old ring (box-shadow 0 0 0 3px rgba(249,115,22,.15))
      ≈ 2.9:1 against the white field bg — fails 3:1 UI affordance. Replace
      with a clean two-state model: mouse focus shows the orange
      border-color only (subtle, design-aligned); keyboard focus
      (:focus-visible) layers the high-contrast 2px blue ring on top so
      keyboard users get a strong signal that mouse users don't need.

   3. .muted / .hint-inline / ::placeholder text was --ink-400 #8E99A8
      (or raw #9ca3af in some rules) — ≈ 2.5:1 on white = fails. Switch
      to --ink-500 #6A7686 = 4.6:1 ✓. Borders and decorative uses of
      --ink-400 left alone (≥3:1 is acceptable for non-text UI elements).

   4. .validation-message / .required / .modal-danger h3 — raw #dc2626
      = 4.0:1, fails 4.5:1 small-text. Switch to var(--danger) #B91C1C
      = 5.9:1 ✓. Tokenised so future palette tweaks propagate.
   ════════════════════════════════════════════════════════════════════════════ */

/* Fix #1 — .btn-primary text contrast (white-on-orange → dark-brown-on-orange). */
.btn-primary, .action-btn-primary,
.btn-primary:hover, .action-btn-primary:hover,
.btn-primary:focus, .action-btn-primary:focus {
  color: var(--md-sys-color-on-primary);
}

/* Fix #2 — .field focus state. Mouse-focus = orange border-color only.
   Keyboard-focus (:focus-visible) = orange border-color + blue 2px outline. */
.field:focus, input.field:focus, select.field:focus, textarea.field:focus,
input[type="text"]:focus, input[type="number"]:focus, input[type="date"]:focus,
input[type="email"]:focus, input[type="password"]:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand-orange);
  box-shadow: none;  /* drop the 2.9:1 orange-alpha ring */
}
.field:focus-visible, input.field:focus-visible, select.field:focus-visible, textarea.field:focus-visible,
input[type="text"]:focus-visible, input[type="number"]:focus-visible, input[type="date"]:focus-visible,
input[type="email"]:focus-visible, input[type="password"]:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--md-sys-color-secondary);
  outline-offset: 2px;
  border-color: var(--brand-orange);
  box-shadow: none;
}

/* Fix #3 — Muted/hint/placeholder text. Bump from --ink-400 (2.5:1) to
   --ink-500 (4.6:1). Scoped to text uses only; decorative --ink-400 borders
   (e.g. .col-settings-lock icon) are left alone. */
.data-table .muted,
.muted,
.hint,
.hint-inline {
  color: var(--ink-500);
}
::placeholder,
.topbar-search-input::placeholder,
.field::placeholder,
input::placeholder,
textarea::placeholder {
  color: var(--ink-500);
  opacity: 1;  /* Firefox defaults to 0.54 — kills contrast again */
}

/* Fix #4 — Error/required text. Tokenise to var(--danger) for 5.9:1. */
.validation-message,
.login-card .validation-message,
.required,
.modal-danger h3 {
  color: var(--danger);
}

/* ════════════════════════════════════════════════════════════════════════════
   M3-UI-Overhaul Batch A.4 · 2026-06-08 — Icon button hit area + radius (G5)
   ════════════════════════════════════════════════════════════════════════════
   .btn-icon / .btn-icon-danger were 26×26 with 6px radius in app.css:3063+.
   Two issues:

   1. 26×26 fails WCAG 2.2 SC 2.5.8 Target Size Minimum (24×24 is the AA
      floor — passes at 26, but the handoff recommends 40 for desktop
      dense to give comfortable cursor margin and bring close-buttons /
      delete-icons in dense lists within easy reach).

   2. 6px radius is inconsistent with v32-theme's 8px standard
      (.btn-primary/.seg-btn/.field all 8px). Tiny visual drift the eye
      catches across a row of mixed buttons.

   Using min-width / min-height overrides the existing 26×26 width/height
   declarations cleanly (min-* wins when larger than the declared dim).
   Visible glyph stays the same size — only the hit area grows.

   Also covers the FrameActivity modal close ✕ buttons (FrameActivity.razor
   :287, :380) which were `class="icon-btn"` (UNDEFINED) and now ride this
   styling correctly after the rename to `.btn-icon` in the same batch.
   ════════════════════════════════════════════════════════════════════════════ */
.btn-icon,
.btn-icon-danger {
  min-width: 40px;
  min-height: 40px;
  border-radius: 8px;
}

/* M3 Batch B (G4) — screen-reader-only helper text utility. Standard pattern:
   element is removed from visual layout but readable to assistive tech via
   aria-describedby. Used for input help strings, icon-button labels behind
   emoji, etc. */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* ════════════════════════════════════════════════════════════════════════════
   M3-UI-Overhaul Batch D · 2026-06-08 — Sentence case sweep (G6)
   ════════════════════════════════════════════════════════════════════════════
   Per M3-UI-REVIEW-HANDOFF §2 G6: convert mechanically-uppercased UI text
   to sentence case (M3 standard). Allowed to KEEP caps: Antonio brand mark,
   .section-bar / .nav-group-label / .page-stat-label (deliberate display
   treatments, called out as "allowed" in the handoff).

   Targeted overrides — drop text-transform:uppercase from:

   1. Login card heading / subtitle / labels / button (app.css:457-506).
      The login is the founder's first impression; M3 says sentence case
      reads as friendlier and more modern. Brand mark "HORNBACK IMS" stays
      via Antonio's stencil character (text content unchanged).

   2. KPI / page-stat micro-labels rendered without a specific scope.
      Keeps .page-stat-label as ALLOWED caps per handoff.

   The unchanged display strings (e.g. "Sign in") already arrive sentence-
   case from the razor; this rule just stops force-shouting them.
   ════════════════════════════════════════════════════════════════════════════ */
.login-card h1,
.login-card .subtitle,
.login-card label,
.login-btn {
  text-transform: none;
  letter-spacing: normal;
}

/* Pill text — handoff §2 G6 calls out "DELETED" → "Deleted", "YOU" → "You".
   Razor literals get fixed at source; here we also catch the .pill-deleted
   class which has its own text-transform:uppercase in app.css. */
.pill-deleted,
.pill-you {
  text-transform: none;
  letter-spacing: 0.02em;
}

/* Sentence-case sweep — pattern #1 (2026-06-25).
   Keep uppercase: .page-toolbar h1 / .section-bar / .nav-group-label (brand moments).
   Sentence-case everything else readable at body size. */
.toolbar-left .subtitle,
.page-toolbar .subtitle,
.toolbar-left p {
  text-transform: none;
  letter-spacing: normal;
}
.form-field label,
.form-field > label {
  text-transform: none;
  letter-spacing: normal;
}
.filter-field-label {
  text-transform: none;
  letter-spacing: 0.02em;
}

/* M3 Batch D · Sub-Assemblies tabs — proper class-based rules replacing the
   ~250-char inline style="..." block on every .sa-tab-btn (handoff §3
   Section 5 Sub-Assemblies finding: "sa-tab-btn overridden by huge inline
   style= repainting active/inactive (hardcoded borders/box-shadow) →
   defeats theme; two tab styles in one file. Delete inline style.").
   Mirrors the visual treatment exactly but routes through tokens so the
   override layer can actually re-skin tabs without per-page edits. */
/* 2026-06-15 — Sub-Assemblies tabs were the odd one out: an all-around orange border on the active
   tab. Re-skinned to match the entity-tab folder-tab look (orange BOTTOM-border + soft top corners
   + subtle fill) so every tabbed page is consistent. */
.sa-tab-btn {
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  margin-right: 4px;
  margin-bottom: -1px;
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  border-top-left-radius: 7px;
  border-top-right-radius: 7px;
  color: var(--ink-500);
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.sa-tab-btn:hover:not(.active) {
  background: rgba(248, 250, 252, .6);
  color: var(--ink-700);
}
.sa-tab-btn.active {
  background: var(--canvas);
  border-bottom-color: var(--brand-orange);
  color: var(--brand-orange);
  font-weight: 600;
}

/* ════════════════════════════════════════════════════════════════════════════
   M3-UI-Overhaul Batch E · 2026-06-08 — Stat / KPI colour tokens (G3 follow-up)
   ════════════════════════════════════════════════════════════════════════════
   Handoff §2 G3: "KPI/dashboard amber #f59e0b on white ≈2.0:1, fails even
   large-text". Same for purple #a855f7 (~4.0:1) and sky #0ea5e9 (~3.0:1)
   used as page-stat-value colours across Home / DispatchLog / DispatchDashboard
   / DailyReport / Cogs / StockLedger / PurchaseOrders preview tile.

   Replacement tokens — same hue, darker shade, all clear 4.5:1 ✓ on white:

     --stat-warning  amber-700  #B45309 = 4.7:1 ✓  (= V4's --warning)
     --stat-info     sky-700    #0369A1 = 6.5:1 ✓
     --stat-violet   purple-700 #7E22CE = 5.5:1 ✓

   Razor pages updated in the same batch to reference these instead of the
   failing raw hex literals.
   ════════════════════════════════════════════════════════════════════════════ */
:root {
  --stat-warning: var(--warning);  /* #B45309 — already defined in app.css */
  --stat-info:    #0369A1;
  --stat-violet:  #7E22CE;
}

/* ── HR detail panel: clean definition grid (founder feedback 2026-06-24 — profile rows were
   crowded/jammed). Label sits small + muted above its value, generous spacing, two columns. ── */
.def-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3) var(--space-6);
  margin: var(--space-2) 0 0;
}
.def-grid > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.def-grid dt {
  font-size: 11px;
  letter-spacing: .02em;
  color: var(--ink-500);
  margin: 0;
}
.def-grid dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink-900);
  word-break: break-word;
}
.dp-section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-700);
  margin: 0 0 var(--space-2);
}
@media (max-width: 720px) { .def-grid { grid-template-columns: 1fr; } }

/* ── BOM overlay — full-screen scrollable document (SKUs → "View BOM") ──────── */
.bom-overlay-bg {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 500;
}
.bom-overlay-doc {
  position: fixed;
  inset: 0;
  z-index: 501;
  overflow-y: auto;
  background: var(--surface, #fff);
  padding: var(--space-6) var(--space-8);
  max-width: 900px;
  margin: 0 auto;
  outline: none;           /* tabindex="-1" focus target; visual focus via overlay-bg */
}

/* Document letterhead */
.bom-doc-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 2px solid var(--ink-900);
  margin-bottom: var(--space-5);
}
.bom-doc-company { flex: 1; }
.bom-company-name {
  font-family: 'Antonio', sans-serif;
  font-size: 28px;
  font-weight: 700;
  color: var(--ink-950);
  letter-spacing: .04em;
  line-height: 1;
}
.bom-company-sub {
  font-size: 12px;
  color: var(--ink-500);
  letter-spacing: .06em;
  margin-top: 2px;
}
.bom-doc-meta {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
}
.bom-meta-row { display: flex; gap: var(--space-2); align-items: baseline; }
.bom-meta-lbl {
  font-size: 11px;
  color: var(--ink-500);
  min-width: 72px;
  text-align: right;
}
.bom-meta-val {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-900);
}
.bom-doc-actions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* BOM sections */
.bom-section {
  margin-bottom: var(--space-6);
}
.bom-section-hdr {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-900);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--ink-200);
}
.bom-section-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--ink-900);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
}
/* Group row — replaces numbered section headers; title left + group total right */
.bom-group-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 2px solid var(--ink-200);
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-3);
}
.bom-group-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-900);
}
.bom-group-total {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

.bom-sub-lbl {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-600);
  margin: 0 0 var(--space-1);
}
.bom-kind-tag {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-500);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-sm);
  padding: 1px 6px;
  margin-left: var(--space-1);
}
.bom-empty {
  font-size: 12px;
  color: var(--ink-500);
  font-style: italic;
  margin: 0 0 var(--space-2);
}

/* BOM data table — fixed 7-column grid shared by all group tables (Frame fab, Frame paint,
   Sub-asm, Direct parts) so columns lock to the same positions across every section. */
.bom-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 13px;
  margin-bottom: var(--space-2);
}
/* col 1: Part code  col 2: Description (flex)  col 3: Qty  col 4: Unit
   col 5: Purchase rate  col 6: Landed  col 7: Landed total */
.bom-table th:nth-child(1), .bom-table td:nth-child(1) { width: 108px; }
.bom-table th:nth-child(3), .bom-table td:nth-child(3) { width: 52px; }
.bom-table th:nth-child(4), .bom-table td:nth-child(4) { width: 52px; }
.bom-table th:nth-child(5), .bom-table td:nth-child(5) { width: 108px; }
.bom-table th:nth-child(6), .bom-table td:nth-child(6) { width: 108px; }
.bom-table th:nth-child(7), .bom-table td:nth-child(7) { width: 112px; }
.bom-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-600);
  border-bottom: 1px solid var(--ink-200);
  padding: 4px 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bom-table th.num, .bom-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.bom-table td {
  padding: 5px 8px;
  color: var(--ink-800);
  border-bottom: 1px solid var(--ink-100);
  vertical-align: top;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bom-table tbody tr:last-child td { border-bottom: none; }
.bom-table td.mono { font-family: monospace; font-size: 12px; color: var(--ink-500); }

/* Total strip */
.bom-total-strip {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  background: var(--ink-950);
  color: #fff;
  border-radius: var(--r-md);
  margin-top: var(--space-4);
  font-size: 14px;
  font-weight: 600;
}
.bom-total-val {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Secondary total strip — raw material total (lighter than the primary dark strip) */
.bom-total-strip-secondary {
  background: var(--ink-100);
  color: var(--ink-700);
  margin-top: var(--space-2);
  font-weight: 500;
}
.bom-total-val-secondary {
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-700);
}

/* Footer note */
.bom-doc-footer {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: 1px solid var(--ink-100);
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--ink-400);
}

/* ── COGS breakdown modal — reuses .bom-overlay-doc; wider for the cost columns ─────
   The per-row "View COGS" trigger, the 14-column cost table, and the unit summary. */
.cogs-doc { max-width: 1180px; }

/* Row trigger — SKU code + inline magnifier; text-button styling, no width bloat */
.cogs-view-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  padding: 2px 4px;
  margin: -2px -4px;
  font: inherit;
  font-weight: 600;
  color: var(--ink-900);
  cursor: pointer;
  border-radius: var(--r-sm);
}
.cogs-view-btn:hover { color: var(--brand-orange); }
.cogs-view-btn:hover .cogs-view-code { text-decoration: underline; }
.cogs-view-ico { color: var(--ink-400); flex-shrink: 0; }
.cogs-view-btn:hover .cogs-view-ico { color: var(--brand-orange); }
.cogs-view-btn:focus-visible { outline: 3px solid var(--md-sys-color-secondary); outline-offset: 2px; }

/* Wide cost table — horizontal scroll inside the modal doc */
.cogs-table-scroll { overflow-x: auto; margin-bottom: var(--space-2); }
/* 2026-07-11 — size to content (bounded), not width:100%. On an ultra-wide monitor a 100%-width table
   with a handful of short columns stretched across ~2000px, leaving a huge gap before the right-aligned
   ₹/unit column. width:auto + a shared min/max keeps all three breakdown tables compact and aligned. */
/* 2026-07-12 sweep — PicklistManager colour popover was invisible: .picklist-table td has
   overflow:hidden (app.css) and the 42px swatch cell is the popover's containing block, so the
   220px .pill-picker-popover was clipped to the cell. Exempt the swatch cell from clipping and
   open the popover to the RIGHT of the cell (into the row) so it stays inside the scroll area. */
.picklist-table td:first-child { overflow: visible; text-overflow: clip; }
.picklist-table .pill-picker-popover { left: 0; transform: none; }

/* Clean labour-breakdown tables (COGS → Labour) — proper grid + even spacing, first column sized to
   content (not stretched like .cogs-bom-table), numeric columns packed right. Founder UI fix 2026-07-12. */
.cogs-labour-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.cogs-labour-tbl th {
  text-align: left; padding: 8px 14px; font-size: 11px; font-weight: 700; letter-spacing: .02em;
  color: var(--ink-500); border-bottom: 1.5px solid var(--ink-200); white-space: nowrap;
}
.cogs-labour-tbl td {
  padding: 8px 14px; color: var(--ink-800); border-bottom: 1px solid var(--ink-100); white-space: nowrap;
}
.cogs-labour-tbl th.r, .cogs-labour-tbl td.r { text-align: right; font-variant-numeric: tabular-nums; }
.cogs-labour-tbl td:first-child { font-weight: 500; color: var(--ink-900); }
.cogs-labour-tbl tbody tr:hover td { background: var(--ink-50); }
.cogs-labour-tbl tr.tot td {
  border-top: 1.5px solid var(--ink-300); border-bottom: none; font-weight: 700;
  color: var(--ink-900); background: var(--ink-50); padding-top: 9px; padding-bottom: 9px;
}
.cogs-labour-tbl .u { color: var(--ink-500); font-size: 11px; font-weight: 400; }

.cogs-bom-table {
  width: auto;
  min-width: 680px;
  max-width: 1040px;
  border-collapse: collapse;
  font-size: 12px;
}
/* First (label) column absorbs the slack so the numeric columns stay packed to the right, not floated
   far away with empty space in between. */
.cogs-bom-table th:first-child, .cogs-bom-table td:first-child { width: 100%; }
.cogs-bom-table th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--ink-600);
  border-bottom: 1px solid var(--ink-200);
  padding: 4px 8px;
  white-space: nowrap;
}
.cogs-bom-table th.dim-hdr { text-align: center; }
.cogs-bom-table th.num, .cogs-bom-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.cogs-bom-table td {
  padding: 4px 8px;
  color: var(--ink-800);
  border-bottom: 1px solid var(--ink-100);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
}
.cogs-bom-table td.mono { font-family: monospace; font-size: 11px; color: var(--ink-500); }
.cogs-bom-table .cogs-dim-sep { border-left: 1px solid var(--ink-200); }
.cogs-bom-table tbody tr.cogs-subtotal-row td {
  border-top: 1px solid var(--ink-300);
  border-bottom: none;
  font-weight: 700;
  color: var(--ink-800);
  background: var(--ink-50);
}
/* Grand total across all groups — the strongest row in the per-item table */
.cogs-bom-table tbody tr.cogs-grand-row td {
  border-top: 2px solid var(--ink-400);
  border-bottom: none;
  font-weight: 800;
  color: var(--ink-950);
  background: var(--ink-100);
}
/* Each column's grand total as a share of unit COGS */
.cogs-bom-table tbody tr.cogs-pct-row td {
  border-bottom: none;
  font-weight: 700;
  color: var(--ink-600);
  background: var(--ink-100);
}

/* Reconciliation guard note (shown only if per-item landed ≠ summary landed) */
.cogs-recon-warn {
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--r-sm);
  background: var(--warning-soft);
  color: var(--ink-800);
  font-size: 12px;
}

/* Unit cost summary card (values pulled from the COGS row, not recomputed) */
.cogs-summary {
  max-width: 520px;
  margin-top: var(--space-5);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-md);
  padding: var(--space-3) var(--space-4);
  background: var(--ink-50);
}
.cogs-summary-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-700);
  margin-bottom: var(--space-2);
}
.cogs-summary-row,
.cogs-summary-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  padding: 5px 0;
  border-bottom: 1px solid var(--ink-100);
}
.cogs-summary-head {
  border-bottom: 1px solid var(--ink-300);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.cogs-summary-head .cogs-summary-lbl,
.cogs-summary-head .cogs-summary-val,
.cogs-summary-head .cogs-summary-pct {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--ink-500);
}
.cogs-summary-lbl { font-size: 12.5px; color: var(--ink-700); flex: 1 1 auto; }
.cogs-summary-val { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--ink-900); font-weight: 600; min-width: 110px; text-align: right; }
.cogs-summary-pct { font-size: 12px; font-variant-numeric: tabular-nums; color: var(--ink-500); font-weight: 600; min-width: 64px; text-align: right; }
.cogs-summary-row.is-landed {
  border-top: 2px solid var(--ink-300);
  border-bottom: none;
  margin-top: 2px;
  padding-top: 8px;
}
.cogs-summary-row.is-landed .cogs-summary-lbl,
.cogs-summary-row.is-landed .cogs-summary-val,
.cogs-summary-row.is-landed .cogs-summary-pct { font-weight: 800; color: var(--ink-950); }
.cogs-summary-row.is-total {
  border-top: 2px solid var(--brand-orange);
  border-bottom: none;
  margin-top: 4px;
  padding-top: 10px;
}
.cogs-summary-row.is-total .cogs-summary-lbl { font-weight: 800; color: var(--ink-950); font-size: 14px; }
.cogs-summary-row.is-total .cogs-summary-val { font-weight: 800; color: var(--brand-orange); font-size: 16px; }
.cogs-summary-row.is-total .cogs-summary-pct { font-weight: 800; color: var(--ink-950); font-size: 13px; }
/* Landed % is a subtotal, not a competing slice — brackets + quiet weight, overriding the is-landed emphasis. */
.cogs-summary-row.is-landed .cogs-summary-pct.cogs-pct-sub { font-weight: 600; color: var(--ink-500); }
.cogs-bom-table tbody tr.cogs-pct-row td.cogs-pct-sub { color: var(--ink-500); font-weight: 500; }
.cogs-pct-hint { font-weight: 400; color: var(--ink-400); font-size: 11px; }
.cogs-summary-note {
  margin: var(--space-2) 0 0;
  font-size: 11px;
  color: var(--ink-500);
  line-height: 1.4;
}

/* ── Filter chips (status / priority / department filters) ────────────────── */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  align-items: center;
  margin-bottom: var(--space-2);
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  min-height: 36px;
  border: 1.5px solid var(--ink-300);
  border-radius: var(--radius-full, 999px);
  background: transparent;
  color: var(--ink-600);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.filter-chip:hover {
  border-color: var(--brand-orange);
  color: var(--brand-orange);
  background: color-mix(in srgb, var(--brand-orange) 6%, transparent);
}
.filter-chip.active {
  border-color: var(--brand-orange);
  background: color-mix(in srgb, var(--brand-orange) 12%, transparent);
  color: var(--brand-orange);
  font-weight: 600;
}

.chip-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--ink-200);
  color: var(--ink-600);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
}
.filter-chip.active .chip-count {
  background: color-mix(in srgb, var(--brand-orange) 20%, transparent);
  color: var(--brand-orange);
}

.chip-sep {
  display: inline-block;
  width: 1px;
  height: 20px;
  background: var(--ink-200);
  margin: 0 var(--space-1);
  align-self: center;
}

/* ── Warranty Policies page — period display helpers ──────────────────────── */
.wp-period--lifetime {
  color: var(--success);
  font-weight: var(--fw-semibold);
}
.wp-period--none {
  color: var(--ink-400);
}

/* ── Support tickets — SO search result rows (link dispatch modal) ─────────── */
.so-result-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--ink-100);
  transition: background var(--dur-fast);
}
.so-result-row:last-child    { border-bottom: none; }
.so-result-row:hover         { background: var(--ink-50); }
.so-result-row:focus-visible { outline: 2px solid var(--brand-orange); outline-offset: -2px; }
.so-result-row.is-selected   { border-left-color: var(--brand-orange); background: var(--ink-50); }
.so-result-row .so-ref  { font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: var(--fw-semibold); min-width: 8rem; }
.so-result-row .so-name { flex: 1; font-size: var(--fs-sm); }
.so-result-row .so-date { font-size: var(--fs-sm); color: var(--ink-500); }

/* ── Permission matrix (Admin > Roles page) ────────────────────────────────── */
.roles-matrix { overflow-x: auto; }

.roles-matrix-table th.matrix-col,
.roles-matrix-table td.matrix-col {
  width: 72px;
  text-align: center;
  vertical-align: middle;
}

.roles-matrix-table .matrix-section-row td {
  background: var(--surface-dim, #eef2f7);
  font-weight: 600;
  font-size: var(--fs-sm);
  letter-spacing: 0.03em;
  padding: 5px 12px;
  color: var(--ink-700);
}

.roles-matrix-table .matrix-sub-label {
  padding-left: 24px;
  font-size: var(--fs-sm);
}

.roles-matrix-table .matrix-row-inactive td {
  color: var(--ink-400);
}

.roles-matrix-table input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--brand-orange);
}

.roles-matrix-table input[type="checkbox"]:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

/* ── Print — hide all app chrome; only the BOM overlay prints ─────────────── */
@media print {
  .no-print { display: none !important; }
  /* Hide the entire Blazor shell */
  body > .mud-layout,
  body > div > nav,
  body > div > aside,
  .topbar, .navbar, .sidebar, .list-pane, .detail-pane,
  .fullbleed-page, .page-toolbar, .bom-overlay-bg {
    display: none !important;
  }
  /* Unpin the overlay so it flows on the print page */
  .bom-overlay-doc {
    position: static !important;
    padding: 0 !important;
    max-width: 100% !important;
    overflow: visible !important;
    z-index: auto !important;
  }
  /* Ensure tables don't get clipped across pages */
  .bom-table { page-break-inside: auto; }
  .bom-table tr { page-break-inside: avoid; }
  .bom-section { page-break-inside: avoid; }
  .bom-total-strip { background: var(--ink-950) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Support Tickets + Customer Records two-pane layout (list rail + detail).
   These pages use .split-pane / .has-detail, which previously had NO CSS —
   so the detail rendered as a full-width block BELOW the table (off-screen),
   making the page look like "just a table, nothing actionable" (founder report
   2026-07-03). Mirrors the proven .vendors-shell.with-detail pattern.
   ───────────────────────────────────────────────────────────────────────── */
.split-pane {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  width: 100%;
}
.split-pane .detail-pane { display: none; }
.split-pane.has-detail .list-pane {
  flex: 0 0 340px;
  min-width: 300px;
  max-width: 340px;
}
.split-pane.has-detail .detail-pane {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  background: var(--paper);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-lg, 12px);
  position: sticky;
  top: var(--space-3);
  max-height: calc(100vh - 140px);
  overflow-y: auto;
}
@media (max-width: 900px) {
  .split-pane { flex-direction: column; }
  .split-pane.has-detail .list-pane { flex: none; min-width: 0; max-width: none; width: 100%; }
  .split-pane.has-detail .detail-pane { position: static; max-height: none; }
}
/* 2026-07-14 (founder) — Customer Records table must take the FULL page width and scroll
   horizontally. A flex child defaults to min-width:auto, so the wide opt-in column set pushed
   the pane instead of engaging .table-wrap's overflow-x: extra columns were clipped with no
   scrollbar. min-width:0 releases the pane; nowrap + ellipsis (U35) makes wide column sets
   overflow INTO the scroll instead of crushing every cell. */
.split-pane .list-pane { flex: 1 1 auto; min-width: 0; width: 100%; }
.split-pane .cpr-table th,
.split-pane .cpr-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 340px; }
/* 2026-07-14 (founder) — GROW, don't squeeze: with many columns ticked the 100%-width table
   compressed every cell instead of overflowing. max-content lets the table exceed the pane so
   .table-wrap's horizontal scrollbar actually engages; min-width keeps it full-bleed when narrow. */
.split-pane .cpr-table { width: max-content; min-width: 100%; }
/* 2026-07-14 (founder) — Customer Records detail: breathing room + visual hierarchy.
   The pane had zero left padding and label/value pairs rendered at equal weight. */
.split-pane .detail-pane .detail-header { padding: var(--space-3) var(--space-4) var(--space-2); }
.split-pane .detail-pane .detail-body { padding: var(--space-2) var(--space-4) var(--space-4); }
.split-pane .detail-section-title { font-size: 12px; letter-spacing: .4px; color: var(--ink-500);
  text-transform: none; border-bottom: 1px solid var(--ink-200); padding-bottom: 4px; }
.split-pane .detail-section .field-row label,
.split-pane .detail-section dt { color: var(--ink-500); font-size: 12px; }
.split-pane .detail-section dd { color: var(--ink-950); font-weight: 600; }

/* ─────────────────────────────────────────────────────────────────────────
   Support module (Customer Records + Support Tickets) — orphaned-class styling.
   These pages use class names that were never given CSS: .field only styles
   inside .form-section/.side-panel-body/etc (there is no bare .field), and
   .std-input / .detail-section / .detail-dl / .field-group / .field-label /
   .modal-body / several pills have no rule at all. Without these the support
   pages render with default browser inputs + flat sections (functional but
   unpolished). Scoped to support-only containers (.split-pane, .modal) so
   nothing else is affected. Modeled on .form-section .field (app.css:1502).
   Added 2026-07-03 after cross-validation of the support phases.
   ───────────────────────────────────────────────────────────────────────── */

/* Standard-size inputs (founder non-negotiable) on support pages + their modals */
.split-pane .field, .split-pane .std-input,
.split-pane select.field, .split-pane textarea.field,
.detail-pane .field, .detail-pane .std-input,
.detail-pane select.field, .detail-pane textarea.field,
.modal .field, .modal .std-input,
.modal select.field, .modal textarea.field {
  width: 100%;
  min-height: 38px;
  padding: 8px 12px;
  border: 1px solid var(--ink-300);
  border-radius: var(--radius-sharp, 4px);
  font-size: 14px;
  font-family: inherit;
  background: var(--paper);
  color: var(--ink-900);
  box-sizing: border-box;
  transition: border-color var(--dur-fast, .12s);
}
.split-pane textarea.field, .detail-pane textarea.field, .modal textarea.field { min-height: 60px; resize: vertical; }
.split-pane .field:focus, .split-pane .std-input:focus,
.detail-pane .field:focus, .detail-pane .std-input:focus,
.modal .field:focus, .modal .std-input:focus {
  outline: none;
  border-color: var(--brand-orange);
  box-shadow: none;
}

/* Detail sections + key/value lists (support-only class names) */
.detail-section { margin-bottom: var(--space-4); padding-bottom: var(--space-3);
                  border-bottom: 1px solid var(--ink-100); }
.detail-section:last-child { border-bottom: none; }
.detail-section > h4, .detail-section-title {
  margin: 0 0 var(--space-2); font-size: 13px; font-weight: 700;
  letter-spacing: .02em; color: var(--ink-700); }
.detail-dl { display: grid; grid-template-columns: minmax(96px, max-content) 1fr;
             gap: 4px var(--space-3); margin: 0; font-size: 14px; }
.detail-dl dt { color: var(--ink-500); }
.detail-dl dd { margin: 0; color: var(--ink-900); }

/* Form groups + labels */
.field-group { margin-bottom: var(--space-3); }
.field-label { display: block; margin-bottom: 4px; font-size: 13px;
               font-weight: 600; color: var(--ink-700); }

/* Modal body: give tall support modals their own scroll */
.modal-body { max-height: 68vh; overflow-y: auto; }

/* Inline validation messages */
.inline-error { background: color-mix(in srgb, var(--danger) 10%, transparent);
                color: var(--danger); border-radius: var(--radius-sharp, 4px);
                padding: 8px 12px; font-size: 13px; margin-bottom: var(--space-3); }
.inline-warn  { color: var(--warning); font-size: 13px; margin: 4px 0; }

/* Missing status pills used by the support pages */
.pill-danger, .pill-red    { background: color-mix(in srgb, var(--danger) 16%, transparent);  color: var(--ink-900); }
.pill-yellow               { background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--ink-900); }
.pill-grey                 { background: var(--ink-100); color: var(--ink-700); }

/* Support detail header + control rows (support-only class names) */
.detail-header { display: flex; align-items: center; gap: var(--space-2);
                 padding-bottom: var(--space-3); margin-bottom: var(--space-3);
                 border-bottom: 1px solid var(--ink-200); }
.detail-title-group { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.detail-ref { font-weight: 700; }
.detail-title { font-weight: 700; }
.detail-sub { color: var(--ink-500); font-size: 13px; margin-left: var(--space-2); }
.detail-desc { color: var(--ink-700); font-size: 14px; margin: 0 0 var(--space-3); }
.detail-actions { display: flex; gap: var(--space-2); margin-left: auto; }
.detail-body { display: flex; flex-direction: column; }
.status-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.note-compose { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.note-compose-actions { display: flex; gap: var(--space-2); align-items: center; }
.note-type-badge { font-size: 11px; font-weight: 700; text-transform: uppercase;
                   letter-spacing: .03em; color: var(--ink-500); }
.note-text { margin: 0; font-size: 14px; color: var(--ink-900); }

/* Small helpers on support pages */
.empty-row { text-align: center; color: var(--ink-500); padding: var(--space-4); font-size: 14px; }
small.sub, .sub { display: block; color: var(--ink-500); font-size: 12px; }

/* Support edit form: field-group as a grid cell + column-span helpers (2026-07-03 redesign) */
.form-grid .field-group { margin-bottom: 0; display: flex; flex-direction: column; min-width: 0; }
.form-grid .span-2    { grid-column: span 2; }
.form-grid .span-3    { grid-column: span 3; }
.form-grid .span-full { grid-column: 1 / -1; }

.help-text { font-size: 13px; color: var(--ink-500); margin: 0 0 var(--space-2); }

/* ── W0.2 2026-07-04 · SKU ↔ Sub-assembly link master (SkuSubAsmMatrixPanel, "SKU links" tab) ── */
.ssl-tiles { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; margin-bottom: var(--space-3); }
.ssl-tile { display: flex; flex-direction: column; gap: 2px; border: 1px solid var(--ink-200); border-radius: 10px; padding: var(--space-2) var(--space-4); background: var(--paper); }
.ssl-tile-label { font-size: 11px; color: var(--ink-600); }
.ssl-tile-value { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ssl-sku-col { min-width: 64px; }
.ssl-sku-head-btn { background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: var(--space-1) var(--space-2); border-radius: 6px; min-height: 40px; white-space: nowrap; }
.ssl-sku-head-btn:focus-visible { outline: 2px solid var(--brand-orange); outline-offset: 1px; }
.ssl-cell-mark { text-align: center; font-variant-numeric: tabular-nums; }
.ssl-row-partial td { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.ssl-kind-tag { font-size: 11px; color: var(--ink-600); }
.ssl-check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-1) var(--space-4); }
.ssl-check-row { display: flex; align-items: center; gap: var(--space-2); min-height: 40px; cursor: pointer; }
.ssl-confirm-panel { background: color-mix(in srgb, var(--warning) 14%, transparent); border: 1px solid var(--warning); border-radius: 8px; padding: var(--space-3) var(--space-4); margin-top: var(--space-3); }
.ssl-confirm-panel ul { margin: var(--space-1) 0 0; padding-left: var(--space-5); }
/* ── A1 2026-07-05 · transfer-order suggestion overlay (U47: floats, never shifts layout) ── */
.to-suggest {
  position: absolute; top: 100%; left: 0; z-index: 30;
  background: var(--paper); border: 1px solid var(--ink-300); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
  max-height: 260px; overflow-y: auto; margin-top: 2px;
  /* founder 2026-07-15 — was pinned right:0 to the 240px search field, so each GRN suggestion
     (ref + vendor + invoice + PO + date + amount) wrapped across ~4 lines. Widen past the input
     and keep each suggestion on ONE line. */
  min-width: 560px; max-width: 760px; width: max-content;
}
.to-suggest .dropdown-item {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── W0.2 2026-07-04 · Box kits panel (BoxMappings page) ── */
.bk-panel { border: 1px solid var(--ink-200); border-radius: 10px; background: var(--paper); margin-bottom: var(--space-3); overflow: hidden; }
.bk-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) var(--space-4) 0; }
.bk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--space-3); padding: var(--space-3) var(--space-4) var(--space-4); }
.bk-card { border: 1px solid var(--ink-200); border-radius: 10px; padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.bk-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.bk-lines { display: flex; flex-wrap: wrap; gap: 4px; }
.bk-card-foot { display: flex; gap: var(--space-4); font-size: 12px; align-items: center; flex-wrap: wrap; }

/* U47 2026-07-04 — .section-bar's base style (app.css:1754) uses NEGATIVE side margins to
   full-bleed inside side-panel bodies. Inside any .modal (whose body is an overflow container)
   that left overhang is CLIPPED — orange marker + first letters vanish ("FAB"→"AB").
   Neutralise the trick inside every modal so headings keep full side padding. */
.modal .section-bar { margin-left: 0; margin-right: 0; }

/* U46 — wide-family matrices (Zop 32 / ZorQ 16 cols) scroll horizontally; the identifying
   first column stays pinned with an OPAQUE background so rows never lose their label.
   (Header row pinning comes from hornback.initStickyThead; horizontal sticky is safe in Chromium.) */
.ssl-matrix th:first-child,
.ssl-matrix td:first-child {
  position: sticky; left: 0; z-index: 3;
  background: var(--paper);
  border-right: 1px solid var(--ink-200);
  box-shadow: 2px 0 4px rgba(0,0,0,.04);
}
.ssl-matrix tr:nth-child(even) td:first-child { background: var(--paper); }
.ssl-matrix .ssl-row-partial td:first-child { background: color-mix(in srgb, var(--warning) 12%, var(--paper)); }
/* group header rows (kind · size) — opaque, label stays readable while scrolling (first-child sticky applies) */
.ssl-matrix .ssl-group-row td {
  background: var(--ink-100);
  color: var(--ink-700);
  font-weight: 600;
  font-size: 12px;
  text-align: left;
  border-top: 1px solid var(--ink-200);
}
.ssl-size-header { font-size: 11px; font-weight: 600; color: var(--ink-600); margin: var(--space-2) 0 var(--space-1); }
.ssl-base-info { display: block; font-size: 11px; color: var(--ink-600); font-weight: 400; }

/* 2026-07-06 — topbar search switched to type="search" (autofill-pair fix); hide the native
   WebKit clear ✕ so it doesn't double up with the component's own clear button. */
.topbar-search-input::-webkit-search-cancel-button,
.topbar-search-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }

/* 2026-07-06 — switch-user (impersonation) banner. FIXED to the bottom edge, outside the
   .app-shell grid: zero layout shift and no phantom scrollbar on the 100vh shell. z 1200
   deliberately sits ABOVE modals (overlay z 200 / dialog z 201) so "Back to my account"
   is always clickable. Loud on purpose — never forget you're in someone else's view. */
.impersonation-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 6px var(--space-5);
  background: var(--warning);
  color: #fff;
  font-size: 13px;
  box-shadow: 0 -2px 6px rgb(0 0 0 / 25%);
}
.impersonation-banner .imp-msg strong { text-decoration: underline; text-underline-offset: 2px; }
.imp-return-form { margin: 0; }
.imp-return-btn {
  background: #fff;
  color: var(--warning);
  border: none;
  border-radius: var(--radius-md, 8px);
  padding: 4px 14px;
  font-size: 13px;
  font-weight: 600;
  min-height: 28px;
  cursor: pointer;
  white-space: nowrap;
}
.imp-return-btn:hover { background: #ffe9d6; }

/* 2026-07-06 — switch-user picker inside the profile dropdown. Small muted section label
   above the list of switchable users; the profile dropdown can scroll if the list is long. */
.dropdown-subhead {
  padding: 6px 14px 2px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-500, #6b7280);
}
.profile-dropdown .dropdown-body { max-height: 70vh; overflow-y: auto; }

/* 2026-07-06 — personalised welcome landing for users without dashboard access.
   Centred hero card; friendly, not a bare/empty page. Greets by first name. */
.welcome-hero {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--topbar-h, 44px) - 80px);
  padding: var(--space-6);
}
.welcome-card {
  text-align: center;
  max-width: 460px;
  padding: var(--space-6) var(--space-6) calc(var(--space-6) + 4px);
  background: var(--surface, #fff);
  border: 1px solid var(--border-200, #e5e7eb);
  border-radius: 16px;
  box-shadow: 0 6px 24px rgb(0 0 0 / 6%);
}
.welcome-emoji { font-size: 44px; line-height: 1; margin-bottom: var(--space-3); }
.welcome-title { font-size: 26px; font-weight: 700; margin: 0 0 var(--space-2); color: var(--ink-950, #111827); }
.welcome-role { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 0 0 var(--space-3); }
.welcome-brand { color: var(--ink-500, #6b7280); font-size: 14px; }
.welcome-sub { color: var(--ink-600, #4b5563); font-size: 14px; margin: 0; }

/* 2026-07-06 — notification bell (top-bar) + dropdown items. */
.notif-bell-btn { position: relative; }
.notif-badge {
  position: absolute; top: 0; right: 0;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  border-radius: 8px; box-shadow: 0 0 0 2px var(--ink-950);
}
.notif-markall {
  background: none; border: none; color: var(--brand-orange, #d9822b);
  font-size: 12px; font-weight: 600; cursor: pointer; padding: 0;
}
.notif-markall:hover { text-decoration: underline; }
.notif-item {
  display: block; padding: 10px 14px; border-bottom: 1px solid var(--ink-100);
  text-decoration: none; color: var(--ink-900);
}
.notif-item:hover { background: var(--ink-50); }
.notif-item.unread { background: color-mix(in srgb, var(--brand-orange, #d9822b) 8%, transparent); }
.notif-item.unread .notif-item-title::before {
  content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 6px;
  border-radius: 50%; background: var(--brand-orange, #d9822b); vertical-align: middle;
}
.notif-item-title { font-size: 13px; font-weight: 600; }
.notif-item-msg { font-size: 12px; color: var(--ink-600); margin-top: 2px; }
.notif-item-time { font-size: 11px; color: var(--ink-500); margin-top: 3px; }

/* 2026-07-06 founder hotfix — the HR-module pages (Employees, Onboarding, WorkerMasterPanel,
   MyLeaves, PayRuns, Reimbursements, one Inward dialog) shipped using .modal-backdrop/.modal-dialog,
   classes that existed in NO stylesheet (the U45 "ghost modal": the form rendered as plain divs at
   the BOTTOM of the page — founder: "add labour form comes at the bottom, invisible till scroll").
   Defined here as flex-centering aliases of the shared overlay/modal pattern so all 8 dialogs
   render as real centered modals without touching seven .razor files. */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .5);
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.modal-dialog {
  background: var(--paper, #fff);
  border-radius: 8px;
  padding: 24px;
  max-width: 560px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .3);
}

/* ── Tab panel inside a .fullbleed-page (founder 2026-07-07, Salary banner-overlap fix) ──
   Per-tab content under an in-page .entity-tabs strip. Fills the remaining column-flex height
   and scrolls internally; NO negative margins (that's what overlapped the page banner when
   tab panels reused .fullbleed-page). 4px side padding so focus rings aren't clipped. */
.tab-panel-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;   /* only inner .table-wrap scrolls horizontally — kills the double scrollbar (2026-07-09) */
  padding: var(--space-4) 4px var(--space-6);
}

/* ── Review-sweep fixes (2026-07-07 dual-lens UI review) ─────────────────────── */
/* .form-grid-2 was used on 5+ HR pages but never defined — every edit form silently
   collapsed to one column (Employees, Onboarding, WorkerMasterPanel, LeaveManagement,
   MyProfile). Defined here as the intended 2-col grid, same rhythm as .form-grid. */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3) var(--space-4);
  align-items: start;
}
@media (max-width: 720px) { .form-grid-2 { grid-template-columns: 1fr; } }

/* .modal-actions was used bare in 5 PurchaseOrders modals but only had scoped rules
   (.logistics-form .modal-actions) — buttons rendered unaligned. Base rule: */
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

/* .field-error existed in markup (WarrantyPolicies) with no CSS anywhere. */
.field-error {
  color: var(--danger);
  font-size: 12px;
  margin-top: 4px;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   Channel Sales vertical · S3 · 2026-07-11 — ASM MOBILE FIELD APP (/field/*)
   Mobile-first (base = phone, no media query). All classes prefixed `field-`. Tokens only.
   Desktop >=720px: the whole surface is centered to a 480px phone frame so the founder can
   demo it in a normal browser. Bottom tab bar is fixed and constrained to that frame.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* ── Shell ── */
.field-layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--canvas);
  font-family: var(--font-ui);
  color: var(--ink-700);
}
.field-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: var(--space-2) var(--space-4);
  background: var(--ink-950);
  color: var(--paper);
}
.field-brand {
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: var(--ls-snug);
  color: var(--paper);
  white-space: nowrap;
}
.field-brand .field-brand-accent { color: var(--brand-orange-300); }
.field-topbar-spacer { flex: 1 1 auto; }
.field-user {
  font-size: 13px;
  color: var(--ink-200);
  max-width: 40vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.field-logout-form { display: inline-flex; margin: 0; }
.field-logout {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--space-2);
  background: none;
  border: none;
  color: var(--brand-orange-300);
  font-size: 13px;
  font-weight: var(--fw-semibold);
  cursor: pointer;
}
.field-logout:hover { color: var(--paper); text-decoration: underline; }
.field-logout:focus-visible { outline: 3px solid var(--brand-orange-300); outline-offset: 2px; border-radius: var(--r-sm); }

.field-content {
  flex: 1 1 auto;
  padding: var(--space-4);
  padding-bottom: 84px;               /* clear the fixed tab bar */
  overflow-y: auto;
}

/* ── Bottom tab bar ── */
.field-tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 40;
  display: flex;
  background: var(--paper);
  border-top: 1px solid var(--ink-200);
  box-shadow: 0 -2px 8px rgba(15, 23, 42, .06);
}
.field-tab {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 56px;
  padding: var(--space-1) 2px;
  border-top: 3px solid transparent;
  color: var(--ink-500);
  font-size: 11px;
  font-weight: var(--fw-medium);
  text-decoration: none;
  text-align: center;
}
.field-tab:hover { color: var(--ink-700); }
.field-tab:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: -3px; }
.field-tab.active {
  border-top-color: var(--brand-orange);
  color: var(--ink-950);
  font-weight: var(--fw-semibold);
}
.field-tab-icon { font-size: 18px; line-height: 1; }
.field-tab-label { line-height: 1.1; }

/* ── Page header ── */
.field-page-header { margin-bottom: var(--space-4); }
.field-h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 26px;
  letter-spacing: var(--ls-snug);
  color: var(--ink-950);
}
.field-sub {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--ink-500);
}

/* ── Card ── */
.field-card {
  background: var(--paper);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-xl);         /* 12px */
  padding: var(--space-3);
  margin-bottom: var(--space-3);
}
.field-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}
.field-card-title {
  margin: 0;
  font-size: 15px;
  font-weight: var(--fw-semibold);
  color: var(--ink-900);
}
.field-card-city { font-size: 12px; color: var(--ink-500); }
.field-card-body { margin-top: var(--space-2); }
.field-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.field-row-between { justify-content: space-between; }
.field-muted { color: var(--ink-500); font-size: 13px; }
.field-strong { font-weight: var(--fw-semibold); color: var(--ink-900); }
.field-targets {
  display: flex;
  gap: var(--space-4);
  margin-top: var(--space-2);
  font-size: 13px;
}
.field-target-label { color: var(--ink-500); }
.field-target-value { font-weight: var(--fw-semibold); color: var(--ink-900); font-variant-numeric: tabular-nums; }

/* ── Section labels inside a page ── */
.field-section-label {
  margin: var(--space-4) 0 var(--space-2);
  font-size: 12px;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--ink-500);
  font-family: var(--font-mono);
}

/* ── Badges / pills ── */
.field-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: var(--fw-semibold);
  background: var(--ink-100);
  color: var(--ink-700);
}
.field-badge-reorder  { background: var(--accent-soft); color: var(--accent); }
.field-badge-collection { background: var(--warning-soft); color: var(--warning); }
.field-badge-onboarding { background: var(--brand-purple-soft); color: var(--brand-purple); }
.field-pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: var(--fw-semibold);
}
.field-pill-pending  { background: var(--ink-100); color: var(--ink-700); }
.field-pill-visited  { background: var(--success-soft); color: var(--success); }
.field-pill-skipped  { background: var(--danger-soft); color: var(--danger); }
.field-pill-warning  { background: var(--warning-soft); color: var(--warning); }
.field-pill-info     { background: var(--info-soft); color: var(--info); }

/* ── Chips (outcome / terms / mode selectors) ── */
.field-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-1) 0;
}
.field-chip {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--space-3);
  border: 1.5px solid var(--ink-300);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink-700);
  font-size: 13px;
  font-weight: var(--fw-medium);
  cursor: pointer;
}
.field-chip:hover { border-color: var(--ink-500); }
.field-chip:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.field-chip.selected {
  border-color: var(--brand-orange);
  background: var(--brand-orange-soft);
  color: var(--ink-950);
  font-weight: var(--fw-semibold);
}

/* ── Inputs (standard size — min-height 44px, full-width on mobile) ── */
.field-label {
  display: block;
  margin: var(--space-3) 0 var(--space-1);
  font-size: 13px;
  font-weight: var(--fw-medium);
  color: var(--ink-700);
}
.field-req { color: var(--danger); }
.field-input {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--ink-300);
  border-radius: var(--r-md);
  background: var(--paper);
  color: var(--ink-900);
  font-family: var(--font-ui);
  font-size: 15px;                     /* >=16px-ish avoids iOS zoom; 15 acceptable */
  box-sizing: border-box;
}
textarea.field-input { min-height: 76px; padding: var(--space-2) var(--space-3); resize: vertical; }
.field-input::placeholder { color: var(--ink-400); }
.field-input:focus-visible,
.field-input:focus {
  outline: 3px solid var(--brand-orange);
  outline-offset: 1px;
  border-color: var(--brand-orange);
}
.field-input.field-invalid { border-color: var(--danger); }
.field-error-text {
  margin: var(--space-1) 0 0;
  color: var(--danger);
  font-size: 12px;
  font-weight: var(--fw-medium);
}

/* ── Buttons (block, full-width, reuse .btn-primary/.btn-secondary colours) ── */
.field-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.field-actions .btn-primary,
.field-actions .btn-secondary,
.field-btn-block {
  width: 100%;
  min-height: 46px;
  justify-content: center;
}
.field-btn-inline {                    /* small inline action (Skip, change, add) */
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--space-3);
  border: 1.5px solid var(--ink-300);
  border-radius: var(--r-md);
  background: var(--paper);
  color: var(--ink-700);
  font-size: 13px;
  font-weight: var(--fw-medium);
  cursor: pointer;
}
.field-btn-inline:hover { border-color: var(--ink-500); }
.field-btn-inline:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.field-btn-inline.danger { color: var(--danger); border-color: var(--danger-soft); }

/* ── Stock stepper grid ── */
.field-stock-grid { display: flex; flex-direction: column; gap: var(--space-1); }
.field-stock-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) 0;
}
.field-stock-name {
  font-size: 14px;
  color: var(--ink-800);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.field-stepper { display: inline-flex; align-items: center; gap: var(--space-2); }
.field-step-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1.5px solid var(--ink-300);
  border-radius: var(--r-md);
  background: var(--paper);
  color: var(--ink-900);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.field-step-btn:hover { border-color: var(--brand-orange); }
.field-step-btn:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.field-step-btn:disabled { opacity: .4; cursor: not-allowed; }
.field-stepper-val {
  min-width: 40px;
  text-align: center;
  font-size: 16px;
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--ink-900);
}

/* ── Pace / budget meters ── */
.field-meter { margin-top: var(--space-2); }
.field-meter-track {
  height: 8px;
  border-radius: var(--r-full);
  background: var(--ink-150);
  overflow: hidden;
}
.field-meter-fill {
  height: 100%;
  border-radius: var(--r-full);
  background: var(--success);
}
.field-meter-fill.under  { background: var(--warning); }
.field-meter-fill.over   { background: var(--danger); }
.field-meter-caption {
  margin-top: var(--space-1);
  font-size: 12px;
  color: var(--ink-500);
}
.field-nudge {
  margin-top: var(--space-1);
  font-size: 12px;
  font-weight: var(--fw-medium);
  color: var(--warning);
}
.field-warn-banner {
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--r-md);
  background: var(--warning-soft);
  color: var(--warning);
  font-size: 13px;
  font-weight: var(--fw-medium);
}

/* ── Typeahead ── */
.field-typeahead { position: relative; }
.field-typeahead-list {
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: 0;
  border: 1px solid var(--ink-200);
  border-radius: var(--r-md);
  background: var(--paper);
  overflow: hidden;
}
.field-typeahead-item {
  display: block;
  width: 100%;
  text-align: left;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  background: none;
  border: none;
  border-bottom: 1px solid var(--ink-100);
  color: var(--ink-800);
  font-size: 14px;
  cursor: pointer;
}
.field-typeahead-item:last-child { border-bottom: none; }
.field-typeahead-item:hover { background: var(--ink-50); }
.field-typeahead-item:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: -3px; }
.field-typeahead-item .field-ta-code { color: var(--ink-500); font-size: 12px; }
.field-typeahead-add {
  color: var(--accent);
  font-weight: var(--fw-semibold);
}

/* ── Beat suggestions strip ── */
.field-suggest-strip {
  display: flex;
  gap: var(--space-2);
  overflow-x: auto;
  padding-bottom: var(--space-1);
}
.field-suggest-card {
  flex: 0 0 auto;
  width: 180px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-lg);
  background: var(--paper);
}
.field-suggest-name {
  font-size: 13px;
  font-weight: var(--fw-semibold);
  color: var(--ink-900);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Legend (expense caps) ── */
.field-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-2);
  font-size: 12px;
  color: var(--ink-500);
}
.field-legend-item { white-space: nowrap; }

/* ── KPI tiles (scorecard) ── */
.field-kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
}
.field-kpi {
  background: var(--paper);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-xl);
  padding: var(--space-3);
}
.field-kpi-label { font-size: 12px; color: var(--ink-500); }
.field-kpi-value {
  margin-top: 2px;
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--ink-950);
  font-variant-numeric: tabular-nums;
}
.field-kpi-sub { font-size: 12px; color: var(--ink-500); margin-top: 2px; }
.field-kpi-sub.good { color: var(--success); }
.field-kpi-sub.warn { color: var(--warning); }
.field-kpi-sub.bad  { color: var(--danger); }

/* ── Empty state ── */
.field-empty {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  color: var(--ink-500);
}
.field-empty-icon { font-size: 32px; }
.field-empty-title { margin-top: var(--space-2); font-size: 15px; font-weight: var(--fw-semibold); color: var(--ink-700); }
.field-empty-sub { margin-top: var(--space-1); font-size: 13px; color: var(--ink-500); }

/* ── Time in/out stamp buttons ── */
.field-time-row { display: flex; gap: var(--space-2); }
.field-time-btn {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-height: 52px;
  padding: var(--space-2);
  border: 1.5px solid var(--ink-300);
  border-radius: var(--r-md);
  background: var(--paper);
  color: var(--ink-700);
  cursor: pointer;
}
.field-time-btn:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.field-time-btn.stamped { border-color: var(--success); background: var(--success-soft); color: var(--success); }
.field-time-btn-label { font-size: 12px; }
.field-time-btn-value { font-size: 15px; font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }

/* ── Week day tabs use the shared .entity-tabs; no override needed ── */

/* ── Desktop: phone-frame the whole surface ── */
@media (min-width: 720px) {
  .field-layout {
    max-width: 480px;
    margin: 0 auto;
    min-height: 100vh;
    box-shadow: var(--shadow-lg);
  }
  .field-tabbar {
    left: 50%;
    right: auto;
    width: 480px;
    transform: translateX(-50%);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   My Space · adaptive self-service (2026-07-11) — SAME desktop routes + look; a phone-quality
   view below 720px. Width-switch only: no new layouts, no route changes. All classes `msp-`.
   `.msp-page` marks each self-service page's root content; `.app-shell:has(.msp-page)` collapses
   the shell on phones (mirrors the existing :has() switches at v32-theme.css:104 / app.css:686).
   The M3 bottom navigation bar (.msp-tabbar) mirrors the .field-tab look (v32-theme.css:2205+):
   active = orange top-border indicator + --ink-950 text (NO orange fill — U2 stays intact).
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* ── M3 bottom navigation bar — hidden on desktop, shown on phone (<720px) ── */
.msp-tabbar {
  display: none;                       /* desktop default — flipped to flex below 720px */
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 90;                         /* above content; below modal-overlay (200) + toast (300) */
  background: var(--paper);            /* opaque */
  border-top: 1px solid var(--ink-200);
  box-shadow: 0 -2px 8px rgba(15, 23, 42, .06);
  padding-bottom: env(safe-area-inset-bottom);   /* clear the phone home indicator */
}
.msp-tab {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 56px;                    /* ≥48px touch target */
  padding: var(--space-1) 2px;
  border-top: 3px solid transparent;   /* active indicator lives here — no filled-orange competitor */
  color: var(--ink-500);
  font-size: 11px;
  font-weight: var(--fw-medium);
  text-decoration: none;
  text-align: center;
}
.msp-tab:hover { color: var(--ink-700); }
.msp-tab:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: -3px; }
.msp-tab.active {
  border-top-color: var(--brand-orange);
  color: var(--ink-950);
  font-weight: var(--fw-semibold);
}
.msp-tab-icon { font-size: 18px; line-height: 1; }
.msp-tab-label { line-height: 1.1; }

/* ── Responsive utilities (desktop defaults; flipped in the phone block) ── */
.msp-only { display: none; }           /* mobile-only content (card lists): hidden ≥720px, block below */
/* .msp-hide-m: visible on desktop by default; set to display:none below 720px (defined in the phone block) */

/* ── Mobile card-list helpers ── */
.msp-card-btn {                        /* a whole-card that acts as a row-select (mirrors row @onclick) */
  display: block;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.msp-card-btn.selected { border-color: var(--brand-orange); }
.msp-card-btn:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; }
.msp-card-line {                       /* one label:value row inside a mobile card */
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-1);
  font-size: 13px;
}
.msp-card-line .msp-card-k { color: var(--ink-500); }
.msp-btn-row { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
.msp-btn-row > button { flex: 1 1 0; min-height: 48px; justify-content: center; }

/* ═══════════════════════ Phone view (<720px) ═══════════════════════ */
@media (max-width: 719.98px) {
  /* Shell → single column; sidebar hides; topbar (bell + avatar) stays reachable. */
  .app-shell:has(.msp-page) {
    grid-template-columns: 1fr;
    grid-template-areas:
      "topbar"
      "main";
  }
  .app-shell:has(.msp-page) .app-sidebar { display: none; }
  .app-shell:has(.msp-page) .app-main {
    padding: var(--space-3);
    padding-bottom: 88px;              /* clear the fixed .msp-tabbar */
    overflow-x: hidden;
  }

  /* Turn the mobile chrome on. */
  .msp-tabbar { display: flex; }
  .msp-only   { display: block; }
  .msp-hide-m { display: none; }

  /* Full-bleed self-service pages (MyProfile, LeaveApprovals) flow as one scroll — drop the
     desktop fixed-height + negative-margin breakout so nothing is clipped on a phone. */
  .msp-page.fullbleed-page {
    height: auto;
    overflow: visible;
    margin: 0;
    padding: 0;
  }

  /* List+detail pages (MyPayslips, Reimbursements) stack: list first, detail below. */
  .msp-page .list-detail-layout {
    flex-direction: column;
    height: auto;
    overflow: visible;
  }
  .msp-page .list-detail-layout .list-pane {
    max-width: none !important;        /* beat the desktop inline max-width:280px (MyPayslips) */
    width: 100%;
    flex: 0 0 auto;
    border-right: none;
    border-bottom: 1px solid var(--ink-200);
  }
  .msp-page .list-detail-layout .detail-pane.open { width: 100%; }

  /* Forms → single column; file-upload trigger labels reach the 48px touch target. */
  .msp-page .form-grid { grid-template-columns: 1fr; }
  .msp-page .form-section label.btn-secondary {
    min-height: 48px;
    display: inline-flex;
    align-items: center;
  }

  /* MyProfile: two-column kv grid → single column (photo block already centers). */
  .msp-page .view-grid { grid-template-columns: 1fr; }

  /* KPI rows → compact tiles. Cards WITHOUT an inline min-width (MyPayslips 3-up grid) shrink to
     fit 390px; cards with an inline min-width (MyProfile/MyAdvances flex-wrap) keep wrapping 2-up. */
  .msp-page .kpi-card  { min-width: 0; padding: var(--space-2); }
  .msp-page .kpi-value { font-size: 18px; }

  /* Detail panes: the wide claim-lines table already scrolls inside its .table-wrap
     (overflow-x:auto); belt-and-braces so a stray wide child can't push the page sideways. */
  .msp-page .detail-pane { overflow-x: auto; }

  /* Tables that stay visible on a phone (MyPayslips month list + payslip detail, MyAdvances
     recovery schedule): compact horizontal padding so 3–4 columns fit 390px, and ≥48px rows so
     the tappable month list meets the touch-target minimum. */
  .msp-page .data-table td,
  .msp-page .data-table th { padding-left: var(--space-2); padding-right: var(--space-2); }
  .msp-page .data-table td { height: 48px; }
}


/* ── Attachment visual confirmation (field app + My Space claims) · 2026-07-11 ──
   An attached photo must be unmistakable: thumbnail of the actual image inside a
   success-tinted chip (founder: "no visual confirmation that photo is attached"). */
.attach-confirm {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background: var(--success-soft, color-mix(in srgb, var(--success) 12%, transparent));
    border: 1px solid var(--success);
    border-radius: 8px;
    max-width: 100%;
}
.attach-thumb {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--ink-300);
    background: var(--paper);
    flex: 0 0 auto;
}
.attach-check { color: var(--success); font-weight: 700; font-size: 13px; }
.attach-name  { font-size: 12px; color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; display: inline-block; }
.attach-file-pill { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: 1px solid var(--ink-300); border-radius: 999px; font-size: 12px; background: var(--paper); }

/* ══════════════════════════════════════════════════════════════════════════════
   OFFER LETTER GENERATOR · Phase 1 · 2026-07-13
   Chrome (editor layout, clause editor, in-hand card, pills) uses app tokens.
   The letter paper (.offer-paper) is a self-contained legal document — its colours
   are the attorney-vetted brand values from Mansi's tool, kept VERBATIM for PDF
   fidelity (per the build brief: print fidelity beats app tokens INSIDE the letter).
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── List extras ── */
.offer-list-controls { display: flex; justify-content: flex-end; margin-bottom: var(--space-2); }
.data-table th.num-col, .data-table td.num-col { text-align: right; font-variant-numeric: tabular-nums; }
.offer-badge {
    font-size: 10px; padding: 2px 8px; border-radius: 999px; font-weight: 600; margin-left: 4px;
    vertical-align: middle; background: color-mix(in srgb, var(--brand-orange) 14%, var(--paper)); color: var(--ink-950);
}

/* ── Status / clause pills (dark ink on a light token tint → readable contrast) ── */
.pill.offer-pill-draft    { background: color-mix(in srgb, var(--ink-500) 16%, var(--paper));     color: var(--ink-950); }
.pill.offer-pill-sent     { background: color-mix(in srgb, var(--brand-orange) 16%, var(--paper)); color: var(--ink-950); }
.pill.offer-pill-accepted { background: color-mix(in srgb, var(--success) 20%, var(--paper));      color: var(--ink-950); }
.pill.offer-pill-declined { background: color-mix(in srgb, var(--danger) 16%, var(--paper));       color: var(--ink-950); }
.pill.offer-pill-edited   { background: color-mix(in srgb, var(--warning) 18%, var(--paper));      color: var(--ink-950); }
.pill.offer-pill-hidden   { background: color-mix(in srgb, var(--danger) 14%, var(--paper));       color: var(--ink-950); }

/* ── Editor two-pane layout ── */
.offer-editor {
    display: grid; grid-template-columns: minmax(360px, 460px) 1fr;
    gap: var(--space-6); align-items: start;
}
.offer-form-pane { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.offer-preview-pane { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.offer-preview-label { align-self: flex-start; font-size: 12px; color: var(--ink-500); margin-bottom: var(--space-3); }
@media (max-width: 1100px) { .offer-editor { grid-template-columns: 1fr; } }

/* ── In-hand calculator card (screen only — never in PDF) ── */
.offer-inhand {
    margin-top: var(--space-4); border: 1px solid var(--border); border-radius: 10px;
    padding: var(--space-3) var(--space-4); background: var(--paper);
}
.offer-inhand-title {
    font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--ink-500); margin-bottom: var(--space-2);
}
.oih-row { display: flex; justify-content: space-between; gap: var(--space-3); padding: 3px 0; font-size: 12px; color: var(--ink-700); }
.oih-ded { color: var(--danger); }
.oih-total { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 6px; font-weight: 700; color: var(--ink-950); font-size: 13px; }
.oih-annual { color: var(--ink-500); font-size: 11px; }
.oih-val { font-variant-numeric: tabular-nums; }
.oih-note { font-size: 10.5px; color: var(--ink-500); margin-top: 6px; line-height: 1.5; }

/* ── Custom rows / footnotes / add buttons ── */
.ocr-wrap, .ofn-wrap { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--space-2); }
.ocr-row { display: grid; grid-template-columns: 1fr 120px 36px; gap: 6px; align-items: center; }
.ofn-row { display: flex; gap: 6px; align-items: flex-start; }
.ofn-row textarea { flex: 1; }
.offer-add-btn {
    font-size: 12px; color: var(--brand-orange); background: none;
    border: 1px dashed var(--brand-orange); border-radius: 6px; padding: 6px 12px; cursor: pointer; width: 100%;
}
.offer-add-btn:hover { background: color-mix(in srgb, var(--brand-orange) 8%, var(--paper)); }
.offer-add-btn:focus-visible { outline: 2px solid var(--brand-orange); outline-offset: 2px; }

/* ── Clause editor ── */
.offer-clause-head-row { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.offer-clause-editor { display: flex; flex-direction: column; gap: 6px; }
.oce-item { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.oce-item.oce-modified { border-color: var(--warning); }
.oce-item.oce-hidden { opacity: .6; }
.oce-header { display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: pointer; background: var(--paper); -webkit-user-select: none; user-select: none; }
.oce-header:hover { filter: brightness(0.98); }
.oce-header:focus-visible { outline: 2px solid var(--brand-orange); outline-offset: -2px; }
.oce-num { font-size: 11px; font-weight: 700; color: var(--brand-orange); min-width: 18px; }
.oce-title { font-size: 12.5px; font-weight: 600; flex: 1; color: var(--ink-950); }
.oce-body { padding: 10px; border-top: 1px solid var(--border); }
.oce-textarea { min-height: 120px; line-height: 1.6; font-size: 12.5px; }
.oce-subs { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.oce-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }

/* ── Master template editor modal ── */
.offer-template-modal { max-width: 760px; width: 92vw; }
.offer-template-modal .modal-body { max-height: 70vh; overflow-y: auto; }
.otm-item { border: 1px solid var(--border); border-radius: 8px; padding: 10px; margin-bottom: 10px; }
.otm-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.otm-title { flex: 1; }
.otm-active { display: flex; align-items: center; gap: 4px; font-size: 12px; white-space: nowrap; }
.otm-body { min-height: 120px; line-height: 1.6; font-size: 12.5px; }
.otm-actions { display: flex; justify-content: flex-end; margin-top: 6px; }

/* ══════════════════════════════════════════════════════════════════════════════
   THE LETTER PAPER — #offerPaper / .offer-paper. Verbatim port of the tool's
   <style> #offerPaper block. Local --ol-* vars = attorney-vetted brand colours
   (legal doc; --ol-accent #E8650A is the exact vetted hue — do NOT re-tokenise).
   ══════════════════════════════════════════════════════════════════════════════ */
.offer-paper {
    --ol-accent: #E8650A;          /* legal-doc brand orange, verbatim from the vetted tool */
    --ol-accent-light: #FDF1E9;
    --ol-dark: #1A1A1A; --ol-mid: #555; --ol-light: #888; --ol-border: #E2E2E2;
    background: #fff; width: 100%; max-width: 800px; padding: 3rem 3.5rem;
    box-shadow: 0 4px 32px rgba(0,0,0,.09); border-radius: 4px;
    font-family: 'Inter', 'Hanken Grotesk', system-ui, sans-serif;
    font-size: 11.5px; line-height: 1.9; color: #222;
}
.offer-paper .lh { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1.75rem; padding-bottom: 1.25rem; border-bottom: 2px solid var(--ol-accent); }
.offer-paper .lh-logo { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.offer-paper .lh-logo-img { height: 50px; width: auto; }
.offer-paper .lh-logo-sub { font-size: 9.5px; color: var(--ol-light); letter-spacing: .04em; margin-top: 1px; }
.offer-paper .lh-addr { font-size: 10px; color: var(--ol-light); text-align: right; line-height: 1.65; }
.offer-paper .lh-addr a { color: var(--ol-accent); text-decoration: none; }
.offer-paper .date-line { text-align: right; font-size: 10.5px; color: var(--ol-light); margin-bottom: 1.25rem; }
.offer-paper .to-block { margin-bottom: 1.25rem; line-height: 1.7; }
.offer-paper .to-block strong { font-size: 12.5px; }
.offer-paper .subject-line { font-weight: 600; font-size: 12px; margin-bottom: .5rem; color: var(--ol-dark); }
.offer-paper .sep { height: 1px; background: var(--ol-border); margin: 1rem 0; }
.offer-paper p { margin: .5rem 0; font-size: 11.5px; }
.offer-paper .clause-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--ol-accent); margin: 1.25rem 0 .35rem; padding-left: 10px; border-left: 3px solid var(--ol-accent); }
.offer-paper .sub-clause { margin: .35rem 0 .35rem 1rem; padding-left: .75rem; border-left: 2px solid var(--ol-border); font-size: 11px; color: #333; line-height: 1.8; }
.offer-paper .ann-title { text-align: center; font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ol-dark); margin: 1.5rem 0 .2rem; }
.offer-paper .ann-sub { text-align: center; font-size: 10.5px; color: var(--ol-mid); margin-bottom: .75rem; }
.offer-paper .sal-t { width: 100%; border-collapse: collapse; font-size: 11px; margin: .5rem 0; }
.offer-paper .sal-t th { background: var(--ol-accent); color: #fff; padding: 5px 8px; text-align: left; font-weight: 600; font-size: 10px; letter-spacing: .04em; text-transform: uppercase; }
.offer-paper .sal-t th:last-child, .offer-paper .sal-t td:last-child { text-align: right; }
.offer-paper .sal-t th:nth-child(2), .offer-paper .sal-t td:nth-child(2) { text-align: right; }
.offer-paper .sal-t td { padding: 4px 8px; border-bottom: 1px solid var(--ol-border); font-variant-numeric: tabular-nums; }
.offer-paper .sal-indent { padding-left: 16px; }
.offer-paper .sal-t tr.section-row td { background: var(--ol-accent-light); font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--ol-accent); }
.offer-paper .sal-t tr.custom-row td { background: #fafff7; font-style: italic; }
.offer-paper .sal-t tr.subtotal-row td { font-weight: 600; background: #fafafa; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; }
.offer-paper .sal-t tr.grand-row td { font-weight: 700; font-size: 12px; background: var(--ol-accent-light); color: var(--ol-accent); border-top: 2px solid var(--ol-accent); }
.offer-paper .footnotes { font-size: 10px; color: var(--ol-light); margin-top: .5rem; line-height: 1.7; }
.offer-paper .sig-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 2rem; font-size: 11px; }
.offer-paper .sig-line { border-top: 1px solid var(--ol-border); margin-bottom: .5rem; padding-top: .35rem; color: var(--ol-light); }
.offer-paper .sig-right { text-align: right; }
.offer-paper .sig-img { height: 58px; width: auto; display: block; margin: 8px 0 4px auto; }
.offer-paper .sig-muted { color: var(--ol-light); }

@media print {
    .offer-editor { display: block; }
    .offer-form-pane, .offer-preview-label { display: none; }
    .offer-paper { box-shadow: none; border-radius: 0; max-width: 100%; padding: 0; }
    .offer-paper .clause-head { page-break-after: avoid; }
    .offer-paper .sal-t, .offer-paper .sig-grid { page-break-inside: avoid; }
    .offer-paper p { orphans: 3; widows: 3; }
}
