/* ============================================================================
 * components.css — Direction B reskin, loaded LAST. Group 1: SHELL
 * (sidebar · topbar · nav · buttons · KPI cards · chips). Uses !important +
 * high specificity to win over the legacy inline cascade. Markup/JS untouched.
 * ========================================================================== */

/* ---- app canvas + base type --------------------------------------------- */
body{font-family:var(--font);color:var(--text);-webkit-font-smoothing:antialiased;letter-spacing:-.006em}

/* ---- APP SHELL: viewport-locked so the content scrolls INSIDE .main-area,
   which lets the sticky topbar actually stick (a body-level scroll defeats
   position:sticky). Sidebar is already position:fixed. ---------------------- */
html,body{height:100%!important}
body{overflow:hidden!important}
#app.app{height:100vh!important;overflow:hidden!important}
.main-area{height:100vh!important;overflow-y:auto!important;overflow-x:hidden!important;padding-top:0!important}

/* ---- SIDEBAR ------------------------------------------------------------- */
#sidebar.sidebar{background:var(--surface)!important;border-right:1px solid var(--border)!important}
.sidebar-brand{padding:16px 16px 12px!important;border-bottom:1px solid var(--border)!important}
.brand-mark{border-radius:8px!important;box-shadow:var(--sh-sm)}
.brand-title{font-weight:600!important;letter-spacing:-.02em!important}
.brand-sub,.brand-version{color:var(--text-3)!important;letter-spacing:.06em}
.sidebar-nav{padding:8px 10px!important}

.nav-item{position:relative;display:flex;align-items:center;gap:10px;width:100%;
  background:transparent!important;color:var(--text-2)!important;border:0!important;
  padding:8px 11px!important;border-radius:var(--r-md)!important;min-height:36px;font-weight:500!important;
  transition:background .15s var(--ease-out),color .15s var(--ease-out)!important}
.nav-item svg{color:var(--text-3)!important;width:var(--ico-md);height:var(--ico-md);transition:color .15s var(--ease-out)}
.nav-item:hover{background:var(--surface-3)!important;color:var(--text)!important}
.nav-item:hover svg{color:var(--text-2)!important}
.nav-item.active{background:var(--brand-bg)!important;color:var(--brand-700)!important;font-weight:600!important}
.nav-item.active svg{color:var(--brand)!important}
.nav-item.active::before{content:"";position:absolute;left:-10px;top:7px;bottom:7px;width:3px;
  border-radius:0 3px 3px 0;background:var(--brand)}
.nav-badge{margin-left:auto!important;background:var(--brand)!important;color:#fff!important;
  font-family:var(--mono);font-size:11px!important;font-weight:600!important;border-radius:20px!important;padding:1px 7px!important}
.sidebar-foot{border-top:1px solid var(--border)!important;padding:8px 10px!important}

/* ---- TOPBAR — sticky so it never scrolls away on long tables/kanban ------ */
header.topbar{position:sticky!important;top:0!important;z-index:30!important;
  border-bottom:1px solid var(--border)!important;padding:14px 24px!important;background:var(--surface)!important}
#topbarEyebrow{font-size:10.5px!important;letter-spacing:.12em!important;text-transform:uppercase;color:var(--text-3)!important;font-weight:600!important}
#topbarTitle{font-family:var(--font)!important;font-weight:600!important;letter-spacing:-.028em!important;color:var(--text)!important}
#topbarTitle em,h1 em{font-style:normal!important;color:var(--brand)!important}

/* ---- HEADROOM — hide the sticky topbar on scroll-down, reveal on scroll-up.
 * Headroom.js (public/js/headroom.min.js) toggles the classes; wiring lives in
 * erp-headroom.js with the .main-area scroller. We only animate transform (GPU)
 * so long tables/kanban stay smooth. Slide curve = --ease-drawer. ------------ */
header.topbar.headroom{will-change:transform;transition:transform .24s var(--ease-drawer)!important}
header.topbar.headroom--pinned{transform:translateY(0)!important}
header.topbar.headroom--unpinned{transform:translateY(-100%)!important}
/* A page toolbar pinned BELOW the header has to travel with it. Shipped's
   filter bar sticks at top:64px — a gap the header was assumed to be filling —
   so when the header slid away the bar hung in mid-air over the table with a
   header-shaped hole above it. It now slides out by its own height plus that
   offset, on the same curve, and comes back with the header on scroll-up.
   Generic on purpose: any sticky page toolbar gets this without new CSS. */
.main-area .pane-head-slim,
.main-area .page-toolbar{transition:transform .24s var(--ease-drawer)}
.main-area.hdr-unpinned .pane-head-slim,
.main-area.hdr-unpinned .page-toolbar{transform:translateY(calc(-100% - 64px))}
@media (prefers-reduced-motion: reduce){
  /* Same contract as the header above: motion-sensitive users keep it in place
     rather than watching two bars slide. */
  .main-area .pane-head-slim,
  .main-area .page-toolbar{transition:none}
  .main-area.hdr-unpinned .pane-head-slim,
  .main-area.hdr-unpinned .page-toolbar{transform:none}
}
@media (prefers-reduced-motion: reduce){
  /* keep it readable for motion-sensitive users — never slide, never disappear */
  header.topbar.headroom{transition:none!important}
  header.topbar.headroom--unpinned{transform:translateY(0)!important}
}

/* ---- BUTTONS ------------------------------------------------------------- */
.btn,.btn-primary,#refresh-btn{border-radius:var(--r-md)!important;font-weight:550!important;
  transition:transform .12s var(--ease-out),background .15s var(--ease-out),border-color .15s var(--ease-out),box-shadow .15s var(--ease-out)!important}
.btn:active,.btn-primary:active,#refresh-btn:active{transform:scale(.97)}
.btn-primary,#refresh-btn{background:var(--brand)!important;border:1px solid var(--brand)!important;color:#fff!important;box-shadow:var(--sh-sm)}
.btn-primary:hover,#refresh-btn:hover{background:var(--brand-600)!important;border-color:var(--brand-600)!important}

/* Module-prefixed buttons (Accounting acct-btn, Order-sheet os-btn*, Workspace
 * wsx-btn*, PrintFlow pfx-btn) share the shell button FEEL — radius, weight,
 * transition, tactile press. No !important and no colors here: each module's
 * own variant styling (ghost/warn/primary) stays authoritative; this only
 * fills the polish gaps so buttons stop feeling like different products. */
