/* erp/static/erp/css/theme2.css */
/* ============================================================
   Relylok ERP – NEW CORE COMPONENT THEME (layered on top of theme.css)
   - Only NEW universal building blocks live here (erp-*)
   - Page-specific styles can use page-* later
   - This file is self-contained (has its own :root + body defaults)
   ============================================================ */

/* Global uppercase for text inputs/textareas/selects.
   Email fields excluded (they're lowercase). */
input[type="text"],
input[type="search"],
input:not([type]),
textarea,
select {
  text-transform: uppercase;
}
input[type="email"] {
  text-transform: lowercase;
}

/* Case-sensitive fields — opt out of the global uppercase via data-no-upper.
   Pairs with the matching JS skip in partials/footer.html upperize(). Anything
   marked [data-no-upper] preserves case both visually and on submission, so
   what the user sees in the field is what's actually stored. Used today for
   e-invoice IRN/QR fields; available for any future case-sensitive input. */
input[data-no-upper],
textarea[data-no-upper] {
  text-transform: none;
}

/* Static-text uppercaser for print letterhead — labels (Phone, Email, Web,
   GSTIN, etc.) and the company info read uppercase consistent with the rest
   of the ERP. Case-sensitive content (email address, website URL, IRN, Ack
   No, QR data) opts out via .lowercase or .preserve-case spans. */
.print-letterhead {
  text-transform: uppercase;
}
.print-letterhead .lowercase {
  text-transform: lowercase;
}
.print-letterhead .preserve-case {
  text-transform: none;
}

/* Library/data tables display all cell content in uppercase.
   Email cells excluded via .cell-email class.
   Case-preserving cells (URLs, slugs, tokens) opt out via .cell-no-upper. */
@media screen {
  .erp-table tbody td {
    text-transform: uppercase;
  }
  .erp-table tbody td.cell-email,
  .erp-table tbody td .cell-email {
    text-transform: lowercase;
  }
  .erp-table tbody td.cell-no-upper,
  .erp-table tbody td .cell-no-upper {
    text-transform: none;
  }
}

/* ---------- Root: colours, fonts, basic sizing ---------- */
/* These mirror your existing palette so everything stays consistent */

:root {
  /* Colours */
  /* Brand colours */
  --blue-main: #0f4aa1;                       /* primary actions, links */
  --table-header-bg: #2f6fbf;                 /* solid table-header bar — softer than blue-main so it doesn't dominate across the ~56 tables (15-07-2026) */
  --blue-light: #e3edf9;                      /* hover backgrounds, highlights */
  --blue-soft: #e3f2fd;                       /* soft blue for selection highlights in dropdowns/rows */
  --blue-selected: #bbdefb;                   /* selected row highlight (darker than soft) */
  --red-accent: #c80000;                      /* destructive actions, errors */

  /* Semantic action colours */
  --green-main: #28a745;                      /* success, finalize, approve */
  --green-light: #e5f6e8;                     /* success badge background */
  --green-soft: #e8f5e9;                      /* soft green for SO row backgrounds */
  --green-selected: #c8e6c9;                  /* selected green row (darker than soft) */
  --teal-main: #17a2b8;                       /* print, export actions */
  --teal-light: #e7f6f8;                      /* teal hover background */
  --grey-main: #6c757d;                       /* info, utility, disabled */
  --grey-light: #f1f3f5;                      /* grey hover background */
  --yellow-main: #ffc107;                     /* draft, warning, pending */
  --yellow-light: #fff9c4;                    /* yellow badge background */
  --yellow-border: #f0c75e;                   /* darker yellow for badge/chip borders */
  --yellow-text: #8a6500;                     /* dark amber text on yellow bg */
  --yellow-highlight: #fff700;                /* highlighter-pen yellow — vivid, marker-like */
  --green-text: #1a7f37;                      /* dark green text on green bg */
  --red-light: #f4dcdc;                       /* danger badge background */
  --red-text: #9a2222;                        /* dark red text on red-light bg */
  --red-border: #d05050;                      /* mid-red for badge borders */

  /* Status-badge categorisation tokens (Apr-30 — chip-style sweep) */
  --indigo-main: #4f46e5;                     /* "approved" — distinct from submitted's blue */
  --indigo-light: #ebebfa;                    /* approved chip background */
  --purple-main: #7c3aed;                     /* "frozen / sealed" — locked / e-invoice filed */
  --purple-light: #f1ebfd;                    /* locked chip background */

  /* Backgrounds & surfaces */
  --bg-main: #f4f6f9;
  --card-bg: #ffffff;
  --border-soft: #d4d9e2;
  --border-light: #eee;                       /* lighter border for dropdown items, table cells */
  --surface-light: #f5f5f5;                   /* light surface for terms/summary backgrounds */
  --surface-muted: #f8f9fa;                   /* very light grey for totals row backgrounds */
  --surface-subtle: #f9f9f9;                  /* subtle grey for commercial text backgrounds */
  --surface-faded: #fafafa;                   /* faded surface for table label cells */

  /* Text colours */
  --text-main: #1f2933;
  --text-muted: #6b7280;
  --text-soft: #6b7280;                       /* alias for muted */
  --text-faded: #999;                         /* faded text for drag handles, empty states */
  --text-secondary: #666;                     /* secondary text for descriptions, hints */
  --text-dark: #333;                          /* dark text for hover states */
  --text-on-primary: #ffffff;                 /* white text on solid buttons */
  --text-link: #1a4f8b;                       /* link/action text in dropdowns */
  --text-error-light: #c00;                   /* light error text for inline messages */
  --text-italic: #555;                        /* italic text for amount words */

  /* Message colours */
  --message-success-background-color: #e5f6e8;
  --message-success-color: #166534;
  --message-success-border: #86efac;
  --message-error-background-color: #fee2e2;
  --message-error-color: #b91c1c;
  --message-error-border: #b91c1c;

  /* Extra surface / state colours derived from hard-coded values */
  --pill-bg: #f1f5f9;                         /* pill/tag background */
  --field-readonly-bg: #f3f4f6;               /* readonly field background */
  --danger-hover-bg: #ffecec;                 /* red button hover background */
  --hover-light: #f0f0f0;                     /* light hover for LQP buttons */

  /* Module accent palette — 15 colours organised by family.
     Used by .mod-pill (foveal pill next to page title) and the page-
     header left stripe (peripheral channel). Saturated values picked
     to read clearly at favicon size + on white card backgrounds.
     Family hint: warm = sales/outbound; cool = purchase/inbound;
     accents = production/QA; slate = masters & settings. */

  /* Sales / Outbound (warm) */
  --module-qtn:      #f59e0b;  /* QTN — amber (modern punchy) */
  --module-so:       #dc2626;  /* SO  — pure red (separated from PI orange) */
  --module-pi:       #ea580c;  /* PI  — true orange (distinct from QTN amber) */
  --module-qpl:      #9b59b6;  /* QPL — purple */
  --module-sd:       #27ae60;  /* SD  — green */
  --module-cndn:     #c2185b;  /* CN/DN — magenta */

  /* Purchase / Inbound (cool) */
  --module-rfq:      #5d6d7e;  /* RFQ — slate */
  --module-po:       #2c3e50;  /* PO  — dark steel */
  --module-rjw:      #b8956a;  /* RJW — light brown / khaki-tan */
  --module-grn:      #5d4037;  /* GRN — saddle brown (distinct from RJW terracotta) */
  --module-stk:      #117864;  /* STK — Stock — deep teal */

  /* Production / QA (accents) */
  --module-wo:       #16a085;  /* WO  — teal */
  --module-ic:       #9ca3af;  /* IC  — light grey (calibration / metrology feel) */

  /* Masters & Settings */
  --module-cust:     #2980b9;  /* Customer master — blue */
  --module-supplier: #0e7490;  /* Supplier master — cyan (split from CUST blue) */
  --module-cfg:      #52525b;  /* settings/config masters — neutral grey (distinct from RFQ slate) */


  /* Typography */
  /* Open Sans is named FIRST and explicitly, and installed on the server
     (20-08-2026). Everything after it is fallback only.

     Why the font is named rather than left to the stack: on Linux none of
     system-ui / Segoe UI / Roboto / Helvetica Neue exist, and fontconfig does
     not report a family missing - it silently substitutes. Prints came out in
     whatever the system default happened to be.

     Why Open Sans specifically. Selawik (Microsoft's metric-compatible Segoe UI
     stand-in) was tried first and rejected: it has NO italic face at all, so the
     italic "amount in words" line on every invoice, quotation, SO, PI and credit
     note silently rendered upright. Noto Sans was tried next and rejected by
     Ashim on sight: its capital I carries top and bottom bars at every weight,
     which Segoe UI does not, and part numbers are full of capital I. Open Sans
     has a plain capital I, a real drawn italic, and is Apache-licensed.
     Verified by extracting the embedded fonts from a real generated PDF and
     rendering the glyphs - not by trusting a font downloaded separately. */
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* Font sizes */
  --font-size-7xs: 7px;
  --font-size-6xs: 7.5px;
  --font-size-5xs: 8px;
  --font-size-4xs: 9px;
  --font-size-xxxs: 10px;
  --font-size-xxs: 11px;
  --font-size-xs: 12px;
  --font-size-sm: 13px;
  --font-size-md: 14px;
  --font-size-lg: 16px;
  --font-size-xl: 18px;
  --font-size-2xl: 22px;
  --font-size-3xl: 25px;
  --font-size-4xl: 28px;
  --font-size-5xl: 34px;
  --font-size-6xl: 40px;

  /* Force all form elements to inherit the system font */
  input, select, textarea, button {
  font-family: var(--font-sans);
}

  /* Radii + shadow — unified to one value (3px) for consistency.
     Originals preserved in comments so we can soften back if needed. */
  --radius-soft: 3px;          /* was 6px */
  --radius-card: 3px;          /* was 12px - now matches --radius-soft */
  --radius-small: 2px;         /* was 3px - small radius for LQP buttons */
  --shadow-soft: 0 4px 10px rgba(15, 74, 161, 0.06);
  --shadow-dropdown: 0 4px 10px rgba(0,0,0,0.1);  /* dropdown box shadow */
  --shadow-modal: 0 4px 20px rgba(0,0,0,0.3);     /* modal box shadow */
  --shadow-drag: 0 4px 12px rgba(0,0,0,0.2);      /* dragging row shadow */
  --overlay-bg: rgba(0,0,0,0.5);                  /* modal overlay background */
}

/* Screen uses the base :root values above (originals). No screen-only override.
   Previous Claude had added a +1px screen bump yesterday; we stepped through
   -1 / -2 / -1.5 today and decided to go back to the original base values. */

/* ---------- Global reset & base body ---------- */
/* You already have this in theme.css; we repeat here so theme2 is stand-alone.
   When both are loaded, values are effectively identical. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-sans);
  font-size: var(--font-size-md);
  color: var(--text-main);
  background-color: var(--bg-main);
}

/* ---------- Page main wrapper ---------- */
/* Generic content area – same concept as home page's main div */
.erp-page-main {
  min-height: 100vh;
  padding: 14px 22px 22px;
  display: flex;
  flex-direction: column;
}

/* ============================================================
   HEADER BLOCK (white container with title + back button)
   Used by: All pages
   ============================================================ */

/* White rounded container that sits below the browser top */
.erp-header-container {
  background-color: var(--card-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-card);   /* was 12px hard-coded */
  padding: 16px 16px;          /* adjust this to control header height */
  margin: 4px auto 12px auto;
  box-shadow: 0 2px 4px rgba(15, 30, 67, 0.08);
  /* width to be specified in each page */
}

/* Flex row inside the header: title on left, actions (Back/Logout) on right */
.erp-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* Header title text (we’ll reuse this everywhere) */
.erp-header-title {
  margin: 0;
  font-size: var(--font-size-xl);
  font-weight: 600;
  color: var(--blue-main);
}

/* Optional right block if we ever want stacked text on the right */
.erp-header-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: var(--font-size-xs);
  color: var(--text-muted);
}

/* ============================================================
   ERP BUTTON SYSTEM (pill-shaped)
   Used for Back to Home, Save, etc.
   ============================================================ */

/* Optional row wrapper to align primary page buttons */
.erp-button-row {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}

/* Sticky-bottom variant for long forms — bar sticks to viewport bottom
   while you scroll, settles into its natural position when you reach
   the form's end. Trial: applied to one form only; revert if it doesn't
   feel right. position:sticky requires no overflow:hidden on ancestors;
   the standard erp-page-main → erp-page-inner → erp-card chain is fine. */
.erp-button-row.erp-button-row-sticky {
  position: sticky;
  bottom: 0;
  background: var(--card-bg);
  padding: 10px 14px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  box-shadow: 0 2px 4px rgba(15, 30, 67, 0.08);
  z-index: 50;
  align-items: center;
}

/* Base ERP button – everything builds from this */
.erp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: var(--font-size-sm);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    transform 0.08s ease;
}

.erp-btn:active {
  transform: translateY(1px);
}

/* ==========================================================
   BUTTON COLORS
   - Primary (blue solid): Save, Generate, Search
   - Success (green solid): Finalize, Submit, Approve
   - Secondary (blue outline): Back, Cancel, Clear, View, Edit
   - Danger (red outline): Delete, Archive, Amend, Reject
   - Teal (teal outline): Print, Export
   - Grey (grey outline): Info, LQP, Utility
   ========================================================== */

/* Primary – solid blue */
.erp-btn-primary {
  background-color: var(--blue-main);
  color: var(--text-on-primary);
  border-color: var(--blue-main);
}
.erp-btn-primary:hover {
  filter: brightness(1.05);
}

/* Success – solid green */
.erp-btn-success {
  background-color: var(--green-main);
  color: var(--text-on-primary);
  border-color: var(--green-main);
}
.erp-btn-success:hover {
  filter: brightness(1.05);
}

/* Secondary – blue outline (View, Edit, Back, Cancel, Clear) */
.erp-btn-secondary {
  background-color: var(--card-bg);
  color: var(--blue-main);
  border-color: var(--blue-main);
}
.erp-btn-secondary:hover {
  background-color: var(--blue-light);
}

/* Danger – red outline (Delete, Archive, Amend, Reject) */
.erp-btn-danger {
  background-color: var(--card-bg);
  color: var(--red-accent);
  border-color: var(--red-accent);
}
.erp-btn-danger:hover {
  background-color: var(--danger-hover-bg);
}

/* Teal – teal outline (Print, Export) */
.erp-btn-teal {
  background-color: var(--card-bg);
  color: var(--teal-main);
  border-color: var(--teal-main);
}
.erp-btn-teal:hover {
  background-color: var(--teal-light);
}

/* Grey – grey outline (Info, LQP, Utility) */
.erp-btn-grey {
  background-color: var(--card-bg);
  color: var(--grey-main);
  border-color: var(--grey-main);
}
.erp-btn-grey:hover {
  background-color: var(--grey-light);
}

/* ==========================================================
   BUTTON SIZES
   ========================================================== */

/* Extra-small – for inline/toggle buttons */
.erp-btn-xs {
  padding: 4px 10px;
  font-size: var(--font-size-xs);
}

/* Row – smallest, for table action buttons */
.erp-btn-row {
  padding: 2px 6px;
  font-size: var(--font-size-xs);
  line-height: 1.2;
  margin-right: 4px;
}

/* Disabled state for all .erp-btn variants. */
.erp-btn:disabled,
.erp-btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* Per-row three-dot menu (⋯) — replaces the flat list of per-row action
   icons in library/master tables. The cell stays at ~36px wide; the menu
   renders actions status-gated, same as before. */