.acct-btn,.os-btn,.pfx-btn,[class^="wsx-btn"],[class*=" wsx-btn"]{
  border-radius:var(--r-md);font-weight:550;
  transition:transform .12s var(--ease-out),background .15s var(--ease-out),border-color .15s var(--ease-out),box-shadow .15s var(--ease-out)}
.acct-btn:active,.os-btn:active,.pfx-btn:active,[class^="wsx-btn"]:active,[class*=" wsx-btn"]:active{transform:scale(.97)}
@media (prefers-reduced-motion: reduce){
  .acct-btn,.os-btn,.pfx-btn,[class^="wsx-btn"],[class*=" wsx-btn"]{transition:none}
  .acct-btn:active,.os-btn:active,.pfx-btn:active,[class^="wsx-btn"]:active,[class*=" wsx-btn"]:active{transform:none}
}

/* ---- KPI CARDS ----------------------------------------------------------- */
.kpi{background:var(--surface)!important;border:1px solid var(--border)!important;border-radius:var(--r-lg)!important;
  box-shadow:var(--sh-sm)!important;position:relative;overflow:hidden;transition:box-shadow .18s var(--ease-out)}
.kpi::after{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--brand);opacity:.85}
.kpi.accent-warn::after,.kpi.accent-amber::after{background:var(--warn)}
.kpi.accent-danger::after,.kpi.accent-red::after{background:var(--danger)}
.kpi.accent-info::after{background:var(--info)}
@media (hover:hover) and (pointer:fine){.kpi:hover{box-shadow:var(--sh-md)!important}}

/* ---- generic surfaces (cards / panels used app-wide) --------------------- */
.card,.panel,.section-card{border-radius:var(--r-lg)!important;border:1px solid var(--border)!important;box-shadow:var(--sh-sm)!important}

/* ---- status chips / pills (stage badges etc.) --------------------------- */
.chip,.pill,.status-chip{border-radius:20px!important;font-weight:550!important}

/* ===========================================================================
 * GROUP 2 — Orders table + Kanban
 * ========================================================================= */

/* ---- pane header (shared by kanban + list views) ------------------------ */
.pane-head{padding:16px 24px!important}
.pane-head h2,.pane-head .meta{letter-spacing:-.01em}

/* ---- kanban toolbar: segmented + filter pills --------------------------- */
.kb-toolbar{gap:10px!important}
.kb-seg{background:var(--surface-3)!important;border-radius:var(--r-md)!important;padding:3px!important;border:1px solid var(--border)!important}
.kb-seg button{border:0!important;background:transparent!important;color:var(--text-2)!important;font-weight:550!important;border-radius:7px!important;padding:5px 12px!important;transition:color .15s var(--ease-out),background .15s var(--ease-out)}
.kb-seg button.on{background:var(--surface)!important;color:var(--brand-700)!important;box-shadow:var(--sh-sm)!important}
.qf-pill{border:1px solid var(--border)!important;background:var(--surface)!important;color:var(--text-2)!important;border-radius:20px!important;font-weight:550!important;padding:5px 12px!important;transition:transform .12s var(--ease-out),border-color .15s var(--ease-out),background .15s var(--ease-out)}
.qf-pill:hover{border-color:var(--border-strong)!important;background:var(--surface-2)!important}
.qf-pill:active{transform:scale(.97)}
.qf-pill.active,.qf-pill.on{background:var(--brand-bg)!important;color:var(--brand-700)!important;border-color:var(--brand-ring)!important}

/* ---- kanban board + lanes + cards -----------------------------------------
   The !important lane/head/count/card overrides that lived here (surface-2
   lanes, 600-weight heads, mono count pills, r-md cards) are GONE — they were
   flattening the colour-identity tints. The orders kanban now renders the
   Sample Tracker's SMX anatomy (tinted lanes .26/.09/.38, 800/12.5px heads,
   bare "(n)" counts, 10px white cards) straight from index.html's base rules.
   Only the Hold-divider identity stays. */
.kanban-hold-divider-label{color:var(--danger)!important;font-weight:600!important;letter-spacing:.02em}
.kanban-hold-divider-count{font-family:var(--mono);color:var(--danger-fg,#B23A34)!important}

/* ---- owner rule (11 Aug 2026): stages side-scroll on phones, never stack --
   The grouped kanban (.kb-grouped, Card table) switches to display:block in
   index.html, which stacks the stage columns vertically on a phone. This
   mobile-only override restores the base board's flex row — every stage is a
   fixed-width column you swipe through, with snap. Desktop grouped mode is
   untouched. !important because the index.html rule it corrects also wins on
   specificity otherwise. */
@media (max-width: 768px){
  .kanban-board.kb-grouped{display:flex!important;flex-wrap:nowrap;overflow-x:auto!important;overflow-y:hidden!important;gap:12px;-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;padding-bottom:16px}
  .kanban-board.kb-grouped>*{flex:0 0 auto}
  .kanban-board.kb-grouped .kanban-lane{flex:0 0 78vw;max-width:78vw;scroll-snap-align:start}
}

/* ---- universal data tables (orders/customers/shipped/tasks/approvals) ---- */
table thead th{background:var(--surface-2)!important;border-bottom:1px solid var(--border)!important;
  text-transform:uppercase;font-size:11px!important;letter-spacing:.05em!important;color:var(--text-3)!important;font-weight:600!important;padding:8px 14px!important}
table tbody td{border-bottom:1px solid var(--border)!important;padding:8px 14px!important;vertical-align:middle}
table tbody tr{transition:background .12s var(--ease-out)}
@media (hover:hover) and (pointer:fine){table tbody tr:hover{background:var(--surface-2)!important}}
/* tabular numerals for any cell that holds a number/id */
td .mono,.num,.cell-num,td[data-num]{font-family:var(--mono);font-feature-settings:"tnum"}

/* ---- owner rule (2 Aug 2026): tables + lists are CENTER-aligned ------------
 * Headers and content alike, everywhere. !important so it also beats the many
 * inline style="text-align:left/right" attributes scattered through renderers
 * (a stylesheet !important declaration wins over a non-important inline one). */
table th,table td{text-align:center!important}
/* Owner follow-up (2 Aug): centring is for TABLES only. The mobile CARD
 * layouts (a row becomes a card, each cell a "label … value" line) keep their
 * original look — label left, value right — because centring a value between
 * a left-hand label and the card edge reads badly. Each card layout is
 * restored inside ITS OWN breakpoint, so a table that is still a real table at
 * that width stays centred. */
@media (max-width:900px){
  #leadsPipeline .lll-table tbody td{text-align:left!important}
}
@media (max-width:760px){
  #customersView #ciTable td{text-align:right!important}
  #customersView #ciTable td[data-label="Customer"]{text-align:left!important}
}
@media (max-width:720px){
  .sales-orders-table td,.kpi-pop-table td,.om-list-table td{text-align:right!important}
  .sales-orders-table td[data-label="Order ID"],.kpi-pop-table td.kpi-pop-name,
  .om-list-table td.id,.om-list-table td.blk{text-align:left!important}
}
@media (max-width:700px){
  .roles-matrix-table tbody td{text-align:left!important}
}

/* ---- TABLET LANDSCAPE (iPad ~1024–1366px): wide data tables ---------------
 * The app drops to its mobile card layout at ≤900px, so iPad landscape runs
 * the full desktop tables. Two fixes there: (1) denser cells + slightly
 * smaller type so more columns fit, and (2) let any table that's still wider
 * than its card scroll HORIZONTALLY inside the card instead of being clipped
 * by .main-area's overflow-x:hidden (which made the right columns vanish). */
@media (min-width:901px) and (max-width:1366px){
  table thead th{padding:7px 10px!important;font-size:10.5px!important}
  table tbody td{padding:7px 10px!important;font-size:12.5px}
  /* common table wrappers across the app → scroll instead of clip/overflow */
  .card-table,.kpi-pop-table-wrap,.sales-orders-scroll,.customers-table-wrap,
  .users-table-wrap,.shipped-table-wrap,.table-scroll,.trk-table-wrap,
  .list-modal-body,.kpi-pop-body{overflow-x:auto!important;-webkit-overflow-scrolling:touch}
  /* keep tables from forcing the page wider than the viewport */
  .card-table>table,.sales-orders-table{max-width:none}
}

/* ===========================================================================
 * GROUP 4 — Production / OVX / CMT / PrintFlow / Accessories overlays
 * ========================================================================= */
#prodTrackerOverlay,#accessoriesOverlay,#printingOverlay,#storeLedgerOverlay,#vendorMasterOverlay{background:var(--bg)!important}

/* order-picker cards (production tracker) */
.pf-order{background:var(--surface)!important;border:1px solid var(--border)!important;border-radius:var(--r-md)!important;
  box-shadow:var(--sh-sm)!important;transition:box-shadow .15s var(--ease-out),border-color .15s var(--ease-out),transform .12s var(--ease-out)!important}
@media (hover:hover) and (pointer:fine){.pf-order:hover{box-shadow:var(--sh-md)!important;border-color:var(--border-strong)!important}}
.pf-order:active{transform:scale(.995)}

/* overlay header buttons */
#pfDashBtn,#pfBackBtn,#pfCloseBtn,.pfx-close,.pfx-back{border-radius:var(--r-md)!important;transition:background .15s var(--ease-out),transform .12s var(--ease-out)!important}
#pfCloseBtn:active,#pfBackBtn:active,#pfDashBtn:active,.pfx-close:active{transform:scale(.95)}

/* per-order stage tracking UI (fabric pipeline + garment line) */
.pf-stage,.pt-tile,.pt-tiles,.pt-card,.pf-stage-card{border:1px solid var(--border)!important;border-radius:var(--r-lg)!important;background:var(--surface)!important;box-shadow:var(--sh-sm)!important}
.pf-tab{transition:color .15s var(--ease-out),background .15s var(--ease-out)!important;border-radius:var(--r-md)!important}
.pf-tab.active{color:var(--brand-700)!important}
.pt-vend{transition:color .15s var(--ease-out)}

/* shared accessories + printing board (pfx-*) */
.pfx-wrap{background:var(--bg)!important}
.pfx-top{border-bottom:1px solid var(--border)!important;background:var(--surface)!important}
.pfx-board{gap:14px!important}
.pfx-card,.pfx-col,.pfx-lane{background:var(--surface)!important;border:1px solid var(--border)!important;border-radius:var(--r-md)!important;box-shadow:var(--sh-sm)!important;transition:box-shadow .15s var(--ease-out)!important}
@media (hover:hover) and (pointer:fine){.pfx-card:hover{box-shadow:var(--sh-md)!important}}

/* ===========================================================================
 * GROUP 6 — Modals, forms, AI assistant panel
 * ========================================================================= */

/* modals / dialogs / drawers — modals stay center-origin (emil) */
.app-dialog,.modal,.side-drawer,.file-viewer{background:var(--surface)!important;border:1px solid var(--border)!important;
  border-radius:var(--r-xl)!important;box-shadow:var(--sh-lg)!important}
.app-dialog-title,.modal-title,.side-drawer-title{font-weight:600!important;letter-spacing:-.02em!important}
/* emil: modal scales in from its center (0.97 + opacity), backdrop fades. Modals
   are occasional, so a subtle entrance is delight, not annoyance. */
.app-dialog,.modal-card,.modal-content{animation:dlgIn .16s var(--ease-out)}
@keyframes dlgIn{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}
@media (prefers-reduced-motion:reduce){.app-dialog,.modal-card,.modal-content{animation:none!important}}

/* form controls — consistent border + brand focus ring (the Shadow-DOM calc is
   isolated and unaffected). */
input[type=text],input[type=search],input[type=number],input[type=email],input[type=tel],
input[type=date],input[type=password],input:not([type]),select,textarea{
  border-radius:var(--r-md)!important;border:1px solid var(--border)!important;background:var(--surface)!important;
  font-family:var(--font);transition:border-color .15s var(--ease-out),box-shadow .15s var(--ease-out)!important}
input[type=text]:focus,input[type=search]:focus,input[type=number]:focus,input[type=email]:focus,
input[type=tel]:focus,input[type=date]:focus,input[type=password]:focus,input:not([type]):focus,select:focus,textarea:focus{
  border-color:var(--brand)!important;box-shadow:0 0 0 3px var(--brand-ring)!important;outline:none!important}

/* AI assistant chat panel */
.ai-chat,.ai-chat-thread{background:var(--surface)!important}
.ai-msg.user,.ai-msg-user{background:var(--brand-bg)!important;color:var(--brand-700)!important;border-radius:var(--r-lg)!important}
.ai-msg.bot,.ai-msg.assistant,.ai-msg-bot{background:var(--surface-2)!important;border:1px solid var(--border)!important;border-radius:var(--r-lg)!important}
.ai-nav-chip{background:var(--brand-bg)!important;color:var(--brand-700)!important;border:1px solid var(--brand-ring)!important;border-radius:20px!important;transition:transform .12s var(--ease-out)}
.ai-nav-chip:active{transform:scale(.96)}

/* ---- KPI card polish (ui-ux-pro-max + emil): premium depth WITHOUT movement.
 * These cards re-render on live data and a transform-lift caused hover flicker
 * (removed 13 Jun) — so the "lift" comes from shadow + a brand-tinted border,
 * never transform. Plus tabular numerals so big values read crisp & aligned.
 * Hover gated to fine pointers; touch gets a tap (:active) depth cue instead. */
.kpi.kpi-clickable,.ci-kpi{transition:box-shadow .18s var(--ease-out),border-color .18s var(--ease-out)}
.kpi-value,.k-val,.ci-kpi .num{font-feature-settings:"tnum" 1;letter-spacing:-.015em}
@media (hover:hover) and (pointer:fine){
  .kpi.kpi-clickable:hover,.ci-kpi:hover{box-shadow:var(--sh-md);border-color:var(--brand-300)}
}
@media (hover:none){ .kpi.kpi-clickable:active,.ci-kpi:active{box-shadow:var(--sh-md)} }

/* ═══════════════════════════════════════════════════════════════════════════
 * REDESIGN PASS 1 — topbar + dashboard (ui-ux-pro-max direction, green identity)
 * Bold-but-on-brand: confident typography, a green accent system on section
 * headers, consistent depth + motion. Typography/decoration only — no layout
 * changes, so zero feature/density loss.
 * ══════════════════════════════════════════════════════════════════════════ */

/* Section headers → a crisp uppercase eyebrow with a green accent bar, so each
 * dashboard band reads as a deliberate section rather than loose text. */
.kpi-section-label{
  display:flex!important; align-items:center; gap:9px;
  font-size:11px!important; font-weight:800!important; letter-spacing:.085em!important;
  text-transform:uppercase!important; color:var(--text-2)!important;
}
.kpi-section-label::before{
  content:""; flex:none; width:3px; height:13px; border-radius:2px;
  background:linear-gradient(180deg,var(--brand),var(--brand-300));
}

/* Topbar title → tighter, more confident hierarchy (eyebrow + bold title). */
.main-area > .topbar .topbar-title .eyebrow{ font-weight:800!important; letter-spacing:.13em!important; }
.main-area > .topbar .topbar-title h1{ font-weight:700!important; letter-spacing:-.02em!important; }

/* Topbar action icons → consistent, calm hover so the header feels intentional. */
.main-area > .topbar .topbar-right .notif-bell,
.main-area > .topbar .topbar-right #custTopBtn{ transition:background .14s var(--ease-out),border-color .14s var(--ease-out); }
@media (hover:hover) and (pointer:fine){
  .main-area > .topbar .topbar-right .notif-bell:hover,
  .main-area > .topbar .topbar-right #custTopBtn:hover{ background:var(--surface-3); border-color:var(--border-strong); }
}

/* KPI label → quieter, wider-tracked so the big value dominates (clear hierarchy). */
.kpi-label,.k-sub:first-child{ letter-spacing:.04em; }

/* Data-table row highlight on hover — the data-dense-dashboard signature the
 * ui-ux-pro-max generator flagged ("row highlighting on hover"). Faint brand tint. */
@media (hover:hover) and (pointer:fine){
  table tbody tr:hover{ background:var(--brand-bg); }
}
/* Visible focus ring for keyboard nav (accessibility + a more deliberate feel).
 * Only on keyboard focus (:focus-visible), so mouse clicks stay clean. */
.btn:focus-visible,.btn-primary:focus-visible,.kpi.kpi-clickable:focus-visible,
.nav-item:focus-visible,.topbar-right .notif-bell:focus-visible,
.acct-btn:focus-visible,.os-btn:focus-visible,.pfx-btn:focus-visible,
[class^="wsx-btn"]:focus-visible,[class*=" wsx-btn"]:focus-visible,
input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:2px solid var(--brand); outline-offset:2px;
  box-shadow:0 0 0 4px var(--brand-ring);
}

/* ---- COMPONENT STATES — inline field errors, panel retry, button busy -----
 * Primitives for the three states the audit found missing app-wide.
 * JS helpers live in js/erp-ui-states.js (erpFieldError / erpPanelError /
 * erpBtnBusy). aria-invalid is the canonical hook so screen readers get it. */
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"],.input-error{
  border-color:var(--danger)!important;
  box-shadow:0 0 0 3px rgba(192,68,61,.14)!important;
}
.field-error-msg{display:block;margin-top:4px;font-size:11.5px;font-weight:550;color:var(--danger);line-height:1.35}
/* Panel-level fetch failure — replaces toast-only errors with a persistent,
 * retryable inline state. Rendered by erpPanelError(container, msg, retryFn). */