.row-menu-btn {
  width: 28px; height: 28px;
  border: 1px solid transparent;
  border-radius: var(--radius-soft);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; line-height: 1;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  padding: 0;
}
.row-menu-btn:hover,
.row-menu-btn.open {
  background: var(--blue-light);
  border-color: var(--blue-main);
  color: var(--blue-main);
}
td.action-cell { text-align: center; padding: 4px; position: relative; }
.row-menu {
  display: none;
  position: absolute;
  top: calc(100% + 2px); right: 6px;
  background: var(--card-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  box-shadow: var(--shadow-dropdown);
  z-index: 100;
  min-width: 140px;
  padding: 4px 0;
  white-space: nowrap;
  text-align: left;
}
.row-menu.open { display: block; }
.row-menu-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  color: var(--text-main);
  text-decoration: none;
  font-size: var(--font-size-sm);
  cursor: pointer;
  white-space: nowrap;
  border: none; background: transparent; width: 100%;
  text-align: left;
  font-family: inherit;
  text-transform: none;
  letter-spacing: normal;
}
.row-menu-item:hover { background: var(--blue-light); color: var(--blue-main); }
.row-menu-item.danger:hover { background: #fce4e4; color: var(--red-accent); }
.row-menu-item svg { flex-shrink: 0; }
/* External-link indicator for menu items that open in a new tab
   (View / Print / Open — read-only actions). Sits right next to the
   label text (small space, no auto-margin push to row's right edge). */
/* External-link indicator — Lucide square-arrow-out-up-right rendered
   via CSS mask so a single SVG asset is reused everywhere it appears.
   `--icon-external-link` holds the path data; selectors below apply it
   as a mask, with `currentColor` filling the shape so the arrow inherits
   the link's text colour automatically. */
:root {
  --icon-external-link: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6"/><path d="m21 3-9 9"/><path d="M15 3h6v6"/></svg>');
}
.row-menu-item[target="_blank"]::after {
  content: "";
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin-left: 3px;
  background-color: currentColor;
  -webkit-mask-image: var(--icon-external-link);
          mask-image: var(--icon-external-link);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  vertical-align: -0.1em;
  opacity: 0.85;
}
.row-menu-divider { height: 1px; background: var(--border-soft); margin: 4px 0; }
.row-menu form { margin: 0; display: block; }

/* Row-menu nested submenu — used by SD library 3-dot to host the full
   print list as a fly-out (Print ▸). Lives inside .row-menu, renders
   to the right by default, flips to left if clipped at viewport edge.
   ============================================================ */
.row-submenu-parent {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  color: var(--text-main);
  font-size: var(--font-size-sm);
  cursor: pointer;
  white-space: nowrap;
}
.row-submenu-parent:hover {
  background: var(--blue-light);
  color: var(--blue-main);
}
.row-submenu-parent::after {
  content: "\25B8"; /* ▸ right-pointing triangle */
  margin-left: auto;
  padding-left: 8px;
  opacity: 0.7;
  font-size: 0.95em;
}
.row-submenu-parent.is-open {
  background: var(--blue-soft);
  color: var(--blue-main);
}
.row-submenu {
  display: none;
  position: absolute;
  left: 100%; top: -5px;
  background: var(--card-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  box-shadow: var(--shadow-dropdown);
  min-width: 200px;
  padding: 4px 0;
  z-index: 101;
  white-space: nowrap;
  margin-left: -1px;
  /* Long fly-outs cap to viewport with internal scroll. JS sets the
     numeric max-height at open time; this rule is the safety floor. */
  overflow-y: auto;
  max-height: calc(100vh - 40px);
}
.row-submenu-parent.is-open .row-submenu { display: block; }
.row-submenu-parent.flip-left .row-submenu {
  left: auto; right: 100%;
  margin-left: 0; margin-right: -1px;
}
.row-submenu-parent.flip-up .row-submenu {
  top: auto; bottom: -5px;
}
.row-submenu a {
  display: flex; align-items: center;
  padding: 6px 12px;
  color: var(--text-main);
  text-decoration: none;
  font-size: var(--font-size-sm);
  cursor: pointer;
  white-space: nowrap;
}
.row-submenu a:hover {
  background: var(--blue-light);
  color: var(--blue-main);
}
.row-submenu a[target="_blank"]::after {
  content: "";
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin-left: 4px;
  background-color: currentColor;
  -webkit-mask-image: var(--icon-external-link);
          mask-image: var(--icon-external-link);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  vertical-align: -0.1em;
  opacity: 0.85;
}
.row-submenu .dd-divider {
  height: 1px;
  background: var(--border-soft);
  margin: 4px 0;
}
.row-submenu .open-all {
  font-style: italic;
  color: var(--blue-main);
}

/* ============================================================
   QUICK LINKS — modules-page External Links flyout (B2)
   Each category renders as a .mod-link row inside the Quick Links
   card; the row owns a .ql-submenu that flies out to the right with
   the category's links. Click toggles open/close (touch-friendly);
   hover also opens (mouse). JS handles edge-detect for flip-left.
   ============================================================ */
.ql-cat-wrap {
  position: relative;
}
.ql-cat-toggle {
  cursor: pointer;
  user-select: none;
}
.ql-cat-toggle::after {
  content: "\25B8"; /* ▸ */
  margin-left: auto;
  padding-left: 8px;
  opacity: 0.7;
  font-size: 0.95em;
  color: var(--text-soft);
}
.ql-cat-toggle.is-open {
  background: var(--blue-soft);
  color: var(--blue-main);
}
.ql-cat-toggle.is-open::after {
  color: var(--blue-main);
  opacity: 1;
}
.ql-cat-count {
  margin-left: 6px;
  color: var(--text-soft);
  font-size: var(--font-size-xs);
  font-weight: normal;
}
.ql-submenu {
  display: none;
  position: absolute;
  left: 100%; top: -4px;
  margin-left: -1px;
  width: max-content;
  max-width: 380px;
  background: var(--card-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  box-shadow: var(--shadow-dropdown);
  z-index: 200;
  padding: 4px 0;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}
.ql-cat-wrap:hover .ql-submenu,
.ql-cat-wrap.is-open .ql-submenu { display: block; }
.ql-cat-wrap.flip-left .ql-submenu {
  left: auto; right: 100%;
  margin-left: 0; margin-right: -1px;
}
.ql-cat-wrap.flip-up .ql-submenu {
  top: auto; bottom: -4px;
}
.ql-submenu a {
  display: flex; align-items: center;
  padding: 7px 12px;
  color: var(--text-main);
  text-decoration: none;
  font-size: var(--font-size-sm);
  white-space: nowrap;
}
.ql-submenu a:hover {
  background: var(--blue-light);
  color: var(--blue-main);
}
.ql-submenu a[target="_blank"]::after {
  content: "";
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin-left: auto;
  padding-left: 8px;
  box-sizing: content-box;
  background-color: currentColor;
  -webkit-mask-image: var(--icon-external-link);
          mask-image: var(--icon-external-link);
  -webkit-mask-size: 0.95em 0.95em;
          mask-size: 0.95em 0.95em;
  -webkit-mask-position: right center;
          mask-position: right center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  vertical-align: -0.1em;
  opacity: 0.85;
}

/* ============================================================
   HOME PAGE PANELS + TOOL BUTTONS
   These are universal enough to reuse for other menus as well,
   so they get erp- prefix. We also keep .btn-tool / .pill aliases.
   ============================================================ */

/* Grid for the three main panels: Masters / Operations / Tools */
.erp-panel-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding-bottom: 10px;
  align-items: stretch;
}

.erp-panel-grid .erp-panel {
  height: 100%;                      /* fill the grid cell */
  display: flex;                     /* vertical layout */
  flex-direction: column;            /* header top → links bottom */
}

@media screen and (max-width: 800px) {
  .erp-panel-grid {
    grid-template-columns: 1fr;
  }
}

/* Individual panel card (Masters / Operations / Tools) */
.erp-panel {
  background-color: var(--card-bg);
  border-radius: var(--radius-card);   /* was 12px hard-coded */
  border: 0.75px solid var(--border-soft);
  padding: 20px 30px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}

/* Panel title (e.g. “Masters”) */
.erp-panel-title {
  font-size: var(--font-size-xl);
  font-weight: 600;
  margin: 0 0 8px 0;
  padding-bottom: 4px;
  border-bottom: 0.75px solid var(--border-soft);
  color: var(--blue-main);
}

/* Inline variant – used as section heading inside cards (no bottom margin/border) */
.erp-section-title {
  font-size: var(--font-size-lg);
  font-weight: 600;
  margin: 0;
  color: var(--blue-main);
}

/* Remove bullets + extra margins from UL lists inside panels */
.erp-panel ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.erp-panel ul li {
  margin-bottom: 6px;
}

/* "Pill" – grey rounded label for not-yet-implemented features */
.erp-pill,
.pill { /* .pill kept as alias for existing HTML */
  display: inline-block;
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius-soft);
  font-size: var(--font-size-md);
  text-align: center;
  background-color: var(--pill-bg);
  border: 1px dashed var(--blue-main);
  color: var(--text-main);
  box-sizing: border-box;
}

/* Tool navigation buttons inside Home panels */
.erp-btn-tool,
.btn-tool { /* .btn-tool kept as alias so old pages don’t break */
  display: inline-block;
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius-soft);
  font-size: var(--font-size-md);
  text-align: center;
  background-color: var(--card-bg);
  border: 1px solid var(--blue-main);
  color: var(--blue-main);
  text-decoration: none; /* keeps the url from being underlined*/
  box-sizing: border-box;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    transform 0.08s ease;
}

.erp-btn-tool:hover,
.btn-tool:hover {
  background-color: var(--blue-light);
}

.erp-btn-tool:active,
.btn-tool:active {
  transform: translateY(1px);
}

/* Card divider utility */
.erp-card-divider {
  margin-top: 12px;
  border-top: 1px solid var(--border-soft);
  width: 100%;
}

/* Standard ERP section card (used in Company/Customer/etc.) */
.erp-card {
  background-color: var(--card-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  padding: 10px 14px;
  margin-bottom: 10px;
  box-shadow: 0 2px 4px rgba(15, 30, 67, 0.08);
}

/* Top-spacing utility for stacked cards on settings / form pages.
   Replaces ad-hoc style="margin-top: 12px" inline styles. */
.erp-card-mt { margin-top: 12px; }

/* Larger padding variant — used on launcher pages (Modules, Settings home)
   where each card lists nav links and benefits from extra breathing room. */
.erp-card-pad-lg { padding: 18px 20px; }

/* Form-row label with a right-side action link (e.g. "Get Rate ↗" beside an
   Exchange Rate input). Sits ABOVE the input, using the same vertical slot as
   the bare label so the input remains aligned with sibling form-rows. */
.form-label-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.form-label-action {
  font-size: var(--font-size-xs);
  color: var(--blue-main);
  text-decoration: none;
  white-space: nowrap;
}
.form-label-action:hover { text-decoration: underline; }

/* ============================================================
   PAGINATION — used below library tables (Part Master + future)
   - Page nav buttons (First / Prev / Next / Last) are themed blue
   - Page info span shows "Page N of M (X total)"
   - Go-to-page form jumps directly without N clicks
   ============================================================ */
.erp-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  padding: 8px 0;
  font-size: var(--font-size-xs);
  flex-wrap: wrap;
  /* Closes the table off. Without this the strip sits flush against the last
     row with no line, no gap and no background of its own, so the card's white
     bleeds through and reads as if it covers the table's borders.
     --border-soft is the same colour the table's own cell borders use, so the
     line reads as the grid's closing edge rather than a new element. */
  border-top: 1px solid var(--border-soft);
}
.erp-page-link {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--blue-main);
  color: var(--blue-main);
  border-radius: var(--radius-soft);
  text-decoration: none;
  background-color: var(--card-bg);
  transition: background-color 0.12s ease;
}
.erp-page-link:hover {
  background-color: var(--blue-light);
}
.erp-page-info {
  padding: 4px 10px;
  color: var(--text-muted);
}
.erp-page-goto {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  flex-wrap: nowrap;
  white-space: nowrap;
}
.erp-page-goto label {
  margin: 0;
  color: var(--text-muted);
  white-space: nowrap;
}
/* Higher specificity than .erp-card input[type="number"] { width: 100% }.
   Width auto-scales by digit count of the last page via .pg-d-{N} modifier
   set in the template (e.g. .pg-d-2 for "of 47", .pg-d-4 for "of 1234"). */
.erp-card .erp-page-goto input[type="number"],
.erp-page-goto input[type="number"] {
  width: 36px;
  padding: 4px 6px;
  text-align: center;
  flex: 0 0 auto;
}
.erp-page-goto input.pg-d-2 { width: 40px; }
.erp-page-goto input.pg-d-3 { width: 48px; }
.erp-page-goto input.pg-d-4 { width: 58px; }
.erp-page-goto input.pg-d-5 { width: 70px; }

/* In-form line-search: red border on the input when the typed term
   matches zero rows in the items table. Match-state feedback (G border)
   is intentionally omitted — match is already visible via row highlighting
   + scroll-to-first-match, so a green border would just duplicate signal.
   Class toggled by each form's line-search JS handler. */
.erp-card input.search-no-match,
input.search-no-match {
  border: 2px solid var(--red-accent) !important;
  outline: none;
}

/* Part Master in-table search "exists" badge — three-state Y/P/N indicator
   shown next to the search input. */
.pm-search-badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-soft);
  color: white;
  font-weight: 600;
  font-size: var(--font-size-xs);
  white-space: nowrap;
}
.pm-search-badge--y { background: var(--green-main); }
.pm-search-badge--p { background: var(--yellow-main, #e6a700); }
.pm-search-badge--n { background: var(--red-accent); }
.erp-page-goto .erp-page-info {
  white-space: nowrap;
  padding: 4px 4px;
}

/* ==========================================================
   MODULE IDENTITY — pill + page-header stripe
   Two reinforcing channels of "you are in module X" identity.

   Usage on a page template:
     <body class="mod-so">                 ← drives stripe colour
       …
       <h1 class="erp-header-title">
         <span class="mod-pill">SO</span>  ← foveal pill at title
         Sale Order Library
       </h1>

   Each body.mod-X selector binds --mod-current to the module's accent
   var so .mod-pill and the header stripe can both pick it up without
   needing per-module duplicates of the actual style rules.
   ========================================================== */
body.module-qtn      { --mod-current: var(--module-qtn); }
body.module-so       { --mod-current: var(--module-so); }
body.module-pi       { --mod-current: var(--module-pi); }
body.module-qpl      { --mod-current: var(--module-qpl); }
body.module-sd       { --mod-current: var(--module-sd); }
body.module-cndn     { --mod-current: var(--module-cndn); }
body.module-rfq      { --mod-current: var(--module-rfq); }
body.module-po       { --mod-current: var(--module-po); }
body.module-rjw      { --mod-current: var(--module-rjw); }
body.module-grn      { --mod-current: var(--module-grn); }
body.module-stk      { --mod-current: var(--module-stk); }
body.module-wo       { --mod-current: var(--module-wo); }
body.module-ic       { --mod-current: var(--module-ic); }
body.module-cust     { --mod-current: var(--module-cust); }
body.module-supplier { --mod-current: var(--module-supplier); }
body.module-cfg      { --mod-current: var(--module-cfg); }

/* Pill — small coloured badge that sits inline next to the page title.
   Inherits its colour from body.mod-X. Falls back to text-muted if no
   module class is set so it never crashes silently in styled pages. */
.mod-pill {
  display: inline-block;
  background: var(--mod-current, var(--text-muted));
  color: #fff;
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  vertical-align: 3px;
  margin-right: 10px;
  white-space: nowrap;
}

/* Page-header left stripe — peripheral channel. Only applies to the
   .erp-header-container (not every card on the page) so it stays
   contained to the page-identity zone. */
body[class*="module-"] .erp-header-container {
  border-left: 10px solid var(--mod-current, transparent);
}

/* ==========================================================
   STATUS BAR + INLINE DOC CHAIN
   Mounted in the Status Bar of doc forms (e.g. shipping_document.html).
   Left cluster: Status badge + Amendment + Last updated.
   Right cluster (auto-pushed by flex): doc-chain trail of module-coloured
   pills walking the lineage Qtn → SO → QPL → SD → CN/DN.
   ========================================================== */
/* Status bar uses 3 named grid areas (left / center / right) so each
   element lands in its semantic slot regardless of source order OR
   how many children are actually rendered. Forms with only 2
   children (status-bar-left + doc-chain-counts) keep left-aligned
   status info on the left and right-aligned doc-chain on the right;
   the empty center area collapses harmlessly. Forms with 3 children
   (SD: + doc-no-chip in middle) get the chip true-centered. */
.status-bar-row {
  margin-top: 12px;
  display: grid;
  grid-template-areas: "left center right";
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
}
.status-bar-row > .status-bar-left   { grid-area: left;  justify-self: start; }
.status-bar-row > .doc-no-chip       { grid-area: center; justify-self: center; }
.status-bar-row > .doc-chain-counts  { grid-area: right; justify-self: end; }
.status-bar-left {
  display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}

/* ============================================================
   UNIFIED CHIP PALETTE — three tokens derived from --mod-current
   via color-mix. Mirrors the visual treatment of the big
   "Shipment Against: LUT" badge (pale bg / dark text / mid
   border) but applied at any module color via a single rule.
   Use these inside ANY chip-style badge that needs to read
   crisply on a white card while announcing module identity.
   ============================================================ */
body[class*="module-"] {
  /* Derive in oklch so the perceived hue stays stable when darkened.
     srgb mixing produces olive/brown for warm colours (amber → olive,
     orange → brown) — the chip text drifted off the module identity.
     oklch keeps amber readable as amber, orange as orange, etc. */
  --mod-chip-bg:     color-mix(in oklch, var(--mod-current) 14%, white);
  --mod-chip-text:   color-mix(in oklch, var(--mod-current) 60%, black);
  --mod-chip-border: color-mix(in oklch, var(--mod-current) 70%, white);
}

/* Doc-no chip — sits in the middle of the status bar on every doc form
   so the doc number is the eye-magnet. Compact form of the big
   "Shipment Against" badge: same label/value split (muted label + bold
   value) but sized to fit the status bar without growing its height. */
.doc-no-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-soft);
  background: var(--mod-chip-bg, #f5f5f5);
  color: var(--mod-chip-text, var(--text-muted));
  border: 2px solid var(--mod-chip-border, var(--border-soft));
  white-space: nowrap;
  letter-spacing: 0.3px;
}
.doc-no-chip-label {
  font-size: var(--font-size-lg);
  opacity: 0.75;
  font-weight: 500;
}
.doc-no-chip-value {
  font-size: var(--font-size-lg);
  font-weight: 700;
}

/* Status badge INSIDE a document form's status bar only (Ashim, 20-08-2026:
   both header badges wanted bigger). Deliberately scoped to .status-bar-row
   rather than bumping .status-badge itself — that class is used in 28
   templates, including every library's status column and line-level markers
   in so.html and shipping_document.html. Enlarging it globally would undo the
   library table uniformity done 19-08. Do NOT fold this into .status-badge. */
.status-bar-row .status-badge {
  font-size: var(--font-size-sm);
  padding: 5px 11px;
}

/* ============================================================
   STATUS CHIP — semantic-color variant of doc-no-chip pattern
   for selection-confirmation indicators (e.g. LUT vs Tax-Paid
   on the SD Shipment Against picker). Same compact label/value
   split, but colours come from semantic tokens (success / warn /
   danger), not module identity. */
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 3px 12px;
  border-radius: var(--radius-soft);
  border: 2px solid;
  white-space: nowrap;
  letter-spacing: 0.3px;
}
.status-chip-label {
  font-size: var(--font-size-xs);
  opacity: 0.75;
  font-weight: 500;
}
.status-chip-value {
  font-size: var(--font-size-sm);
  font-weight: 700;
}
.status-chip--success {
  background: var(--green-light);
  color: var(--green-text);
  border-color: var(--green-main);
}
.status-chip--warning {
  background: var(--yellow-light);
  color: var(--yellow-text);
  border-color: var(--yellow-border);
}
.status-chip--danger {
  background: var(--red-light);
  color: var(--red-text);
  border-color: var(--red-border);
}