.panel-error{display:flex;flex-direction:column;align-items:center;gap:10px;
  padding:28px 18px;text-align:center;color:var(--text-2);font-size:13px}
.panel-error .pe-ico{width:34px;height:34px;border-radius:50%;background:var(--danger-bg);
  color:var(--danger);display:grid;place-items:center;font-size:16px;font-weight:700}
.panel-error .pe-retry{border:1px solid var(--border-strong);background:var(--surface);
  color:var(--text);border-radius:var(--r-md);padding:7px 16px;font:inherit;font-size:12.5px;
  font-weight:600;cursor:pointer;transition:background .15s var(--ease-out),border-color .15s var(--ease-out)}
.panel-error .pe-retry:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-bg)}
/* Button busy — spinner replaces label visually; button keeps its box size.
 * Toggle with erpBtnBusy(btn, true/false). Works on .btn-primary and module buttons. */
.btn-busy{position:relative!important;pointer-events:none;color:transparent!important}
.btn-busy::after{content:"";position:absolute;inset:0;margin:auto;width:14px;height:14px;
  border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;
  animation:erpBtnSpin .7s linear infinite}
.btn-busy.btn-busy-dark::after{border-color:rgba(60,117,56,.25);border-top-color:var(--brand)}
@keyframes erpBtnSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){
  .btn-busy::after{animation-duration:1.4s}
}