/* Form row that places radios on the left + status chip on the right */
.form-row-radios-with-chip {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 6px 0;
  font-size: var(--font-size-xs);
  flex-wrap: wrap;
}

/* Inline radio group inside a form-row — overrides the bold/block label
   styling from .form-row label so each radio choice reads as inline option
   text, not a field label. Padding matches a normal text input's height so
   the radios align vertically with sibling fields in the same grid row.
   Used by the SD Shipment Against picker and anywhere else that lays
   radios horizontally. */
.radio-group {
  display: flex;
  gap: 28px;
  align-items: center;
  flex-wrap: wrap;
  padding: 6px 0;
  font-size: var(--font-size-sm);
}
.form-row .radio-group label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0 4px;
  font-weight: normal;
  font-size: var(--font-size-sm);
  cursor: pointer;
}
.form-row .radio-group input[type="radio"] {
  margin: 0;
  vertical-align: middle;
}

/* Inline chain counts — one button per upstream/downstream doc type.
   Replaces the visual chain trail (didn't scale to 5+ docs per stage).
   Each button: [TYPE] N where N is the count. Hover → popover lists the
   doc numbers as click-through links. Module-coloured per doc-type. */
.doc-chain-counts {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 12px;
}
.doc-chain-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px 2px 4px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid var(--border-soft);
  font-size: 11px;
  white-space: nowrap;
  cursor: pointer;
  position: relative;
  transition: box-shadow 0.12s;
}
.doc-chain-count:hover,
.doc-chain-count:focus-within {
  box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}
.doc-chain-count-type {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 8px;
  background: var(--text-muted);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.4px;
}
.doc-chain-count-num {
  font-weight: 700;
  color: var(--text-main);
  padding-right: 2px;
}
/* Module-colour the type chip per doc type */
/* ==========================================================
   SO LIBRARY — split-delivery batch dates in CDD column
   Each batch on its own line within the cell, with status chip-tone:
   done = muted green strikethrough, partial = yellow, pending = neutral.
   ========================================================== */
.so-batch-line {
  display: inline-block;
  font-size: 11px;
  padding: 1px 0;
}
.so-batch-done {
  color: var(--green-main);
  text-decoration: line-through;
  opacity: 0.75;
}
.so-batch-partial {
  color: var(--yellow-main);
  font-weight: 600;
}
.so-batch-pending {
  color: var(--text-main);
}
.so-delivery-badge-late { font-size: 10px; color: var(--red-accent); }
.so-delivery-badge-pending { font-size: 10px; color: var(--yellow-main); }
.so-delivery-badge-on-time { font-size: 10px; color: var(--green-main); }
/* Inline icon next to badge text — sits on the text x-line, inherits colour */
.badge-icon {
  display: inline-block;
  vertical-align: middle;
  margin-bottom: 1px;
  flex-shrink: 0;
}
.so-closure-badge {
  font-size: 10px;
  color: var(--orange-main, #e67e22);
  font-weight: 600;
}


/* ==========================================================
   PRE-SUBMIT CONFIRM MODAL (SD)
   Lists every side-effect a Submit click will trigger — doc-number
   allocation, qty_shipped updates, auto-close cascades, etc. Reuses
   the .lqp-modal-overlay infrastructure for the modal frame; styles
   here are submit-summary-specific.
   ========================================================== */
.sd-submit-intro {
  background: var(--yellow-light, #fff7e1);
  border-left: 4px solid var(--yellow-border, #f0c75e);
  padding: 8px 12px;
  border-radius: 0 4px 4px 0;
  margin-bottom: 14px;
  font-size: 12px;
  color: var(--yellow-text, #8a6500);
}
.sd-submit-intro strong { color: var(--text-main); }

.sd-submit-section { margin-bottom: 14px; }
.sd-submit-section-title {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.6px;
  font-weight: 700; color: var(--text-muted);
  margin-bottom: 6px; padding-bottom: 4px;
  border-bottom: 1px solid var(--border-soft);
}
.sd-submit-list { list-style: none; margin: 0; padding: 0; }
.sd-submit-item {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 8px; border-radius: 3px;
  font-size: 12px;
}
.sd-submit-item:hover { background: var(--surface-faded); }
.sd-submit-bullet {
  flex-shrink: 0; width: 8px; height: 8px;
  border-radius: 50%; margin-top: 5px;
  background: var(--text-muted);
}
.sd-submit-sev-block .sd-submit-bullet { background: var(--red-accent); }
.sd-submit-sev-warn .sd-submit-bullet { background: var(--yellow-text, #8a6500); }
.sd-submit-sev-normal .sd-submit-bullet { background: var(--green-main); }
.sd-submit-sev-info .sd-submit-bullet { background: var(--blue-main); }
.sd-submit-sev-stub .sd-submit-bullet { background: #c0c8d3; }
.sd-submit-sev-block .sd-submit-text strong { color: var(--red-accent); }
.sd-submit-sev-stub .sd-submit-text { opacity: 0.6; font-style: italic; }

.sd-submit-text { flex: 1; }
.sd-submit-text strong { color: var(--text-main); }
.sd-submit-detail {
  display: block; font-size: 11px;
  color: var(--text-muted); margin-top: 2px;
}
.sd-submit-foot-hint {
  font-size: 11px; color: var(--text-muted); font-style: italic;
}

/* Modal width variant — smaller than the default 1050px (used for
   confirm modals that don't need the full library width). */
.lqp-modal.lqp-modal-sm { max-width: 720px; }

/* Modal footer with split layout — left text + right action buttons */
.lqp-modal-footer-split {
  display: flex; justify-content: space-between; align-items: center;
}
.lqp-modal-footer-actions {
  display: flex; gap: 8px;
}


/* ==========================================================
   DOC DIFF VIEW (amendment comparison)
   Side-by-side OLD vs NEW comparison page. Used by so_diff.html;
   pattern reusable for SD/QPL/Qtn/PI diffs once the trial proves out.
   Diff-specific layout + change-highlight primitives. Common patterns
   (cards, tables, badges) come from existing theme2 classes.
   ========================================================== */
.doc-diff-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
}
.doc-diff-col-header {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 10px; padding-bottom: 8px;
  border-bottom: 2px solid var(--border-soft);
}
.doc-diff-col-header.doc-diff-col-old { border-bottom-color: var(--text-muted); }
.doc-diff-col-header.doc-diff-col-new { border-bottom-color: var(--blue-main); }
.doc-diff-col-title { font-size: 14px; font-weight: 700; }
.doc-diff-col-sub { font-size: 11px; color: var(--text-muted); }

.doc-diff-field-row {
  display: grid; grid-template-columns: 160px 1fr;
  padding: 5px 6px; font-size: 12px; align-items: baseline;
  border-bottom: 1px solid #f0f0f0;
}
.doc-diff-field-row:last-child { border-bottom: none; }
.doc-diff-field-label {
  color: var(--text-muted); font-weight: 600; font-size: 11px;
}
.doc-diff-field-val { color: var(--text-main); }
.doc-diff-field-row.doc-diff-changed {
  background: #fff7e1;
  border-left: 3px solid #f0c75e;
  padding-left: 4px;
}

/* Highlight for inline value-changed text (within a cell) */
.doc-diff-cell-changed {
  background: #ffe5b3;
  padding: 1px 4px;
  border-radius: 3px;
  font-weight: 700;
}

/* Summary strip + chips */
.doc-diff-summary {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  font-size: 12px; margin-bottom: 14px;
}
.doc-diff-summary-right { margin-left: auto; }
.doc-diff-amount { font-weight: 700; color: var(--text-main); }
.doc-diff-amount-up { color: var(--green-main); }
.doc-diff-amount-down { color: var(--red-accent); }

.doc-diff-chip {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
}
.doc-diff-chip-added { background: #d1fae5; color: #1a7f37; }
.doc-diff-chip-changed { background: #fff7e1; color: #8a6500; }
.doc-diff-chip-removed { background: #fbe2e5; color: #c80000; }
.doc-diff-chip-none { background: var(--surface-faded); color: var(--text-muted); }

.doc-diff-section-label {
  font-size: 11px; text-transform: uppercase; font-weight: 700;
  color: var(--text-muted); letter-spacing: 0.5px;
  margin: 18px 0 6px;
}
.doc-diff-empty {
  text-align: center; padding: 12px;
  color: var(--text-muted); font-style: italic;
  background: var(--surface-faded); border-radius: 3px;
}

/* "Compare against" picker */
.doc-diff-vs-picker {
  display: flex; gap: 8px; align-items: center;
  background: var(--blue-soft);
  padding: 8px 14px;
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  margin-bottom: 14px;
  font-size: 12px;
}
.doc-diff-vs-picker select {
  padding: 4px 8px; font-size: 12px;
  border: 1px solid var(--border-soft); border-radius: 3px;
}
.doc-diff-hint { color: var(--text-muted); font-size: 11px; }

/* Diff-table row tints */
.doc-diff-lines tr.doc-diff-row-changed td { background: #fff7e1; }
.doc-diff-lines tr.doc-diff-row-added td { background: #d1fae5; }
.doc-diff-lines tr.doc-diff-row-removed td {
  background: #fbe2e5;
  text-decoration: line-through;
  opacity: 0.7;
}
.doc-diff-lines tr.doc-diff-row-unchanged td { color: var(--text-muted); }
.doc-diff-lines td.num { text-align: right; }
.doc-diff-cell-desc { font-size: 11px; }
.doc-diff-cell-attrs { font-size: 10px; color: var(--text-muted); }

/* WO library pickers — chip displays + line-level marking dropdown
   + modal checklist styling (Step 3b, 07-05-2026). Reuses .lqp-modal*
   for the modal frame. */
.wo-chip-row {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.wo-chip {
  display: inline-block;
  background: var(--blue-light);
  color: var(--blue-main);
  border: 1px solid var(--blue-main);
  padding: 2px 8px;
  border-radius: 3px;
  font-size: var(--font-size-xs);
  font-weight: 600;
}
.wo-chip-empty {
  color: var(--text-muted);
  font-style: italic;
  font-size: var(--font-size-xs);
}
.wo-line-marking {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--font-size-xs);
  white-space: nowrap;
}
.wo-line-marking-label {
  margin: 0; font-weight: 500; color: var(--text-muted);
}
.wo-line-marking-select {
  font-size: var(--font-size-xs);
  padding: 3px 6px;
  min-width: 150px;
}
.wo-modal-checklist {
  list-style: none; padding: 0; margin: 0;
}
.wo-modal-checklist li {
  padding: 6px 0;
  border-bottom: 1px solid var(--border-soft);
}
.wo-modal-checklist li:last-child { border-bottom: none; }
.wo-modal-checklist label {
  display: flex; gap: 8px; align-items: center;
  cursor: pointer;
  font-weight: normal;
  margin: 0;
}
.wo-modal-empty {
  color: var(--text-muted);
  font-style: italic;
  padding: 12px 0;
}

/* Toggle row + multi-section layout (added 2026-05-07) */
.doc-diff-toggle-row {
  display: flex; gap: 14px; align-items: center;
  margin-bottom: 14px;
}
.doc-diff-toggle-label {
  display: inline-flex; gap: 8px; align-items: center;
  font-weight: 600; font-size: 13px; cursor: pointer;
}
.doc-diff-toggle-label input[type="checkbox"] {
  width: 16px; height: 16px; cursor: pointer;
}

.doc-diff-section { margin-bottom: 4px; }
.doc-diff-section-count {
  font-weight: 500; text-transform: none; letter-spacing: 0;
  font-size: 11px; color: var(--text-muted); margin-left: 6px;
}

.doc-diff-identity {
  display: inline-flex; gap: 10px; align-items: baseline;
}
.doc-diff-id-old, .doc-diff-id-new {
  display: inline-flex; gap: 6px; align-items: baseline;
}
.doc-diff-id-sub { font-size: 11px; color: var(--text-muted); }
.doc-diff-id-arrow { color: var(--text-muted); font-weight: 600; }

.doc-diff-summary-chips {
  display: inline-flex; gap: 8px; align-items: center; flex-wrap: wrap;
}

/* "View only changes" toggle (default ON via body.diff-only-changes) */
body.diff-only-changes .doc-diff-field-row:not(.doc-diff-changed) {
  display: none;
}
body.diff-only-changes .doc-diff-section[data-changed="0"] {
  display: none;
}
body.diff-only-changes .doc-diff-lines tr.doc-diff-row-unchanged {
  display: none;
}

.doc-chain-count.mod-qtn .doc-chain-count-type { background: var(--module-qtn); }
.doc-chain-count.mod-so  .doc-chain-count-type { background: var(--module-so); }
.doc-chain-count.mod-pi  .doc-chain-count-type { background: var(--module-pi); }
.doc-chain-count.mod-qpl .doc-chain-count-type { background: var(--module-qpl); }
.doc-chain-count.mod-inv .doc-chain-count-type { background: var(--module-sd); }
.doc-chain-count.mod-cn  .doc-chain-count-type,
.doc-chain-count.mod-dn  .doc-chain-count-type { background: var(--module-cndn); }

/* Hover popover — lists the actual doc numbers under each count button.
   Pure CSS hover/focus-within; no JS. */
.doc-chain-popover {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 140px;
  background: #fff;
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.12);
  padding: 4px 0;
  z-index: 100;
  flex-direction: column;
}
.doc-chain-count:hover .doc-chain-popover,
.doc-chain-count:focus-within .doc-chain-popover {
  display: flex;
}
.doc-chain-popover-link {
  display: block;
  padding: 4px 12px;
  font-size: 12px;
  color: var(--blue-main);
  text-decoration: none;
  white-space: nowrap;
}
.doc-chain-popover-link:hover {
  background: var(--blue-light);
  color: var(--blue-accent);
}

/* Small right-side hint text inside a panel header */
.erp-panel-hint {
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--text-muted);
  margin-left: 6px;
}

/* Messages wrapper */
.erp-messages {
  margin-bottom: 8px;
}

/* Message bubble */
.erp-message {
  font-size: var(--font-size-xs);
  padding: 6px 10px;
  border-radius: var(--radius-soft);
  margin-bottom: 12px;
}

.erp-message-success {
  background-color: var(--message-success-background-color);
  color: var(--message-success-color);
  border: 1px solid var(--message-success-border);
}

.erp-message-error {
  background-color: var(--message-error-background-color);
  color: var(--message-error-color);
  border: 1px solid var(--message-error-border);
}

/* Generic inner page container: centers content, width decided per page */
.erp-page-inner {
  margin: 0 auto;
  width: 100%;
  max-width: 100%;
}

/* ===========================================================
   PAGE WIDTH CLASSES — apply on .erp-page-inner AND
   .erp-header-container so the header lines up with the body.
   These are the ONLY allowed page widths. No inline widths.
   =========================================================== */
.w-narrow  { max-width: 900px  !important; width: 100% !important; margin-left: auto !important; margin-right: auto !important; }
.w-medium  { max-width: 1050px !important; width: 100% !important; margin-left: auto !important; margin-right: auto !important; }
.w-wide    { max-width: 1500px !important; width: 100% !important; margin-left: auto !important; margin-right: auto !important; }


/* ===========================================================
   ERP FORM + FIELD STANDARDISATION
   =========================================================== */

/* Base label styling */
label {
  display: block;
  font-size: var(--font-size-sm);   /* bumped from xs → sm */
  margin-bottom: 2px;
}

/* Red star used to mark mandatory fields */
.required-star {
  color: var(--red-accent);
  margin-left: 2px;
}

/* Labels inside ERP cards */
.erp-card label {
  display: block;
  font-size: var(--font-size-sm);   /* bumped from xs → sm */
  margin-bottom: 2px;
}

/* Checkboxes (slightly smaller with right spacing) */
.erp-card input[type="checkbox"] {
  transform: scale(0.9);
  margin-right: 6px;
}

/* Checkbox row – text aligned vertically with checkbox */
.checkbox-row {
  display: flex;
  align-items: center;
  font-size: var(--font-size-xs);
  margin-bottom: 10px;
}

/* Two-column grid used by Company Master blocks */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 24px;
}

/* Single row inside the grid */
.form-row {
  margin-bottom: 6px;
}

/* Form row label + value hierarchy.
   The label is constant chrome you already know; the VALUE is what you are
   there to read. Previously the label was both larger (13px) and bolder (600)
   than its value (12px / 400) — inverted weighting, and with everything inside
   a 12-13px band there was no hierarchy for the eye to lock onto, so dense
   header/meta blocks read as an undifferentiated blur. ~60% of fields on the
   big forms are disabled/readonly auto-fill, i.e. read rather than typed, so
   legibility of the value matters more than label prominence.
   Label now recedes; value dominates. (01-08-2026) */
/* TYPOGRAPHY — every field caption inside a card, wherever it sits in the
   markup. Deliberately broad: many labels (e.g. the SD transport block) live
   in unclassed divs or layout tables, and scoping to .form-row alone left them
   at the browser default, so forms looked half-converted. */
.erp-card label {
  font-weight: 500;
  font-size: var(--font-size-xxs);
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

/* LAYOUT — only stacked field rows. Kept separate from the typography above
   so labels that WRAP a control (checkbox/radio, display:flex) are not forced
   to block and broken onto their own line. */
.form-row label,
.address-block label {
  display: block;
  margin-bottom: 2px;
}

/* (The matching .form-row VALUE styling lives just after the .erp-card input
   block further down — it has to follow that rule in source order to win.) */

/* “Full width” cells in the grid – span both columns */
.full-row,
.col-span-2 {
  grid-column: 1 / -1;
}

/* File upload grid for documents (2 columns) */
.file-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 24px;
}

/* Document upload list — stacked rows with label + controls */
.doc-upload-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.doc-upload-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 8px 10px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-soft);
  background: var(--surface-light);
}

.doc-upload-label {
  min-width: 140px;
  font-size: var(--font-size-sm);
  font-weight: 600;
  padding-top: 4px;
  flex-shrink: 0;
}

.doc-upload-controls {
  flex: 1;
  min-width: 0;
}

.doc-current-file {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
  font-size: var(--font-size-xs);
}

.doc-file-link {
  color: var(--text-link);
  text-decoration: none;
  word-break: break-all;
}
.doc-file-link:hover {
  text-decoration: underline;
}

.doc-delete-label {
  display: flex;
  align-items: center;
  gap: 3px;
  color: var(--red-accent);
  font-size: var(--font-size-xs);
  cursor: pointer;
  white-space: nowrap;
}

.doc-delete-cb {
  width: auto !important;
  transform: scale(0.85);
}

.doc-upload-controls input[type="file"] {
  font-size: var(--font-size-xs);
  width: 100%;
}

/* Statutory grid: wider left column, narrower right column */
.statutory-grid {
  display: grid;
  grid-template-columns: 1.3fr 0.9fr;
  gap: 8px 16px;
}

/* Validation error text below fields */
.error-text {
  font-size: var(--font-size-xs);
  color: var(--message-error-color);
  margin-top: 2px;
}

/* Red highlight for error fields (input/select/textarea) */
.has-error input,
.has-error select,
.has-error textarea {
  border-color: var(--message-error-border) !important;
  background-color: var(--message-error-background-color) !important;
}

/* Hide Django’s default ul.errorlist bullets */
ul.errorlist {
  display: none;
}

/* Shipping block hidden when “same as billing” is checked */
.shipping-details-hidden {
  display: none;
}

/* Footer wrapper – align like Home, full block width */
.erp-footer {
  text-align: left;
  font-size: var(--font-size-xs);
  margin-top: 8px;
  margin-bottom: 16px;
}

/* Divider line above footer */
.erp-card-divider {
  width: 100%;
  border-top: 1px solid var(--border-soft);
  margin: 12px 0;
}

/* ---------- UNIVERSAL ERP FIELD APPEARANCE ---------- */

/* Field block - wrapper for label + input with consistent spacing */
.erp-field-block {
  margin-bottom: 12px;
}
.erp-field-block:last-of-type {
  margin-bottom: 0;
}

/* Field block label - semi-bold for visibility */
.erp-field-block label {
  display: block;
  font-weight: 600;
  margin-bottom: 4px;
  font-size: var(--font-size-sm);
}

/* Normal field appearance – standardised height via padding + line-height */
.erp-card input[type="text"],
.erp-card input[type="email"],
.erp-card input[type="file"],
.erp-card input[type="date"],
.erp-card input[type="datetime-local"],
.erp-card input[type="time"],
.erp-card input[type="number"],
.erp-card input[type="tel"],
.erp-card input[type="password"],
.erp-card input[type="url"],
.erp-card select,
.erp-card textarea {
  width: 100%;
  padding: 6px 8px;
  font-size: var(--font-size-xs);
  line-height: 1.3; /* standardised internal line-height */
  border-radius: var(--radius-soft);
  border: 1px solid var(--border-soft);
  outline: none;
  background-color: var(--card-bg);
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease,
    background-color 0.12s ease;
}

/* Header/meta VALUES sit one step up from the 12px base, to out-rank the
   receded label above them (see .form-row label). Must follow the rule above:
   same specificity, so source order decides. Scoped to .form-row so line-item
   TABLE inputs keep 12px — those column widths are tuned for it.
   13px, not 14: compared side by side on real records, 14 read as heavier than
   the data warranted. 13 still clears the 11px label by two steps and is
   reinforced by weight (500 -> 600) and colour (muted -> dark). (01-08-2026) */
.form-row input[type="text"],
.form-row input[type="email"],
.form-row input[type="date"],
.form-row input[type="datetime-local"],
.form-row input[type="time"],
.form-row input[type="number"],
.form-row input[type="tel"],
.form-row input[type="password"],
.form-row input[type="url"],
.form-row input[type="search"],
.form-row select,
.form-row textarea,
/* Header fields that are NOT wrapped in .form-row and would otherwise be left
   behind at 12px while everything around them moved: the SD Post-Shipment
   block (laid out in a table, hence no .form-row) and the SO/SD address
   panels. Named explicitly rather than widening to all card inputs — that
   would sweep the line-item grids too. */
.post-shipment-section input[type="text"],
.post-shipment-section input[type="date"],
.post-shipment-section input[type="datetime-local"],
.post-shipment-section input[type="time"],
.post-shipment-section input[type="number"],
.post-shipment-section select {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text-main);
}

/* Addresses are multi-line prose, not a single value: they take the same size
   step as other values but NOT the semi-bold — five bold lines read as
   shouting and crowd the fixed-height box. */
.address-block textarea {
  font-size: var(--font-size-sm);
  font-weight: 400;
  color: var(--text-main);
}

/* Focused (active) state */
.erp-card input[type="text"]:focus,
.erp-card input[type="email"]:focus,
.erp-card input[type="file"]:focus,
.erp-card input[type="date"]:focus,
.erp-card input[type="datetime-local"]:focus,
.erp-card input[type="time"]:focus,
.erp-card input[type="number"]:focus,
.erp-card input[type="tel"]:focus,
.erp-card input[type="password"]:focus,
.erp-card input[type="url"]:focus,
.erp-card select:focus,
.erp-card textarea:focus {
  border-color: var(--blue-main);
  background-color: var(--card-bg);
  outline: none;
}

/* Hover state for selects */
.erp-card select:hover:not(:disabled) {
  border-color: var(--blue-main);
}

/* Read-only fields */
.erp-card input[readonly],
.erp-card textarea[readonly] {
  background-color: var(--field-readonly-bg);
}

/* Disabled (locked) fields */
.erp-card input:disabled,
.erp-card select:disabled,
.erp-card textarea:disabled {
  background-color: var(--field-readonly-bg);
  cursor: not-allowed;
}

/* Auto-filled header/meta values must stay READABLE, not greyed out.
   Most .form-row fields are disabled/readonly (data pulled from the source
   doc), and WebKit/Blink force their own grey via -webkit-text-fill-color,
   which overrides `color` on disabled inputs. Pin both so a locked value is
   as legible as a typed one — the lock is conveyed by the background, not by
   fading the data. (01-08-2026) */
.form-row input:disabled,
.form-row select:disabled,
.form-row textarea:disabled,
.form-row input[readonly],
.form-row textarea[readonly],
.address-block textarea:disabled,
.address-block textarea[readonly] {
  color: var(--text-main);
  -webkit-text-fill-color: var(--text-main);
  opacity: 1;
}

/* Remove browser default invalid red borders */
.erp-card input:invalid,
.erp-card select:invalid,
.erp-card textarea:invalid {
  box-shadow: none;
  border-color: var(--border-soft);
}

/* Ensure focus border shows even when required selects are invalid (empty) */
.erp-card select:invalid:focus,
.erp-card select:invalid:focus-visible {
  border-color: var(--blue-main);
}

/* View mode - readonly fields (used in QTN/SO/QPL view states).
   Skip natively-disabled/readonly inputs so their browser-default
   cursor:not-allowed (the "blocked" 🚫 icon) still shows on hover —
   pointer-events:none would otherwise suppress it across the form. */
.view-mode input:not(:disabled):not([readonly]),
.view-mode select:not(:disabled):not([readonly]),
.view-mode textarea:not(:disabled):not([readonly]) {
  background: var(--field-readonly-bg) !important;
  pointer-events: none;
}

/* Escape the view-mode lock for sections that are intentionally edited
   AFTER the parent doc is locked. Examples:
     - SD Post-Shipment Details (EWB/AWB/delivered date)
     - SO Activity Notes
     - SD E-Invoice Details (IRN/Ack/QR — pasted from portal after SD
       submit, before e-invoice Lock; uses .always-editable)
     - Line-items search box (read-only lookup tool — should work even
       on submitted docs so users can find a part in a 50-line table
       without scrolling)
   Three specific selectors plus a generic `.always-editable` (matches
   class on a parent OR directly on the input). Disabled/readonly
   inputs are excluded so they keep their normal locked look +
   cursor:not-allowed. */
.view-mode .always-editable input:not(:disabled):not([readonly]),
.view-mode input.always-editable:not(:disabled):not([readonly]),
.view-mode .always-editable select:not(:disabled):not([readonly]),
.view-mode select.always-editable:not(:disabled):not([readonly]),
.view-mode .always-editable textarea:not(:disabled):not([readonly]),
.view-mode textarea.always-editable:not(:disabled):not([readonly]),
.view-mode .activity-notes-section input:not(:disabled):not([readonly]),
.view-mode .activity-notes-section select:not(:disabled):not([readonly]),
.view-mode .activity-notes-section textarea:not(:disabled):not([readonly]),
.view-mode .post-shipment-section input:not(:disabled):not([readonly]),
.view-mode .post-shipment-section select:not(:disabled):not([readonly]),
.view-mode .post-shipment-section textarea:not(:disabled):not([readonly]) {
  background: var(--card-bg) !important;
  pointer-events: auto !important;
}

/* When .has-error is applied inside the post-shipment section, ensure
   the red border + bg win over the post-shipment editable card-bg. */
.view-mode .post-shipment-section .has-error input,
.view-mode .post-shipment-section .has-error select,
.view-mode .post-shipment-section .has-error textarea {
  border-color: var(--message-error-border) !important;
  background-color: var(--message-error-background-color) !important;
}

/* Alert banner — yellow/red dismissable warning above library tables on
   SO / Qtn / Calibration. Same visual pattern as QPL's drift-warning
   banner. Dismiss via X; auto-reappears on (new session OR 24h)
   whichever earlier. Per-library state via localStorage + sessionStorage
   keyed by data-alert-key on the banner element. */
.erp-banner-alert {
  margin-bottom: 12px;
  padding: 10px 14px;
  background: var(--yellow-light);
  border: 1px solid var(--yellow-border);
  border-left-width: 4px;
  border-radius: 4px;
  font-size: var(--font-size-sm);
  color: var(--text-main);
  display: none;
  align-items: flex-start;
  gap: 10px;
}
.erp-banner-alert.erp-banner-alert--shown {
  display: flex;
}
.erp-banner-alert.severity-red {
  background: var(--danger-hover-bg);
  border-color: var(--red-accent);
}
.erp-banner-alert .alert-bell-svg {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  fill: var(--yellow-main);
  stroke: var(--yellow-main);
  margin-top: 2px;
}
.erp-banner-alert.severity-red .alert-bell-svg {
  fill: var(--red-accent);
  stroke: var(--red-accent);
}
.erp-banner-alert-body {
  flex: 1;
  min-width: 0;
}
.erp-banner-alert-title {
  font-weight: 600;
  margin-bottom: 4px;
}
.erp-banner-alert-list {
  margin: 0;
  padding-left: 18px;
}
.erp-banner-alert-list li {
  margin: 2px 0;
}
.erp-banner-alert-list a {
  color: var(--blue-main);
  text-decoration: none;
}
.erp-banner-alert-list a:hover {
  text-decoration: underline;
}
.erp-banner-alert-close {
  flex-shrink: 0;
  background: transparent;
  border: none;
  font-size: 20px;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 4px;
}
.erp-banner-alert-close:hover {
  color: var(--red-accent);
}

/* SD form — Permissive-drafts banners + QPL DRAFT picker tag.
   Surfaces when SD is linked to a QPL that's still in Draft (banner
   says: invoice can be drafted but not submitted) or Cancelled (banner
   says: re-link required). DRAFT tag in the picker dropdown marks rows
   that come from the relaxed status filter. */
.sd-qpl-draft-banner {
  margin-bottom: 12px;
  padding: 8px 12px;
  background: var(--yellow-light);
  border: 1px solid var(--yellow-border);
  border-left: 4px solid var(--yellow-border);
  border-radius: 4px;
  font-size: var(--font-size-sm);
}
.sd-qpl-cancelled-banner {
  margin-bottom: 12px;
  padding: 8px 12px;
  background: var(--danger-hover-bg);
  border: 1px solid var(--red-accent);
  border-left: 4px solid var(--red-accent);
  border-radius: 4px;
  font-size: var(--font-size-sm);
}
.qpl-draft-tag {
  display: inline-block;
  padding: 0 6px;
  font-size: 10px;
  font-weight: 600;
  background: var(--yellow-light);
  border: 1px solid var(--yellow-border);
  border-radius: 3px;
  color: var(--text-main);
  vertical-align: middle;
}

/* Per-row alert tint + inline bell — companion to .erp-banner-alert.
   When the user dismisses the banner, alerted rows in the main table
   stay marked via a subtle row tint (yellow or red severity) and an
   inline bell next to the alert-driving date column (CDD on SO lib,
   Expires on Qtn lib, Next Cal on Calibration lib).

   Solid background-color (not translucent overlay) so the tint reads
   identically on white and grey zebra rows. The .erp-table-zebra +
   .js-data-row selector chain bumps specificity to (0,3,3), beating
   the zebra rule's (0,2,3) — needed because zebra is later in the
   file and source order would otherwise win on equal specificity. */
.row-alert-yellow > td,
.erp-table-zebra tbody tr.js-data-row.row-alert-yellow td {
  background-color: #fff7e1;
}
.row-alert-red > td,
.erp-table-zebra tbody tr.js-data-row.row-alert-red td {
  background-color: #fbe2e5;
}
.alert-bell-inline {
  width: 12px;
  height: 12px;
  vertical-align: -2px;
  margin-left: 4px;
  fill: var(--yellow-main);
  stroke: var(--yellow-main);
  flex-shrink: 0;
}
.row-alert-red .alert-bell-inline {
  fill: var(--red-accent);
  stroke: var(--red-accent);
}

/* Floating scroll arrows in upper-right of wide tables.
   Opt-in via class .erp-scroll-arrows-host on the scroll wrapper.
   JS (erp_scroll_arrows.js) wraps the scroller in .erp-scroll-arrows-wrap
   and injects the .erp-scroll-arrows div + two .erp-scroll-arrow buttons.
   Hidden entirely when content fits; per-direction is-disabled at each edge. */
.erp-scroll-arrows-wrap {
  position: relative;
  /* reserve a thin strip above the scroller for the floating arrows;
     keeps them out of the table header. */
  padding-top: 22px;
}
.erp-scroll-arrows {
  position: absolute;
  top: 2px;
  right: 6px;
  display: flex;
  gap: 6px;
  z-index: 5;
  pointer-events: none;       /* container itself transparent to clicks */
}
/* Make the table-responsive region a vertical scroll container too
   (was overflow-x only). Headers + bottom scrollbar stay visible at
   the bounded edges of this region as the user scrolls within it.
   `overscroll-behavior: contain` stops the wheel from "bubbling" to
   the page when the table hits its top/bottom — kills the irritating
   "scroll inside, then outside" jump. */
.erp-scroll-arrows-wrap .erp-table-responsive {
  max-height: 70vh;
  overflow: auto;
  overscroll-behavior: contain;
}
/* Inside the wrap, every thead th becomes sticky-top:0 inside the
   bounded scroll region. Library templates already have this inline;
   this rule provides it for tables that don't (Shipment Register etc.).
   For the inline ones the values are identical so no visual change. */
.erp-scroll-arrows-wrap thead th {
  position: sticky;
  top: 0;
  background: var(--table-header-bg);
  z-index: 1;
}
.erp-scroll-arrow {
  pointer-events: auto;
  background: transparent;
  border: none;
  padding: 0 2px;
  color: var(--grey-main);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  user-select: none;
}
.erp-scroll-arrow:hover { color: var(--blue-main); }
.erp-scroll-arrow.is-disabled {
  color: var(--border-soft);
  cursor: not-allowed;
}

/* Sticky right action column on library tables.
   Pins the 3-dot action menu to the right edge while horizontally
   scrolling, so users don't have to round-trip (scroll down to find
   the bottom scrollbar → scroll right → scroll back up to the row).
   No-op when the table fits its container — sticky only kicks in when
   there's actual horizontal overflow.
   The thead th:last-child gets right:0 too, making the corner cell
   2-axis sticky (top + right). zebra/hover bg rules already target
   td so the action cell follows the row colour automatically. */
.erp-table tbody td.action-cell {
  position: sticky;
  right: 0;
  z-index: 1;
  background: var(--card-bg);
}
/* Corner cell (top + right sticky) needs higher z-index than the body
   action cells, otherwise during vertical scroll the body cell renders
   on top of the header. Inline `z-index:1` in library templates would
   tie with body cells; !important here trumps inline so the corner
   reliably sits at z-index 3 (above body action cells AND regular
   header cells). Explicit position:sticky + top:0 keep the rule
   self-sufficient even if a future template omits the inline styles.

   :has() scopes the rule to tables that actually have a sticky-right
   action cell — without this, data-column tables (QPL entry, QPL
   summary) get the last header cell stickied even though their last
   column isn't an action col, causing it to render incorrectly during
   vertical scroll. */
.erp-table:has(td.action-cell) thead th:last-child {
  position: sticky;
  top: 0;
  right: 0;
  z-index: 3 !important;
  background: var(--table-header-bg);
}

/* FROZEN FIRST COLUMN — the mirror of the sticky action cell above.
   Keeps the document number in view while reading across a wide library
   table, so you never lose which row you are on. No-op when the table fits
   its container; sticky only engages on real horizontal overflow.

   OPT-IN via .erp-table-stickyfirst, deliberately. The action-cell rule can
   key off .action-cell because only libraries have that class; a first
   column has no such natural hook, and form line-item tables and print
   templates must not inherit this.

   Background is a FALLBACK only. The zebra, hover and row-alert rules all
   target `td` and sit later in this file at equal or higher specificity, so
   the frozen cell follows its own row's colour — striped, hovered or alerted
   — exactly as the action cell already does.

   Requires border-collapse:separate on the table (every library sets it
   inline), otherwise the cell borders belong to the table rather than the
   cell and vanish as it detaches. */
.erp-table-stickyfirst tbody td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--card-bg);
}

/* Corner cell — sticky on BOTH axes, so it must outrank the body cells of
   its own column (z-index 1) and the ordinary header cells (z-index 1,
   inline in the templates). Same reasoning and same value as the
   top-right corner above. */
.erp-table-stickyfirst thead th:first-child {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 3 !important;
  background: var(--table-header-bg);
}

/* Sticky header row for the same tables, from one place rather than an inline
   style on every th. Eight of the eleven libraries already carry these exact
   three declarations inline, so this is a no-op for them — it exists so the
   three that never got them (PO, CN, GRN) behave the same without adding
   inline styles to forty header cells. */
.erp-table-stickyfirst thead th {
  position: sticky;
  top: 0;
  background: var(--table-header-bg);
  z-index: 1;
}

/* View mode - collapse items-table no-print cells (drag handles, action
   buttons, delete slots) since they're empty in view-only renders and just
   leave blank columns. Scoped to .erp-table cells so non-table .no-print
   utilities (top-of-page action button rows etc.) stay visible. */
.view-mode .erp-table th.no-print,
.view-mode .erp-table td.no-print { display: none; }

/* Global disabled inputs - ensure text is visible */
input:disabled,
textarea:disabled,
select:disabled {
  color: var(--text-main) !important;
  -webkit-text-fill-color: var(--text-main) !important;
  opacity: 1 !important;
}

/* Remove number input spinners */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}


/* Error (unfocused) */
.has-error input,
.has-error select,
.has-error textarea {
  border-color: var(--message-error-border) !important;
  background-color: var(--message-error-background-color) !important;
}

/* Error label turns red */
.has-error label {
  color: var(--red-accent) !important;
}

/* Ensure error state stays red even when field is focused */
.erp-card .has-error input:focus,
.erp-card .has-error select:focus,
.erp-card .has-error textarea:focus {
  border-color: var(--message-error-border) !important;
  background-color: var(--message-error-background-color) !important;
  box-shadow: none !important;
}

/* ===========================================================
   TABLE UTILITIES – STANDARD ROWS, ZEBRA, ACTION BUTTONS
   =========================================================== */

/* Standard ERP table density (row height controlled by padding + line-height) */
.erp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-xs);
}