/* ═══════════════════════════════════════════════════════════════════════════
 * GLASSMORPHISM — frosted translucent surfaces, perf-safe.
 * Applied ONLY to small fixed/floating elements (sticky topbar, dock, menus,
 * modals, chat panel). Blur is GPU-cheap on small surfaces; we deliberately
 * NEVER blur large scrolling content (cards, tables, lists) so scroll stays 60fps.
 * Gated behind @supports so unsupported browsers keep the solid fallback.
 * ══════════════════════════════════════════════════════════════════════════ */
/* SCOPE (17 Jul 2026): glass is now allowed on THREE chrome surfaces only —
 * the left rails, the dock, and the header. Everything else is solid. Panels,
 * popovers and menus were frosted; they are opaque now. Modal scrims keep their
 * dim (a scrim is meant to be see-through) but lose the blur.
 * Do NOT reintroduce backdrop-filter outside this block: besides the look, it
 * makes an element a containing block for `position:fixed` descendants, which
 * has already broken fixed children more than once (see #wsxPanel + the chat
 * expand-to-centre note in workspace.css). */
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  /* Sticky page header → frosted, content scrolls softly beneath it */
  .main-area > .topbar{
    background:rgba(252,252,250,.72)!important;
    -webkit-backdrop-filter:blur(12px) saturate(1.4); backdrop-filter:blur(12px) saturate(1.4);
  }
  /* macOS-style dock */
  #wsxDock{ background:rgba(255,255,255,.6)!important;
    -webkit-backdrop-filter:blur(18px) saturate(1.5); backdrop-filter:blur(18px) saturate(1.5); }
}
/* ── Solid everywhere else ──────────────────────────────────────────────────
 * ONE authoritative rule rather than chasing ~20 individual sites: it kills the
 * frost on every element EXCEPT the chrome surfaces named above. It also reaches
 * the CSS the JS modules inject at runtime and inline styles (a stylesheet
 * !important outranks an inline declaration), so a module can't quietly re-frost
 * a page. `backdrop-filter:none` is the initial value, so this is a no-op on the
 * elements that never had it.
 * Keep-list: .topbar (header) · #wsxDock (dock) · #sidebar, .lds-rail,
 * #settingsNav (left rails). Add here — never by re-adding blur elsewhere. */
*:not(.topbar):not(#wsxDock):not(#sidebar):not(.lds-rail):not(#settingsNav){
  -webkit-backdrop-filter:none!important; backdrop-filter:none!important; }

/* Glass = translucent background + blur. The rule above removes only the BLUR,
 * so every element that was translucent BY DESIGN must also go opaque — else it
 * just looks see-through, which is worse than the glass was.
 * SCRIMS ARE DELIBERATELY EXCLUDED: a fixed inset:0 dim layer (.modal-backdrop,
 * .app-dialog-backdrop, .wa-back, .trk-pop-backdrop, .wsx-*-bd …) is *meant* to
 * show the page through it. Those keep their rgba dim and lose only the frost. */
/* .wsx-edge-btn is NOT in this list. It has real state backgrounds — purple
 * when focus is on, brand green + white bubble for chat — and a blanket
 * `background:#fff!important` here outranked them (and, being a shorthand,
 * wiped background-image too), painting live buttons blank white. Trying to
 * carve states out with :not() only raised specificity and broke a different
 * one. It now sets its own opaque base in workspace.css, next to its states,
 * where ordinary cascade rules apply and no !important fight is needed. */
#wsxPanel,.ai-panel,.wsx-pop,.erp-ctx,.wsx-row-menu,
.wsx-snooze-menu,.wsx-msgmenu,.wsx-mention-pop{ background:#fff!important; }
#accessoriesOverlay .pfx-top{ background:#fff!important; }
.ovx-acc.open .ovx-acc-body{ background:#fff!important; }
/* `body` prefix is REQUIRED on these two, not stylistic: redesign-pages.css
 * loads AFTER components.css and declares their translucent background with
 * !important too. Equal specificity + both !important = the later sheet wins,
 * so a plain `.login-card{...!important}` here silently lost and the card stayed
 * see-through with the blur already stripped — the worst of both. The extra
 * `body` outranks it instead of relying on source order. */
body #shippedView .pane-head-slim{ background:#fff!important; }
body .login-card{ background:#fff!important; }

@media (prefers-reduced-motion:reduce){
  .nav-item,.btn,.btn-primary,#refresh-btn,.kpi,.kanban-card,.qf-pill,.kb-seg button,table tbody tr,.pf-order,.pfx-card,input,select,textarea{transition:none!important}
}

/* Mobile: drop things that don't belong on a phone.
   - OVX order header: hide the Basecamp ("B") and WhatsApp icons.
   - The workflow builder is a desktop-only drag/drop canvas — hide the overlay
     (the !important beats its inline display:flex, so it can't open) and its
     launch buttons so nothing invites a dead tap. */
@media (max-width:600px){
  #orderModalChatSlot, #orderModalWhatsappSlot { display:none !important; }
  #wfOverlay, #wfLauncher, #wfHeroOpen, #wfNewBtn { display:none !important; }
}

/* The in-app file viewer is a focused, topmost action — it must sit ABOVE any
   panel that can open it (WhatsApp chat z11000, group browser z100000, order
   modals, etc.). Convention: a popup opened from within another overlay must
   stack above it; viewers/dialogs are topmost. */
#_orderSheetPreviewModal { z-index: 200000 !important; }

/* ═══ LAYER SCALE — one ladder, three rungs ═════════════════════════════════
   The ERP grew ~30 ad-hoc z-indexes (3000 … 2147483647/max-int), each bumped to
   win a fight with the last one. That escalation IS the "it opened behind the
   current page" bug, and it buried the toast (10110) under ~15 layers.

   The rungs (owner's rule):
     3rd  --z-live    the live display / base page content
     2nd  --z-page    a newly opened module or page. erpLayer.raise() hands each
                      new overlay the NEXT number, so whatever you opened LAST is
                      on top — pages stack instead of hiding behind each other.
     1st  --z-toast   toasts. Always on top. Nothing above, ever.

   A blocking confirm (.app-dialog-backdrop) sits just under the toast: it must
   cover every page (you can't navigate past it), but transient feedback must
   still be readable over it — so it drops from max-int to --z-dialog.

   New overlays: use these tokens, never a bigger magic number. */
:root {
  --z-live:   1;
  --z-page:   100000;       /* erpLayer.raise() counts up from here */
  --z-dialog: 2147483000;   /* blocking confirm/alert — above pages, below toast */
  --z-toast:  2147483647;   /* the ceiling */
}
/* body-scoped (0,1,1) so these win on specificity, not just load order. */
body .toast,
body .undo-toast          { z-index: var(--z-toast) !important; }
body .app-dialog-backdrop { z-index: var(--z-dialog) !important; }

/* A floating control owned by one page, while another page is on screen (index.html erpSyncPageOwned,
   mobile audit F05/F06): [data-erp-owner="<page>"] gets this class from the page switch, never by hand. */
.erp-owner-off { display: none !important; }

/* ── Filtered-out rows ───────────────────────────────────────────────────────
   listSearchFilter() used to hide rows with an inline `style.display='none'`.
   That works on a plain <tr>, but loses to any rule carrying !important — and
   #usersView .user-card-mobile sets `display:flex!important`, so on a phone the
   user search filtered nothing while the same box worked perfectly on desktop.
   An !important class beats an !important rule of equal specificity by coming
   later, and this file is loaded after redesign-pages.css is not — so keep the
   selector specific enough to win outright. */
.list-filter-hidden,
#usersView .list-filter-hidden,
.users-view .list-filter-hidden { display: none !important; }

/* ── thumb sizes on a phone (16 Sep, measured on the iPhone capture) ─────
 * 123 controls came in under 44×44. Almost all of them were the right
 * HEIGHT and too narrow: the topbar icon buttons were 34×44 on 22 of the 29
 * screens, the modal header buttons 32×44, the avatars 40×40. The filter
 * selects and search fields were both short and set at 11–13.5px, which is
 * what makes iOS zoom the page when you tap into them. Phones only. */
@media (max-width: 760px), (hover: none) and (pointer: coarse) {
  .notif-bell, #refresh-btn, .customize-btn-ic, .cw-bell, .modal-close,
  .wsx-pop-x, .mhx-avsel, .user-avatar, .user-edit, .user-logout,
  .modal-header-chat-btn, .order-sheet-btn-header {
    min-width: 44px !important; min-height: 44px !important;
  }
  .shipped-tab, .shipped-metric-pill, .sales-metric-pill, .ent-link { min-height: 44px !important; }
  .qf-pill, .vm-edit { min-width: 44px !important; min-height: 44px !important; }
  .cap-btn, .shipped-status-toggle button { min-height: 44px !important; min-width: 44px !important; }
  .list-search input { min-height: 44px !important; font-size: 17px !important; }
  .ent-link { min-width: 44px !important; }
  #pbSearch, #acxSearch, #vmSearch, #ciSearch, .pfx-search, #settingsNavSearch,
  #shippedFyFilter, #shippedPeriodFilter, .sales-filter-select, .ci-select, .pfx-sel {
    min-height: 44px !important; font-size: 17px !important;
  }
  /* ios-pwa.css now sets every phone field to 16px with a :not(#\#)x2 rule that outranks module rules
     (mobile audit F12). These were made 17px on purpose (16 Sep): a third :not(#\#) keeps them at 17. */
  html body :is(.list-search input, #pbSearch, #acxSearch, #vmSearch, #ciSearch, .pfx-search, #settingsNavSearch,
    #shippedFyFilter, #shippedPeriodFilter, .sales-filter-select, .ci-select, .pfx-sel, .erp-ed-find input):not(#\#):not(#\#):not(#\#) {
    font-size: 17px !important;
  }
}

/* ── the phone dock (16 Sep 2026) ────────────────────────────────────────────
 * Four destinations the person chose, plus More. Replaces the hamburger drawer
 * as the way around the ERP on a phone; see public/js/erp-dock.js for why it
 * is a projection of the sidebar rather than a second navigation.
 * Phones only — the desktop sidebar is untouched. */
@media (max-width: 900px) {
  .erp-dock {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    display: grid; grid-template-columns: repeat(5, 1fr);
    padding: 6px 6px calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(255, 255, 255, .97);
    -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
    border-top: 1px solid var(--border, #E6E6E0);
  }
  .erp-dk {
    position: relative; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 4px; min-height: 48px; padding: 6px 2px; min-width: 0;
    border: 0; background: transparent; border-radius: 9px; cursor: pointer;
    color: var(--text-3, #6C6C64); font: 600 12px var(--font-sans, inherit);
    -webkit-tap-highlight-color: transparent;
  }
  .erp-dk-ic { display: flex; }
  .erp-dk-ic svg { width: 20px; height: 20px; stroke-width: 1.75; }
  .erp-dk-l { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .erp-dk.on { color: var(--brand, #3C7538); background: rgba(60, 117, 56, .08); }
  .erp-dk:active { background: var(--surface-3, #F1F1ED); }
  .erp-dk-b {
    position: absolute; top: 2px; left: 50%; transform: translateX(4px);
    min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
    background: var(--danger-fg, #B23A34); color: #fff;
    font: 700 10.5px var(--mono, ui-monospace); display: grid; place-items: center;
  }
  /* Content has to clear the dock, and the drawer is no longer the way out. */
  body.erp-dock-on .main-area { padding-bottom: calc(78px + env(safe-area-inset-bottom, 0px)); }
  body.erp-dock-on .sidebar-toggle { display: none !important; }
  body.erp-dock-on .punch-fab, body.erp-dock-on .wsx-mob-fab { bottom: calc(80px + env(safe-area-inset-bottom, 0px)); }
  /* ── NOTHING PRIMARY UNDER THE DOCK (mobile audit F04 · F05 · F10 · F11, 21 Oct 2026) ──────────────────────
   * The dock owns the bottom --erp-dock-h of the screen. Every floating control that anchors to the bottom
   * (Mail's Compose circle, My tasks' "+ New task", the "Notifications are off" bar, the punch button …) is
   * measured from the dock's top edge instead of the screen's, in ONE list here — a new bottom FAB joins this
   * list or it sits under the dock (guarded by test/mobile-shell.test.mjs). Measured live at 390 px: Compose
   * centre hit the dock (F04), "+ New task" sat ON the dock over its first slot (F05, z 50 > 46) and the push
   * bar covered the dock completely (F10). !important: the bar carries an inline bottom, Mail injects its own
   * sheet after this one. The chat + bell buttons already ride above the dock (workspace.css). */
  body.erp-dock-on { --erp-dock-h: calc(78px + env(safe-area-inset-bottom, 0px)); }
  body.erp-dock-on .mhx-fab { bottom: calc(var(--erp-dock-h) + 14px) !important; }
  body.erp-dock-on #erpPushBar { bottom: calc(var(--erp-dock-h) + 10px) !important; }
  /* "+ New task" moves to the LEFT corner: the chat button owns the right one above the dock. */
  body.erp-dock-on .mobile-fab { bottom: calc(var(--erp-dock-h) + 14px) !important; left: 16px; right: auto !important; }
  /* …and the page keeps a strip free for that row of floating buttons, so the last row of any list, the
   * last field of a form and a lane's last card can always be scrolled clear of chat / bell (F11: Orders
   * "Country", Fabric Program "Body length", Kanban "On hold" were under them with no way out). */
  body.erp-dock-on .main-area { padding-bottom: calc(78px + 72px + env(safe-area-inset-bottom, 0px)); }
  /* …and so do the FULL-PAGE trackers (.erp-work-page: Fabric & CMT, Printing, Order sheet, Vendors, Cockpit,
   * Instore, Accessories). They are position:fixed OVER .main-area, so its padding never reached them, and on a
   * phone their own bottom action bar ("Upload artwork", "+ Add an order", "Receive D-742-02") sat under this
   * dock, out of reach (live QA at 390 px, 27 Sep 2026). The strip is reserved INSIDE the page (padding), never by
   * lifting it (`bottom`): see the erp-dock-visible rule in index.html for why a gap under the page is worse.
   * The chat and notification buttons ride above a page's action bar: see the :has() rule at the end of this file.
   * Accessories v2 (Phase 9, 5 Oct 2026) joins with its own dock (.a2-dock: "Raise a PO", "Approve", "Hand over to production"). */
  body.erp-dock-on .erp-work-page { padding-bottom: calc(78px + env(safe-area-inset-bottom, 0px)); }
  /* the page's action bar no longer meets the home indicator (this dock does), so it drops its 30px foot */
  body.erp-dock-on .erp-work-page :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock) { padding-bottom: 12px !important; }

  /* sheets — More, and Edit your dock */
  .erp-sheet-back { position: fixed; inset: 0; z-index: 60; background: rgba(27, 27, 25, .32); display: flex; align-items: flex-end; }
  .erp-sheet {
    width: 100%; max-height: 88vh; overflow: auto; -webkit-overflow-scrolling: touch;
    background: var(--surface, #fff); border-radius: 18px 18px 0 0;
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  }
  .erp-sheet-tall .erp-sheet { max-height: 94vh; }
  .erp-sheet-grab { width: 38px; height: 4px; border-radius: 999px; background: var(--border-strong, #D6D6CE); margin: 9px auto 3px; }
  .erp-sheet-h { display: flex; align-items: center; gap: 10px; padding: 6px 16px 10px; }
  .erp-sheet-h h2 { margin: 0; font-size: 16.5px; font-weight: 600; letter-spacing: -.01em; }
  .erp-sheet-edit {
    margin-left: auto; min-height: 44px; display: inline-flex; align-items: center; gap: 7px;
    padding: 0 13px; border: 1px solid var(--border-strong, #D6D6CE); border-radius: 9px;
    background: var(--surface, #fff); color: var(--text-2, #54544E);
    font: 600 13.5px var(--font-sans, inherit); cursor: pointer;
  }
  .erp-sheet-lede { margin: 0; padding: 0 16px 11px; font-size: 13px; line-height: 1.5; color: var(--text-2, #54544E); }
  .erp-sheet-empty { margin: 0; padding: 4px 16px 18px; font-size: 13.5px; color: var(--text-3, #6C6C64); }
  .erp-more-g { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; padding: 0 16px 16px; }
  .erp-more-t {
    position: relative; min-height: 84px; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 7px; padding: 8px 5px; cursor: pointer;
    border: 1px solid var(--border, #E6E6E0); background: var(--surface-2, #FBFBF9); border-radius: 11px;
    color: var(--text-2, #54544E); font: 600 12px var(--font-sans, inherit); text-align: center;
  }
  .erp-more-ic svg { width: 19px; height: 19px; stroke-width: 1.75; }
  /* Two lines, never cut (mobile audit F29): "Maintenance & renewals", "Order Sheet tracker", "Analytics
     dashboard" were cut at 102px. A tile is 84px tall with room for a second line; a word too long for the
     tile breaks rather than vanishing. */
  .erp-more-l { max-width: 100%; overflow: hidden; white-space: normal; overflow-wrap: anywhere; line-height: 1.25;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
  .erp-more-t .erp-dk-b { top: 7px; left: auto; right: 9px; transform: none; }
  .erp-ed-msg {
    margin: 0 16px 10px; padding: 9px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.45;
    background: var(--warn-bg, #F6ECD9); border: 1px solid #EADFC8; color: #8A5A0B;
  }
  .erp-ed-rows { border-top: 1px solid var(--border, #E6E6E0); }
  /* The whole row toggles, not just the switch — 54px of target instead of 30,
     and nobody has to hit a pill with a thumb. */
  .erp-ed-row { display: flex; align-items: center; gap: 11px; min-height: 54px; padding: 6px 16px; border-bottom: 1px solid var(--border, #E6E6E0); cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .erp-ed-row:active { background: var(--surface-3, #F1F1ED); }
  .erp-ed-ic { color: var(--text-3, #6C6C64); flex: none; display: flex; }
  .erp-ed-ic svg { width: 18px; height: 18px; stroke-width: 1.75; }
  .erp-ed-l { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 500; }
  .erp-ed-l small { display: block; font-size: 12px; font-weight: 400; color: var(--text-3, #6C6C64); margin-top: 1px; }
  /* Off was --border (#E6E6E0) carrying a WHITE knob — 1.15:1 between the two,
     on an almost-white sheet, so the switch read as a pale smudge and you could
     not tell the state at a glance. The track is darker now, the rail has an
     inset hairline so it reads as a track rather than a blob, and the knob has a
     real edge. (16 Sep 2026) */
  /* ios-pwa.css gives EVERY button min-height:44px on a touch screen. On a 46px
     wide pill with border-radius:999px that produced a 46x44 CIRCLE — which is
     what "the toggle switches look bad" was. min-height beats height, so the
     opt-out has to be min-height too. Safe because the ROW is the target now:
     54px, and tapping anywhere on it toggles. */
  .erp-ed-tg {
    flex: none; width: 46px; height: 30px; min-height: 30px; border: 0; border-radius: 999px;
    background: #C7C6BB; position: relative; cursor: pointer; padding: 0;
    /* The RING carries the 3:1 non-text contrast against the sheet, not the
       fill — so the switch has a definite edge without turning into a dark slab. */
    box-shadow: inset 0 0 0 1px rgba(27, 27, 25, .32);
    transition: background .14s var(--ease-out, ease);
  }
  .erp-ed-tg::after {
    content: ""; position: absolute; top: 3px; left: 3px; width: 24px; height: 24px;
    border-radius: 999px; background: #fff;
    box-shadow: 0 1px 2px rgba(27, 27, 25, .3), 0 0 0 1px rgba(27, 27, 25, .07);
    transition: left .14s var(--ease-out, ease);
  }
  .erp-ed-tg.on { background: var(--brand, #3C7538); box-shadow: inset 0 0 0 1px rgba(27, 27, 25, .14); }
  .erp-ed-tg.on::after { left: 19px; }
  .erp-ed-tg:focus-visible { outline: 2px solid var(--brand, #3C7538); outline-offset: 2px; }
  .erp-sheet-foot { display: flex; gap: 9px; padding: 12px 16px 4px; border-top: 1px solid var(--border, #E6E6E0); }
  .erp-sheet-btn {
    flex: 1 1 0; min-height: 46px; border-radius: 10px; cursor: pointer;
    border: 1px solid var(--border-strong, #D6D6CE); background: var(--surface, #fff);
    color: var(--text, #1B1B19); font: 600 15px var(--font-sans, inherit);
  }
  .erp-sheet-btn.primary { background: var(--brand, #3C7538); border-color: var(--brand, #3C7538); color: #fff; }
  body.erp-sheet-open { overflow: hidden; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .erp-ed-tg::after { transition: none; }
}

/* the dock's find box — 51 destinations is past the point where scanning works */
@media (max-width: 900px) {
  .erp-ed-find { padding: 0 16px 10px; }
  .erp-ed-find input {
    width: 100%; box-sizing: border-box; min-height: 44px; padding: 0 13px;
    border: 1px solid var(--border-strong, #D6D6CE); border-radius: 10px;
    background: var(--surface, #fff); color: var(--text, #1B1B19);
    font: 400 17px var(--font-sans, inherit);   /* 17px: under 16 and iOS zooms the page */
  }
  .erp-ed-find input:focus { outline: 2px solid var(--brand, #3C7538); outline-offset: 1px; }
}

/* While a full-page tracker shows its own action bar on a phone (Printing, Order sheet, Fabric & CMT), the chat
 * and notification buttons ride above that bar instead of covering its right-hand button (27 Sep 2026). :has()
 * keeps it self-healing: the moment the page closes (inline display:none) or its bar empties, the buttons drop
 * back. A browser without :has() drops the rule and the buttons stay where they were. */
@media (max-width: 760px) {
  body.erp-dock-on:has(.erp-work-page:not([style*="none"]) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)) #wsxMobChat { bottom: calc(18px + env(safe-area-inset-bottom, 0px) + 78px + 74px) !important; }
  body.erp-dock-on:has(.erp-work-page:not([style*="none"]) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)) #wsxMobNotifFab { bottom: calc(22px + env(safe-area-inset-bottom, 0px) + 78px + 74px) !important; }
  /* A tracker ORDER page with its own bottom action bar (Fabric & CMT order, Accessories order, Order sheet,
   * Printing order) hides the dock, as the order page (OVX) already does (mobile audit F22, 21 Oct 2026): the top
   * bar (63px) + the page's bar + the dock (69px) left about half the screen for the order. The page drops the
   * dock's reserved strip, its bar takes the home-indicator foot back and the chat buttons ride just above the bar.
   * ONLY WHILE THE PAGE SHOWS ITS OWN WAY BACK (review, 21 Oct 2026): the Order sheet and Printing LIST pages fill
   * their bar too ("Upload a sheet", "Gate · Add an order") and have no back / ✕ in their header, so with the dock
   * hidden (the hamburger is already hidden while the dock is on) a phone had no way off those pages. The dock
   * steps aside only while the page carries its back control (‹ Orders / Back to orders / the order's own back). */
  body.erp-dock-on:has(.erp-work-page:not([style*="none"]) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)):has(.erp-work-page:not([style*="none"]) :is(#t2Back, #o2Back, [data-act="back"], [data-act="back-list"], [data-act="back-order"])) #wsxMobChat { bottom: calc(18px + env(safe-area-inset-bottom, 0px) + 74px) !important; }
  body.erp-dock-on:has(.erp-work-page:not([style*="none"]) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)):has(.erp-work-page:not([style*="none"]) :is(#t2Back, #o2Back, [data-act="back"], [data-act="back-list"], [data-act="back-order"])) #wsxMobNotifFab { bottom: calc(22px + env(safe-area-inset-bottom, 0px) + 74px) !important; }
  body.erp-dock-on:has(.erp-work-page:not([style*="none"]) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)):has(.erp-work-page:not([style*="none"]) :is(#t2Back, #o2Back, [data-act="back"], [data-act="back-list"], [data-act="back-order"])) #erpDock { display: none !important; }
  body.erp-dock-on .erp-work-page:not([style*="none"]):has(:is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)):has(:is(#t2Back, #o2Back, [data-act="back"], [data-act="back-list"], [data-act="back-order"])) { padding-bottom: 0 !important; }
  body.erp-dock-on .erp-work-page:not([style*="none"]):has(:is(.p2-dock, .o2-dock, .t2-dock, .a2-dock):not(:empty)):has(:is(#t2Back, #o2Back, [data-act="back"], [data-act="back-list"], [data-act="back-order"])) :is(.p2-dock, .o2-dock, .t2-dock, .a2-dock) { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important; }
}