/* Table cells and headers – compact height + full grid borders */
.erp-table th,
.erp-table td {
  padding: 3px 6px;
  line-height: 2.0;
  border: 1px solid var(--border-soft);
}

/* Table header styling — distinct header treatment (Option A2, 15-07-2026):
   the old light tint + weight-600 read like a body row on zebra tables.
   Solid header bar (--table-header-bg, a softer blue than brand so it
   doesn't dominate across ~56 tables), white uppercase label, taller.
   Column dividers are faint WHITE lines (grey borders would vanish on the
   fill); the bottom edge matches the fill so no seam shows.
   One rule, propagates to all .erp-table tables.
   NOTE: library headers set inline `background:var(--blue-light)` for sticky
   positioning, and inline wins over this rule — those inline th backgrounds
   are swept to var(--table-header-bg) so the bar shows while scrolling. The
   two sticky-header helpers (~L2118 / ~L2169) are also set to it. */
.erp-table thead th {
  background-color: var(--table-header-bg);
  color: #ffffff;
  font-weight: 700;
  line-height: 2.8;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-color: rgba(255, 255, 255, 0.3);
  border-bottom-color: var(--table-header-bg);
}

/* Small second-line label under a header caption, e.g. "PO / Ex / Ship" beneath
   Qty, or a currency code beneath Unit Price. Size and weight only — the colour
   is deliberately NOT set so it inherits the header bar's white. The SO form
   previously set this inline as var(--text-muted), a grey tuned for light
   backgrounds, which left the label all but invisible against the blue fill. */
.erp-table thead th .th-sub {
  font-size: 10px;
  font-weight: 400;
}

/* Table sorting arrows on sortable headers.
   Works with window.ErpTableSort.wire() from erp_table_sort.js.
   A th is sortable when it has attribute data-sort set to a value other
   than "none"; the JS adds the .sortable class on wire-up. */
.erp-table th.sortable {
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}
/* Server-side sort link in a table header (_partials/_sort_header.html).
   Inherits the header bar's white text — it is a header first, a link second,
   so it must not turn blue like body links. */
.erp-table thead th .erp-sort-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  display: inline-block;
}
.erp-table thead th .erp-sort-link:hover {
  text-decoration: underline;
}

.erp-table th.sortable:hover {
  /* Keep the solid header colour on hover. Most tables set an inline
     background on each th (sticky headers) which already overrides this, so a
     pale tint only ever showed on tables without it (e.g. shipment register),
     making the white header text fade. cursor:pointer above still signals sortability. */
  background-color: var(--table-header-bg);
}

/* Active-sort up/down indicator is rendered into the inline
   <span class="erp-sort-indicator"></span> by erp_table_sort.js (setIndicator).
   No CSS ::after fallback — single indicator path keeps font sizing
   consistent with the th label. Templates that wire the helper must include
   the span inside each sortable th. */

/* Extra breathing room between table and card edge */
.erp-card .erp-table {
  margin-bottom: 12px;
}

/* Zebra table rows – opt-in via .erp-table-zebra.
   nth-child is the FALLBACK (correct only when no rows are hidden). Tables wired
   with ErpTableSort get .zebra-odd/.zebra-even applied by JS (restripe) based on
   VISIBLE rows only — so collapsed amendment rows don't break the alternation.
   The class rules below override nth-child (higher specificity). */
.erp-table-zebra tbody tr:nth-child(odd) td {
  background-color: var(--card-bg);
}

.erp-table-zebra tbody tr:nth-child(even) td {
  background-color: var(--bg-main);
}

.erp-table-zebra tbody tr.zebra-odd td {
  background-color: var(--card-bg);
}

.erp-table-zebra tbody tr.zebra-even td {
  background-color: var(--bg-main);
}

.erp-table-zebra tbody tr:hover td {
  background-color: var(--blue-light);
}

/* ==========================================================
   TABLE ACTION BUTTON ALIASES (backward compatibility)
   Use .erp-btn .erp-btn-row .erp-btn-secondary etc. instead
   ========================================================== */
.erp-table-action-btn { 
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 6px;
  border-radius: 999px;
  font-size: var(--font-size-xs);
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  margin-right: 4px;
  white-space: nowrap;
  background-color: var(--card-bg);
}
.erp-table-action-edit {
  color: var(--blue-main);
  border-color: var(--blue-main);
}
.erp-table-action-edit:hover {
  background-color: var(--blue-light);
}
.erp-table-action-delete {
  color: var(--red-accent);
  border-color: var(--red-accent);
}
.erp-table-action-delete:hover {
  background-color: var(--danger-hover-bg);
}
.erp-table-action-print {
  color: var(--teal-main);
  border-color: var(--teal-main);
}
.erp-table-action-print:hover {
  background-color: var(--teal-light);
}
.erp-table-action-info {
  color: var(--grey-main);
  border-color: var(--grey-main);
}
.erp-table-action-info:hover {
  background-color: var(--grey-light);
}


/* ==========================================================
   CIRCULAR DELETE BUTTON (for form row deletion)
   Red X in circle, used in line item tables
   Usage: <button class="del-btn-circle"><svg width="8" height="8" viewBox="0 0 10 10"><line x1="2" y1="2" x2="8" y2="8" stroke="currentColor"/><line x1="8" y1="2" x2="2" y2="8" stroke="currentColor"/></svg></button>
   ========================================================== */

.del-btn-circle {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--red-accent);
  border: 1px solid var(--red-accent);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.del-btn-circle:hover {
  background: var(--danger-hover-bg);
}

.del-btn-circle:disabled {
  border-color: var(--border-soft);
  color: var(--border-soft);
  cursor: not-allowed;
  background: transparent;
}

/* ==========================================================
   PRICE-BREAK CHILD ROWS (Qtn form) — non-computing qty-slab
   alternates nested under a base line. No Sr. No., muted,
   never enter any total. See price_break_plan.md.
   ========================================================== */
.pbreak-row td {
  color: var(--text-muted);
  font-size: var(--font-size-xs);
  border-top: none;
  padding-top: 2px;
  padding-bottom: 4px;
}
.pbreak-label {
  font-style: italic;
  padding-left: 16px;
  white-space: nowrap;
}
.pbreak-row input.pb-num {
  text-align: right;
  font-size: var(--font-size-xs);
  color: var(--text-main);
}
.pbreak-noamt {
  text-align: right;
  color: var(--text-muted);
}
.pbreak-cell-r { text-align: right; }
.pbreak-cell-c { text-align: center; }
.pb-add {
  font-size: 10px;
  padding: 1px 4px;
  margin-top: 2px;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border-soft);
  border-radius: 3px;
  cursor: pointer;
  white-space: nowrap;
}
.pb-add:hover {
  color: var(--blue-main);
  border-color: var(--blue-main);
}

/* ===========================================================
   CIRCULAR DONE BUTTON (for marking items complete)
   Green check in circle, mirrors del-btn-circle
   Usage: <button class="done-btn-circle"><svg width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="2,5 4.5,7.5 8,3"/></svg></button>
   =========================================================== */

.done-btn-circle {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--green-main);
  border: 1px solid var(--green-main);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.done-btn-circle:hover {
  background: var(--green-light);
}

.done-btn-circle:disabled {
  border-color: var(--border-soft);
  color: var(--border-soft);
  cursor: not-allowed;
  background: transparent;
}

/* ===========================================================
   CIRCULAR RESET BUTTON (for resetting form row values)
   Yellow minus in circle, used in other charges rows
   Usage: <button class="reset-btn-circle"><svg width="8" height="8" viewBox="0 0 10 10"><line x1="2" y1="5" x2="8" y2="5" stroke="currentColor" stroke-width="1.5"/></svg></button>
   =========================================================== */

.reset-btn-circle {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--yellow-main);
  border: 1px solid var(--yellow-main);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.reset-btn-circle:hover {
  background: var(--yellow-light);
}

.reset-btn-circle:disabled {
  border-color: var(--border-soft);
  color: var(--border-soft);
  cursor: not-allowed;
  background: transparent;
}

/* ===========================================================
   ADD BUTTON (CIRCLE) – GREEN +
   Usage: <button class="add-btn-circle"><svg width="10" height="10" viewBox="0 0 10 10"><line x1="5" y1="1" x2="5" y2="9" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="5" x2="9" y2="5" stroke="currentColor" stroke-width="1.5"/></svg></button>
   =========================================================== */

.add-btn-circle {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--green-main);
  border: 1px solid var(--green-main);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.add-btn-circle:hover {
  background: var(--green-light);
}

.add-btn-circle:disabled {
  border-color: var(--border-soft);
  color: var(--border-soft);
  cursor: not-allowed;
  background: transparent;
}

/* ===========================================================
   ACTION CIRCLE BUTTONS – TABLE ROW ACTIONS
   20px circles with SVG icons for row-level actions.
   Colour follows function per ERP button conventions.

   Icons:
     Edit     – pencil        (act-blue)
     Duplicate – two squares  (act-blue)
     View     – eye           (act-blue)
     Archive  – box with lid  (act-red)
     Cancel   – X             (act-red)
     Modify   – pencil + line (act-red)
     Restore  – up arrow      (act-green)
     Print    – printer       (act-teal)

   Usage:
     <a href="..." class="act-circle act-blue" title="Edit">
       <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 1.5L10.5 3.5L4 10H2V8L8.5 1.5Z"/></svg>
     </a>
     <button class="act-circle act-red" title="Archive">
       <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="1" width="10" height="3" rx="0.5"/><path d="M2 4v6.5a.5.5 0 00.5.5h7a.5.5 0 00.5-.5V4"/><path d="M5 7h2"/></svg>
     </button>
   =========================================================== */

.act-circle {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: 1px solid;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  text-decoration: none;
  box-sizing: border-box;
  vertical-align: middle;
}
.act-circle svg { display: block; }
.act-circle:hover { filter: brightness(1.1); }
.act-circle:disabled {
  border-color: var(--border-soft);
  color: var(--border-soft);
  cursor: not-allowed;
  background: transparent;
}

/* Blue – secondary actions: View, Edit, Duplicate */
.act-blue { color: var(--blue-main); border-color: var(--blue-main); }
.act-blue:hover { background: var(--blue-light); }
a.act-blue { color: var(--blue-main); }

/* Red – destructive actions: Archive, Cancel, Modify (Amend) */
.act-red { color: var(--red-accent); border-color: var(--red-accent); }
.act-red:hover { background: var(--danger-hover-bg); }
a.act-red { color: var(--red-accent); }

/* Green – recovery/positive: Restore */
.act-green { color: var(--green-main); border-color: var(--green-main); }
.act-green:hover { background: var(--green-light); }
a.act-green { color: var(--green-main); }

/* Teal – output actions: Print, Export */
.act-teal { color: var(--teal-main); border-color: var(--teal-main); }
.act-teal:hover { background: var(--teal-light); }
a.act-teal { color: var(--teal-main); }

/* Focus ring for action circles */
.act-circle:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 2px;
}

/* Action circle group – spacing between adjacent circles */
.act-group {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  width: 100%;
}
/* Ensure forms inside act-group don't break flex layout */
.act-group form {
  display: inline-flex;
  margin: 0;
  padding: 0;
}

/* ===========================================================
   BUTTON FOCUS (KEYBOARD TAB) – STANDARD ERP BEHAVIOUR
   =========================================================== */

/* Base focus style for ERP buttons and small table action buttons */
.erp-btn:focus-visible,
.erp-table-action-btn:focus-visible {
  outline: 1px solid var(--blue-main);   /* you set this to 1px */
  outline-offset: 2px;
}

/* Danger variants get a red focus ring instead of blue */
.erp-btn-danger:focus-visible,
.erp-table-action-delete:focus-visible {
  outline: 1px solid var(--red-accent);
}

/* Success variants get a green focus ring */
.erp-btn-success:focus-visible {
  outline: 1px solid var(--green-main);
}

/* ===========================================================
   QUICK PACKING LIST (QPL) – DRAFT PACKING LIST TABLE
   - Column widths locked so cartons line up visually
   - Only applies where .qpl-pl-table is used in HTML
   =========================================================== */

.qpl-pl-table {
  table-layout: fixed;
  width: 100%;
}

/* Column width hints – used via <colgroup> in QPL template */
.qpl-pl-table col.col-sr      { width: 4%;  }
.qpl-pl-table col.col-part    { width: 10%; }
.qpl-pl-table col.col-hsn     { width: 8%; }
.qpl-pl-table col.col-desc    { width: 40%; }
.qpl-pl-table col.col-qty     { width: 8%;  }
.qpl-pl-table col.col-boxno   { width: 8%;  }
.qpl-pl-table col.col-breakup { width: 8%;  }
.qpl-pl-table col.col-net     { width: 8%;  }
.qpl-pl-table col.col-gross   { width: 9%;  }

/* Contacts table: deterministic layout */
/* Contacts table: responsive deterministic layout */
.erp-contacts-table {
  table-layout: fixed;
  width: 100%;
}

/* Inputs/selects fill their cells AND are allowed to shrink */
.erp-contacts-table input,
.erp-contacts-table select {
  width: 100%;
  min-width: 0;            /* critical: prevents inputs forcing overflow */
  box-sizing: border-box;
}

/* Column widths (percent-based, totals 100%) */
.erp-contacts-table th:nth-child(1),
.erp-contacts-table td:nth-child(1) { width: 8%; }   /* Salutation */

.erp-contacts-table th:nth-child(2),
.erp-contacts-table td:nth-child(2) { width: 16%; }  /* Contact name */

.erp-contacts-table th:nth-child(3),
.erp-contacts-table td:nth-child(3) { width: 14%; }  /* Designation */

.erp-contacts-table th:nth-child(4),
.erp-contacts-table td:nth-child(4) { width: 12%; }  /* Phone */

.erp-contacts-table th:nth-child(5),
.erp-contacts-table td:nth-child(5) { width: 24%; }  /* Email */

.erp-contacts-table th:nth-child(6),
.erp-contacts-table td:nth-child(6) { width: 10%; }  /* Location */

.erp-contacts-table th:nth-child(7),
.erp-contacts-table td:nth-child(7) { width: 8%; text-align: center; }  /* Primary */

.erp-contacts-table th:nth-child(8),
.erp-contacts-table td:nth-child(8) { width: 8%; text-align: center; }  /* Action */


/* Scrollable table wrapper with sticky header */


/* ==========================================================
   STATUS BADGES
   Standard document status badges used across ERP
   ========================================================== */

.status-badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: var(--radius-soft);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  white-space: nowrap;
}

/* QPL Shipment Value: goods value at packing time, derived live from the
   source SO line rates. Shown on the QPL form and the Office/Summary prints
   (never the Packing print). */
.qpl-shipment-value {
  margin-top: 10px;
  text-align: right;
  font-size: var(--font-size-sm);
}
/* Read-only Shipment Value in the QPL form header row. Derived, never posted —
   styled like the other auto-filled (disabled) header fields beside it. */
.qpl-shipment-value-field {
  min-width: 150px;
}
.qpl-shipment-value-field input {
  background: var(--field-readonly-bg);
  font-weight: 600;
  cursor: default;
}
.qpl-shipment-value-note {
  display: block;
  font-size: var(--font-size-xs);
  color: var(--text-muted);
  font-style: italic;
}

/* Source-quote badge in the SO Part No cell: shows which offer a line came
   from on a multi-quote SO. Rendered live by the JS loader (inline styles,
   legacy) and, from server reload, by the template using this class. Keep the
   two visually identical. */
.source-qtn-badge {
  font-size: 9px;
  background: var(--blue-light, #e3f2fd);
  color: var(--blue, #1565c0);
  padding: 1px 4px;
  border-radius: 3px;
  margin-right: 4px;
  white-space: nowrap;
}

/* Modal overlay used by long-running async actions (e.g. SD Save All PDFs).
   Locks the screen while the request is in flight; auto-removed on response. */
.save-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}
.save-overlay-card {
  background: var(--card-bg);
  padding: 28px 36px;
  border-radius: var(--radius-soft);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
  text-align: center;
  min-width: 380px;
}
.save-overlay-title {
  font-size: var(--font-size-md);
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--text-main);
}
.save-overlay-sub {
  font-size: var(--font-size-sm);
  color: var(--text-main);
  margin-bottom: 18px;
}
.save-overlay-bar {
  width: 100%;
  height: 8px;
  background: var(--surface-light);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}
.save-overlay-bar-fill {
  position: absolute;
  top: 0; bottom: 0;
  width: 30%;
  background: linear-gradient(90deg, transparent, var(--blue-main), transparent);
  animation: save-overlay-bar-anim 1.6s linear infinite;
}
@keyframes save-overlay-bar-anim {
  0%   { left: -30%; }
  100% { left: 100%; }
}

/* Status-badge variants for fully/partial states (no inline styles). */
/* Delivery-performance outcome badges. Theme2 had no "late" state — only
   badge-fully / badge-partial and the delivered/dispatched chips, none of which
   mean missed-a-promise. The alternatives were inline colour styles (the debt
   being removed elsewhere) or misusing a delivered chip to mean late. Three
   rules, one place. (06-08-2026) */
.status-badge.badge-ontime {
  background: var(--green-light);
  color: var(--green-text);
}
.status-badge.badge-late-week {
  background: var(--yellow-light);
  color: var(--yellow-text);
}
.status-badge.badge-late {
  background: var(--red-light);
  color: var(--red-accent);
}
/* Text-only companions to the trio above, for stat strips where a pill
   background would break the bar's uniform typography: same colours, same
   meaning, no background. */
.status-text-ontime { color: var(--green-text); }
.status-text-late-week { color: var(--yellow-text); }
.status-text-late { color: var(--red-accent); }

.status-badge.badge-fully {
  background: var(--green-light);
  color: var(--green-text);
  margin-left: 8px;
}
.status-badge.badge-partial {
  background: var(--yellow-light);
  color: var(--yellow-text);
  border: 1px solid var(--yellow-border);
  margin-left: 8px;
}

/* Library list-cell helper — table cell hosting one or two .chip-tight chips.
   Centred, no-wrap so chips stay on one line in narrow columns. */
.cell-chips {
  text-align: center;
  white-space: nowrap;
}
/* Library list-cell empty marker — '—' rendered when there's nothing to show. */
.cell-empty {
  color: var(--text-main);
  font-size: var(--font-size-xs);
}

/* Tight chip — used by Qtn library Order State + PO library Receipt State.
   Two chips per cell (lines + qty). Auto-sizes to content via inline-block.
   Variant via .chip-fully / .chip-partial / .chip-open modifier classes. */
.chip-tight {
  display: inline-block;
  padding: 2px 6px;
  margin: 0 1px;
  border-radius: var(--radius-soft);
  font-size: var(--font-size-xs);
  font-weight: 600;
  white-space: nowrap;
  line-height: 1.4;
  border: 1px solid transparent;
}
.chip-tight.chip-fully {
  background: var(--green-light);
  color: var(--green-text);
  border-color: var(--green-main);
}
.chip-tight.chip-partial {
  background: var(--yellow-light);
  color: var(--yellow-text);
  border-color: var(--yellow-border);
}
.chip-tight.chip-open {
  background: var(--surface-light);
  color: var(--text-main);
  border-color: var(--border-soft);
}

/* Document statuses — categorised chip scheme (30-Apr-2026 sweep).
   All status badges are chip-style: light bg + main-coloured text +
   main-coloured border. Categories:
     PRE-ISSUE       yellow      .status-draft
     ACTIVE          blue        .status-submitted
     ACTIVE          indigo      .status-approved   (distinct from submitted)
     IN-FLIGHT       teal        .status-released, .status-in_progress
     FROZEN          purple      .status-locked
     DONE-POSITIVE   green       .status-closed, .status-invoiced,
                                 .status-finalized, .status-completed
     DONE-NEGATIVE   red         .status-cancelled, .status-lapsed
     REPLACED        grey        .status-superseded
   The N/M variants (.status-submitted-fully etc.) are unchanged — they
   were already chip-style and predate this sweep. */

/* PRE-ISSUE */
.status-draft {
  background: var(--yellow-light); color: var(--yellow-text);
  border: 1px solid var(--yellow-border);
}

/* ACTIVE / awaiting party action */
.status-submitted {
  background: var(--blue-light); color: var(--blue-main);
  border: 1px solid var(--blue-main);
}
.status-approved {
  background: var(--indigo-light); color: var(--indigo-main);
  border: 1px solid var(--indigo-main);
}

/* N/M sub-states — already chip-style, kept as-is */
.status-submitted-fully {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-submitted-partial {
  background: var(--yellow-light); color: var(--yellow-text);
  border: 1px solid var(--yellow-border);
}
.status-approved-fully {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-approved-partial {
  background: var(--yellow-light); color: var(--yellow-text);
  border: 1px solid var(--yellow-border);
}
/* Qtn with some lines ordered into SO(s), balance still open ("Part-Ordered N/M").
   Yellow like approved-partial — commercially live, not yet fully consumed. */
.status-part-ordered {
  background: var(--yellow-light); color: var(--yellow-text);
  border: 1px solid var(--yellow-border);
}

/* IN-FLIGHT / WORKING */
.status-released {
  background: var(--teal-light); color: var(--teal-main);
  border: 1px solid var(--teal-main);
}
.status-in_progress {
  background: var(--teal-light); color: var(--teal-main);
  border: 1px solid var(--teal-main);
}

/* FROZEN / SEALED */
.status-locked {
  background: var(--purple-light); color: var(--purple-main);
  border: 1px solid var(--purple-main);
}

/* DONE — POSITIVE END */
.status-closed {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-invoiced {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-finalized {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-completed {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}

/* DONE — NEGATIVE END */
.status-cancelled {
  background: var(--danger-hover-bg); color: var(--red-accent);
  border: 1px solid var(--red-accent);
}
.status-lapsed {
  background: var(--danger-hover-bg); color: var(--red-accent);
  border: 1px solid var(--red-accent);
}

/* REPLACED */
.status-superseded {
  background: var(--grey-light); color: var(--grey-main);
  border: 1px solid var(--grey-main);
}

/* CALIBRATION STATUSES — used by the Inst cal library Status col chip */
.status-calibrated {
  background: var(--green-light); color: var(--green-text);
  border: 1px solid var(--green-main);
}
.status-due {
  background: var(--danger-hover-bg); color: var(--red-accent);
  border: 1px solid var(--red-accent);
}
.status-cnr {
  background: var(--grey-light); color: var(--grey-main);
  border: 1px solid var(--grey-main);
}

/* CALIBRATION WORKING-SET CELL BG — used on the Inst cal library
   Set col td to mark which gauge set the row belongs to. Visual key
   only; the short code text (WS1/WS2/MS) is the actual data.
   Selector specificity overrides .erp-table-zebra's (0,2,3) zebra rule. */
.erp-table-zebra tbody tr td.ws-cell-1      { background-color: var(--yellow-highlight); }
.erp-table-zebra tbody tr td.ws-cell-2      { background-color: var(--teal-light); }
.erp-table-zebra tbody tr td.ws-cell-master { background-color: var(--green-light); }


/* ==========================================================
   TABLE RESPONSIVE WRAPPER
   Use .erp-table-responsive around tables that may overflow
   ========================================================== */

.erp-table-responsive {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.erp-table-responsive > .erp-table {
  min-width: 800px;
}


/* ==========================================================
   DROPDOWN COMPONENTS
   Shared dropdown styles for customer/part/quotation search
   ========================================================== */

/* Dropdown item - used in search dropdowns throughout ERP */
.dd-item { 
  padding: 6px 10px; 
  cursor: pointer; 
  font-size: var(--font-size-xs); 
  border-bottom: 1px solid var(--border-light); 
}
.dd-item:hover, .dd-item.active { 
  background: var(--blue-light); 
}
.dd-item:last-child { 
  border-bottom: none; 
}

/* Dropdown container - absolute positioned search results */
.erp-dropdown {
  display: none;
  position: absolute;
  z-index: 1000;
  top: 100%;
  left: 0;
  right: 0;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  background: var(--card-bg);
  box-shadow: var(--shadow-dropdown);
  max-height: 200px;
  overflow-y: auto;
}

/* Dropdown list - alternate class name for dropdown container */
.dropdown-list {
  display: none;
  position: absolute;
  z-index: 1000;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 2px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  background: var(--card-bg);
  box-shadow: var(--shadow-dropdown);
  max-height: 200px;
  overflow-y: auto;
}
.dropdown-list.open {
  display: block;
}

/* Dropdown wrapper */
.dropdown-wrap {
  position: relative;
}

/* Dropdown input - clickable field that opens dropdown */
.dropdown-input {
  width: 100%;
  cursor: pointer;
  background: var(--card-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M2 4l4 4 4-4'/%3E%3C/svg%3E") no-repeat right 10px center;
  padding-right: 28px;
}
.dropdown-input:read-only,
.erp-card .dropdown-input:read-only,
.erp-card input.dropdown-input[readonly] {
  background-color: var(--card-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
}
.dropdown-input.disabled {
  background-color: var(--field-readonly-bg);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* Empty dropdown item */
.dd-item-empty {
  padding: 8px 10px;
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

/* ==========================================================
   THEMED NATIVE <select>  (.erp-select)
   For short fixed-option pickers (GST rate, gender, etc.)
   where typeahead is overkill. Matches .dropdown-input look.
   ========================================================== */
.erp-select,
.erp-card select,
.form-row select,
.form-grid-2 select,
.form-grid-3 select {
  width: 100%;
  box-sizing: border-box;
  font-family: inherit;
  font-size: var(--font-size-xs);
  line-height: 1.3;
  padding: 6px 26px 6px 8px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  background-color: var(--card-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  color: var(--text-main);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  height: auto;
}

/* Header selects take the field-VALUE size, like their input siblings. The
   appearance rule above also lists .form-row select and sets the 12px base;
   it sits later in the file, so on equal specificity it would win and leave
   dropdowns a size below the text fields beside them. */
.form-row select,
.post-shipment-section select {
  font-size: var(--font-size-sm);
  font-weight: 600;
}

.erp-select:focus,
.erp-card select:focus,
.form-row select:focus,
.form-grid-2 select:focus,
.form-grid-3 select:focus {
  outline: none;
  border-color: var(--blue-main, #4a7bb7);
  box-shadow: 0 0 0 2px rgba(74, 123, 183, 0.15);
}
.erp-select:disabled,
.form-row select:disabled {
  background-color: var(--field-readonly-bg);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* ==========================================================
   LEGACY DROPDOWN CLASS ALIASES
   rm-dropdown / rm-dd-item / dropdown-list remain functional
   until their templates migrate to the canonical .erp-dropdown
   / .dd-item classes. Styles forwarded below.
   ========================================================== */
.rm-dropdown {
  display: none;
  position: absolute;
  z-index: 1000;
  top: 100%;
  left: 0;
  right: 0;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  background: var(--card-bg);
  box-shadow: var(--shadow-dropdown);
  max-height: 200px;
  overflow-y: auto;
}
.rm-dd-item {
  padding: 6px 10px;
  cursor: pointer;
  font-size: var(--font-size-xs);
  border-bottom: 1px solid var(--border-light);
}
.rm-dd-item:hover,
.rm-dd-item.active {
  background: var(--blue-light);
}
.rm-dd-item:last-child {
  border-bottom: none;
}


/* ==========================================================
   LQP (LAST QUOTED PRICE) BUTTON
   Small button for accessing price history on line items
   ========================================================== */

.lqp-btn {
  padding: 2px 5px;
  font-size: 9px;
  border: 1px solid var(--text-faded);
  background: transparent;
  color: var(--text-secondary);
  font-weight: 600;
  border-radius: var(--radius-small);
  cursor: pointer;
}
.lqp-btn:hover {
  background: var(--hover-light);
  border-color: var(--text-secondary);
  color: var(--text-dark);
}


/* ==========================================================
   LQP MODAL
   Modal dialog for viewing price history
   ========================================================== */

.lqp-modal-overlay {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--overlay-bg);
  z-index: 9999;
  justify-content: center;
  align-items: center;
}
.lqp-modal-overlay.active { display: flex; }

.lqp-modal {
  background: var(--card-bg);
  border-radius: var(--radius-soft);
  box-shadow: var(--shadow-modal);
  max-width: 1050px;
  width: 95%;
  max-height: 90vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.lqp-modal-header {
  padding: 12px 16px;
  background: var(--blue-light);
  color: var(--text-main);
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.lqp-modal-close {
  background: none;
  border: none;
  color: var(--text-main);
  font-size: var(--font-size-xl);
  cursor: pointer;
  padding: 0 4px;
}
.lqp-modal-close:hover { opacity: 0.8; }

.lqp-modal-body {
  padding: 16px;
  overflow-y: auto;
  flex: 1;
}

.lqp-modal-footer {
  padding: 12px 16px;
  border-top: 1px solid var(--border-soft);
  text-align: right;
}

/* LQP table inside modal */
.lqp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-xs);
}
.lqp-table th, .lqp-table td {
  border: 1px solid var(--border-soft);
  padding: 8px 10px;
  text-align: left;
}
.lqp-table th {
  background: var(--surface-light);
  font-weight: 600;
}
.lqp-table tr.selectable { cursor: pointer; }
.lqp-table tr.selectable:hover { background: var(--blue-soft); }
.lqp-table tr.selected { background: var(--blue-selected); }

/* No price quoted message */
.lqp-npq { 
  color: var(--text-main); 
  font-style: italic; 
  text-align: center; 
  padding: 20px; 
}


/* ==========================================================
   DRAG AND DROP ROW STYLES
   Used for reordering line items in quotation/SO
   ========================================================== */

.drag-handle { 
  cursor: grab; 
  padding: 4px 8px; 
  color: var(--text-faded);
  font-size: var(--font-size-md);
  user-select: none;
}
.drag-handle:hover { color: var(--text-dark); }
.drag-handle:active { cursor: grabbing; }

.item-row {
  transition: transform 0.15s ease;
}
.item-row.dragging {
  position: relative;
  z-index: 100;
  box-shadow: var(--shadow-drag);
  background: var(--card-bg) !important;
}
.item-row.move-up {
  transform: translateY(-100%);
}
.item-row.move-down {
  transform: translateY(100%);
}


/* ==========================================================
   COMMERCIAL TERMS STYLES
   Terms summary and commercial text display
   ========================================================== */

.commercial-text { 
  display: none; 
  font-size: var(--font-size-xs); 
  color: var(--text-dark); 
  margin-top: 4px; 
  padding: 4px 6px; 
  background: var(--surface-subtle); 
  border-radius: var(--radius-soft); 
}

.terms-summary { 
  margin-top: 10px; 
  padding: 10px; 
  background: var(--surface-light); 
  border-radius: var(--radius-soft); 
  font-size: var(--font-size-xs); 
  line-height: 1.6; 
}
.terms-summary div { margin-bottom: 4px; }


/* ==========================================================
   PRINT TOTALS STYLES
   Totals row styling for printed documents
   ========================================================== */

.totals-row-print { 
  display: table-footer-group; 
  background: var(--surface-muted); 
}
.totals-row-print td { 
  padding: 5px 5px !important; 
  font-weight: 600; 
}
.totals-row-print tr:first-child td { 
  border-top: 2px solid var(--border-soft); 
}

.amount-words { 
  font-style: italic; 
  color: var(--text-italic); 
  text-align: right; 
  margin-top: 8px; 
  padding-top: 8px; 
  border-top: 1px solid var(--border-soft); 
}


/* ==========================================================
   FORM GRID LAYOUTS
   Grid layouts for form sections (2, 3, 4 columns)
   ========================================================== */

.form-grid-3 { 
  display: grid; 
  grid-template-columns: repeat(3, 1fr); 
  gap: 10px; 
}
.form-grid-4 { 
  display: grid; 
  grid-template-columns: repeat(4, 1fr); 
  gap: 10px; 
}
.form-grid-3 .form-row, 
.form-grid-4 .form-row { 
  margin-bottom: 0; 
}


/* ==========================================================
   INLINE FIELD STYLES
   Compact inline label + input layouts
   ========================================================== */

.inline-field { 
  display: flex; 
  align-items: center; 
  gap: 8px; 
}
.inline-field label { 
  white-space: nowrap; 
  font-weight: 500; 
  font-size: var(--font-size-sm); 
  min-width: auto; 
  margin: 0; 
}
.inline-field input, 
.inline-field select { 
  flex: 1; 
}

.inline-row { 
  display: flex; 
  align-items: center; 
  gap: 15px; 
  flex-wrap: wrap; 
}


/* ==========================================================
   PANEL HEADER ROW
   Header row with title and actions inside panels
   ========================================================== */

.erp-panel-header-row { 
  display: flex; 
  justify-content: space-between; 
  align-items: center; 
  margin-bottom: 10px; 
}
.erp-panel-header-row .erp-panel-title {
  margin: 0;
}

/* Library list header row — title + search-form + (optional Hide button)
   on a single line. Title left, search elements right-aligned, Hide on
   far right. Wraps to multiple lines on narrow viewports.
   Used by every *_library.html template in place of separate header
   row + below-row search form. */
.erp-lib-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.erp-lib-header-row .erp-panel-title {
  margin: 0;
  border-bottom: none;
  padding-bottom: 0;
  flex-shrink: 0;
}
.erp-lib-search-form {
  margin: 0;
  flex: 1;
  min-width: 0;
}
.erp-lib-search-form .erp-lib-search-row {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* Specificity bump on these — the global .erp-card input/select rule
   (specificity 0,1,1) sets width:100%; we beat it with two classes
   (0,2,0) so the search-row inputs stay compact. */
.erp-lib-search-row .erp-lib-search-input {
  flex: 1;
  min-width: 180px;
  max-width: 340px;
  width: auto;
  padding: 6px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 3px;
  font-size: var(--font-size-sm);
}
.erp-lib-search-row .erp-lib-search-select {
  width: 130px;
  padding: 6px 8px;
  border: 1px solid var(--border-soft);
  border-radius: 3px;
  font-size: var(--font-size-sm);
}
.erp-lib-search-checkbox {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: var(--font-size-xs);
  cursor: pointer;
  white-space: nowrap;
}
.erp-lib-search-checkbox input[type="checkbox"] {
  width: auto;
}


/* ==========================================================
   ADDITIONAL UTILITIES
   ========================================================== */

/* Compact card variant */
.erp-card.compact {
  padding: 8px 10px;
}

/* Search result highlight - covers table rows and item rows */
.search-highlight td,
.item-row.search-highlight,
tr.search-highlight,
tr.search-highlight td {
  background-color: var(--yellow-main) !important;
}

/* Hidden utility class */
.hidden {
  display: none !important;
}

/* Library cross-reference links — uniform across every library table.
   Every link to another doc (SO → Qtn, PI → SO, SD → QPL/SO, etc.) uses
   this class + opens in new tab. The matching column header gets the
   .lib-link-col class so users see a small ↗ arrow on the column itself
   (instead of cluttering every cell with a per-link arrow). */
.lib-link {
  color: var(--blue-main);
  text-decoration: underline;
}
.lib-link:hover {
  color: var(--blue-accent);
}

/* Column header marker — inline span next to the label tells the user
   "links in this column open in a new tab". Templates currently render
   <span class="lib-link-arrow">↗</span>; the literal ↗ inside is hidden
   via font-size:0 and the Lucide square-arrow-out-up-right is painted on
   top via mask-image (matches the auto-arrow used on row-menu items). */
.lib-link-arrow {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-left: 4px;
  font-size: 0;                  /* collapses the literal ↗ inside */
  vertical-align: middle;
  background-color: currentColor;/* matches the th label colour */
  -webkit-mask-image: var(--icon-external-link);
          mask-image: var(--icon-external-link);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}


/* ==========================================================
   CALCULATOR RESULT TABLE
   Used by: pipe, tube, thread, machining calculators
   ========================================================== */

.result-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
}
.result-table th {
  text-align: left;
  padding: 8px 6px 4px;
  font-weight: 600;
  color: var(--blue-main);
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  border-bottom: 1px solid var(--border-soft);
}
.result-table td {
  padding: 6px;
  border-bottom: 1px solid var(--border-light);
}
.result-table td.key {
  width: 55%;
  color: var(--text-main);
}
.result-table td.value {
  text-align: right;
  font-family: monospace;
  color: var(--text-main);
}
.result-table tr.highlight td {
  background: var(--yellow-light);
}


/* ==========================================================
   INFO BADGES
   Used by: calculators, calibration
   ========================================================== */

.badge-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.badge {
  display: inline-flex;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--font-size-xs);
  background-color: var(--blue-light);
  color: var(--blue-main);
}
.badge-warning {
  background-color: #fef2f2;
  color: var(--red-accent);
}


/* ==========================================================
   RADIO GROUP
   Used by: tube, machining calculators
   ========================================================== */

.radio-group {
  display: flex;
  gap: 16px;
  margin-top: 4px;
}
.radio-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--font-size-sm);
  cursor: pointer;
}
.radio-option input[type="radio"] {
  accent-color: var(--blue-main);
  margin: 0;
}


/* ==========================================================
   HSN/CARTON ROW STYLES
   Used by: QPL form and print
   ========================================================== */

.hsn-header-row td { 
  font-weight: 600; 
  background: var(--blue-light) !important; 
}
.hsn-total-row td { 
  font-weight: 600; 
  background: var(--green-light) !important; 
}
.carton-total-row td { 
  font-weight: 600; 
  background: var(--yellow-light) !important; 
}
.hsn-spacer-row td { 
  height: 20px; 
  background: transparent !important; 
  border: none !important; 
}
.wo-change-highlight td { 
  background: #FFF3E0 !important; 
}


/* ==========================================================
   PRINT WATERMARK
   Used by: QPL print, SO print
   ========================================================== */

.watermark {
  position: fixed;
  top: 35%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-30deg);
  font-size: 80pt;
  color: rgba(200, 0, 0, 0.25);
  font-weight: bold;
  z-index: 9999;
  pointer-events: none;
  letter-spacing: 10px;
}


/* ==========================================================
   RAW MATERIAL MASTER PAGE STYLES
   ========================================================== */

/* Page container */
.rm-page {
  width: 100%;
  margin: 0 auto;
}

/* Form + Search row layout */
.rm-form-search-row {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-top: 12px;
}

.rm-form-panel {
  flex: 1 1 auto;
}

.rm-search-panel {
  flex: 0 1 35%;
}

/* Search result cell */
.rm-search-result-cell {
  width: 45px;
  text-align: center;
}

/* Description column in table */
.rm-desc-col {
  max-width: 280px;
  white-space: normal;
  word-break: break-word;
}

/* Auto-generated field styling */
.auto-field {
  background-color: var(--surface-light) !important;
  cursor: default;
}

/* Table scroll container */
.rm-table-scroll {
  max-height: 420px;
  overflow-y: auto;
}

/* Sticky header for RM tables */
.rm-sticky-header {
  position: sticky;
  top: 0;
  background: var(--blue-light);
  z-index: 1;
}

/* Empty cell styling */
.rm-empty-cell {
  text-align: center;
  color: var(--text-muted);
}

/* .rm-dropdown / .rm-dd-item moved upward and unified with .erp-dropdown /
   .dd-item (hover now uses blue-light). See aliases near line 1441. */

/* ==========================================================
   UTILITY CLASSES
   Replaces common inline style="..." patterns across templates.
   ========================================================== */

/* ---------- Text alignment ---------- */
.text-right  { text-align: right; }
.text-center { text-align: center; }
.text-left   { text-align: left; }

/* ---------- Font weight ---------- */
.fw-bold     { font-weight: 600; }
.fw-bolder   { font-weight: 700; }

/* ---------- Font size shortcuts ---------- */
.text-xs  { font-size: var(--font-size-xs); }
.text-sm  { font-size: var(--font-size-sm); }

/* ---------- Text colour shortcuts ---------- */
.text-muted { color: var(--text-muted); }

/* ---------- Spacing ---------- */
.mt-4   { margin-top: 4px; }
.mt-8   { margin-top: 8px; }
.mt-12  { margin-top: 12px; }
.mb-4   { margin-bottom: 4px; }
.mb-10  { margin-bottom: 10px; }
.mb-12  { margin-bottom: 12px; }
.mb-16  { margin-bottom: 16px; }

/* ---------- Flex layouts ---------- */
/* Row with space-between (panel headers, status bars) */
.flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* Centered row with gap (title + hint combos) */
.flex-center {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Simple row with gap (form field groups) */
.flex-row {
  display: flex;
  gap: 12px;
}

/* Wrapping row (common fields section) */
.flex-wrap-row {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
}

/* Right-aligned row (bottom action buttons) */
.flex-end {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
}

.flex-1  { flex: 1; }

/* ---------- Position ---------- */
.pos-rel { position: relative; }

/* ---------- Display ---------- */
.d-inline { display: inline; }
.hidden   { display: none; }

/* ---------- Form grids ---------- */
.form-grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 15px;
}

/* ---------- Search input (compact, for table filters) ---------- */
.erp-search-input {
  width: 150px;
  font-size: var(--font-size-xs);
  padding: 4px 8px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  outline: none;
}
.erp-search-input:focus {
  border-color: var(--blue-main);
}

/* ---------- Dropdown empty message ---------- */
.dd-empty-msg {
  padding: 8px 12px;
  color: var(--text-muted);
  font-size: var(--font-size-xs);
}

/* ---------- SO multi-select: selected state ---------- */
.dd-item.selected {
  background: var(--green-light) !important;
  font-weight: bold;
}

/* ---------- Carton header (packing list) ---------- */
.carton-header {
  background: var(--blue-light);
  padding: 6px 12px;
  border-radius: 6px 6px 0 0;
  font-weight: 600;
  font-size: var(--font-size-sm);
}

/* ---------- Totals row in tables (bold + blue-light bg) ---------- */
.totals-row {
  font-weight: 600;
  background: var(--blue-light);
}
.totals-row-bold {
  font-weight: 700;
  background: var(--blue-light);
}

/* ---------- Info bar (loaded SOs, details strip) ---------- */
.erp-info-bar {
  background: var(--surface-faded);
  padding: 8px 12px;
  border-radius: var(--radius-soft);
  font-size: var(--font-size-xs);
}

/* ---------- Missing data highlight ---------- */
.missing-data {
  background: var(--message-error-background-color) !important;
}

/* ---------- Collapsible panels ---------- */
.collapsed > .entry-content,
.collapsed > .summary-content {
  display: none;
}

/* ---------- Entry mode radio group ---------- */
.entry-mode-radios {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-bottom: 12px;
}
.entry-mode-radios input[type="radio"] { margin: 0; }
.entry-mode-radios label { font-weight: normal; cursor: pointer; margin-right: 14px; }

/* ---------- Breadcrumb ---------- */
.erp-breadcrumb {
  font-size: var(--font-size-md);
  color: var(--blue-main);
  margin-bottom: 2px;
  padding: 0;
}
.erp-breadcrumb a {
  color: var(--blue-main);
  text-decoration: none;
}
.erp-breadcrumb a:hover {
  text-decoration: underline;
}
.erp-breadcrumb .erp-breadcrumb-sep {
  margin: 0 5px;
  color: var(--blue-main);
}
.erp-breadcrumb .erp-breadcrumb-current {
  color: var(--blue-main);
}

/* ==== FILTER BARS, VIEW BUTTONS, TABLE STATES, BADGES ==== */
/* Shared primitives for report/register pages. Added 2026-04-22 for
   Reports hub + Shipment Register. Reusable by any future report. */

.erp-filter-bar {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding: 10px;
  background: var(--surface-muted);
  border-radius: var(--radius-soft);
}
.erp-filter-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.erp-filter-col > label {
  font-size: 11px;
  color: var(--text-muted);
  font-weight: 500;
}
.erp-filter-col > input,
.erp-filter-col > select {
  padding: 6px 10px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  font-size: var(--font-size-xs);
  background: #fff;
}

.erp-view-buttons {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  padding: 8px 12px;
  background: var(--blue-light);
  border-radius: var(--radius-soft);
  margin-bottom: 12px;
}

.erp-col-toggles {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
  padding: 6px 12px;
  background: var(--surface-muted);
  border-radius: var(--radius-soft);
  margin-bottom: 12px;
  font-size: var(--font-size-xs);
  color: var(--text-muted);
}
.erp-col-toggles label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  user-select: none;
}
.erp-col-toggles input[type="checkbox"] {
  width: auto;
  margin: 0;
}

/* When .erp-col-toggles sits inside the blue .erp-view-buttons row,
   drop its own background / padding / margin so it visually merges into
   the parent bar (no grey strip inside the blue strip). */
.erp-view-buttons .erp-col-toggles {
  background: transparent;
  padding: 0;
  margin: 0;
  border-radius: 0;
}

.erp-table-summary-row {
  background: var(--blue-light);
  font-weight: 600;
}

.erp-table-col-hidden {
  display: none !important;
}

/* Opt-in: forces every cell in the table to stay on one line.
   Use on library / register tables where row-height stability matters
   more than text fitting into a narrow column. Horizontal scroll
   handles overflow via the .erp-table-responsive wrapper. */
.erp-table-nowrap th,
.erp-table-nowrap td {
  white-space: nowrap;
}

/* ==========================================================
   LIBRARY READABILITY helpers — visual hierarchy so the eye
   snaps to what matters instead of a uniform grey wall.
   Shared across library tables (status pills already exist as
   .status-badge). Reusable; apply per-cell.
   ========================================================== */
/* Primary key — the doc number your eye lands on first. */
.lib-docno { font-weight: 700; color: var(--blue-main); }
/* The doc number is also the link that opens the record — the most frequent
   action in any library, so it should not be buried in the row menu. Styling
   is deliberately UNCHANGED from the span it replaces (Ashim, 19-08-2026):
   no underline at rest, so the column looks exactly as it did. The underline
   on hover is the only added signal, and it costs nothing when not hovered. */
a.lib-docno { text-decoration: none; }
a.lib-docno:hover { text-decoration: underline; color: var(--blue-accent); }
/* Secondary text — dates, currency codes, PO date: present, not competing. */
.lib-muted { color: var(--grey-main); }
.lib-sub   { color: var(--grey-main); font-size: 11px; }   /* sub-line under a cell */
.lib-cur   { color: var(--grey-main); font-size: 11px; font-weight: 400; }  /* currency code */
/* Numbers — right-aligned, tabular so columns line up. */
.lib-num        { text-align: right; font-variant-numeric: tabular-nums; }
.lib-num-strong { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
/* Pending — amber when there's an outstanding balance; faint when 0/none. */
.lib-pending      { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--yellow-text); }
.lib-pending-zero { text-align: right; color: var(--faded, #aab2bd); }
/* Left status accent bar on the first cell — scan open vs closed by colour.
   Colours follow the SAME categories as the status badges documented at the
   top of the badge block (~L3067), so bar and pill never say different things
   about one row:
     PRE-ISSUE yellow · ACTIVE blue then indigo · IN-FLIGHT teal ·
     FROZEN purple · DONE-POSITIVE green · DONE-NEGATIVE red · REPLACED grey

   Realigned 19-08-2026. Two rules had drifted from that scheme — draft was
   grey where its badge is yellow, and cancelled was grey where its badge is
   red — and several statuses had no rule at all, so their bar rendered
   transparent and the column looked broken. Ashim spotted it on the Qtn
   library: 3 "Partially Ordered" quotations out of 125 had no bar.

   A status with no rule here still degrades safely to transparent rather
   than to a wrong colour. Add new statuses to the category they belong to. */
.erp-table td.lib-accent { border-left: 3px solid transparent; }

/* PRE-ISSUE */
.erp-table tr.lib-acc-draft td.lib-accent { border-left-color: var(--yellow-main); }
/* ACTIVE */
.erp-table tr.lib-acc-submitted td.lib-accent { border-left-color: var(--blue-main); }
.erp-table tr.lib-acc-approved  td.lib-accent { border-left-color: var(--indigo-main); }
/* ACTIVE, part-progressed. Class names deliberately mirror the badge names —
   .status-approved-partial pairs with .lib-acc-approved-partial — so the two
   cannot be changed independently without the mismatch being obvious. */
.erp-table tr.lib-acc-partially-ordered td.lib-accent,
.erp-table tr.lib-acc-part-ordered      td.lib-accent,
.erp-table tr.lib-acc-approved-partial  td.lib-accent,
.erp-table tr.lib-acc-partially-shipped td.lib-accent { border-left-color: var(--yellow-main); }
/* IN-FLIGHT */
.erp-table tr.lib-acc-released    td.lib-accent,
.erp-table tr.lib-acc-in_progress td.lib-accent,
.erp-table tr.lib-acc-in-progress td.lib-accent { border-left-color: var(--teal-main); }
/* FROZEN */
.erp-table tr.lib-acc-locked td.lib-accent { border-left-color: var(--purple-main); }
/* DONE-POSITIVE */
.erp-table tr.lib-acc-closed          td.lib-accent,
.erp-table tr.lib-acc-invoiced        td.lib-accent,
.erp-table tr.lib-acc-finalized       td.lib-accent,
.erp-table tr.lib-acc-completed       td.lib-accent,
.erp-table tr.lib-acc-shipped         td.lib-accent,
/* Approved AND every line ordered (or over-ordered) — the work is done even
   though the status field still reads "Approved". Pairs with the green
   .status-approved-fully badge. Ashim, 19-08-2026: "shouldn't fully ordered
   or excess ordered be green?" — yes, and the bar was showing indigo. */
.erp-table tr.lib-acc-approved-fully  td.lib-accent { border-left-color: var(--green-main); }
/* DONE-NEGATIVE */
.erp-table tr.lib-acc-cancelled td.lib-accent,
.erp-table tr.lib-acc-lapsed    td.lib-accent { border-left-color: var(--red-accent); }
/* REPLACED */
.erp-table tr.lib-acc-superseded td.lib-accent { border-left-color: var(--grey-main); }

.erp-badge-type {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-soft);
  font-size: 10px;
  font-weight: 600;
  line-height: 1.4;
}
.erp-badge-type.dom {
  background: var(--blue-light);
  color: var(--blue-main);
}
.erp-badge-type.exp {
  background: var(--green-light);
  color: var(--green-main);
}

/* ==========================================================
   Customer Aliases modal (Phase 3.5 Chunk 2b)
   Used on Part Master form; opens via Aliases button.
   ========================================================== */
.alias-modal {
  max-width: 1100px;
}
/* Part code shown next to the title in monospace */
.alias-modal-pc {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: var(--font-size-xs);
  color: var(--text-muted);
  font-weight: 400;
  margin-left: 4px;
}
/* Master values strip — sets context for what the override fields fall back to */
.alias-master-strip {
  background: var(--surface-light, #fafbfc);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-soft);
  padding: 8px 12px;
  margin-bottom: 10px;
  font-size: var(--font-size-xs);
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.alias-master-strip strong {
  color: var(--text-muted);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.alias-master-strip span { color: var(--text-main); }
.alias-modal-hint {
  margin: 0 0 12px;
  color: var(--text-muted);
  font-size: var(--font-size-sm);
}
.alias-table {
  font-size: var(--font-size-xs);
}
.alias-col-customer  { width: 230px; }
.alias-col-pn        { width: 170px; }
.alias-col-drg       { width: 170px; }
.alias-col-action    { width: 40px; text-align: center; }
.alias-table th .required-star { margin-left: 0; }  /* tighten star next to label */
.alias-add-row {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.alias-add-row span {
  font-size: var(--font-size-sm);
  color: var(--green-main);
  font-weight: 600;
}
.alias-delete-flag { display: none; }  /* DELETE checkbox stays in DOM, hidden from view */
.alias-modal-footer {
  display: flex;
  align-items: center;
  gap: 8px;
}
.alias-save-status {
  margin-right: auto;
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

.erp-status-delivered {
  color: var(--green-main);
  font-weight: 600;
}
.erp-status-dispatched {
  color: var(--yellow-main);
  font-weight: 600;
}

/* Doc + date merged cell — the number on top line, date below in muted small text.
   Used in Shipment Register to keep column count compact. */
.erp-cell-doc-date {
  line-height: 1.3;
}
.erp-cell-doc-date > .doc-no {
  display: block;
  font-weight: 500;
}
.erp-cell-doc-date > .doc-date {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
}

/* =====================================================================
   CN / DN Form Module
   Mirrors SD invoice form (FC + INR cols, charges, totals, locked FX).
   .cndn-fc body class flips on the .cndn-inr-only columns.
   ===================================================================== */

/* Body-level flag — INR cols hidden when not FC. */
body:not(.cndn-fc) .cndn-inr-only { display: none !important; }

/* Banner */
.cndn-banner {
  padding: 12px 16px;
  margin-bottom: 12px;
  border-left: 4px solid;
}
.cndn-banner-cn { background: #ffebee; border-left-color: #c62828; }
.cndn-banner-dn { background: #e3f2fd; border-left-color: #1565c0; }
.cndn-banner-cn .cndn-banner-title { color: #c62828; }
.cndn-banner-dn .cndn-banner-title { color: #1565c0; }
.cndn-banner-sub { margin-left: 10px; font-size: 13px; color: #555; }
.cndn-banner-status { float: right; }

.cndn-status-meta { color: var(--text-muted); font-size: var(--font-size-xs); }

/* Section card */
.cndn-section { padding: 12px 16px; margin-bottom: 12px; }
.cndn-divider { margin-bottom: 12px; }

/* Grids */
.cndn-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.cndn-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.cndn-grid-span-3 { grid-column: 1 / 4; }

.req-mark { color: red; }
.cndn-reason-input { width: 100%; }

/* Items header bar */
.cndn-items-header { display: flex; justify-content: space-between; align-items: center; }
.cndn-items-title { margin: 0; }
.cndn-items-actions { display: flex; gap: 8px; align-items: center; }
.cndn-search-input { width: 220px; font-size: var(--font-size-xs); padding: 4px 8px; }

/* Items table column widths. INR cols collapse via cndn-inr-only when not FC. */
.cndn-items-table .col-sn       { width: 3%;  text-align: center; }
.cndn-items-table .col-code     { width: 9%;  text-align: center; }
.cndn-items-table .col-desc     { width: 22%; text-align: center; }
.cndn-items-table .col-hsn      { width: 7%;  text-align: center; }
.cndn-items-table .col-gst      { width: 5%;  text-align: center; }
.cndn-items-table .col-qty      { width: 6%;  text-align: center; }
.cndn-items-table .col-uom      { width: 5%;  text-align: center; }
.cndn-items-table .col-rate     { width: 8%;  text-align: center; }
.cndn-items-table .col-amt      { width: 9%;  text-align: center; }
.cndn-items-table .col-rate-inr { width: 7%;  text-align: center; }
.cndn-items-table .col-amt-inr  { width: 8%;  text-align: center; }
.cndn-items-table .col-reason   { width: 8%;  text-align: center; }
.cndn-items-table .col-affects  { width: 5%;  text-align: center; }
.cndn-items-table .col-del      { width: 3%;  text-align: center; }

.cell-center { text-align: center; }
.cell-right  { text-align: right; }
.cell-strong { font-weight: 600; }
.cell-italic { font-style: italic; }
.cell-label  { font-weight: 500; }
.cell-desc-view { white-space: normal; line-height: 1.3; }
.cell-center-input { text-align: center; }
.cell-right-input  { text-align: right; }
.cell-reason-select { width: 100%; font-size: 11px; }

/* Charges table */
.cndn-charges-table .col-charge-label { width: 40%; }
.cndn-charges-table .col-charge-fc    { width: 30%; text-align: right; }
.cndn-charges-table .col-charge-inr   { width: 30%; text-align: right; }
.charge-label-input { width: 95%; }

/* Totals — right-aligned summary block */
.cndn-totals-table { margin-left: auto; max-width: 600px; }
.cndn-totals-table td { padding: 6px 10px; }
.cndn-totals-grand td { border-top: 2px solid #444; font-size: 1.05em; }

.cndn-remarks { width: 100%; }

/* E-invoice */
.cndn-einv-row { margin-bottom: 12px; }
.cndn-einv-actions { display: flex; gap: 8px; }
.cndn-einv-upload-label { cursor: pointer; margin: 0; }
.cndn-einv-file { display: none; }

/* Action row */
.cndn-actions-row { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }

/* SD library badge — small chip next to status when an SD has linked
   submitted CN/DN. Helps users avoid double-issuing against the same SD. */
.cndn-link-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  background: #fff3e0;
  color: #c62828;
  border: 1px solid #c62828;
  border-radius: 3px;
  letter-spacing: 0.3px;
  vertical-align: middle;
}

/* Picker modal — uses lqp-modal-* infrastructure for the frame */
.cndn-picker-modal { width: 95%; max-width: 1300px; }
.cndn-picker-header-inv { font-weight: 600; color: var(--text-muted); margin-left: 6px; font-size: 13px; }
.cndn-picker-hint { margin-top: 0; font-size: 13px; color: var(--text-muted); }
.cndn-picker-table { font-size: var(--font-size-sm); }
.cndn-picker-charges-title { margin-top: 16px; margin-bottom: 6px; font-weight: 600; }
.cndn-picker-charges-table { font-size: var(--font-size-sm); }

.cndn-picker-table .picker-col-check    { width: 4%;  text-align: center; }
.cndn-picker-table .picker-col-line     { width: 4%;  text-align: center; }
.cndn-picker-table .picker-col-part     { width: 12%; }
.cndn-picker-table .picker-col-desc     { width: 32%; }
.cndn-picker-table .picker-col-orig     { width: 9%;  text-align: right; }
.cndn-picker-table .picker-col-cred     { width: 9%;  text-align: right; }
.cndn-picker-table .picker-col-bal      { width: 9%;  text-align: right; }
.cndn-picker-table .picker-col-rate     { width: 9%;  text-align: right; }
.cndn-picker-table .picker-col-pickqty  { width: 12%; text-align: right; }

.cndn-picker-charges-table .picker-col-check   { width: 4%;  text-align: center; }
.cndn-picker-charges-table .picker-col-orig    { width: 16%; text-align: right; }
.cndn-picker-charges-table .picker-col-cred    { width: 16%; text-align: right; }
.cndn-picker-charges-table .picker-col-bal     { width: 16%; text-align: right; }
.cndn-picker-charges-table .picker-col-pickamt { width: 18%; text-align: right; }

.cndn-picker-row-disabled { color: var(--text-muted); background: #fafafa; }

/* ---------- Print ---------- */
@media print {
  .no-print { display: none !important; }
  .erp-btn, .erp-header-actions { display: none !important; }
  .erp-breadcrumb { display: none !important; }
}

